From 9b697ed28f78ac01d87608f179a4d4f4d5b4de04 Mon Sep 17 00:00:00 2001 From: Nolan Check Date: Fri, 15 Apr 2011 22:34:54 +0000 Subject: [PATCH] DX11: I think I've figured out where the game enables texture offsets for lines and points. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7461 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/VideoCommon/Src/BPMemory.h | 3 + .../Src/LineGeometryShader.cpp | 87 +++++++++------- .../Plugin_VideoDX11/Src/LineGeometryShader.h | 2 +- .../Src/PointGeometryShader.cpp | 98 +++++++++++-------- .../Src/PointGeometryShader.h | 2 +- .../Plugin_VideoDX11/Src/VertexManager.cpp | 14 ++- 6 files changed, 123 insertions(+), 83 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPMemory.h b/Source/Core/VideoCommon/Src/BPMemory.h index bcee41461f..9a0a8850db 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.h +++ b/Source/Core/VideoCommon/Src/BPMemory.h @@ -790,6 +790,9 @@ union TCInfo u32 scale_minus_1 : 16; u32 range_bias : 1; u32 cylindric_wrap : 1; + // These bits only have effect in the s field of TCoordInfo + u32 line_offset : 1; + u32 point_offset : 1; }; u32 hex; }; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.cpp index 61a7985fbb..eff9a9847e 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.cpp @@ -25,17 +25,20 @@ namespace DX11 { -union LineGSParams +struct LineGSParams { - struct - { - FLOAT LineWidth; // In units of 1/6 of an EFB pixel - FLOAT TexOffset; - FLOAT VpWidth; // Width and height of the viewport in EFB pixels - FLOAT VpHeight; - }; + FLOAT LineWidth; // In units of 1/6 of an EFB pixel + FLOAT TexOffset; + FLOAT VpWidth; // Width and height of the viewport in EFB pixels + FLOAT VpHeight; + FLOAT TexOffsetEnable[8]; // For each tex coordinate, whether to apply offset to it (1 on, 0 off) +}; + +union LineGSParams_Padded +{ + LineGSParams params; // Constant buffers must be a multiple of 16 bytes in size. - u8 pad[16]; // Pad to the next multiple of 16 bytes + u8 pad[(sizeof(LineGSParams) + 15) & ~15]; }; static const char LINE_GS_COMMON[] = @@ -50,6 +53,7 @@ static const char LINE_GS_COMMON[] = "float TexOffset;\n" "float VpWidth;\n" "float VpHeight;\n" + "float TexOffsetEnable[8];\n" "} Params;\n" "}\n" @@ -91,40 +95,39 @@ static const char LINE_GS_COMMON[] = "#error NUM_TEXCOORDS not defined\n" "#endif\n" - // Apply TexOffset to all tex coordinates in the vertex - // FIXME: The game may be able to enable TexOffset for some coords and - // disable for others, but where is that information stored? + // Apply TexOffset to all tex coordinates in the vertex. + // They can each be enabled seperately. "#if NUM_TEXCOORDS >= 1\n" - "r0.tex0.x += Params.TexOffset;\n" - "r1.tex0.x += Params.TexOffset;\n" + "r0.tex0.x += Params.TexOffset * Params.TexOffsetEnable[0];\n" + "r1.tex0.x += Params.TexOffset * Params.TexOffsetEnable[0];\n" "#endif\n" "#if NUM_TEXCOORDS >= 2\n" - "r0.tex1.x += Params.TexOffset;\n" - "r1.tex1.x += Params.TexOffset;\n" + "r0.tex1.x += Params.TexOffset * Params.TexOffsetEnable[1];\n" + "r1.tex1.x += Params.TexOffset * Params.TexOffsetEnable[1];\n" "#endif\n" "#if NUM_TEXCOORDS >= 3\n" - "r0.tex2.x += Params.TexOffset;\n" - "r1.tex2.x += Params.TexOffset;\n" + "r0.tex2.x += Params.TexOffset * Params.TexOffsetEnable[2];\n" + "r1.tex2.x += Params.TexOffset * Params.TexOffsetEnable[2];\n" "#endif\n" "#if NUM_TEXCOORDS >= 4\n" - "r0.tex3.x += Params.TexOffset;\n" - "r1.tex3.x += Params.TexOffset;\n" + "r0.tex3.x += Params.TexOffset * Params.TexOffsetEnable[3];\n" + "r1.tex3.x += Params.TexOffset * Params.TexOffsetEnable[3];\n" "#endif\n" "#if NUM_TEXCOORDS >= 5\n" - "r0.tex4.x += Params.TexOffset;\n" - "r1.tex4.x += Params.TexOffset;\n" + "r0.tex4.x += Params.TexOffset * Params.TexOffsetEnable[4];\n" + "r1.tex4.x += Params.TexOffset * Params.TexOffsetEnable[4];\n" "#endif\n" "#if NUM_TEXCOORDS >= 6\n" - "r0.tex5.x += Params.TexOffset;\n" - "r1.tex5.x += Params.TexOffset;\n" + "r0.tex5.x += Params.TexOffset * Params.TexOffsetEnable[5];\n" + "r1.tex5.x += Params.TexOffset * Params.TexOffsetEnable[5];\n" "#endif\n" "#if NUM_TEXCOORDS >= 7\n" - "r0.tex6.x += Params.TexOffset;\n" - "r1.tex6.x += Params.TexOffset;\n" + "r0.tex6.x += Params.TexOffset * Params.TexOffsetEnable[6];\n" + "r1.tex6.x += Params.TexOffset * Params.TexOffsetEnable[6];\n" "#endif\n" "#if NUM_TEXCOORDS >= 8\n" - "r0.tex7.x += Params.TexOffset;\n" - "r1.tex7.x += Params.TexOffset;\n" + "r0.tex7.x += Params.TexOffset * Params.TexOffsetEnable[7];\n" + "r1.tex7.x += Params.TexOffset * Params.TexOffsetEnable[7];\n" "#endif\n" "outStream.Append(l0);\n" @@ -139,8 +142,8 @@ LineGeometryShader::LineGeometryShader() { // Create constant buffer for uploading data to geometry shader - D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(LineGSParams), - D3D11_BIND_CONSTANT_BUFFER); + D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(LineGSParams_Padded), + D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); m_paramsBuffer = CreateBufferShared(&bd, NULL); CHECK(m_paramsBuffer, "create line geometry shader params buffer"); D3D::SetDebugObjectName(m_paramsBuffer, "line geometry shader params buffer"); @@ -149,7 +152,7 @@ LineGeometryShader::LineGeometryShader() } bool LineGeometryShader::SetShader(u32 components, float lineWidth, - float texOffset, float vpWidth, float vpHeight) + float texOffset, float vpWidth, float vpHeight, const bool* texOffsetEnable) { if (!m_ready) return false; @@ -191,12 +194,22 @@ bool LineGeometryShader::SetShader(u32 components, float lineWidth, { if (shaderIt->second) { - LineGSParams params = {}; - params.LineWidth = lineWidth; - params.TexOffset = texOffset; - params.VpWidth = vpWidth; - params.VpHeight = vpHeight; - D3D::g_context->UpdateSubresource(m_paramsBuffer, 0, NULL, ¶ms, 0, 0); + D3D11_MAPPED_SUBRESOURCE map; + HRESULT hr = D3D::g_context->Map(m_paramsBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + if (SUCCEEDED(hr)) + { + LineGSParams* params = (LineGSParams*)map.pData; + params->LineWidth = lineWidth; + params->TexOffset = texOffset; + params->VpWidth = vpWidth; + params->VpHeight = vpHeight; + for (int i = 0; i < 8; ++i) + params->TexOffsetEnable[i] = texOffsetEnable[i] ? 1.f : 0.f; + + D3D::g_context->Unmap(m_paramsBuffer, 0); + } + else + ERROR_LOG(VIDEO, "Failed to map line gs params buffer"); DEBUG_LOG(VIDEO, "Line params: width %f, texOffset %f, vpWidth %f, vpHeight %f", lineWidth, texOffset, vpWidth, vpHeight); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.h b/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.h index 81d164db6a..0b266109c2 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/LineGeometryShader.h @@ -33,7 +33,7 @@ public: // Returns true on success, false on failure bool SetShader(u32 components, float lineWidth, float texOffset, - float vpWidth, float vpHeight); + float vpWidth, float vpHeight, const bool* texOffsetEnable); private: bool m_ready; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.cpp b/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.cpp index 8cf592863c..b83c9ee8d7 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.cpp @@ -25,17 +25,20 @@ namespace DX11 { -union PointGSParams +struct PointGSParams { - struct - { - FLOAT PointSize; // In units of 1/6 of an EFB pixel - FLOAT TexOffset; - FLOAT VpWidth; // Width and height of viewport in EFB pixels - FLOAT VpHeight; - }; + FLOAT PointSize; // In units of 1/6 of an EFB pixel + FLOAT TexOffset; + FLOAT VpWidth; // Width and height of viewport in EFB pixels + FLOAT VpHeight; + FLOAT TexOffsetEnable[8]; // For each tex coordinate, whether to apply offset to it (1 on, 0 off) +}; + +union PointGSParams_Padded +{ + PointGSParams params; // Constant buffers must be a multiple of 16 bytes in size. - u8 pad[16]; // Pad to the next multiple of 16 bytes + u8 pad[(sizeof(PointGSParams) + 15) & ~15]; }; static const char POINT_GS_COMMON[] = @@ -50,6 +53,7 @@ static const char POINT_GS_COMMON[] = "float TexOffset;\n" "float VpWidth;\n" "float VpHeight;\n" + "float TexOffsetEnable[8];\n" "} Params;\n" "}\n" @@ -80,44 +84,44 @@ static const char POINT_GS_COMMON[] = // FIXME: The game may be able to enable TexOffset for some coords and // disable for others, but where is that information stored? "#if NUM_TEXCOORDS >= 1\n" - "ptLL.tex0.xy += float2(0,1) * texOffset;\n" - "ptLR.tex0.xy += texOffset;\n" - "ptUR.tex0.xy += float2(1,0) * texOffset;\n" + "ptLL.tex0.xy += float2(0,1) * texOffset * Params.TexOffsetEnable[0];\n" + "ptLR.tex0.xy += texOffset * Params.TexOffsetEnable[0];\n" + "ptUR.tex0.xy += float2(1,0) * texOffset * Params.TexOffsetEnable[0];\n" "#endif\n" "#if NUM_TEXCOORDS >= 2\n" - "ptLL.tex1.xy += float2(0,1) * texOffset;\n" - "ptLR.tex1.xy += texOffset;\n" - "ptUR.tex1.xy += float2(1,0) * texOffset;\n" + "ptLL.tex1.xy += float2(0,1) * texOffset * Params.TexOffsetEnable[1];\n" + "ptLR.tex1.xy += texOffset * Params.TexOffsetEnable[1];\n" + "ptUR.tex1.xy += float2(1,0) * texOffset * Params.TexOffsetEnable[1];\n" "#endif\n" "#if NUM_TEXCOORDS >= 3\n" - "ptLL.tex2.xy += float2(0,1) * texOffset;\n" - "ptLR.tex2.xy += texOffset;\n" - "ptUR.tex2.xy += float2(1,0) * texOffset;\n" + "ptLL.tex2.xy += float2(0,1) * texOffset * Params.TexOffsetEnable[2];\n" + "ptLR.tex2.xy += texOffset * Params.TexOffsetEnable[2];\n" + "ptUR.tex2.xy += float2(1,0) * texOffset * Params.TexOffsetEnable[2];\n" "#endif\n" "#if NUM_TEXCOORDS >= 4\n" - "ptLL.tex3.xy += float2(0,1) * texOffset;\n" - "ptLR.tex3.xy += texOffset;\n" - "ptUR.tex3.xy += float2(1,0) * texOffset;\n" + "ptLL.tex3.xy += float2(0,1) * texOffset * Params.TexOffsetEnable[3];\n" + "ptLR.tex3.xy += texOffset * Params.TexOffsetEnable[3];\n" + "ptUR.tex3.xy += float2(1,0) * texOffset * Params.TexOffsetEnable[3];\n" "#endif\n" "#if NUM_TEXCOORDS >= 5\n" - "ptLL.tex4.xy += float2(0,1) * texOffset;\n" - "ptLR.tex4.xy += texOffset;\n" - "ptUR.tex4.xy += float2(1,0) * texOffset;\n" + "ptLL.tex4.xy += float2(0,1) * texOffset * Params.TexOffsetEnable[4];\n" + "ptLR.tex4.xy += texOffset * Params.TexOffsetEnable[4];\n" + "ptUR.tex4.xy += float2(1,0) * texOffset * Params.TexOffsetEnable[4];\n" "#endif\n" "#if NUM_TEXCOORDS >= 6\n" - "ptLL.tex5.xy += float2(0,1) * texOffset;\n" - "ptLR.tex5.xy += texOffset;\n" - "ptUR.tex5.xy += float2(1,0) * texOffset;\n" + "ptLL.tex5.xy += float2(0,1) * texOffset * Params.TexOffsetEnable[5];\n" + "ptLR.tex5.xy += texOffset * Params.TexOffsetEnable[5];\n" + "ptUR.tex5.xy += float2(1,0) * texOffset * Params.TexOffsetEnable[5];\n" "#endif\n" "#if NUM_TEXCOORDS >= 7\n" - "ptLL.tex6.xy += float2(0,1) * texOffset;\n" - "ptLR.tex6.xy += texOffset;\n" - "ptUR.tex6.xy += float2(1,0) * texOffset;\n" + "ptLL.tex6.xy += float2(0,1) * texOffset * Params.TexOffsetEnable[6];\n" + "ptLR.tex6.xy += texOffset * Params.TexOffsetEnable[6];\n" + "ptUR.tex6.xy += float2(1,0) * texOffset * Params.TexOffsetEnable[6];\n" "#endif\n" "#if NUM_TEXCOORDS >= 8\n" - "ptLL.tex7.xy += float2(0,1) * texOffset;\n" - "ptLR.tex7.xy += texOffset;\n" - "ptUR.tex7.xy += float2(1,0) * texOffset;\n" + "ptLL.tex7.xy += float2(0,1) * texOffset * Params.TexOffsetEnable[7];\n" + "ptLR.tex7.xy += texOffset * Params.TexOffsetEnable[7];\n" + "ptUR.tex7.xy += float2(1,0) * texOffset * Params.TexOffsetEnable[7];\n" "#endif\n" "outStream.Append(ptLL);\n" @@ -132,8 +136,8 @@ PointGeometryShader::PointGeometryShader() { // Create constant buffer for uploading data to geometry shader - D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(PointGSParams), - D3D11_BIND_CONSTANT_BUFFER); + D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(PointGSParams_Padded), + D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); m_paramsBuffer = CreateBufferShared(&bd, NULL); CHECK(m_paramsBuffer, "create point geometry shader params buffer"); D3D::SetDebugObjectName(m_paramsBuffer, "point geometry shader params buffer"); @@ -142,7 +146,7 @@ PointGeometryShader::PointGeometryShader() } bool PointGeometryShader::SetShader(u32 components, float pointSize, - float texOffset, float vpWidth, float vpHeight) + float texOffset, float vpWidth, float vpHeight, const bool* texOffsetEnable) { if (!m_ready) return false; @@ -184,12 +188,22 @@ bool PointGeometryShader::SetShader(u32 components, float pointSize, { if (shaderIt->second) { - PointGSParams params = {}; - params.PointSize = pointSize; - params.TexOffset = texOffset; - params.VpWidth = vpWidth; - params.VpHeight = vpHeight; - D3D::g_context->UpdateSubresource(m_paramsBuffer, 0, NULL, ¶ms, 0, 0); + D3D11_MAPPED_SUBRESOURCE map; + HRESULT hr = D3D::g_context->Map(m_paramsBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + if (SUCCEEDED(hr)) + { + PointGSParams* params = (PointGSParams*)map.pData; + params->PointSize = pointSize; + params->TexOffset = texOffset; + params->VpWidth = vpWidth; + params->VpHeight = vpHeight; + for (int i = 0; i < 8; ++i) + params->TexOffsetEnable[i] = texOffsetEnable[i] ? 1.f : 0.f; + + D3D::g_context->Unmap(m_paramsBuffer, 0); + } + else + ERROR_LOG(VIDEO, "Failed to map point gs params buffer"); DEBUG_LOG(VIDEO, "Point params: size %f, texOffset %f, vpWidth %f, vpHeight %f", pointSize, texOffset, vpWidth, vpHeight); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.h b/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.h index 89e4f55707..eb9422b4fa 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/PointGeometryShader.h @@ -33,7 +33,7 @@ public: // Returns true on success, false on failure bool SetShader(u32 components, float pointSize, float texOffset, - float vpWidth, float vpHeight); + float vpWidth, float vpHeight, const bool* texOffsetEnable); private: bool m_ready; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index 6682f3a7a0..09cd73e48f 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -136,7 +136,12 @@ void VertexManager::Draw(UINT stride) float vpWidth = 2.0f * xfregs.viewport.wd; float vpHeight = -2.0f * xfregs.viewport.ht; - if (m_lineShader.SetShader(g_nativeVertexFmt->m_components, lineWidth, texOffset, vpWidth, vpHeight)) + bool texOffsetEnable[8]; + for (int i = 0; i < 8; ++i) + texOffsetEnable[i] = bpmem.texcoords[i].s.line_offset; + + if (m_lineShader.SetShader(g_nativeVertexFmt->m_components, lineWidth, + texOffset, vpWidth, vpHeight, texOffsetEnable)) { D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); D3D::g_context->DrawIndexed(IndexGenerator::GetLineindexLen(), m_lineDrawIndex, 0); @@ -152,7 +157,12 @@ void VertexManager::Draw(UINT stride) float vpWidth = 2.0f * xfregs.viewport.wd; float vpHeight = -2.0f * xfregs.viewport.ht; - if (m_pointShader.SetShader(g_nativeVertexFmt->m_components, pointSize, texOffset, vpWidth, vpHeight)) + bool texOffsetEnable[8]; + for (int i = 0; i < 8; ++i) + texOffsetEnable[i] = bpmem.texcoords[i].s.point_offset; + + if (m_pointShader.SetShader(g_nativeVertexFmt->m_components, pointSize, + texOffset, vpWidth, vpHeight, texOffsetEnable)) { D3D::g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); D3D::g_context->DrawIndexed(IndexGenerator::GetPointindexLen(), m_pointDrawIndex, 0);