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;