diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj index f70efea502..f1334b8f8f 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj @@ -44,7 +44,6 @@ - @@ -69,7 +68,6 @@ - diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters index a83db06c6a..d6f7331c37 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters @@ -33,9 +33,6 @@ Render - - Render - Render @@ -99,9 +96,6 @@ Render - - Render - Render diff --git a/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp b/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp deleted file mode 100644 index 7fcb02ff8d..0000000000 --- a/Source/Core/VideoBackends/D3D/LineGeometryShader.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include - -#include "VideoBackends/D3D/D3DBase.h" -#include "VideoBackends/D3D/D3DShader.h" -#include "VideoBackends/D3D/D3DState.h" -#include "VideoBackends/D3D/LineGeometryShader.h" -#include "VideoCommon/VertexShaderGen.h" - -namespace DX11 -{ - -struct LineGSParams -{ - 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[(sizeof(LineGSParams) + 15) & ~15]; -}; - -static const char LINE_GS_COMMON[] = -// The struct VS_OUTPUT used by the vertex shader goes here. -"// dolphin-emu line geometry shader common part\n" - -"cbuffer cbParams : register(b0)\n" -"{\n" - "struct\n" // Should match LineGSParams above - "{\n" - "float LineWidth;\n" - "float TexOffset;\n" - "float VpWidth;\n" - "float VpHeight;\n" - "float TexOffsetEnable[8];\n" - "} Params;\n" -"}\n" - -"[maxvertexcount(4)]\n" -"void main(line VS_OUTPUT input[2], inout TriangleStream outStream)\n" -"{\n" - // Pretend input[0] is on the bottom and input[1] is on top. - // We generate vertices to the left and right. - - "VS_OUTPUT l0 = input[0];\n" - "VS_OUTPUT r0 = l0;\n" - "VS_OUTPUT l1 = input[1];\n" - "VS_OUTPUT r1 = l1;\n" - - // GameCube/Wii's line drawing algorithm is a little quirky. It does not - // use the correct line caps. Instead, the line caps are vertical or - // horizontal depending the slope of the line. - - "float2 offset;\n" - "float2 to = abs(input[1].pos.xy - input[0].pos.xy);\n" - // FIXME: What does real hardware do when line is at a 45-degree angle? - // FIXME: Lines aren't drawn at the correct width. See Twilight Princess map. - "if (Params.VpHeight*to.y > Params.VpWidth*to.x) {\n" - // Line is more tall. Extend geometry left and right. - // Lerp Params.LineWidth/2 from [0..VpWidth] to [-1..1] - "offset = float2(Params.LineWidth/Params.VpWidth, 0);\n" - "} else {\n" - // Line is more wide. Extend geometry up and down. - // Lerp Params.LineWidth/2 from [0..VpHeight] to [1..-1] - "offset = float2(0, -Params.LineWidth/Params.VpHeight);\n" - "}\n" - - "l0.pos.xy -= offset * input[0].pos.w;\n" - "r0.pos.xy += offset * input[0].pos.w;\n" - "l1.pos.xy -= offset * input[1].pos.w;\n" - "r1.pos.xy += offset * input[1].pos.w;\n" - -"#ifndef NUM_TEXCOORDS\n" -"#error NUM_TEXCOORDS not defined\n" -"#endif\n" - - // Apply TexOffset to all tex coordinates in the vertex. - // They can each be enabled separately. -"#if NUM_TEXCOORDS >= 1\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 * 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 * 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 * 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 * 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 * 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 * 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 * Params.TexOffsetEnable[7];\n" - "r1.tex7.x += Params.TexOffset * Params.TexOffsetEnable[7];\n" -"#endif\n" - - "outStream.Append(l0);\n" - "outStream.Append(r0);\n" - "outStream.Append(l1);\n" - "outStream.Append(r1);\n" -"}\n" -; - -LineGeometryShader::LineGeometryShader() - : m_ready(false), m_paramsBuffer(nullptr) -{ } - -void LineGeometryShader::Init() -{ - m_ready = false; - - HRESULT hr; - - // Create constant buffer for uploading data to geometry shader - - D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(LineGSParams_Padded), - D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); - hr = D3D::device->CreateBuffer(&bd, nullptr, &m_paramsBuffer); - CHECK(SUCCEEDED(hr), "create line geometry shader params buffer"); - D3D::SetDebugObjectName(m_paramsBuffer, "line geometry shader params buffer"); - - m_ready = true; -} - -void LineGeometryShader::Shutdown() -{ - m_ready = false; - - for (auto& it : m_shaders) - { - SAFE_RELEASE(it.second); - } - m_shaders.clear(); - - SAFE_RELEASE(m_paramsBuffer); -} - -bool LineGeometryShader::SetShader(u32 components, float lineWidth, - float texOffset, float vpWidth, float vpHeight, const bool* texOffsetEnable) -{ - if (!m_ready) - return false; - - // Make sure geometry shader for "components" is available - ComboMap::iterator shaderIt = m_shaders.find(components); - if (shaderIt == m_shaders.end()) - { - // Generate new shader. Warning: not thread-safe. - static char buffer[16384]; - ShaderCode code; - code.SetBuffer(buffer); - GenerateVSOutputStruct(code, API_D3D); - code.Write("\n%s", LINE_GS_COMMON); - - std::stringstream numTexCoordsStream; - numTexCoordsStream << xfmem.numTexGen.numTexGens; - - INFO_LOG(VIDEO, "Compiling line geometry shader for components 0x%.08X (num texcoords %d)", - components, xfmem.numTexGen.numTexGens); - - const std::string& numTexCoordsStr = numTexCoordsStream.str(); - D3D_SHADER_MACRO macros[] = { - { "NUM_TEXCOORDS", numTexCoordsStr.c_str() }, - { nullptr, nullptr } - }; - ID3D11GeometryShader* newShader = D3D::CompileAndCreateGeometryShader(code.GetBuffer(), macros); - if (!newShader) - { - WARN_LOG(VIDEO, "Line geometry shader for components 0x%.08X failed to compile", components); - // Add dummy shader to prevent trying to compile again - m_shaders[components] = nullptr; - return false; - } - - shaderIt = m_shaders.insert(std::make_pair(components, newShader)).first; - } - - if (shaderIt != m_shaders.end()) - { - if (shaderIt->second) - { - D3D11_MAPPED_SUBRESOURCE map; - HRESULT hr = D3D::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::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); - - D3D::stateman->SetGeometryShader(shaderIt->second); - D3D::stateman->SetGeometryConstants(m_paramsBuffer); - - return true; - } - else - return false; - } - else - return false; -} - -} diff --git a/Source/Core/VideoBackends/D3D/LineGeometryShader.h b/Source/Core/VideoBackends/D3D/LineGeometryShader.h deleted file mode 100644 index 4bcb159314..0000000000 --- a/Source/Core/VideoBackends/D3D/LineGeometryShader.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include "VideoCommon/VideoCommon.h" - -struct ID3D11Buffer; -struct ID3D11GeometryShader; - -namespace DX11 -{ - -// This class manages a collection of line geometry shaders, one for each -// vertex format. -class LineGeometryShader -{ - -public: - - LineGeometryShader(); - - void Init(); - void Shutdown(); - // Returns true on success, false on failure - bool SetShader(u32 components, float lineWidth, float texOffset, - float vpWidth, float vpHeight, const bool* texOffsetEnable); - -private: - - bool m_ready; - - ID3D11Buffer* m_paramsBuffer; - - typedef std::map ComboMap; - - ComboMap m_shaders; - -}; - -} diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 86f93fc9ad..840725fb53 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -1252,11 +1252,6 @@ void Renderer::SetDitherMode() // TODO: Set dither mode to bpmem.blendmode.dither } -void Renderer::SetLineWidth() -{ - // TODO -} - void Renderer::SetSamplerState(int stage, int texindex) { const FourTexUnits &tex = bpmem.tex[texindex]; diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h index ac03cace98..33e3cf0681 100644 --- a/Source/Core/VideoBackends/D3D/Render.h +++ b/Source/Core/VideoBackends/D3D/Render.h @@ -19,7 +19,6 @@ public: void SetDepthMode() override; void SetLogicOpMode() override; void SetDitherMode() override; - void SetLineWidth() override; void SetSamplerState(int stage,int texindex) override; void SetInterlacingMode() override; void SetViewport() override; diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index 6ba3bc3391..dcd1ad1569 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -49,14 +49,12 @@ void VertexManager::CreateDeviceObjects() m_currentBuffer = 0; m_bufferCursor = MAX_BUFFER_SIZE; - m_lineShader.Init(); m_pointShader.Init(); } void VertexManager::DestroyDeviceObjects() { m_pointShader.Shutdown(); - m_lineShader.Shutdown(); for (int i = 0; i < MAX_BUFFER_COUNT; i++) { @@ -147,28 +145,16 @@ void VertexManager::Draw(u32 stride) } else if (current_primitive_type == PRIMITIVE_LINES) { - float lineWidth = float(bpmem.lineptwidth.linesize) / 6.f; - float texOffset = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff]; - float vpWidth = 2.0f * xfmem.viewport.wd; - float vpHeight = -2.0f * xfmem.viewport.ht; + D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); + D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); + D3D::stateman->SetGeometryShader(GeometryShaderCache::GetActiveShader()); - bool texOffsetEnable[8]; + D3D::stateman->Apply(); + D3D::context->DrawIndexed(indices, startIndex, baseVertex); - for (int i = 0; i < 8; ++i) - texOffsetEnable[i] = bpmem.texcoords[i].s.line_offset; + INCSTAT(stats.thisFrame.numDrawCalls); - if (m_lineShader.SetShader(components, lineWidth, - texOffset, vpWidth, vpHeight, texOffsetEnable)) - { - D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); - - D3D::stateman->Apply(); - D3D::context->DrawIndexed(indices, startIndex, baseVertex); - - INCSTAT(stats.thisFrame.numDrawCalls); - - D3D::stateman->SetGeometryShader(nullptr); - } + D3D::stateman->SetGeometryShader(nullptr); } else //if (current_primitive_type == PRIMITIVE_POINTS) { diff --git a/Source/Core/VideoBackends/D3D/VertexManager.h b/Source/Core/VideoBackends/D3D/VertexManager.h index bd84128ff1..12e3bf2d4b 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.h +++ b/Source/Core/VideoBackends/D3D/VertexManager.h @@ -4,7 +4,6 @@ #pragma once -#include "VideoBackends/D3D/LineGeometryShader.h" #include "VideoBackends/D3D/PointGeometryShader.h" #include "VideoCommon/VertexManagerBase.h" @@ -40,7 +39,6 @@ private: enum { MAX_BUFFER_COUNT = 2 }; ID3D11Buffer* m_buffers[MAX_BUFFER_COUNT]; - LineGeometryShader m_lineShader; PointGeometryShader m_pointShader; std::vector LocalVBuffer; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index f26a1460ce..b717e3cf35 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -881,9 +881,6 @@ void Renderer::DrawDebugInfo() GLsizei count = static_cast(stats.efb_regions.size() * 2*6); glDrawArrays(GL_LINES, 0, count); - // Restore Line Size - SetLineWidth(); - // Clear stored regions stats.efb_regions.clear(); } @@ -1901,17 +1898,6 @@ void Renderer::SetDitherMode() glDisable(GL_DITHER); } -void Renderer::SetLineWidth() -{ - float fratio = xfmem.viewport.wd != 0 ? - ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f; - if (bpmem.lineptwidth.linesize > 0) - // scale by ratio of widths - glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL && bpmem.lineptwidth.pointsize > 0) - glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f); -} - void Renderer::SetSamplerState(int stage, int texindex) { auto const& tex = bpmem.tex[texindex]; diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h index 98bd424257..db843179a9 100644 --- a/Source/Core/VideoBackends/OGL/Render.h +++ b/Source/Core/VideoBackends/OGL/Render.h @@ -57,7 +57,6 @@ public: void SetDepthMode() override; void SetLogicOpMode() override; void SetDitherMode() override; - void SetLineWidth() override; void SetSamplerState(int stage,int texindex) override; void SetInterlacingMode() override; void SetViewport() override; diff --git a/Source/Core/VideoCommon/BPFunctions.cpp b/Source/Core/VideoCommon/BPFunctions.cpp index 29a6d5b643..604840efdd 100644 --- a/Source/Core/VideoCommon/BPFunctions.cpp +++ b/Source/Core/VideoCommon/BPFunctions.cpp @@ -62,11 +62,6 @@ void SetScissor() g_renderer->SetScissorRect(rc); } -void SetLineWidth() -{ - g_renderer->SetLineWidth(); -} - void SetDepthMode() { g_renderer->SetDepthMode(); diff --git a/Source/Core/VideoCommon/BPFunctions.h b/Source/Core/VideoCommon/BPFunctions.h index ff7e928f8a..01f9bc9bbe 100644 --- a/Source/Core/VideoCommon/BPFunctions.h +++ b/Source/Core/VideoCommon/BPFunctions.h @@ -18,7 +18,6 @@ namespace BPFunctions void FlushPipeline(); void SetGenerationMode(); void SetScissor(); -void SetLineWidth(); void SetDepthMode(); void SetBlendMode(); void SetDitherMode(); diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 6a32b7f245..6c4ad70331 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -1371,7 +1371,6 @@ void BPReload() // note that PixelShaderManager is already covered since it has its own DoState. SetGenerationMode(); SetScissor(); - SetLineWidth(); SetDepthMode(); SetLogicOpMode(); SetDitherMode(); diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index ca4ef96a43..ee6da0fe4d 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -4,6 +4,7 @@ #include +#include "VideoCommon/BPMemory.h" #include "VideoCommon/GeometryShaderGen.h" #include "VideoCommon/LightingShaderGen.h" #include "VideoCommon/VertexManagerBase.h" @@ -43,17 +44,22 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A uid_data->primitive_type = primitive_type; const unsigned int vertex_in = primitive_type + 1; - uid_data->stereo = g_ActiveConfig.iStereoMode > 0; const unsigned int vertex_out = primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4; + uid_data->stereo = g_ActiveConfig.iStereoMode > 0; if (ApiType == API_OPENGL) { // Insert layout parameters if (g_ActiveConfig.backend_info.bSupportsGSInstancing) + { out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[primitive_type], g_ActiveConfig.iStereoMode > 0 ? 2 : 1); + out.Write("layout(triangle_strip, max_vertices = %d) out;\n", vertex_out); + } else + { out.Write("layout(%s) in;\n", primitives_ogl[primitive_type]); - out.Write("layout(triangle_strip, max_vertices = %d) out;\n", g_ActiveConfig.backend_info.bSupportsGSInstancing ? vertex_out : vertex_out * 2); + out.Write("layout(triangle_strip, max_vertices = %d) out;\n", g_ActiveConfig.iStereoMode > 0 ? vertex_out * 2 : vertex_out); + } } out.Write("%s", s_lighting_struct); @@ -98,15 +104,15 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("};\n"); - out.Write("[maxvertexcount(%d)]\n", vertex_out); if (g_ActiveConfig.backend_info.bSupportsGSInstancing) { - out.Write("[instance(%d)]\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); - out.Write("void main(%s VS_OUTPUT o[%d], inout TriangleStream Output, in uint InstanceID : SV_GSInstanceID)\n{\n", primitives_d3d[primitive_type], vertex_in); + out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, g_ActiveConfig.iStereoMode > 0 ? 2 : 1); + out.Write("void main(%s VS_OUTPUT o[%d], inout TriangleStream output, in uint InstanceID : SV_GSInstanceID)\n{\n", primitives_d3d[primitive_type], vertex_in); } else { - out.Write("void main(%s VS_OUTPUT o[%d], inout TriangleStream Output)\n{\n", primitives_d3d[primitive_type], vertex_in); + out.Write("[maxvertexcount(%d)]\n", g_ActiveConfig.iStereoMode > 0 ? vertex_out * 2 : vertex_out); + out.Write("void main(%s VS_OUTPUT o[%d], inout TriangleStream output)\n{\n", primitives_d3d[primitive_type], vertex_in); } out.Write("\tGS_OUTPUT gs;\n"); @@ -114,6 +120,27 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("\tVS_OUTPUT f;\n"); + if (primitive_type == PRIMITIVE_LINES) + { + // GameCube/Wii's line drawing algorithm is a little quirky. It does not + // use the correct line caps. Instead, the line caps are vertical or + // horizontal depending the slope of the line. + + out.Write("\tfloat2 offset;\n"); + out.Write("\tfloat2 to = abs(o[1].pos.xy - o[0].pos.xy);\n"); + // FIXME: What does real hardware do when line is at a 45-degree angle? + // FIXME: Lines aren't drawn at the correct width. See Twilight Princess map. + out.Write("\tif (" I_VIEWPORT".y * to.y > " I_VIEWPORT".x * to.x) {\n"); + // Line is more tall. Extend geometry left and right. + // Lerp LineWidth/2 from [0..VpWidth] to [-1..1] + out.Write("\t\toffset = float2(" I_LINEPTWIDTH"[0] / " I_VIEWPORT".x, 0);\n"); + out.Write("\t} else {\n"); + // Line is more wide. Extend geometry up and down. + // Lerp LineWidth/2 from [0..VpHeight] to [1..-1] + out.Write("\t\toffset = float2(0, -" I_LINEPTWIDTH"[0] / " I_VIEWPORT".y);\n"); + out.Write("\t}\n"); + } + if (g_ActiveConfig.iStereoMode > 0) { // If the GPU supports invocation we don't need a for loop and can simply use the @@ -121,24 +148,22 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A if (g_ActiveConfig.backend_info.bSupportsGSInstancing) out.Write("\tint eye = InstanceID;\n"); else - out.Write("\tfor (int eye = 0; eye < %d; ++eye) {\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); + out.Write("\tfor (int eye = 0; eye < 2; ++eye) {\n"); } out.Write("\tfor (int i = 0; i < %d; ++i) {\n", vertex_in); - - out.Write("\t\tf = o[i];\n"); - out.Write("\t\tfloat4 pos = o[i].pos;\n"); + out.Write("\tVS_OUTPUT f = o[i];\n"); if (g_ActiveConfig.iStereoMode > 0) { // Select the output layer if (ApiType == API_OPENGL) { - out.Write("\t\tgl_Layer = eye;\n"); - out.Write("\t\tlayer = eye;\n"); + out.Write("\tgl_Layer = eye;\n"); + out.Write("\tlayer = eye;\n"); } else - out.Write("\t\tgs.layer = eye;\n"); + out.Write("\tgs.layer = eye;\n"); // For stereoscopy add a small horizontal offset in Normalized Device Coordinates proportional // to the depth of the vertex. We retrieve the depth value from the w-component of the projected @@ -147,30 +172,40 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A // the depth value. This results in objects at a distance smaller than the convergence // distance to seemingly appear in front of the screen. // This formula is based on page 13 of the "Nvidia 3D Vision Automatic, Best Practices Guide" - out.Write("\t\tf.clipPos.x = o[i].clipPos.x + " I_STEREOPARAMS"[eye] * (o[i].clipPos.w - " I_STEREOPARAMS"[2]);\n"); - out.Write("\t\tpos.x = o[i].pos.x + " I_STEREOPARAMS"[eye] * (o[i].pos.w - " I_STEREOPARAMS"[2]);\n"); - out.Write("\t\tf.pos.x = pos.x;\n"); + out.Write("\tf.clipPos.x += " I_STEREOPARAMS"[eye] * (o[i].clipPos.w - " I_STEREOPARAMS"[2]);\n"); + out.Write("\tf.pos.x += " I_STEREOPARAMS"[eye] * (o[i].pos.w - " I_STEREOPARAMS"[2]);\n"); } - if (ApiType == API_OPENGL) - out.Write("\t\tgl_Position = pos;\n"); + if (primitive_type == PRIMITIVE_LINES) + { + out.Write("\tVS_OUTPUT l = f;\n"); + out.Write("\tVS_OUTPUT r = f;\n"); - out.Write("\t\t%s = f;\n", (ApiType == API_OPENGL) ? "vs" : "gs.vs"); + out.Write("\tl.pos.xy -= offset * l.pos.w;\n"); + out.Write("\tr.pos.xy += offset * r.pos.w;\n"); - if (ApiType == API_OPENGL) - out.Write("\t\tEmitVertex();\n"); + for (unsigned int i = 0; i < bpmem.genMode.numtexgens; ++i) + { + out.Write("\tr.tex%d.x += " I_LINEPTWIDTH"[2] * (" I_TEXOFFSETFLAGS"[%d] % 2);\n", i, i); + } + + EmitVertex(out, "l", ApiType); + EmitVertex(out, "r", ApiType); + } else - out.Write("\t\tOutput.Append(gs);\n"); + { + EmitVertex(out, "f", ApiType); + } out.Write("\t}\n"); if (ApiType == API_OPENGL) out.Write("\tEndPrimitive();\n"); else - out.Write("\tOutput.RestartStrip();\n"); + out.Write("\toutput.RestartStrip();\n"); - if (!g_ActiveConfig.backend_info.bSupportsGSInstancing) - out.Write("\t}\n"); + if (g_ActiveConfig.iStereoMode > 0 && !g_ActiveConfig.backend_info.bSupportsGSInstancing) + out.Write("\t}\n"); out.Write("}\n"); @@ -181,6 +216,20 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A } } +template +static inline void EmitVertex(T& out, const char *vertex, API_TYPE ApiType) +{ + if (ApiType == API_OPENGL) + out.Write("\tgl_Position = %s.pos;\n", vertex); + + out.Write("\t%s = %s;\n", (ApiType == API_OPENGL) ? "vs" : "gs.vs", vertex); + + if (ApiType == API_OPENGL) + out.Write("\tEmitVertex();\n"); + else + out.Write("\toutput.Append(gs);\n"); +} + void GetGeometryShaderUid(GeometryShaderUid& object, u32 primitive_type, API_TYPE ApiType) { GenerateGeometryShader(object, primitive_type, ApiType); diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index f59458e523..ef68d665a6 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -57,7 +57,6 @@ public: virtual void SetDepthMode() = 0; virtual void SetLogicOpMode() = 0; virtual void SetDitherMode() = 0; - virtual void SetLineWidth() = 0; virtual void SetSamplerState(int stage,int texindex) = 0; virtual void SetInterlacingMode() = 0; virtual void SetViewport() = 0;