diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index a4acddc40b..0d585aca2d 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -451,7 +451,9 @@ const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL WRITE(p, "void main(\n"); - WRITE(p, " out half4 ocol0 : COLOR0,\n"); + WRITE(p, " out float4 ocol0 : COLOR0,\n"); + if (HLSL) + WRITE(p, " out float4 ocol1 : COLOR1,\n"); WRITE(p, " out float depth : DEPTH,\n"); // compute window position if needed because binding semantic WPOS is not widely supported @@ -522,12 +524,20 @@ const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL // use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format... if (bpmem.ztex2.op == ZTEXTURE_ADD) - WRITE(p, "depth = frac(dot("I_ZBIAS"[0].xyzw, textemp.xyzw) + "I_ZBIAS"[1].w + zCoord);\n"); + WRITE(p, "zCoord = frac(dot("I_ZBIAS"[0].xyzw, textemp.xyzw) + "I_ZBIAS"[1].w + zCoord);\n"); else if (bpmem.ztex2.op == ZTEXTURE_REPLACE) - WRITE(p, "depth = frac(dot("I_ZBIAS"[0].xyzw, textemp.xyzw) + "I_ZBIAS"[1].w);\n"); - else - WRITE(p, "depth = zCoord;\n"); + WRITE(p, "zCoord = frac(dot("I_ZBIAS"[0].xyzw, textemp.xyzw) + "I_ZBIAS"[1].w);\n"); + + WRITE(p, "depth = zCoord;\n"); + if(HLSL) + { + //WRITE(p, "ocol1 = float4(1.0f/255.0f,2.0f/255.0f,3.0f/255.0f,0.0f);\n"); + WRITE(p, "float4 EncodedDepth = frac(zCoord * float4(254.0f*255.0f,255.0f,254.0f/255.0f,254.0f*255.0f*255.0f));\n"); + //WRITE(p, "EncodedDepth -= EncodedDepth.aarg * float4(1.0f/255.0f,1.0f/255.0f,1.0f/255.0f,0.0f);\n"); + WRITE(p, "ocol1 = EncodedDepth;\n"); + + } //if (bpmem.genMode.numindstages ) WRITE(p, "prev.rg = indtex0.xy;\nprev.b = 0;\n"); if (!WriteAlphaTest(p, HLSL)) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp index deda094ffe..8536198d65 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.cpp @@ -485,6 +485,14 @@ void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) } } +void RefreshVertexDeclaration() +{ + if (m_VtxDecl) + { + D3D::dev->SetVertexDeclaration(m_VtxDecl); + } +} + void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl) { if (!decl) { diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h index 40ab5c6237..d34b4e91d5 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DBase.h @@ -63,7 +63,8 @@ int GetBackBufferWidth(); int GetBackBufferHeight(); LPDIRECT3DSURFACE9 GetBackBufferSurface(); LPDIRECT3DSURFACE9 GetBackBufferDepthSurface(); - +LPDIRECT3DVERTEXBUFFER9 GetquadVB(); +LPDIRECT3DVERTEXDECLARATION9 GetBasicvertexDecl(); const D3DCAPS9 &GetCaps(); const char *PixelShaderVersionString(); const char *VertexShaderVersionString(); @@ -74,6 +75,7 @@ void SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture); void SetRenderState(D3DRENDERSTATETYPE State, DWORD Value); void SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value); void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value); +void RefreshVertexDeclaration(); void SetVertexDeclaration(LPDIRECT3DVERTEXDECLARATION9 decl); void ApplyCachedState(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp index a1b30a3dc2..3e6fb7e4b2 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.cpp @@ -208,10 +208,24 @@ void SaveRenderStates() void RestoreRenderStates() { - D3D::SetTexture(0, texture_old); - - dev->SetPixelShader(ps_old); - dev->SetVertexShader(vs_old); + if(texture_old) + { + D3D::SetTexture(0, texture_old); + texture_old->Release(); + texture_old = NULL; + } + if(ps_old) + { + dev->SetPixelShader(ps_old); + ps_old->Release(); + ps_old = NULL; + } + if(vs_old) + { + dev->SetVertexShader(vs_old); + vs_old->Release(); + vs_old = NULL; + } for (int i = 0; i < 6; i++) { @@ -374,4 +388,37 @@ void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v RestoreRenderStates(); } +void drawShadedTexQuad(IDirect3DTexture9 *texture, + const RECT *rSource, + int SourceWidth, + int SourceHeight, + const RECT *rDest, + IDirect3DPixelShader9 *PShader, + IDirect3DVertexShader9 *Vshader) +{ + SaveRenderStates(); + + float span = ((rSource->right-rSource->left - 1.0f) * (rDest->right - rDest->left))/(SourceWidth*((rDest->right - rDest->left)-1.0f)); + float u1=((0.5f+rSource->left)/(float) SourceWidth)-(span*0.5f/(float)(rDest->right - rDest->left)); + float u2=u1+span; + span = ((rSource->bottom-rSource->top - 1.0f) * (rDest->bottom - rDest->top))/(SourceHeight*((rDest->bottom - rDest->top)-1.0f)); + float v1=((0.5f+rSource->top)/(float) SourceHeight)-(span*0.5f/(float)(rDest->bottom - rDest->top)); + float v2=v1+span; + + struct Q2DVertex { float x,y,z,rhw,u,v; } coords[4] = { + {(float)rDest->left-1.0f, (float)rDest->top-1.0f, 0.0f, 1.0f, u1, v1}, + {(float)rDest->right, (float)rDest->top-1.0f, 0.0f,1.0f, u2, v1}, + {(float)rDest->right, (float)rDest->bottom, 0.0f,1.0f, u2, v2}, + {(float)rDest->left-1.0f, (float)rDest->bottom, 0.0f,1.0f, u1, v2} + }; + dev->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + dev->SetVertexShader(Vshader); + dev->SetPixelShader(PShader); + dev->SetTexture(0, texture); + dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coords, sizeof(Q2DVertex)); + D3D::RefreshVertexDeclaration(); + RestoreRenderStates(); + +} + } // namespace diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h index dc59ff3b6d..e61f6b06e1 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DUtil.h @@ -58,4 +58,13 @@ namespace D3D extern CD3DFont font; void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1=0, float v1=0, float u2=1, float v2=1); + void drawShadedTexQuad(IDirect3DTexture9 *texture, + const RECT *rSource, + int SourceWidth, + int SourceHeight, + const RECT *rDest, + IDirect3DPixelShader9 *PShader, + IDirect3DVertexShader9 *Vshader); + void SaveRenderStates(); + void RestoreRenderStates(); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp index f9d73bc169..c0772b2b4d 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.cpp @@ -23,34 +23,62 @@ namespace FBManager { -static LPDIRECT3DTEXTURE9 s_efb_color_texture; -static LPDIRECT3DTEXTURE9 s_efb_colorBuffer_texture; -static LPDIRECT3DTEXTURE9 s_efb_depth_texture; -static LPDIRECT3DTEXTURE9 s_efb_depthBuffer_texture; -static LPDIRECT3DSURFACE9 s_efb_color_surface; -static LPDIRECT3DSURFACE9 s_efb_depth_surface; +static LPDIRECT3DTEXTURE9 s_efb_color_texture;//Texture thats contains the color data of the render target +static LPDIRECT3DTEXTURE9 s_efb_colorRead_texture;//1 pixel texture for temporal data store +static LPDIRECT3DTEXTURE9 s_efb_depth_texture;//Texture thats contains the depth data of the render target +static LPDIRECT3DTEXTURE9 s_efb_depthRead_texture;//1 pixel texture for temporal data store -static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer; -static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer; +static LPDIRECT3DSURFACE9 s_efb_depth_surface;//Depth Surface +static LPDIRECT3DSURFACE9 s_efb_depthColor_surface;//Depth, color encoded Surface +static LPDIRECT3DSURFACE9 s_efb_color_surface;//Color Surface +static LPDIRECT3DSURFACE9 s_efb_color_ReadBuffer;//Surface 0 of s_efb_colorRead_texture +static LPDIRECT3DSURFACE9 s_efb_depth_ReadBuffer;//Surface 0 of s_efb_depthRead_texture -static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer; -static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer; +static LPDIRECT3DSURFACE9 s_efb_color_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data +static LPDIRECT3DSURFACE9 s_efb_depth_OffScreenReadBuffer;//System memory Surface that can be locked to retriebe the data -static D3DFORMAT s_efb_color_surface_Format; -static D3DFORMAT s_efb_depth_surface_Format; +static D3DFORMAT s_efb_color_surface_Format;//Format of the color Surface +static D3DFORMAT s_efb_depth_surface_Format;//Format of the Depth color encoded Surface #undef CHECK #define CHECK(hr,Message) if (FAILED(hr)) { PanicAlert(__FUNCTION__ " FAIL: %s" ,Message); } -LPDIRECT3DSURFACE9 GetEFBColorRTSurface() { return s_efb_color_surface; } -LPDIRECT3DSURFACE9 GetEFBDepthRTSurface() { return s_efb_depth_surface; } -LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface() { return s_efb_color_OffScreenReadBuffer; } -LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface() { return s_efb_depth_OffScreenReadBuffer; } +LPDIRECT3DSURFACE9 GetEFBColorRTSurface() +{ + return s_efb_color_surface; +} +LPDIRECT3DSURFACE9 GetEFBDepthRTSurface() +{ + return s_efb_depth_surface; +} + +LPDIRECT3DSURFACE9 GetEFBDepthEncodedSurface() +{ + return s_efb_depthColor_surface; +} + +LPDIRECT3DSURFACE9 GetEFBColorOffScreenRTSurface() +{ + return s_efb_color_OffScreenReadBuffer; +} +LPDIRECT3DSURFACE9 GetEFBDepthOffScreenRTSurface() +{ + return s_efb_depth_OffScreenReadBuffer; +} + +LPDIRECT3DSURFACE9 GetEFBColorReadSurface() +{ + + return s_efb_color_ReadBuffer; +} +LPDIRECT3DSURFACE9 GetEFBDepthReadSurface() +{ + + return s_efb_depth_ReadBuffer; +} -LPDIRECT3DSURFACE9 GetEFBColorReadSurface() { return s_efb_color_ReadBuffer; } -LPDIRECT3DSURFACE9 GetEFBDepthReadSurface() { return s_efb_depth_ReadBuffer; } D3DFORMAT GetEFBDepthRTSurfaceFormat(){return s_efb_depth_surface_Format;} D3DFORMAT GetEFBColorRTSurfaceFormat(){return s_efb_color_surface_Format;} @@ -63,14 +91,9 @@ LPDIRECT3DTEXTURE9 GetEFBColorTexture(const EFBRectangle& sourceRc) LPDIRECT3DTEXTURE9 GetEFBDepthTexture(const EFBRectangle &sourceRc) { - // Depth textures not supported under DX9. We're gonna fake this - // with a secondary render target later. return s_efb_depth_texture; } - - - void Create() { @@ -79,29 +102,55 @@ void Create() int target_height = Renderer::GetTargetHeight(); s_efb_color_surface_Format = D3DFMT_A8R8G8B8; //get the framebuffer texture - HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, + HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_color_surface_Format, D3DPOOL_DEFAULT, &s_efb_color_texture, NULL); - CHECK(hr,"Create Color Texture"); - //get the Surface - hr = s_efb_color_texture->GetSurfaceLevel(0, &s_efb_color_surface); - CHECK(hr,"Get Color Surface"); - //create a one pixel texture to work as a buffer for peeking - hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, - D3DPOOL_DEFAULT, &s_efb_colorBuffer_texture, NULL); - if (!FAILED(hr)) + if(s_efb_color_texture) { - //get the surface for the peeking texture - hr = s_efb_colorBuffer_texture->GetSurfaceLevel(0, &s_efb_color_ReadBuffer); - CHECK(hr,"Get Color Pixel Surface"); - //create an offscreen surface that we can lock to retrieve the data - hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL ); - CHECK(hr,"Create Color offScreen Surface"); + s_efb_color_texture->GetSurfaceLevel(0,&s_efb_color_surface); + } + CHECK(hr,"Create Color Texture"); + 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"); + if(s_efb_colorRead_texture) + { + s_efb_colorRead_texture->GetSurfaceLevel(0,&s_efb_color_ReadBuffer); } + //create an offscreen surface that we can lock to retrieve the data + hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_color_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_color_OffScreenReadBuffer, NULL ); + CHECK(hr,"Create Color offScreen Surface"); //Select Zbuffer format supported by hadware. if (g_ActiveConfig.bEFBAccessEnable) { - //depth format in prefered order + + hr = D3D::dev->CreateDepthStencilSurface(target_width, target_height, D3DFMT_D24X8, + D3DMULTISAMPLE_NONE, 0, FALSE, &s_efb_depth_surface, NULL); + CHECK(hr,"CreateDepthStencilSurface"); + + s_efb_depth_surface_Format = D3DFMT_A8R8G8B8; + //get the framebuffer Depth texture + HRESULT hr = D3D::dev->CreateTexture(target_width, target_height, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_surface_Format, + D3DPOOL_DEFAULT, &s_efb_depth_texture, NULL); + CHECK(hr,"Depth Color Texture"); + //get the Surface + if(s_efb_depth_texture) + { + s_efb_depth_texture->GetSurfaceLevel(0,&s_efb_depthColor_surface); + } + //create a one pixel texture to work as a buffer for peeking + hr = D3D::dev->CreateTexture(1, 1, 1, D3DUSAGE_RENDERTARGET, s_efb_depth_surface_Format, + D3DPOOL_DEFAULT, &s_efb_depthRead_texture, NULL); + CHECK(hr,"Create Depth Read texture"); + if(s_efb_depthRead_texture) + { + s_efb_depthRead_texture->GetSurfaceLevel(0,&s_efb_depth_ReadBuffer); + } + //create an offscreen surface that we can lock to retrieve the data + hr = D3D::dev->CreateOffscreenPlainSurface(1, 1, s_efb_depth_surface_Format, D3DPOOL_SYSTEMMEM, &s_efb_depth_OffScreenReadBuffer, NULL ); + CHECK(hr,"Create Depth offScreen Surface"); + + /*//depth format in prefered order D3DFORMAT *DepthTexFormats = new D3DFORMAT[3]; DepthTexFormats[0] = D3DFMT_D32F_LOCKABLE; DepthTexFormats[1] = D3DFMT_D16_LOCKABLE; @@ -116,7 +165,7 @@ void Create() s_efb_depth_ReadBuffer = s_efb_depth_surface; s_efb_depth_OffScreenReadBuffer = s_efb_depth_surface; CHECK(hr,"CreateDepthStencilSurface"); - delete [] DepthTexFormats; + delete [] DepthTexFormats;*/ } else { @@ -129,44 +178,51 @@ void Create() void Destroy() { - if(s_efb_depth_ReadBuffer) - s_efb_depth_ReadBuffer->Release(); - s_efb_depth_ReadBuffer = NULL; - if(s_efb_depth_OffScreenReadBuffer) - s_efb_depth_OffScreenReadBuffer->Release(); +if(s_efb_depth_surface) +s_efb_depth_surface->Release(); +s_efb_depth_surface=NULL; - if(s_efb_depth_surface) - s_efb_depth_surface->Release(); - s_efb_depth_surface = NULL; - - if(s_efb_depthBuffer_texture) - s_efb_depthBuffer_texture->Release(); - s_efb_depthBuffer_texture=NULL; +if(s_efb_depthColor_surface) +s_efb_depthColor_surface->Release(); +s_efb_depthColor_surface=NULL; - if(s_efb_depth_texture) - s_efb_depth_texture->Release(); - s_efb_depth_texture = NULL; +if(s_efb_color_surface) +s_efb_color_surface->Release(); +s_efb_color_surface=NULL; - if(s_efb_color_OffScreenReadBuffer ) - s_efb_color_OffScreenReadBuffer->Release(); - s_efb_color_OffScreenReadBuffer = NULL; - - if(s_efb_color_ReadBuffer ) - s_efb_color_ReadBuffer->Release(); - s_efb_color_ReadBuffer = NULL; +if(s_efb_color_ReadBuffer) +s_efb_color_ReadBuffer->Release(); +s_efb_color_ReadBuffer=NULL; + +if(s_efb_depth_ReadBuffer) +s_efb_depth_ReadBuffer->Release(); +s_efb_depth_ReadBuffer=NULL; + +if(s_efb_color_OffScreenReadBuffer) +s_efb_color_OffScreenReadBuffer->Release(); +s_efb_color_OffScreenReadBuffer=NULL; + +if(s_efb_depth_OffScreenReadBuffer) +s_efb_depth_OffScreenReadBuffer->Release(); +s_efb_depth_OffScreenReadBuffer=NULL; + +if(s_efb_color_texture) + s_efb_color_texture->Release(); +s_efb_color_texture=NULL; + +if(s_efb_colorRead_texture) +s_efb_colorRead_texture->Release(); +s_efb_colorRead_texture=NULL; + +if(s_efb_depth_texture) +s_efb_depth_texture->Release(); +s_efb_depth_texture=NULL; + +if(s_efb_depthRead_texture) +s_efb_depthRead_texture->Release(); +s_efb_depthRead_texture=NULL; - if(s_efb_color_surface) - s_efb_color_surface->Release(); - s_efb_color_surface = NULL; - - if(s_efb_colorBuffer_texture) - s_efb_colorBuffer_texture->Release(); - s_efb_colorBuffer_texture = NULL; - - if(s_efb_color_texture) - s_efb_color_texture->Release(); - s_efb_color_texture = NULL; } } // namespace \ No newline at end of file diff --git a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.h b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.h index ddf8377df5..a1b36ac44a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/FramebufferManager.h @@ -40,6 +40,7 @@ D3DFORMAT GetEFBDepthRTSurfaceFormat(); D3DFORMAT GetEFBColorRTSurfaceFormat(); LPDIRECT3DSURFACE9 GetEFBColorReadSurface(); LPDIRECT3DSURFACE9 GetEFBDepthReadSurface(); +LPDIRECT3DSURFACE9 GetEFBDepthEncodedSurface(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp index dafed61dfb..b762d85993 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp @@ -34,6 +34,19 @@ PixelShaderCache::PSCache PixelShaderCache::PixelShaders; const PixelShaderCache::PSCacheEntry *PixelShaderCache::last_entry; static float lastPSconstants[C_COLORMATRIX+16][4]; +static LPDIRECT3DPIXELSHADER9 s_ColorMatrixProgram = 0; +static LPDIRECT3DPIXELSHADER9 s_ColorCopyProgram = 0; + +LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorMatrixProgram() +{ + return s_ColorMatrixProgram; +} + +LPDIRECT3DPIXELSHADER9 PixelShaderCache::GetColorCopyProgram() +{ + return s_ColorCopyProgram; +} + void SetPSConstant4f(int const_number, float f1, float f2, float f3, float f4) { if( lastPSconstants[const_number][0] != f1 || lastPSconstants[const_number][1] != f2 || @@ -63,6 +76,25 @@ void SetPSConstant4fv(int const_number, const float *f) void PixelShaderCache::Init() { + char pmatrixprog[1024]; + sprintf(pmatrixprog,"uniform sampler samp0 : register(s0);\n" + "uniform float4 cColMatrix[5] : register(c%d);\n" + "void main(\n" + "out float4 ocol0 : COLOR0,\n" + " in float3 uv0 : TEXCOORD0){\n" + "float4 texcol = tex2D(samp0,uv0.xy);\n" + "ocol0 = float4(dot(texcol,cColMatrix[0]),dot(texcol,cColMatrix[1]),dot(texcol,cColMatrix[2]),dot(texcol,cColMatrix[3])) + cColMatrix[4];\n" + "}\n",C_COLORMATRIX); + char pcopyprog[1024]; + sprintf(pcopyprog,"uniform sampler samp0 : register(s0);\n" + "void main(\n" + "out float4 ocol0 : COLOR0,\n" + " in float3 uv0 : TEXCOORD0){\n" + "ocol0 = tex2D(samp0,uv0.xy);\n" + "}\n"); + + s_ColorMatrixProgram = D3D::CompilePixelShader(pmatrixprog, (int)strlen(pmatrixprog)); + s_ColorCopyProgram = D3D::CompilePixelShader(pcopyprog, (int)strlen(pcopyprog)); Clear(); } @@ -80,6 +112,12 @@ void PixelShaderCache::Clear() void PixelShaderCache::Shutdown() { + if(s_ColorMatrixProgram) + s_ColorMatrixProgram->Release(); + s_ColorMatrixProgram = NULL; + if(s_ColorCopyProgram) + s_ColorCopyProgram->Release(); + s_ColorCopyProgram=NULL; Clear(); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h index b9e84b45bd..c227128151 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.h @@ -59,6 +59,8 @@ public: static void Clear(); static void Shutdown(); static bool SetShader(bool dstAlpha); + static LPDIRECT3DPIXELSHADER9 GetColorMatrixProgram(); + static LPDIRECT3DPIXELSHADER9 GetColorCopyProgram(); #if defined(_DEBUG) || defined(DEBUGFAST) static std::string GetCurrentShaderCode(); #endif diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 1c5a564778..1b40fd91ca 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -63,6 +63,7 @@ static u32 s_blendMode; char st[32768]; + // State translation lookup tables static const D3DBLEND d3dSrcFactors[8] = { @@ -98,6 +99,7 @@ void SetupDeviceObjects() PixelShaderManager::Dirty(); // Tex and shader caches will recreate themselves over time. + } // Kill off all POOL_DEFAULT device objects. @@ -159,15 +161,25 @@ bool Renderer::Init() for (int stage = 0; stage < 8; stage++) D3D::SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, g_ActiveConfig.iMaxAnisotropy); - - D3D::dev->Clear(0, NULL, D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(255,255,255),1.0f,0); + D3DVIEWPORT9 vp; + vp.X = 0; + vp.Y = 0; + vp.Width = s_backbuffer_width; + vp.Height = s_backbuffer_height; + vp.MinZ = 0.0f; + vp.MaxZ = 0.0f; + D3D::dev->SetViewport(&vp); D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 0, 0); - + D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface()); + D3D::dev->SetRenderTarget(1, FBManager::GetEFBDepthEncodedSurface()); D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface()); - + vp.Width = s_target_width; + vp.Height = s_target_height; + vp.MinZ = 0.0f; + vp.MaxZ = 0.0f; + D3D::dev->SetViewport(&vp); D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x0, 1.0f, 0); - D3D::BeginFrame(); D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true); return true; @@ -209,9 +221,9 @@ void dumpMatrix(D3DXMATRIX &mtx) TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc) { TargetRectangle result; - result.left = (rc.left * s_target_width) / EFB_WIDTH; + result.left = (rc.left * s_target_width) / EFB_WIDTH ; result.top = (rc.top * s_target_height) / EFB_HEIGHT; - result.right = (rc.right * s_target_width) / EFB_WIDTH; + result.right = (rc.right * s_target_width) / EFB_WIDTH ; result.bottom = (rc.bottom * s_target_height) / EFB_HEIGHT; return result; } @@ -261,32 +273,49 @@ void CheckForResize() static void EFBTextureToD3DBackBuffer(const EFBRectangle& sourceRc) { // Set the backbuffer as the rendering target - D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); D3D::dev->SetDepthStencilSurface(NULL); - - // Blit our render target onto the backbuffer. - // TODO: Change to a quad so we can do post processing. + D3D::dev->SetRenderTarget(1, NULL); + D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); + TargetRectangle src_rect, dst_rect; src_rect = Renderer::ConvertEFBRectangle(sourceRc); ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect); - - //LPD3DXSPRITE pSprite=NULL; - //D3DXCreateSprite(D3D::dev, &pSprite); - //D3DXVECTOR3 pos(0,0,0); - //EFBRectangle efbRect; - // - //pSprite->Begin(D3DXSPRITE_ALPHABLEND); - //pSprite->Draw(FBManager::GetEFBColorTexture(efbRect),NULL, NULL, &pos, 0xFFFFFFFF); - //pSprite->End(); - //pSprite->Release(); + D3DVIEWPORT9 vp; + vp.X = 0; + vp.Y = 0; + vp.Width = s_backbuffer_width; + vp.Height = s_backbuffer_height; + vp.MinZ = 0.0f; + vp.MaxZ = 0.0f; + D3D::dev->SetViewport(&vp); D3D::dev->Clear(0,NULL, D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0); + vp.X = dst_rect.left; + vp.Y = dst_rect.top; + vp.Width = dst_rect.right - dst_rect.left; + vp.Height = dst_rect.bottom - dst_rect.top; + vp.MinZ = 0.0f; + vp.MaxZ = 0.0f; + D3D::dev->SetViewport(&vp); - // todo, to draw the EFB texture to the backbuffer instead of StretchRect - D3D::dev->StretchRect(FBManager::GetEFBColorRTSurface(), src_rect.AsRECT(), - D3D::GetBackBufferSurface(), dst_rect.AsRECT(), - D3DTEXF_LINEAR); + EFBRectangle efbRect; + + + + LPDIRECT3DTEXTURE9 read_texture = FBManager::GetEFBColorTexture(efbRect); + RECT destinationrect; + destinationrect.bottom = dst_rect.bottom; + destinationrect.left = dst_rect.left; + destinationrect.right = dst_rect.right; + destinationrect.top = dst_rect.top; + RECT sourcerect; + sourcerect.bottom = src_rect.bottom; + sourcerect.left = src_rect.left; + sourcerect.right = src_rect.right; + sourcerect.top = src_rect.top; + D3D::drawShadedTexQuad(read_texture,&sourcerect,Renderer::GetTargetWidth(),Renderer::GetTargetHeight(),&destinationrect,PixelShaderCache::GetColorCopyProgram(),VertexShaderCache::GetSimpleVertexSahder()); + // Finish up the current frame, print some stats if (g_ActiveConfig.bOverlayStats) { @@ -301,14 +330,11 @@ static void EFBTextureToD3DBackBuffer(const EFBRectangle& sourceRc) OSD::DrawMessages(); - // u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; - - // Clear the render target. We probably don't need to do this every frame. - //D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, 0x0, 1.0f, 0); - - // Set rendering target back to the EFB rendering texture D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface()); + D3D::dev->SetRenderTarget(1, FBManager::GetEFBDepthEncodedSurface()); D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface()); + + VertexShaderManager::SetViewportChanged(); } @@ -386,10 +412,11 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect return; } - D3D::EndFrame(); + Renderer::ResetAPIState(); D3DDumpFrame(); EFBTextureToD3DBackBuffer(sourceRc); - D3D::BeginFrame(); + D3D::EndFrame(); + DEBUGGER_LOG_AT((NEXT_XFB_CMD|NEXT_EFB_CMD|NEXT_FRAME), {printf("StretchRect, EFB->XFB\n");}); @@ -399,21 +426,12 @@ void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRect xfbAddr, fbWidth, fbHeight, sourceRc.left, sourceRc.top, sourceRc.right, sourceRc.bottom);} ); - - - RECT rc; - rc.left = 0; - rc.top = 0; - rc.right = (LONG)s_target_width; - rc.bottom = (LONG)s_target_height; - D3D::dev->SetScissorRect(&rc); - D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, false); - - UpdateViewport(); - Swap(0,FIELD_PROGRESSIVE,0,0); // we used to swap the buffer here, now we will wait - // until the XFB pointer is updated by VI - D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, true); + // until the XFB pointer is updated by VI + D3D::BeginFrame(); + Renderer::RestoreAPIState(); + UpdateViewport(); + } bool Renderer::SetScissorRect() @@ -432,10 +450,27 @@ bool Renderer::SetScissorRect() rc.bottom = (int)(rc.bottom * yScale); if (rc.left < 0) rc.left = 0; - if (rc.right > s_target_width) rc.right = s_target_width; + if (rc.right < 0) rc.right = 0; + if (rc.left > s_target_width) rc.left = s_target_width; + if (rc.right > s_target_width) rc.right = s_target_width; if (rc.top < 0) rc.top = 0; + if (rc.bottom < 0) rc.bottom = 0; + if (rc.top > s_target_height) rc.top = s_target_height; if (rc.bottom > s_target_height) rc.bottom = s_target_height; - + /*LONG temprc = 0; + if(rc.right < rc.left) + { + temprc = rc.right; + rc.right = rc.left; + rc.left = temprc; + } + if(rc.bottom < rc.top) + { + temprc = rc.bottom; + rc.bottom = rc.top; + rc.top = temprc; + } + D3D::dev->SetScissorRect(&rc);*/ if (rc.right >= rc.left && rc.bottom >= rc.top) { D3D::dev->SetScissorRect(&rc); @@ -443,9 +478,10 @@ bool Renderer::SetScissorRect() } else { - WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom); + WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom); return false; } + return true; } void Renderer::SetColorMask() @@ -460,10 +496,9 @@ void Renderer::SetColorMask() u32 Renderer::AccessEFB(EFBAccessType type, int x, int y) { - //Get the working buffer LPDIRECT3DSURFACE9 pBuffer = (type == PEEK_Z || type == POKE_Z) ? - FBManager::GetEFBDepthRTSurface() : FBManager::GetEFBColorRTSurface(); + FBManager::GetEFBDepthEncodedSurface() : FBManager::GetEFBColorRTSurface(); //get the temporal buffer to move 1pixel data LPDIRECT3DSURFACE9 RBuffer = (type == PEEK_Z || type == POKE_Z) ? FBManager::GetEFBDepthReadSurface() : FBManager::GetEFBColorReadSurface(); @@ -482,11 +517,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y) PanicAlert("No %s!", (type == PEEK_Z || type == POKE_Z) ? "Z-Buffer" : "Color EFB"); return 0; } - // Z buffer lock not suported: returning - if((type == PEEK_Z || type == POKE_Z) && BufferFormat == D3DFMT_D24X8) - { - return 0; - } // Get the rectangular target region covered by the EFB pixel. EFBRectangle efbPixelRc; @@ -506,30 +536,25 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y) RectToLock.right = targetPixelRc.right; RectToLock.top = targetPixelRc.top; - //lock the buffer - - if(!(BufferFormat == D3DFMT_D32F_LOCKABLE || BufferFormat == D3DFMT_D16_LOCKABLE)) + hr = D3D::dev->StretchRect(pBuffer,&RectToLock,RBuffer,NULL, D3DTEXF_NONE); + if(FAILED(hr)) { - //the hard support stretchrect in both color and z so use it - hr = D3D::dev->StretchRect(pBuffer,&RectToLock,RBuffer,NULL, D3DTEXF_NONE); - if(FAILED(hr)) - { - PanicAlert("Unable to stretch data to buffer"); - return 0; - } - //retriebe the pixel data to the local memory buffer - D3D::dev->GetRenderTargetData(RBuffer,pOffScreenBuffer); - if(FAILED(hr)) - { - PanicAlert("Unable to copy data to mem buffer"); - return 0; - } - //change the rect to lock the entire one pixel buffer - RectToLock.bottom = 1; - RectToLock.left = 0; - RectToLock.right = 1; - RectToLock.top = 0; - } + PanicAlert("Unable to stretch data to buffer"); + return 0; + } + //retriebe the pixel data to the local memory buffer + D3D::dev->GetRenderTargetData(RBuffer,pOffScreenBuffer); + if(FAILED(hr)) + { + PanicAlert("Unable to copy data to mem buffer"); + return 0; + } + //change the rect to lock the entire one pixel buffer + RectToLock.bottom = 1; + RectToLock.left = 0; + RectToLock.right = 1; + RectToLock.top = 0; + //the surface is good.. lock it if((hr = pOffScreenBuffer->LockRect(&drect, &RectToLock, D3DLOCK_READONLY)) != D3D_OK) { @@ -540,25 +565,18 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y) switch(type) { case PEEK_Z: - { - switch (BufferFormat) { - case D3DFMT_D32F_LOCKABLE: - val = ((float *)drect.pBits)[0]; - z = ((u32)(val * 0xffffff));// 0xFFFFFFFF; - break; - case D3DFMT_D16_LOCKABLE: - val = ((float)((u16 *)drect.pBits)[0])/((float)0xFFFF); - z = ((u32)(val * 0xffffff)); - break; - default: - z = ((u32 *)drect.pBits)[0] >> 8; - break; - }; - // [0.0, 1.0] ==> [0, 0xFFFFFFFF] - - break; + static float ffrac = 255.0f/254.0f; + z = ((u32 *)drect.pBits)[0]; + float fvalue = (((float)(z & 0xFF)) / 255.0f) * ffrac; + fvalue += (((float)((z>>8) & 0xFF)) / 255.0f) * (ffrac/255.0f); + fvalue += (((float)((z>>16) & 0xFF)) / 255.0f) * (ffrac/(255.0f*255.0f)); + fvalue += (((float)((z>>24) & 0xFF)) / 255.0f) * (ffrac/(255.0f*255.0f*255.0f)); + if(fvalue>1.0f)fvalue=1.0f; + if(fvalue<0.0f)fvalue=0.0f; + z = ((u32)(fvalue * 0xffffff)); } + break; case POKE_Z: // TODO: Get that Z value to poke from somewhere //((float *)drect.pBits)[0] = val; @@ -568,7 +586,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y) case PEEK_COLOR: z = ((u32 *)drect.pBits)[0]; break; - case POKE_COLOR: // TODO: Get that ARGB value to poke from somewhere //((float *)drect.pBits)[0] = val; @@ -577,9 +594,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, int x, int y) } - pOffScreenBuffer->UnlockRect(); - - + pOffScreenBuffer->UnlockRect(); // TODO: in RE0 this value is often off by one, which causes lighting to disappear return z; @@ -605,6 +620,14 @@ void UpdateViewport() vp.Y = (int)(ceil(xfregs.rawViewport[4] + xfregs.rawViewport[1] - (scissorYOff)) * MValueY); vp.Width = (int)ceil(abs((int)(2 * xfregs.rawViewport[0])) * MValueX); vp.Height = (int)ceil(abs((int)(2 * xfregs.rawViewport[1])) * MValueY); + if(vp.X < 0) vp.X = 0; + if(vp.Y < 0) vp.Y = 0; + if(vp.X > s_target_width) vp.X = s_target_width; + if(vp.Y > s_target_height) vp.Y = s_target_height; + if(vp.Width < 0) vp.Width = 0; + if(vp.Height < 0) vp.Height = 0; + if(vp.Width > (s_target_width - vp.X)) vp.Width = s_target_width - vp.X; + if(vp.Height > (s_target_height - vp.Y)) vp.Height = s_target_height - vp.Y; //some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work vp.MinZ = 0.0f;//(xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f; vp.MaxZ = 1.0f;//xfregs.rawViewport[5] / 16777216.0f; @@ -719,3 +742,29 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) // Flip/present backbuffer to frontbuffer here D3D::Present(); } + +void Renderer::ResetAPIState() +{ + D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + D3D::SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + D3D::SetRenderState(D3DRS_ZENABLE, FALSE); + D3D::SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + DWORD color_mask = D3DCOLORWRITEENABLE_ALPHA| D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; + D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask); +} + +void Renderer::RestoreAPIState() +{ + // Gets us back into a more game-like state. + + UpdateViewport(); + + if (bpmem.zmode.testenable) D3D::SetRenderState(D3DRS_ZENABLE, TRUE); + if (bpmem.zmode.updateenable) D3D::SetRenderState(D3DRS_ZWRITEENABLE, TRUE); + + D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); + SetScissorRect(); + SetColorMask(); + SetBlendMode(true); +} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index db4f5d0247..3f51af74f7 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -27,7 +27,12 @@ #include "D3DBase.h" #include "D3DTexture.h" +#include "D3DUtil.h" #include "FramebufferManager.h" +#include "PixelShaderCache.h" +#include "PixelShaderManager.h" +#include "VertexShaderManager.h" +#include "VertexShaderCache.h" #include "Render.h" @@ -257,9 +262,12 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, return &entry; } +#undef CHECK +#define CHECK(hr) if (FAILED(hr)) { PanicAlert(__FUNCTION__ " FAIL"); } // EXTREMELY incomplete. void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle &source_rect) { + HRESULT hr = S_OK; int efb_w = source_rect.GetWidth(); int efb_h = source_rect.GetHeight(); @@ -271,19 +279,20 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo iter = textures.find(address); if (iter != textures.end()) { - if (!iter->second.isRenderTarget) + if (iter->second.isRenderTarget && iter->second.w == tex_w && iter->second.h == tex_h) + { + + tex = iter->second.texture; + iter->second.frameCount = frameCount; + goto have_texture; + } + else { // Remove it and recreate it as a render target iter->second.texture->Release(); iter->second.texture = 0; textures.erase(iter); } - else - { - tex = iter->second.texture; - iter->second.frameCount = frameCount; - goto have_texture; - } } { @@ -293,14 +302,16 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo entry.frameCount = frameCount; entry.w = tex_w; entry.h = tex_h; - - D3D::dev->CreateTexture(tex_w, tex_h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0); + entry.fmt = copyfmt; + + hr = D3D::dev->CreateTexture(tex_w, tex_h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0); + CHECK(hr); textures[address] = entry; tex = entry.texture; } have_texture: - TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect); + /*TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect); RECT source_rc; source_rc.left = targetSource.left; source_rc.top = targetSource.top; @@ -317,8 +328,162 @@ have_texture: srcSurface = FBManager::GetEFBColorRTSurface(); D3D::dev->StretchRect(srcSurface, &source_rc, destSurface, &dest_rc, D3DTEXF_LINEAR); destSurface->Release(); + return;*/ + float colmat[16]= {0.0f}; + float fConstAdd[4] = {0.0f}; - DEBUGGER_LOG_AT((NEXT_XFB_CMD|NEXT_EFB_CMD|NEXT_FRAME|NEXT_NEW_TEXTURE|NEXT_FLUSH), - {printf("StretchRect, EFB (%d,%d) -> Texture at 0x%08X (%d,%d)\n",efb_w,efb_h,address,tex_w,tex_h);}); - DEBUGGER_PAUSE_AT((NEXT_EFB_CMD|NEXT_NEW_TEXTURE),false); + if (bFromZBuffer) + { + switch(copyfmt) + { + case 0: // Z4 + case 1: // Z8 + colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1; + break; + + case 3: // Z16 //? + colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1; + case 11: // Z16 (reverse order) + colmat[2] = colmat[6] = colmat[10] = colmat[13] = 1; + break; + case 6: // Z24X8 + colmat[0] = 1; + colmat[5] = 1; + colmat[10] = 1; + colmat[15] = 1; + break; + case 9: // Z8M + colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1; + break; + case 10: // Z8L + colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; + break; + case 12: // Z16L + colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1; + break; + default: + ERROR_LOG(VIDEO, "Unknown copy zbuf format: 0x%x", copyfmt); + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; + break; + } + } + else if (bIsIntensityFmt) + { + fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = 16.0f/255.0f; + switch (copyfmt) + { + case 0: // I4 + case 1: // I8 + case 2: // IA4 + case 3: // IA8 + // TODO - verify these coefficients + colmat[0] = 0.257f; colmat[1] = 0.504f; colmat[2] = 0.098f; + colmat[4] = 0.257f; colmat[5] = 0.504f; colmat[6] = 0.098f; + colmat[8] = 0.257f; colmat[9] = 0.504f; colmat[10] = 0.098f; + + if (copyfmt < 2) + { + fConstAdd[3] = 16.0f / 255.0f; + colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f; + } + else// alpha + colmat[15] = 1; + + break; + default: + ERROR_LOG(VIDEO, "Unknown copy intensity format: 0x%x", copyfmt); + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; + break; + } + } + else + { + switch (copyfmt) + { + case 0: // R4 + case 8: // R8 + colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; + break; + case 2: // RA4 + case 3: // RA8 + colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1; + break; + + case 7: // A8 + colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1; + break; + case 9: // G8 + colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1; + break; + case 10: // B8 + colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1; + break; + case 11: // RG8 + colmat[0] = colmat[4] = colmat[8] = colmat[13] = 1; + break; + case 12: // GB8 + colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1; + break; + + case 4: // RGB565 + colmat[0] = colmat[5] = colmat[10] = 1; + fConstAdd[3] = 1; // set alpha to 1 + break; + case 5: // RGB5A3 + case 6: // RGBA8 + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; + break; + + default: + ERROR_LOG(VIDEO, "Unknown copy color format: 0x%x", copyfmt); + colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; + break; + } + } + // Make sure to resolve anything we need to read from. + LPDIRECT3DTEXTURE9 read_texture = bFromZBuffer ? FBManager::GetEFBDepthTexture(source_rect) : FBManager::GetEFBColorTexture(source_rect); + + // We have to run a pixel shader, for color conversion. + Renderer::ResetAPIState(); // reset any game specific settings + LPDIRECT3DSURFACE9 Rendersurf = NULL; + hr = tex->GetSurfaceLevel(0,&Rendersurf); + CHECK(hr); + D3D::dev->SetDepthStencilSurface(NULL); + D3D::dev->SetRenderTarget(1, NULL); + D3D::dev->SetRenderTarget(0, Rendersurf); + + D3DVIEWPORT9 vp; + + // Stretch picture with increased internal resolution + vp.X = 0; + vp.Y = 0; + vp.Width = tex_w; + vp.Height = tex_h; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + hr = D3D::dev->SetViewport(&vp); + CHECK(hr); + RECT destrect; + destrect.bottom = tex_h; + destrect.left = 0; + destrect.right = tex_w; + destrect.top = 0; + + + PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation + //TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect); + RECT sourcerect; + sourcerect.bottom = source_rect.bottom; + sourcerect.left = source_rect.left; + sourcerect.right = source_rect.right; + sourcerect.top = source_rect.top; + + D3D::drawShadedTexQuad(read_texture,&sourcerect, EFB_WIDTH , EFB_HEIGHT,&destrect,PixelShaderCache::GetColorMatrixProgram(),NULL); + + D3D::dev->SetRenderTarget(0, FBManager::GetEFBColorRTSurface()); + D3D::dev->SetRenderTarget(1, FBManager::GetEFBDepthEncodedSurface()); + D3D::dev->SetDepthStencilSurface(FBManager::GetEFBDepthRTSurface()); + VertexShaderManager::SetViewportChanged(); + Renderer::RestoreAPIState(); + Rendersurf->Release(); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp index 6a09e86fc9..6153402e6b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp @@ -35,6 +35,13 @@ const VertexShaderCache::VSCacheEntry *VertexShaderCache::last_entry; static float GC_ALIGNED16(lastVSconstants[C_FOGPARAMS+8][4]); +static LPDIRECT3DVERTEXSHADER9 SimpleVertexSahder; + +LPDIRECT3DVERTEXSHADER9 VertexShaderCache::GetSimpleVertexSahder() +{ + return SimpleVertexSahder; +} + void SetVSConstant4f(int const_number, float f1, float f2, float f3, float f4) { if (lastVSconstants[const_number][0] != f1 || @@ -121,6 +128,21 @@ void SetMultiVSConstant4fv(int const_number, int count, const float *f) void VertexShaderCache::Init() { + char vSimpleProg[1024]; + sprintf(vSimpleProg,"struct VSOUTPUT\n" + "{\n" + "float4 vPosition : POSITION;\n" + "float4 vTexCoord : TEXCOORD0;\n" + "};\n" + "VSOUTPUT main( float4 inPosition : POSITION, float4 inUV : TEXCOORD0)\n" + "{\n" + "VSOUTPUT OUT = (VSOUTPUT)0;\n" + "OUT.vPosition = inPosition;\n" + "OUT.vTexCoord = inUV;\n" + "return OUT;\n" + "}\n"); + + SimpleVertexSahder = D3D::CompileVertexShader(vSimpleProg, (int)strlen(vSimpleProg)); Clear(); } @@ -138,6 +160,8 @@ void VertexShaderCache::Clear() void VertexShaderCache::Shutdown() { + if(SimpleVertexSahder) + SimpleVertexSahder->Release(); Clear(); } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h index 8fc5d0cf56..f6ad37f1ab 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.h @@ -56,6 +56,7 @@ public: static void Cleanup(); static void Shutdown(); static bool SetShader(u32 components); + static LPDIRECT3DVERTEXSHADER9 GetSimpleVertexSahder(); #if defined(_DEBUG) || defined(DEBUGFAST) static std::string GetCurrentShaderCode(); #endif