mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Implement pixel data reinterpretation on EFB format change.
Whatever that means, it fixes that stupid Super Mario Sunshine glitch and possibly lots of other stuff, so test as many glitchy games as possible with this ;) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6669 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -397,7 +397,7 @@ void drawShadedTexQuad(IDirect3DTexture9 *texture,
|
||||
float u2=((float)rSource->right) * sw;
|
||||
float v1=((float)rSource->top) * sh;
|
||||
float v2=((float)rSource->bottom) * sh;
|
||||
float g = 1.0/Gamma;
|
||||
float g = 1.0f/Gamma;
|
||||
|
||||
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,G; } coords[4] = {
|
||||
{-1.0f - dw,-1.0f + dh, 0.0f,1.0f, u1, v2, sw, sh, g},
|
||||
@ -432,7 +432,7 @@ void drawShadedTexSubQuad(IDirect3DTexture9 *texture,
|
||||
float u2= rSource->right * sw;
|
||||
float v1= rSource->top * sh;
|
||||
float v2= rSource->bottom * sh;
|
||||
float g = 1.0/Gamma;
|
||||
float g = 1.0f/Gamma;
|
||||
|
||||
struct Q2DVertex { float x,y,z,rhw,u,v,w,h,G; } coords[4] = {
|
||||
{ rDest->left - dw , rDest->top + dh, 1.0f,1.0f, u1, v2, sw, sh, g},
|
||||
|
@ -45,6 +45,9 @@ FramebufferManager::FramebufferManager()
|
||||
s_efb.color_OffScreenReadBuffer = NULL;
|
||||
s_efb.depth_OffScreenReadBuffer = NULL;
|
||||
|
||||
s_efb.color_reinterpret_texture = NULL;
|
||||
s_efb.color_reinterpret_surface = NULL;
|
||||
|
||||
s_efb.color_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
s_efb.depth_surface_Format = D3DFMT_FORCE_DWORD;
|
||||
s_efb.depth_ReadBuffer_Format = D3DFMT_FORCE_DWORD;
|
||||
@ -62,6 +65,7 @@ FramebufferManager::FramebufferManager()
|
||||
hr = s_efb.color_texture->GetSurfaceLevel(0, &s_efb.color_surface);
|
||||
}
|
||||
CHECK(hr, "Create color texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
|
||||
hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb.color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb.colorRead_texture, NULL);
|
||||
CHECK(hr, "Create Color Read Texture (hr=%#x)", hr);
|
||||
@ -130,6 +134,15 @@ FramebufferManager::FramebufferManager()
|
||||
// Create an offscreen surface that we can lock to retrieve the data
|
||||
hr = D3D::dev->CreateOffscreenPlainSurface(4, 4, s_efb.depth_ReadBuffer_Format, D3DPOOL_SYSTEMMEM, &s_efb.depth_OffScreenReadBuffer, NULL);
|
||||
CHECK(hr, "Create depth offscreen surface (hr=%#x)", hr);
|
||||
|
||||
// create resources for ReinterpretPixelData
|
||||
hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb.color_surface_Format,
|
||||
D3DPOOL_DEFAULT, &s_efb.color_reinterpret_texture, NULL);
|
||||
if (s_efb.color_reinterpret_texture)
|
||||
{
|
||||
hr = s_efb.color_reinterpret_texture->GetSurfaceLevel(0, &s_efb.color_reinterpret_surface);
|
||||
}
|
||||
CHECK(hr, "Create color reinterpret texture (size: %dx%d; hr=%#x)", target_width, target_height, hr);
|
||||
}
|
||||
|
||||
FramebufferManager::~FramebufferManager()
|
||||
@ -144,6 +157,8 @@ FramebufferManager::~FramebufferManager()
|
||||
SAFE_RELEASE(s_efb.colorRead_texture);
|
||||
SAFE_RELEASE(s_efb.depth_texture);
|
||||
SAFE_RELEASE(s_efb.depthRead_texture);
|
||||
SAFE_RELEASE(s_efb.color_reinterpret_texture);
|
||||
SAFE_RELEASE(s_efb.color_reinterpret_surface);
|
||||
}
|
||||
|
||||
XFBSourceBase* FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height)
|
||||
|
@ -85,6 +85,18 @@ public:
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorReadSurface() { return s_efb.color_ReadBuffer; }
|
||||
static LPDIRECT3DSURFACE9 GetEFBDepthReadSurface() { return s_efb.depth_ReadBuffer; }
|
||||
|
||||
static LPDIRECT3DTEXTURE9 GetEFBColorReinterpretTexture() { return s_efb.color_reinterpret_texture; }
|
||||
static LPDIRECT3DSURFACE9 GetEFBColorReinterpretSurface() { return s_efb.color_reinterpret_surface; }
|
||||
static void SwapReinterpretTexture()
|
||||
{
|
||||
LPDIRECT3DSURFACE9 swapsurf = GetEFBColorReinterpretSurface();
|
||||
LPDIRECT3DTEXTURE9 swaptex = GetEFBColorReinterpretTexture();
|
||||
s_efb.color_reinterpret_surface = GetEFBColorRTSurface();
|
||||
s_efb.color_reinterpret_texture = GetEFBColorTexture();
|
||||
s_efb.color_surface = swapsurf;
|
||||
s_efb.color_texture = swaptex;
|
||||
}
|
||||
|
||||
private:
|
||||
XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height);
|
||||
void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc);
|
||||
@ -98,6 +110,9 @@ private:
|
||||
LPDIRECT3DTEXTURE9 depth_texture;//Texture thats contains the depth data of the render target
|
||||
LPDIRECT3DTEXTURE9 depthRead_texture;//4 pixel texture for temporal data store
|
||||
|
||||
LPDIRECT3DTEXTURE9 color_reinterpret_texture;//buffer used for ReinterpretPixelData
|
||||
LPDIRECT3DSURFACE9 color_reinterpret_surface;//corresponding surface
|
||||
|
||||
LPDIRECT3DSURFACE9 depth_surface;//Depth Surface
|
||||
LPDIRECT3DSURFACE9 color_surface;//Color Surface
|
||||
LPDIRECT3DSURFACE9 color_ReadBuffer;//Surface 0 of colorRead_texture
|
||||
|
@ -52,7 +52,9 @@ enum
|
||||
};
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 s_CopyProgram[NUM_COPY_TYPES][PixelShaderCache::NUM_DEPTH_CONVERSION_TYPES][MAX_SSAA_SHADERS];
|
||||
static LPDIRECT3DPIXELSHADER9 s_ClearProgram = 0;
|
||||
static LPDIRECT3DPIXELSHADER9 s_ClearProgram = NULL;
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgba6_to_rgb8 = NULL;
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgb8_to_rgba6 = NULL;
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram(int SSAAMode)
|
||||
{
|
||||
@ -74,6 +76,51 @@ LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetClearProgram()
|
||||
return s_ClearProgram;
|
||||
}
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgb8 = NULL;
|
||||
static LPDIRECT3DPIXELSHADER9 s_rgba6 = NULL;
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::ReinterpRGBA6ToRGB8()
|
||||
{
|
||||
const char code[] =
|
||||
{
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
" ocol0 = tex2D(samp0,uv0);\n"
|
||||
" float4 src6 = trunc(ocol0 * 63.f);\n"
|
||||
" ocol0.r = src6.r*4.f + trunc(src6.g/16.f);\n" // dst8r = (src6r<<2)|(src6g>>4);
|
||||
" ocol0.g = frac(src6.g/16.f)*16.f*16.f+trunc(src6.b/4.f);\n" // dst8g = ((src6g&0xF)<<4)|(src6b>>2);
|
||||
" ocol0.b = frac(src6.b/4.f)*4.f*64.f+src6.a;\n" // dst8b = ((src6b&0x3)<<6)|src6a;
|
||||
" ocol0.a = 255.f;\n"
|
||||
" ocol0 /= 255.f;\n"
|
||||
"}\n"
|
||||
};
|
||||
if (!s_rgba6_to_rgb8) s_rgba6_to_rgb8 = D3D::CompileAndCreatePixelShader(code, (int)strlen(code));
|
||||
return s_rgba6_to_rgb8;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::ReinterpRGB8ToRGBA6()
|
||||
{
|
||||
const char code[] =
|
||||
{
|
||||
"uniform sampler samp0 : register(s0);\n"
|
||||
"void main(\n"
|
||||
" out float4 ocol0 : COLOR0,\n"
|
||||
" in float2 uv0 : TEXCOORD0){\n"
|
||||
" ocol0 = tex2D(samp0,uv0);\n"
|
||||
" float4 src8 = trunc(ocol0*255.f);\n"
|
||||
" ocol0.r = (src8.r/4.f);\n" // dst6r = src8r>>2;
|
||||
" ocol0.g = frac(src8.r/4.f)*4.f*16.f + (src8.g/16.f);\n" // dst6g = ((src8r&0x3)<<4)|(src8g>>4);
|
||||
" ocol0.b = frac(src8.g/16.f)*16.f*4.f + (src8.b/64.f);\n" // dst6b = ((src8g&0xF)<<2)|(src8b>>6);
|
||||
" ocol0.a = frac(src8.b/64.f)*64.f;\n" // dst6a = src8b&0x3F;
|
||||
" ocol0 /= 63.f;\n"
|
||||
"}\n"
|
||||
};
|
||||
if (!s_rgb8_to_rgba6) s_rgb8_to_rgba6 = D3D::CompileAndCreatePixelShader(code, (int)strlen(code));
|
||||
return s_rgb8_to_rgba6;
|
||||
}
|
||||
|
||||
void SetPSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4)
|
||||
{
|
||||
float f[4] = { f1, f2, f3, f4 };
|
||||
@ -253,7 +300,7 @@ void PixelShaderCache::Shutdown()
|
||||
for(int depthType = 0; depthType < NUM_DEPTH_CONVERSION_TYPES; depthType++)
|
||||
for(int ssaaMode = 0; ssaaMode < MAX_SSAA_SHADERS; ssaaMode++)
|
||||
if(s_CopyProgram[copyMatrixType][depthType][ssaaMode]
|
||||
&& (copyMatrixType == 0 || s_CopyProgram[copyMatrixType][depthType][ssaaMode] != s_CopyProgram[copyMatrixType-1][depthType][ssaaMode]))
|
||||
&& (copyMatrixType == 0 || s_CopyProgram[copyMatrixType][depthType][ssaaMode] != s_CopyProgram[copyMatrixType-1][depthType][ssaaMode]))
|
||||
s_CopyProgram[copyMatrixType][depthType][ssaaMode]->Release();
|
||||
|
||||
for(int copyMatrixType = 0; copyMatrixType < NUM_COPY_TYPES; copyMatrixType++)
|
||||
@ -261,9 +308,13 @@ void PixelShaderCache::Shutdown()
|
||||
for(int ssaaMode = 0; ssaaMode < MAX_SSAA_SHADERS; ssaaMode++)
|
||||
s_CopyProgram[copyMatrixType][depthType][ssaaMode] = NULL;
|
||||
|
||||
if (s_ClearProgram) s_ClearProgram->Release();
|
||||
s_ClearProgram = NULL;
|
||||
|
||||
if (s_ClearProgram) s_ClearProgram->Release();
|
||||
s_ClearProgram = NULL;
|
||||
if (s_rgb8_to_rgba6) s_rgb8_to_rgba6->Release();
|
||||
s_rgb8_to_rgba6 = NULL;
|
||||
if (s_rgba6_to_rgb8) s_rgba6_to_rgb8->Release();
|
||||
s_rgba6_to_rgb8 = NULL;
|
||||
|
||||
Clear();
|
||||
g_ps_disk_cache.Sync();
|
||||
g_ps_disk_cache.Close();
|
||||
|
@ -71,6 +71,8 @@ public:
|
||||
};
|
||||
static LPDIRECT3DPIXELSHADER9 GetDepthMatrixProgram(int SSAAMode, int depthConversionType);
|
||||
static LPDIRECT3DPIXELSHADER9 GetClearProgram();
|
||||
static LPDIRECT3DPIXELSHADER9 ReinterpRGBA6ToRGB8();
|
||||
static LPDIRECT3DPIXELSHADER9 ReinterpRGB8ToRGBA6();
|
||||
};
|
||||
|
||||
|
||||
|
@ -843,6 +843,29 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE
|
||||
RestoreAPIState();
|
||||
}
|
||||
|
||||
void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||
{
|
||||
RECT source;
|
||||
SetRect(&source, 0, 0, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight());
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 pixel_shader;
|
||||
if (convtype == 0) pixel_shader = PixelShaderCache::ReinterpRGB8ToRGBA6();
|
||||
else if (convtype == 2) pixel_shader = PixelShaderCache::ReinterpRGBA6ToRGB8();
|
||||
else
|
||||
{
|
||||
PanicAlert("Trying to reinterpret pixel data with unsupported conversion type %d", convtype);
|
||||
return;
|
||||
}
|
||||
|
||||
// convert data and set the target texture as our new EFB
|
||||
g_renderer->ResetAPIState();
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorReinterpretSurface());
|
||||
D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture(), &source, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), pixel_shader, VertexShaderCache::GetSimpleVertexShader(0));
|
||||
FramebufferManager::SwapReinterpretTexture();
|
||||
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
void Renderer::SetBlendMode(bool forceUpdate)
|
||||
{
|
||||
if (bpmem.blendmode.logicopenable && !forceUpdate)
|
||||
|
@ -36,7 +36,9 @@ public:
|
||||
void Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight, const EFBRectangle& rc,float Gamma);
|
||||
|
||||
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z);
|
||||
|
||||
|
||||
void ReinterpretPixelData(unsigned int convtype);
|
||||
|
||||
void UpdateViewport();
|
||||
|
||||
bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc);
|
||||
|
@ -158,6 +158,7 @@ void InitBackendInfo()
|
||||
g_Config.backend_info.bSupports3DVision = true;
|
||||
g_Config.backend_info.bAllowSignedBytes = false;
|
||||
g_Config.backend_info.bSupportsDualSourceBlend = false;
|
||||
g_Config.backend_info.bSupportsFormatReinterpretation = true;
|
||||
}
|
||||
|
||||
void DllConfig(void *_hParent)
|
||||
|
Reference in New Issue
Block a user