From 91ff420ed659195cc3e18575beb9dca611452432 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 4 Feb 2011 17:00:34 +0000 Subject: [PATCH] D3D11: Implement EFB format reinterpretation. Now someone port this to OpenGL please, kthxbye. Fix some warnings, fix a wrong string, ... git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7061 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/VideoCommon/Src/EmuWindow.cpp | 16 ++--- .../Plugin_VideoDX11/Src/D3DShader.cpp | 2 +- .../Src/FramebufferManager.cpp | 12 ++++ .../Plugin_VideoDX11/Src/FramebufferManager.h | 10 +++ .../Plugin_VideoDX11/Src/PixelShaderCache.cpp | 62 +++++++++++++++++++ .../Plugin_VideoDX11/Src/PixelShaderCache.h | 2 + .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 27 +++++++- Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 2 +- 8 files changed, 122 insertions(+), 11 deletions(-) diff --git a/Source/Core/VideoCommon/Src/EmuWindow.cpp b/Source/Core/VideoCommon/Src/EmuWindow.cpp index 3abbbc76df..c92a4cacb1 100644 --- a/Source/Core/VideoCommon/Src/EmuWindow.cpp +++ b/Source/Core/VideoCommon/Src/EmuWindow.cpp @@ -110,28 +110,28 @@ void FreeLookInput( UINT iMsg, WPARAM wParam ) if (mouseLookEnabled) { GetCursorPos(&point); VertexShaderManager::RotateView((point.x - lastMouse[0]) / 200.0f, (point.y - lastMouse[1]) / 200.0f); - lastMouse[0] = point.x; - lastMouse[1] = point.y; + lastMouse[0] = (float)point.x; + lastMouse[1] = (float)point.y; } if (mouseMoveEnabled) { GetCursorPos(&point); VertexShaderManager::TranslateView((point.x - lastMouse[0]) / 50.0f, (point.y - lastMouse[1]) / 50.0f); - lastMouse[0] = point.x; - lastMouse[1] = point.y; + lastMouse[0] = (float)point.x; + lastMouse[1] = (float)point.y; } break; case WM_RBUTTONDOWN: GetCursorPos(&point); - lastMouse[0] = point.x; - lastMouse[1] = point.y; + lastMouse[0] = (float)point.x; + lastMouse[1] = (float)point.y; mouseLookEnabled= true; break; case WM_MBUTTONDOWN: GetCursorPos(&point); - lastMouse[0] = point.x; - lastMouse[1] = point.y; + lastMouse[0] = (float)point.x; + lastMouse[1] = (float)point.y; mouseMoveEnabled= true; break; case WM_RBUTTONUP: diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp index 8d8ded362b..08d4840a64 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DShader.cpp @@ -62,7 +62,7 @@ bool CompileVertexShader(const char* code, unsigned int len, D3DBlob** blob) std::string msg = (char*)errorBuffer->GetBufferPointer(); msg += "\n\n"; msg += code; - MessageBoxA(0, msg.c_str(), "Error compiling pixel shader", MB_ICONERROR); + MessageBoxA(0, msg.c_str(), "Error compiling vertex shader", MB_ICONERROR); } *blob = NULL; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp index fb847c858e..35f6387fa0 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.cpp @@ -78,6 +78,17 @@ FramebufferManager::FramebufferManager() D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetSRV(), "EFB color texture shader resource view"); D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_tex->GetRTV(), "EFB color texture render target view"); + // Temporary EFB color texture - used in ReinterpretPixelData + texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, target_width, target_height, 1, 1, D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0); + hr = D3D::device->CreateTexture2D(&texdesc, NULL, &buf); + CHECK(hr==S_OK, "create EFB color temp texture (size: %dx%d; hr=%#x)", target_width, target_height, hr); + m_efb.color_temp_tex = new D3DTexture2D(buf, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM); + CHECK(m_efb.color_temp_tex!=NULL, "create EFB color temp texture (size: %dx%d)", target_width, target_height); + SAFE_RELEASE(buf); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_temp_tex->GetTex(), "EFB color temp texture"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_temp_tex->GetSRV(), "EFB color temp texture shader resource view"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_temp_tex->GetRTV(), "EFB color temp texture render target view"); + // AccessEFB - Sysmem buffer used to retrieve the pixel data from color_tex texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ); hr = D3D::device->CreateTexture2D(&texdesc, NULL, &m_efb.color_staging_buf); @@ -138,6 +149,7 @@ FramebufferManager::FramebufferManager() FramebufferManager::~FramebufferManager() { SAFE_RELEASE(m_efb.color_tex); + SAFE_RELEASE(m_efb.color_temp_tex); SAFE_RELEASE(m_efb.color_staging_buf); SAFE_RELEASE(m_efb.resolved_color_tex); SAFE_RELEASE(m_efb.depth_tex); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.h b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.h index ab8b9b049d..83db4370db 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/FramebufferManager.h @@ -87,6 +87,14 @@ public: static D3DTexture2D* &GetResolvedEFBColorTexture(); static D3DTexture2D* &GetResolvedEFBDepthTexture(); + static D3DTexture2D* &GetEFBColorTempTexture() { return m_efb.color_temp_tex; } + static void SwapReinterpretTexture() + { + D3DTexture2D* swaptex = GetEFBColorTempTexture(); + m_efb.color_temp_tex = GetEFBColorTexture(); + m_efb.color_tex = swaptex; + } + private: XFBSourceBase* CreateXFBSource(unsigned int target_width, unsigned int target_height); void GetTargetSize(unsigned int *width, unsigned int *height, const EFBRectangle& sourceRc); @@ -102,6 +110,8 @@ private: ID3D11Texture2D* depth_staging_buf; D3DTexture2D* depth_read_texture; + D3DTexture2D* color_temp_tex; + D3DTexture2D* resolved_color_tex; D3DTexture2D* resolved_depth_tex; } m_efb; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp index 5efb9354dd..2ad9a70faf 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.cpp @@ -48,6 +48,8 @@ ID3D11PixelShader* s_ColorMatrixProgram[2] = {NULL}; ID3D11PixelShader* s_ColorCopyProgram[2] = {NULL}; ID3D11PixelShader* s_DepthMatrixProgram[2] = {NULL}; ID3D11PixelShader* s_ClearProgram = NULL; +ID3D11PixelShader* s_rgba6_to_rgb8 = NULL; +ID3D11PixelShader* s_rgb8_to_rgba6 = NULL; ID3D11Buffer* pscbuf = NULL; const char clear_program_code[] = { @@ -155,6 +157,64 @@ const char depth_matrix_program_msaa[] = { "}\n" }; +ID3D11PixelShader* PixelShaderCache::ReinterpRGBA6ToRGB8() +{ + // TODO: MSAA support.. + const char code[] = { + "sampler samp0 : register(s0);\n" + "Texture2D Tex0 : register(t0);\n" + "void main(\n" + " out float4 ocol0 : SV_Target,\n" + " in float4 pos : SV_Position,\n" + " in float2 uv0 : TEXCOORD0)\n" + "{\n" + " int4 src6 = round(Tex0.Sample(samp0,uv0) * 63.f);\n" + " int4 dst8;\n" + " dst8.r = (src6.r << 2) | (src6.g >> 4);\n" + " dst8.g = ((src6.g & 0xF) << 4) | (src6.b >> 2);\n" + " dst8.b = ((src6.b & 0x3) << 6) | src6.a;\n" + " dst8.a = 255;\n" + " ocol0 = (float4)dst8 / 255.f;\n" + "}" + }; + + if(s_rgba6_to_rgb8) return s_rgba6_to_rgb8; + + s_rgba6_to_rgb8 = D3D::CompileAndCreatePixelShader(code, sizeof(code)); + CHECK(s_rgba6_to_rgb8!=NULL, "Create RGBA6 to RGB8 pixel shader"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)s_rgba6_to_rgb8, "RGBA6 to RGB8 pixel shader"); + return s_rgba6_to_rgb8; +} + +ID3D11PixelShader* PixelShaderCache::ReinterpRGB8ToRGBA6() +{ + // TODO: MSAA support.. + const char code[] = { + "sampler samp0 : register(s0);\n" + "Texture2D Tex0 : register(t0);\n" + "void main(\n" + " out float4 ocol0 : SV_Target,\n" + " in float4 pos : SV_Position,\n" + " in float2 uv0 : TEXCOORD0)\n" + "{\n" + " int4 src8 = round(Tex0.Sample(samp0,uv0) * 255.f);\n" + " int4 dst6;\n" + " dst6.r = src8.r >> 2;\n" + " dst6.g = ((src8.r & 0x3) << 4) | (src8.g >> 4);\n" + " dst6.b = ((src8.g & 0xF) << 2) | (src8.b >> 6);\n" + " dst6.a = src8.b & 0x3F;\n" + " ocol0 = (float4)dst6 / 63.f;\n" + "}\n" + }; + + if(s_rgb8_to_rgba6) return s_rgb8_to_rgba6; + + s_rgb8_to_rgba6 = D3D::CompileAndCreatePixelShader(code, sizeof(code)); + CHECK(s_rgb8_to_rgba6!=NULL, "Create RGB8 to RGBA6 pixel shader"); + D3D::SetDebugObjectName((ID3D11DeviceChild*)s_rgb8_to_rgba6, "RGB8 to RGBA6 pixel shader"); + return s_rgb8_to_rgba6; +} + ID3D11PixelShader* PixelShaderCache::GetColorCopyProgram(bool multisampled) { if (!multisampled || D3D::GetAAMode(g_ActiveConfig.iMultisampleMode).Count == 1) return s_ColorCopyProgram[0]; @@ -297,6 +357,8 @@ void PixelShaderCache::Shutdown() { SAFE_RELEASE(pscbuf); + SAFE_RELEASE(s_rgba6_to_rgb8); + SAFE_RELEASE(s_rgb8_to_rgba6); SAFE_RELEASE(s_ClearProgram); for (int i = 0; i < 2; ++i) { diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h index b3b17e132c..30939cb1ff 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/PixelShaderCache.h @@ -43,6 +43,8 @@ public: static ID3D11PixelShader* GetColorCopyProgram(bool multisampled); static ID3D11PixelShader* GetDepthMatrixProgram(bool multisampled); static ID3D11PixelShader* GetClearProgram(); + static ID3D11PixelShader* ReinterpRGBA6ToRGB8(); + static ID3D11PixelShader* ReinterpRGB8ToRGBA6(); static void InvalidateMSAAShaders(); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index b7d3db4382..52cc7d280c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -784,7 +784,32 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE void Renderer::ReinterpretPixelData(unsigned int convtype) { - // TODO + // TODO: MSAA support.. + D3D11_RECT source = CD3D11_RECT(0, 0, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight()); + + ID3D11PixelShader* 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(); + + D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)g_renderer->GetFullTargetWidth(), (float)g_renderer->GetFullTargetHeight()); + D3D::context->RSSetViewports(1, &vp); + + D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTempTexture()->GetRTV(), NULL); + D3D::SetPointCopySampler(); + D3D::drawShadedTexQuad(FramebufferManager::GetEFBColorTexture()->GetSRV(), &source, g_renderer->GetFullTargetWidth(), g_renderer->GetFullTargetHeight(), pixel_shader, VertexShaderCache::GetSimpleVertexShader(), VertexShaderCache::GetSimpleInputLayout()); + + g_renderer->RestoreAPIState(); + + FramebufferManager::SwapReinterpretTexture(); + D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV()); } void SetSrcBlend(D3D11_BLEND val) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index c52d4e8b22..fe33a25ce3 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -104,7 +104,7 @@ void InitBackendInfo() g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.bAllowSignedBytes = true; g_Config.backend_info.bSupportsDualSourceBlend = true; - g_Config.backend_info.bSupportsFormatReinterpretation = false; + g_Config.backend_info.bSupportsFormatReinterpretation = true; g_Config.backend_info.bSupportsPixelLighting = true; }