From b406e4e1f2c696ba5f6bec04ea2e6a8cc03a02d1 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 14 Dec 2014 21:23:13 +0100 Subject: [PATCH 01/24] VideoCommon: Add a separate constants buffer for the geometry shader. --- .../VideoBackends/D3D/GeometryShaderCache.cpp | 26 ++++++ .../VideoBackends/D3D/GeometryShaderCache.h | 1 + .../Core/VideoBackends/D3D/VertexManager.cpp | 2 +- Source/Core/VideoBackends/D3D/main.cpp | 3 + .../VideoBackends/OGL/ProgramShaderCache.cpp | 14 +++- Source/Core/VideoBackends/OGL/main.cpp | 3 + Source/Core/VideoCommon/BPStructs.cpp | 2 + Source/Core/VideoCommon/CMakeLists.txt | 1 + Source/Core/VideoCommon/ConstantManager.h | 5 +- Source/Core/VideoCommon/GeometryShaderGen.cpp | 9 +- .../VideoCommon/GeometryShaderManager.cpp | 82 +++++++++++++++++++ .../Core/VideoCommon/GeometryShaderManager.h | 29 +++++++ Source/Core/VideoCommon/ShaderGenCommon.h | 6 +- Source/Core/VideoCommon/VertexManagerBase.cpp | 2 + .../Core/VideoCommon/VertexShaderManager.cpp | 12 --- Source/Core/VideoCommon/VideoCommon.vcxproj | 2 + .../VideoCommon/VideoCommon.vcxproj.filters | 6 ++ Source/Core/VideoCommon/VideoState.cpp | 4 + Source/Core/VideoCommon/XFStructs.cpp | 3 + 19 files changed, 189 insertions(+), 23 deletions(-) create mode 100644 Source/Core/VideoCommon/GeometryShaderManager.cpp create mode 100644 Source/Core/VideoCommon/GeometryShaderManager.h diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp index 29172f91a1..6f87e124e7 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -17,6 +17,8 @@ #include "VideoCommon/Debugger.h" #include "VideoCommon/GeometryShaderGen.h" +#include "VideoCommon/GeometryShaderManager.h" +#include "VideoCommon/Statistics.h" #include "VideoCommon/VideoConfig.h" namespace DX11 @@ -37,6 +39,22 @@ ID3D11GeometryShader* GeometryShaderCache::GetCopyGeometryShader() { return Copy ID3D11Buffer* gscbuf = nullptr; +ID3D11Buffer* &GeometryShaderCache::GetConstantBuffer() +{ + // TODO: divide the global variables of the generated shaders into about 5 constant buffers to speed this up + if (GeometryShaderManager::dirty) + { + D3D11_MAPPED_SUBRESOURCE map; + D3D::context->Map(gscbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + memcpy(map.pData, &GeometryShaderManager::constants, sizeof(GeometryShaderConstants)); + D3D::context->Unmap(gscbuf, 0); + GeometryShaderManager::dirty = false; + + ADDSTAT(stats.thisFrame.bytesUniformStreamed, sizeof(GeometryShaderConstants)); + } + return gscbuf; +} + // this class will load the precompiled shaders into our cache class GeometryShaderCacheInserter : public LinearDiskCacheReader { @@ -113,6 +131,12 @@ const char copy_shader_code[] = { void GeometryShaderCache::Init() { + unsigned int gbsize = ((sizeof(GeometryShaderConstants))&(~0xf)) + 0x10; // must be a multiple of 16 + D3D11_BUFFER_DESC gbdesc = CD3D11_BUFFER_DESC(gbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); + HRESULT hr = D3D::device->CreateBuffer(&gbdesc, nullptr, &gscbuf); + CHECK(hr == S_OK, "Create geometry shader constant buffer (size=%u)", gbsize); + D3D::SetDebugObjectName((ID3D11DeviceChild*)gscbuf, "geometry shader constant buffer used to emulate the GX pipeline"); + // used when drawing clear quads ClearGeometryShader = D3D::CompileAndCreateGeometryShader(clear_shader_code); CHECK(ClearGeometryShader != nullptr, "Create clear geometry shader"); @@ -152,6 +176,8 @@ void GeometryShaderCache::Clear() void GeometryShaderCache::Shutdown() { + SAFE_RELEASE(gscbuf); + SAFE_RELEASE(ClearGeometryShader); SAFE_RELEASE(CopyGeometryShader); diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h index 9d38922d04..0c44554412 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h @@ -25,6 +25,7 @@ public: static ID3D11GeometryShader* GeometryShaderCache::GetCopyGeometryShader(); static ID3D11GeometryShader* GetActiveShader() { return last_entry->shader; } + static ID3D11Buffer* &GetConstantBuffer(); private: struct GSCacheEntry diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index abc7f18e33..29fcf1c365 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -140,7 +140,7 @@ void VertexManager::Draw(u32 stride) if (current_primitive_type == PRIMITIVE_TRIANGLES) { D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - D3D::stateman->SetGeometryConstants(VertexShaderCache::GetConstantBuffer()); + D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); D3D::stateman->SetGeometryShader(g_ActiveConfig.iStereoMode > 0 ? GeometryShaderCache::GetActiveShader() : nullptr); D3D::stateman->Apply(); diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 22782cc41c..0126ab8b1d 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -28,6 +28,7 @@ #include "VideoCommon/BPStructs.h" #include "VideoCommon/CommandProcessor.h" #include "VideoCommon/Fifo.h" +#include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/IndexGenerator.h" #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/OpcodeDecoding.h" @@ -187,6 +188,7 @@ void VideoBackend::Video_Prepare() OpcodeDecoder_Init(); VertexShaderManager::Init(); PixelShaderManager::Init(); + GeometryShaderManager::Init(); CommandProcessor::Init(); PixelEngine::Init(); BBox::Init(); @@ -205,6 +207,7 @@ void VideoBackend::Shutdown() // VideoCommon Fifo_Shutdown(); CommandProcessor::Shutdown(); + GeometryShaderManager::Shutdown(); PixelShaderManager::Shutdown(); VertexShaderManager::Shutdown(); OpcodeDecoder_Shutdown(); diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 439c4c9040..08b22e8071 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -13,6 +13,7 @@ #include "VideoCommon/Debugger.h" #include "VideoCommon/DriverDetails.h" +#include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/ImageWrite.h" #include "VideoCommon/PixelShaderManager.h" #include "VideoCommon/Statistics.h" @@ -71,11 +72,14 @@ void SHADER::SetProgramVariables() GLint PSBlock_id = glGetUniformBlockIndex(glprogid, "PSBlock"); GLint VSBlock_id = glGetUniformBlockIndex(glprogid, "VSBlock"); + GLint GSBlock_id = glGetUniformBlockIndex(glprogid, "GSBlock"); if (PSBlock_id != -1) glUniformBlockBinding(glprogid, PSBlock_id, 1); if (VSBlock_id != -1) glUniformBlockBinding(glprogid, VSBlock_id, 2); + if (GSBlock_id != -1) + glUniformBlockBinding(glprogid, GSBlock_id, 3); // Bind Texture Sampler for (int a = 0; a <= 9; ++a) @@ -133,7 +137,7 @@ void SHADER::Bind() void ProgramShaderCache::UploadConstants() { - if (PixelShaderManager::dirty || VertexShaderManager::dirty) + if (PixelShaderManager::dirty || VertexShaderManager::dirty || GeometryShaderManager::dirty) { auto buffer = s_buffer->Map(s_ubo_buffer_size, s_ubo_align); @@ -143,14 +147,20 @@ void ProgramShaderCache::UploadConstants() memcpy(buffer.first + ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align), &VertexShaderManager::constants, sizeof(VertexShaderConstants)); + memcpy(buffer.first + ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align) + ROUND_UP(sizeof(VertexShaderConstants), s_ubo_align), + &GeometryShaderManager::constants, sizeof(GeometryShaderConstants)); + s_buffer->Unmap(s_ubo_buffer_size); glBindBufferRange(GL_UNIFORM_BUFFER, 1, s_buffer->m_buffer, buffer.second, sizeof(PixelShaderConstants)); glBindBufferRange(GL_UNIFORM_BUFFER, 2, s_buffer->m_buffer, buffer.second + ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align), sizeof(VertexShaderConstants)); + glBindBufferRange(GL_UNIFORM_BUFFER, 3, s_buffer->m_buffer, buffer.second + ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align) + ROUND_UP(sizeof(VertexShaderConstants), s_ubo_align), + sizeof(GeometryShaderConstants)); PixelShaderManager::dirty = false; VertexShaderManager::dirty = false; + GeometryShaderManager::dirty = false; ADDSTAT(stats.thisFrame.bytesUniformStreamed, s_ubo_buffer_size); } @@ -419,7 +429,7 @@ void ProgramShaderCache::Init() // then the UBO will fail. glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &s_ubo_align); - s_ubo_buffer_size = ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align) + ROUND_UP(sizeof(VertexShaderConstants), s_ubo_align); + s_ubo_buffer_size = ROUND_UP(sizeof(PixelShaderConstants), s_ubo_align) + ROUND_UP(sizeof(VertexShaderConstants), s_ubo_align) + ROUND_UP(sizeof(GeometryShaderConstants), s_ubo_align); // We multiply by *4*4 because we need to get down to basic machine units. // So multiply by four to get how many floats we have from vec4s diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index eb486c811b..addfcf0533 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -65,6 +65,7 @@ Make AA apply instantly during gameplay if possible #include "VideoCommon/BPStructs.h" #include "VideoCommon/CommandProcessor.h" #include "VideoCommon/Fifo.h" +#include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/ImageWrite.h" #include "VideoCommon/IndexGenerator.h" #include "VideoCommon/LookUpTables.h" @@ -202,6 +203,7 @@ void VideoBackend::Video_Prepare() IndexGenerator::Init(); VertexShaderManager::Init(); PixelShaderManager::Init(); + GeometryShaderManager::Init(); ProgramShaderCache::Init(); g_texture_cache = new TextureCache(); g_sampler_cache = new SamplerCache(); @@ -243,6 +245,7 @@ void VideoBackend::Video_Cleanup() ProgramShaderCache::Shutdown(); VertexShaderManager::Shutdown(); PixelShaderManager::Shutdown(); + GeometryShaderManager::Shutdown(); delete g_perf_query; g_perf_query = nullptr; delete g_vertex_manager; diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index ec7854bace..8996784760 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -14,6 +14,7 @@ #include "VideoCommon/BPFunctions.h" #include "VideoCommon/BPStructs.h" #include "VideoCommon/Fifo.h" +#include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/PerfQueryBase.h" #include "VideoCommon/PixelEngine.h" #include "VideoCommon/PixelShaderManager.h" @@ -125,6 +126,7 @@ static void BPWritten(const BPCmd& bp) case BPMEM_SCISSOROFFSET: // Scissor Offset SetScissor(); VertexShaderManager::SetViewportChanged(); + GeometryShaderManager::SetViewportChanged(); return; case BPMEM_LINEPTWIDTH: // Line Width SetLineWidth(); diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 0dfd12b732..95ebaf7433 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -10,6 +10,7 @@ set(SRCS BoundingBox.cpp FPSCounter.cpp FramebufferManagerBase.cpp GeometryShaderGen.cpp + GeometryShaderManager.cpp HiresTextures.cpp ImageWrite.cpp IndexGenerator.cpp diff --git a/Source/Core/VideoCommon/ConstantManager.h b/Source/Core/VideoCommon/ConstantManager.h index 93c228bc98..9039a1b220 100644 --- a/Source/Core/VideoCommon/ConstantManager.h +++ b/Source/Core/VideoCommon/ConstantManager.h @@ -43,6 +43,9 @@ struct VertexShaderConstants float4 normalmatrices[32]; float4 posttransformmatrices[64]; float4 pixelcentercorrection; - float4 stereoparams; }; +struct GeometryShaderConstants +{ + float4 stereoparams; +}; diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 57009aedaa..2762dcd73b 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -43,11 +43,12 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy // uniforms if (ApiType == API_OPENGL) - out.Write("layout(std140%s) uniform VSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 2" : ""); + out.Write("layout(std140%s) uniform GSBlock {\n", g_ActiveConfig.backend_info.bSupportsBindingLayout ? ", binding = 3" : ""); else - out.Write("cbuffer VSBlock {\n"); - out.Write(s_shader_uniforms); - out.Write("};\n"); + out.Write("cbuffer GSBlock {\n"); + out.Write( + "\tfloat4 " I_STEREOPARAMS";\n" + "};\n"); uid_data->numTexGens = xfmem.numTexGen.numTexGens; uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; diff --git a/Source/Core/VideoCommon/GeometryShaderManager.cpp b/Source/Core/VideoCommon/GeometryShaderManager.cpp new file mode 100644 index 0000000000..f754961cbc --- /dev/null +++ b/Source/Core/VideoCommon/GeometryShaderManager.cpp @@ -0,0 +1,82 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "VideoCommon/GeometryShaderGen.h" +#include "VideoCommon/GeometryShaderManager.h" +#include "VideoCommon/VideoCommon.h" +#include "VideoCommon/VideoConfig.h" +#include "VideoCommon/XFMemory.h" + +// track changes +static bool s_projection_changed, s_viewport_changed; + +GeometryShaderConstants GeometryShaderManager::constants; +bool GeometryShaderManager::dirty; + +void GeometryShaderManager::Init() +{ + memset(&constants, 0, sizeof(constants)); + + Dirty(); +} + +void GeometryShaderManager::Shutdown() +{ +} + +void GeometryShaderManager::Dirty() +{ + s_projection_changed = true; + s_viewport_changed = true; + + dirty = true; +} + +// Syncs the shader constant buffers with xfmem +void GeometryShaderManager::SetConstants() +{ + if (s_projection_changed) + { + s_projection_changed = false; + + if (g_ActiveConfig.iStereoMode > 0 && xfmem.projection.type == GX_PERSPECTIVE) + { + float offset = (g_ActiveConfig.iStereoSeparation / 1000.0f) * (g_ActiveConfig.iStereoSeparationPercent / 100.0f); + constants.stereoparams[0] = (g_ActiveConfig.bStereoSwapEyes) ? offset : -offset; + constants.stereoparams[1] = (g_ActiveConfig.bStereoSwapEyes) ? -offset : offset; + constants.stereoparams[2] = (g_ActiveConfig.iStereoConvergence / 10.0f) * (g_ActiveConfig.iStereoConvergencePercent / 100.0f); + } + else + { + constants.stereoparams[0] = constants.stereoparams[1] = 0; + } + } + + dirty = true; +} + +void GeometryShaderManager::SetViewportChanged() +{ + s_viewport_changed = true; +} + +void GeometryShaderManager::SetProjectionChanged() +{ + s_projection_changed = true; +} + +void GeometryShaderManager::DoState(PointerWrap &p) +{ + p.Do(dirty); + + if (p.GetMode() == PointerWrap::MODE_READ) + { + // Reload current state from global GPU state + // NOTE: This requires that all GPU memory has been loaded already. + Dirty(); + } +} diff --git a/Source/Core/VideoCommon/GeometryShaderManager.h b/Source/Core/VideoCommon/GeometryShaderManager.h new file mode 100644 index 0000000000..d9d8af959f --- /dev/null +++ b/Source/Core/VideoCommon/GeometryShaderManager.h @@ -0,0 +1,29 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "VideoCommon/ConstantManager.h" +#include "VideoCommon/GeometryShaderGen.h" + +class PointerWrap; + +// The non-API dependent parts. +class GeometryShaderManager +{ +public: + static void Init(); + static void Dirty(); + static void Shutdown(); + static void DoState(PointerWrap &p); + + // constant management + static void SetConstants(); + + static void SetViewportChanged(); + static void SetProjectionChanged(); + + static GeometryShaderConstants constants; + static bool dirty; +}; diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index 618d262374..a73290fa44 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -279,7 +279,8 @@ static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type) #define I_NORMALMATRICES "cnmtx" #define I_POSTTRANSFORMMATRICES "cpostmtx" #define I_PIXELCENTERCORRECTION "cpixelcenter" -#define I_STEREOPARAMS "cstereo" + +#define I_STEREOPARAMS "cstereo" static const char s_shader_uniforms[] = "\tfloat4 " I_POSNORMALMATRIX"[6];\n" @@ -290,5 +291,4 @@ static const char s_shader_uniforms[] = "\tfloat4 " I_TRANSFORMMATRICES"[64];\n" "\tfloat4 " I_NORMALMATRICES"[32];\n" "\tfloat4 " I_POSTTRANSFORMMATRICES"[64];\n" - "\tfloat4 " I_PIXELCENTERCORRECTION";\n" - "\tfloat4 " I_STEREOPARAMS";\n"; + "\tfloat4 " I_PIXELCENTERCORRECTION";\n"; diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 84e0bb5efe..7484039137 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -2,6 +2,7 @@ #include "VideoCommon/BPStructs.h" #include "VideoCommon/Debugger.h" +#include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/IndexGenerator.h" #include "VideoCommon/MainBase.h" #include "VideoCommon/NativeVertexFormat.h" @@ -223,6 +224,7 @@ void VertexManager::Flush() // set global constants VertexShaderManager::SetConstants(); PixelShaderManager::SetConstants(); + GeometryShaderManager::SetConstants(); bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index 84cf2d2a01..542328e523 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -512,18 +512,6 @@ void VertexShaderManager::SetConstants() memcpy(constants.projection, correctedMtx.data, 4*16); } - if (g_ActiveConfig.iStereoMode > 0 && xfmem.projection.type == GX_PERSPECTIVE) - { - float offset = (g_ActiveConfig.iStereoSeparation / 1000.0f) * (g_ActiveConfig.iStereoSeparationPercent / 100.0f); - constants.stereoparams[0] = (g_ActiveConfig.bStereoSwapEyes) ? offset : -offset; - constants.stereoparams[1] = (g_ActiveConfig.bStereoSwapEyes) ? -offset : offset; - constants.stereoparams[2] = (g_ActiveConfig.iStereoConvergence / 10.0f) * (g_ActiveConfig.iStereoConvergencePercent / 100.0f); - } - else - { - constants.stereoparams[0] = constants.stereoparams[1] = 0; - } - dirty = true; } } diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index 237becb45e..65488aa4fa 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -61,6 +61,7 @@ + @@ -112,6 +113,7 @@ + diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters index 971bf59bbf..cd4901f303 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj.filters +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj.filters @@ -146,6 +146,9 @@ Shader Generators + + Shader Managers + @@ -284,6 +287,9 @@ Shader Generators + + Shader Managers + diff --git a/Source/Core/VideoCommon/VideoState.cpp b/Source/Core/VideoCommon/VideoState.cpp index a36a5d9d33..337bfd04a0 100644 --- a/Source/Core/VideoCommon/VideoState.cpp +++ b/Source/Core/VideoCommon/VideoState.cpp @@ -8,6 +8,7 @@ #include "VideoCommon/CommandProcessor.h" #include "VideoCommon/CPMemory.h" #include "VideoCommon/Fifo.h" +#include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/PixelEngine.h" #include "VideoCommon/PixelShaderManager.h" #include "VideoCommon/TextureDecoder.h" @@ -50,6 +51,9 @@ static void DoState(PointerWrap &p) VertexShaderManager::DoState(p); p.DoMarker("VertexShaderManager"); + GeometryShaderManager::DoState(p); + p.DoMarker("GeometryShaderManager"); + VertexManager::DoState(p); p.DoMarker("VertexManager"); diff --git a/Source/Core/VideoCommon/XFStructs.cpp b/Source/Core/VideoCommon/XFStructs.cpp index 927fed8077..34820af640 100644 --- a/Source/Core/VideoCommon/XFStructs.cpp +++ b/Source/Core/VideoCommon/XFStructs.cpp @@ -7,6 +7,7 @@ #include "VideoCommon/CPMemory.h" #include "VideoCommon/DataReader.h" #include "VideoCommon/Fifo.h" +#include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/PixelShaderManager.h" #include "VideoCommon/VertexManagerBase.h" #include "VideoCommon/VertexShaderManager.h" @@ -110,6 +111,7 @@ static void XFRegWritten(int transferSize, u32 baseAddress, DataReader src) VertexManager::Flush(); VertexShaderManager::SetViewportChanged(); PixelShaderManager::SetViewportChanged(); + GeometryShaderManager::SetViewportChanged(); nextAddress = XFMEM_SETVIEWPORT + 6; break; @@ -123,6 +125,7 @@ static void XFRegWritten(int transferSize, u32 baseAddress, DataReader src) case XFMEM_SETPROJECTION+6: VertexManager::Flush(); VertexShaderManager::SetProjectionChanged(); + GeometryShaderManager::SetProjectionChanged(); nextAddress = XFMEM_SETPROJECTION + 7; break; From aa4242fd9c807633f090baac2350f786a67ebe3d Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 14 Dec 2014 19:41:16 +0100 Subject: [PATCH 02/24] GeometryShaderGen: Pass the primitive type and always run the generator regardless of stereoscopy. --- .../Core/VideoBackends/D3D/GeometryShaderCache.cpp | 8 ++++---- Source/Core/VideoBackends/D3D/GeometryShaderCache.h | 2 +- Source/Core/VideoBackends/D3D/VertexManager.cpp | 11 ++++------- .../Core/VideoBackends/OGL/ProgramShaderCache.cpp | 11 +++++------ Source/Core/VideoBackends/OGL/ProgramShaderCache.h | 4 ++-- Source/Core/VideoBackends/OGL/VertexManager.cpp | 6 +++--- Source/Core/VideoCommon/GeometryShaderGen.cpp | 13 ++++++------- Source/Core/VideoCommon/GeometryShaderGen.h | 5 +++-- 8 files changed, 28 insertions(+), 32 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp index 6f87e124e7..bed0ff95b7 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -186,14 +186,14 @@ void GeometryShaderCache::Shutdown() g_gs_disk_cache.Close(); } -bool GeometryShaderCache::SetShader(u32 components) +bool GeometryShaderCache::SetShader(u32 primitive_type) { GeometryShaderUid uid; - GetGeometryShaderUid(uid, components, API_D3D); + GetGeometryShaderUid(uid, primitive_type, API_D3D); if (g_ActiveConfig.bEnableShaderDebugging) { ShaderCode code; - GenerateGeometryShaderCode(code, components, API_D3D); + GenerateGeometryShaderCode(code, primitive_type, API_D3D); geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g"); } @@ -222,7 +222,7 @@ bool GeometryShaderCache::SetShader(u32 components) // Need to compile a new shader ShaderCode code; - GenerateGeometryShaderCode(code, components, API_D3D); + GenerateGeometryShaderCode(code, primitive_type, API_D3D); D3DBlob* pbytecode; if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode)) diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h index 0c44554412..fe4aea4a36 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h @@ -18,7 +18,7 @@ public: static void Init(); static void Clear(); static void Shutdown(); - static bool SetShader(u32 components); // TODO: Should be renamed to LoadShader + static bool SetShader(u32 primitive_type); // TODO: Should be renamed to LoadShader static bool InsertByteCode(const GeometryShaderUid &uid, const void* bytecode, unsigned int bytecodelen); static ID3D11GeometryShader* GeometryShaderCache::GetClearGeometryShader(); diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index 29fcf1c365..0bb9735994 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -141,7 +141,7 @@ void VertexManager::Draw(u32 stride) { D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); - D3D::stateman->SetGeometryShader(g_ActiveConfig.iStereoMode > 0 ? GeometryShaderCache::GetActiveShader() : nullptr); + D3D::stateman->SetGeometryShader(GeometryShaderCache::GetActiveShader()); D3D::stateman->Apply(); D3D::context->DrawIndexed(indices, startIndex, baseVertex); @@ -219,13 +219,10 @@ void VertexManager::vFlush(bool useDstAlpha) return; } - if (g_ActiveConfig.iStereoMode > 0) + if (!GeometryShaderCache::SetShader(current_primitive_type)) { - if (!GeometryShaderCache::SetShader(components)) - { - GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR, true, { printf("Fail to set pixel shader\n"); }); - return; - } + GFX_DEBUGGER_PAUSE_LOG_AT(NEXT_ERROR, true, { printf("Fail to set pixel shader\n"); }); + return; } if (g_ActiveConfig.backend_info.bSupportsBBox && BoundingBox::active) diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 08b22e8071..8a159ea9a6 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -171,10 +171,10 @@ GLuint ProgramShaderCache::GetCurrentProgram() return CurrentProgram; } -SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) +SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components, u32 primitive_type) { SHADERUID uid; - GetShaderId(&uid, dstAlphaMode, components); + GetShaderId(&uid, dstAlphaMode, components, primitive_type); // Check if the shader is already set if (last_entry) @@ -211,8 +211,7 @@ SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components ShaderCode gcode; GenerateVertexShaderCode(vcode, components, API_OPENGL); GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components); - if (g_ActiveConfig.iStereoMode > 0) - GenerateGeometryShaderCode(gcode, components, API_OPENGL); + GenerateGeometryShaderCode(gcode, primitive_type, API_OPENGL); if (g_ActiveConfig.bEnableShaderDebugging) { @@ -395,7 +394,7 @@ GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const char* code) return result; } -void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components) +void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components, u32 primitive_type) { GetPixelShaderUid(uid->puid, dstAlphaMode, API_OPENGL, components); GetVertexShaderUid(uid->vuid, components, API_OPENGL); @@ -412,7 +411,7 @@ void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, vertex_uid_checker.AddToIndexAndCheck(vcode, uid->vuid, "Vertex", "v"); ShaderCode gcode; - GenerateGeometryShaderCode(gcode, components, API_OPENGL); + GenerateGeometryShaderCode(gcode, primitive_type, API_OPENGL); geometry_uid_checker.AddToIndexAndCheck(gcode, uid->guid, "Geometry", "g"); } } diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.h b/Source/Core/VideoBackends/OGL/ProgramShaderCache.h index d1e3a5ee54..65eeae2ca0 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.h +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.h @@ -88,8 +88,8 @@ public: static PCacheEntry GetShaderProgram(); static GLuint GetCurrentProgram(); - static SHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components); - static void GetShaderId(SHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 components); + static SHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components, u32 primitive_type); + static void GetShaderId(SHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 components, u32 primitive_type); static bool CompileShader(SHADER &shader, const char* vcode, const char* pcode, const char* gcode = nullptr); static GLuint CompileSingleShader(GLuint type, const char *code); diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp index e696aca536..d5ff396ba0 100644 --- a/Source/Core/VideoBackends/OGL/VertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp @@ -142,11 +142,11 @@ void VertexManager::vFlush(bool useDstAlpha) // the same pass as regular rendering. if (useDstAlpha && dualSourcePossible) { - ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, nativeVertexFmt->m_components); + ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, nativeVertexFmt->m_components, current_primitive_type); } else { - ProgramShaderCache::SetShader(DSTALPHA_NONE, nativeVertexFmt->m_components); + ProgramShaderCache::SetShader(DSTALPHA_NONE, nativeVertexFmt->m_components, current_primitive_type); } // upload global constants @@ -160,7 +160,7 @@ void VertexManager::vFlush(bool useDstAlpha) // run through vertex groups again to set alpha if (useDstAlpha && !dualSourcePossible) { - ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS, nativeVertexFmt->m_components); + ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS, nativeVertexFmt->m_components, current_primitive_type); // only update alpha glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 2762dcd73b..3a2282521e 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -12,7 +12,7 @@ static char text[16384]; template -static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiType) +static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE ApiType) { // Non-uid template parameters will write to the dummy data (=> gets optimized out) geometry_shader_uid_data dummy_data; @@ -26,8 +26,7 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy if (is_writing_shadercode) text[sizeof(text) - 1] = 0x7C; // canary - out.Write("//Geometry Shader for 3D stereoscopy\n"); - + uid_data->primitive_type = primitive_type; uid_data->stereo = g_ActiveConfig.iStereoMode > 0; if (ApiType == API_OPENGL) { @@ -156,12 +155,12 @@ static inline void GenerateGeometryShader(T& out, u32 components, API_TYPE ApiTy } } -void GetGeometryShaderUid(GeometryShaderUid& object, u32 components, API_TYPE ApiType) +void GetGeometryShaderUid(GeometryShaderUid& object, u32 primitive_type, API_TYPE ApiType) { - GenerateGeometryShader(object, components, ApiType); + GenerateGeometryShader(object, primitive_type, ApiType); } -void GenerateGeometryShaderCode(ShaderCode& object, u32 components, API_TYPE ApiType) +void GenerateGeometryShaderCode(ShaderCode& object, u32 primitive_type, API_TYPE ApiType) { - GenerateGeometryShader(object, components, ApiType); + GenerateGeometryShader(object, primitive_type, ApiType); } diff --git a/Source/Core/VideoCommon/GeometryShaderGen.h b/Source/Core/VideoCommon/GeometryShaderGen.h index 3f7dc5198b..93e222b25e 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.h +++ b/Source/Core/VideoCommon/GeometryShaderGen.h @@ -16,11 +16,12 @@ struct geometry_shader_uid_data u32 stereo : 1; u32 numTexGens : 4; u32 pixel_lighting : 1; + u32 primitive_type : 2; }; #pragma pack() typedef ShaderUid GeometryShaderUid; -void GenerateGeometryShaderCode(ShaderCode& object, u32 components, API_TYPE ApiType); -void GetGeometryShaderUid(GeometryShaderUid& object, u32 components, API_TYPE ApiType); +void GenerateGeometryShaderCode(ShaderCode& object, u32 primitive_type, API_TYPE ApiType); +void GetGeometryShaderUid(GeometryShaderUid& object, u32 primitive_type, API_TYPE ApiType); From 332ba4b2100ec4dcda4b2e83eb5b0e2d21e6abc4 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 14 Dec 2014 21:44:33 +0100 Subject: [PATCH 03/24] GeometryShaderManager: Upload Line/Point width constants. --- Source/Core/VideoCommon/BPStructs.cpp | 4 ++ Source/Core/VideoCommon/ConstantManager.h | 3 ++ Source/Core/VideoCommon/GeometryShaderGen.cpp | 5 ++- .../VideoCommon/GeometryShaderManager.cpp | 43 ++++++++++++++++++- .../Core/VideoCommon/GeometryShaderManager.h | 2 + Source/Core/VideoCommon/ShaderGenCommon.h | 5 ++- 6 files changed, 59 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 8996784760..fdf3e15ff2 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -130,6 +130,7 @@ static void BPWritten(const BPCmd& bp) return; case BPMEM_LINEPTWIDTH: // Line Width SetLineWidth(); + GeometryShaderManager::SetLinePtWidthChanged(); return; case BPMEM_ZMODE: // Depth Control PRIM_LOG("zmode: test=%d, func=%d, upd=%d", (int)bpmem.zmode.testenable, @@ -572,7 +573,10 @@ static void BPWritten(const BPCmd& bp) case BPMEM_SU_SSIZE+14: case BPMEM_SU_TSIZE+14: if (bp.changes) + { PixelShaderManager::SetTexCoordChanged((bp.address - BPMEM_SU_SSIZE) >> 1); + GeometryShaderManager::SetTexCoordChanged((bp.address - BPMEM_SU_SSIZE) >> 1); + } return; // ------------------------ // BPMEM_TX_SETMODE0 - (Texture lookup and filtering mode) LOD/BIAS Clamp, MaxAnsio, LODBIAS, DiagLoad, Min Filter, Mag Filter, Wrap T, S diff --git a/Source/Core/VideoCommon/ConstantManager.h b/Source/Core/VideoCommon/ConstantManager.h index 9039a1b220..00f82d681e 100644 --- a/Source/Core/VideoCommon/ConstantManager.h +++ b/Source/Core/VideoCommon/ConstantManager.h @@ -48,4 +48,7 @@ struct VertexShaderConstants struct GeometryShaderConstants { float4 stereoparams; + float4 lineptwidth; + float4 viewport; + u32 texoffsetflags[8]; }; diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 3a2282521e..814ad9c075 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -47,9 +47,12 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("cbuffer GSBlock {\n"); out.Write( "\tfloat4 " I_STEREOPARAMS";\n" + "\tfloat4 " I_LINEPTWIDTH";\n" + "\tfloat4 " I_VIEWPORT";\n" + "\tuint " I_TEXOFFSETFLAGS"[8];\n" "};\n"); - uid_data->numTexGens = xfmem.numTexGen.numTexGens; + uid_data->numTexGens = bpmem.genMode.numtexgens; uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; GenerateVSOutputStruct(out, ApiType); diff --git a/Source/Core/VideoCommon/GeometryShaderManager.cpp b/Source/Core/VideoCommon/GeometryShaderManager.cpp index f754961cbc..70bb151666 100644 --- a/Source/Core/VideoCommon/GeometryShaderManager.cpp +++ b/Source/Core/VideoCommon/GeometryShaderManager.cpp @@ -5,6 +5,7 @@ #include #include +#include "VideoCommon/BPMemory.h" #include "VideoCommon/GeometryShaderGen.h" #include "VideoCommon/GeometryShaderManager.h" #include "VideoCommon/VideoCommon.h" @@ -12,7 +13,11 @@ #include "VideoCommon/XFMemory.h" // track changes -static bool s_projection_changed, s_viewport_changed; +static bool s_projection_changed, s_viewport_changed, s_lineptwidth_changed; + +static const float LINE_PT_TEX_OFFSETS[8] = { + 0.f, 0.0625f, 0.125f, 0.25f, 0.5f, 1.f, 1.f, 1.f +}; GeometryShaderConstants GeometryShaderManager::constants; bool GeometryShaderManager::dirty; @@ -32,6 +37,16 @@ void GeometryShaderManager::Dirty() { s_projection_changed = true; s_viewport_changed = true; + s_lineptwidth_changed = true; + + SetTexCoordChanged(0); + SetTexCoordChanged(1); + SetTexCoordChanged(2); + SetTexCoordChanged(3); + SetTexCoordChanged(4); + SetTexCoordChanged(5); + SetTexCoordChanged(6); + SetTexCoordChanged(7); dirty = true; } @@ -39,6 +54,20 @@ void GeometryShaderManager::Dirty() // Syncs the shader constant buffers with xfmem void GeometryShaderManager::SetConstants() { + if (s_lineptwidth_changed) + { + constants.lineptwidth[0] = bpmem.lineptwidth.linesize / 6.f; + constants.lineptwidth[1] = bpmem.lineptwidth.pointsize / 6.f; + constants.lineptwidth[2] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff]; + constants.lineptwidth[3] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff]; + } + + if (s_viewport_changed) + { + constants.viewport[0] = 2.0f * xfmem.viewport.wd; + constants.viewport[1] = -2.0f * xfmem.viewport.ht; + } + if (s_projection_changed) { s_projection_changed = false; @@ -69,6 +98,18 @@ void GeometryShaderManager::SetProjectionChanged() s_projection_changed = true; } +void GeometryShaderManager::SetLinePtWidthChanged() +{ + s_lineptwidth_changed = true; +} + +void GeometryShaderManager::SetTexCoordChanged(u8 texmapid) +{ + TCoordInfo& tc = bpmem.texcoords[texmapid]; + constants.texoffsetflags[texmapid] = tc.s.line_offset + tc.s.point_offset * 2; + dirty = true; +} + void GeometryShaderManager::DoState(PointerWrap &p) { p.Do(dirty); diff --git a/Source/Core/VideoCommon/GeometryShaderManager.h b/Source/Core/VideoCommon/GeometryShaderManager.h index d9d8af959f..86cd3ee2ea 100644 --- a/Source/Core/VideoCommon/GeometryShaderManager.h +++ b/Source/Core/VideoCommon/GeometryShaderManager.h @@ -23,6 +23,8 @@ public: static void SetViewportChanged(); static void SetProjectionChanged(); + static void SetLinePtWidthChanged(); + static void SetTexCoordChanged(u8 texmapid); static GeometryShaderConstants constants; static bool dirty; diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index a73290fa44..d5a2438316 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -280,7 +280,10 @@ static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type) #define I_POSTTRANSFORMMATRICES "cpostmtx" #define I_PIXELCENTERCORRECTION "cpixelcenter" -#define I_STEREOPARAMS "cstereo" +#define I_STEREOPARAMS "cstereo" +#define I_LINEPTWIDTH "clinept" +#define I_VIEWPORT "cviewport" +#define I_TEXOFFSETFLAGS "ctexoffset" static const char s_shader_uniforms[] = "\tfloat4 " I_POSNORMALMATRIX"[6];\n" From 887c669c288a8aeb432e9b6e9cd0c781bd14faf5 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 14 Dec 2014 21:50:46 +0100 Subject: [PATCH 04/24] GeometryShaderGen: Redefine gl_InvocationID so we can use the same variable name in both backends. --- Source/Core/VideoCommon/GeometryShaderGen.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 814ad9c075..d0e9eb7144 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -59,6 +59,9 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A if (ApiType == API_OPENGL) { + if (g_ActiveConfig.backend_info.bSupportsGSInstancing) + out.Write("#define InstanceID gl_InvocationID\n"); + out.Write("centroid in VS_OUTPUT o[3];\n"); out.Write("centroid out VS_OUTPUT vs;\n"); out.Write("flat out int layer;\n"); @@ -91,12 +94,7 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A // If the GPU supports invocation we don't need a for loop and can simply use the // invocation identifier to determine which layer we're rendering. if (g_ActiveConfig.backend_info.bSupportsGSInstancing) - { - if (ApiType == API_OPENGL) - out.Write("\tint eye = gl_InvocationID;\n"); - else - out.Write("\tint eye = InstanceID;\n"); - } + out.Write("\tint eye = InstanceID;\n"); else out.Write("\tfor (int eye = 0; eye < %d; ++eye) {\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); From 382e1c22db91d863b55d6223d4893cb629dab810 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 14 Dec 2014 22:27:09 +0100 Subject: [PATCH 05/24] GeometryShaderGen: Support multiple primitive types. And make more stereoscopy code optional. --- .../Core/VideoBackends/D3D/VertexManager.cpp | 5 -- .../VideoBackends/OGL/ProgramShaderCache.cpp | 2 +- Source/Core/VideoCommon/BPStructs.cpp | 1 - Source/Core/VideoCommon/GeometryShaderGen.cpp | 79 ++++++++++++------- 4 files changed, 53 insertions(+), 34 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index 0bb9735994..6ba3bc3391 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -12,7 +12,6 @@ #include "VideoBackends/D3D/VertexShaderCache.h" #include "VideoCommon/BoundingBox.h" -#include "VideoCommon/BPMemory.h" #include "VideoCommon/Debugger.h" #include "VideoCommon/IndexGenerator.h" #include "VideoCommon/MainBase.h" @@ -122,10 +121,6 @@ void VertexManager::PrepareDrawBuffers(u32 stride) ADDSTAT(stats.thisFrame.bytesIndexStreamed, indexBufferSize); } -static const float LINE_PT_TEX_OFFSETS[8] = { - 0.f, 0.0625f, 0.125f, 0.25f, 0.5f, 1.f, 1.f, 1.f -}; - void VertexManager::Draw(u32 stride) { u32 components = VertexLoaderManager::GetCurrentVertexFormat()->m_components; diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 8a159ea9a6..d2ec0d049b 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -398,7 +398,7 @@ void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, { GetPixelShaderUid(uid->puid, dstAlphaMode, API_OPENGL, components); GetVertexShaderUid(uid->vuid, components, API_OPENGL); - GetGeometryShaderUid(uid->guid, components, API_OPENGL); + GetGeometryShaderUid(uid->guid, primitive_type, API_OPENGL); if (g_ActiveConfig.bEnableShaderDebugging) { diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index fdf3e15ff2..6a32b7f245 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -129,7 +129,6 @@ static void BPWritten(const BPCmd& bp) GeometryShaderManager::SetViewportChanged(); return; case BPMEM_LINEPTWIDTH: // Line Width - SetLineWidth(); GeometryShaderManager::SetLinePtWidthChanged(); return; case BPMEM_ZMODE: // Depth Control diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index d0e9eb7144..ca4ef96a43 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -6,11 +6,26 @@ #include "VideoCommon/GeometryShaderGen.h" #include "VideoCommon/LightingShaderGen.h" +#include "VideoCommon/VertexManagerBase.h" #include "VideoCommon/VertexShaderGen.h" #include "VideoCommon/VideoConfig.h" static char text[16384]; +static const char* primitives_ogl[] = +{ + "points", + "lines", + "triangles" +}; + +static const char* primitives_d3d[] = +{ + "point", + "line", + "triangle" +}; + template static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE ApiType) { @@ -27,15 +42,18 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A text[sizeof(text) - 1] = 0x7C; // canary 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; + if (ApiType == API_OPENGL) { // Insert layout parameters if (g_ActiveConfig.backend_info.bSupportsGSInstancing) - out.Write("layout(triangles, invocations = %d) in;\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); + out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[primitive_type], g_ActiveConfig.iStereoMode > 0 ? 2 : 1); else - out.Write("layout(triangles) in;\n"); - out.Write("layout(triangle_strip, max_vertices = %d) out;\n", g_ActiveConfig.backend_info.bSupportsGSInstancing ? 3 : 6); + 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("%s", s_lighting_struct); @@ -62,9 +80,11 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A if (g_ActiveConfig.backend_info.bSupportsGSInstancing) out.Write("#define InstanceID gl_InvocationID\n"); - out.Write("centroid in VS_OUTPUT o[3];\n"); + out.Write("centroid in VS_OUTPUT o[%d];\n", vertex_in); out.Write("centroid out VS_OUTPUT vs;\n"); - out.Write("flat out int layer;\n"); + + if (g_ActiveConfig.iStereoMode > 0) + out.Write("flat out int layer;\n"); out.Write("void main()\n{\n"); } @@ -72,18 +92,21 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A { out.Write("struct GS_OUTPUT {\n"); out.Write("\tVS_OUTPUT vs;\n"); - out.Write("\tuint layer : SV_RenderTargetArrayIndex;\n"); + + if (g_ActiveConfig.iStereoMode > 0) + out.Write("\tuint layer : SV_RenderTargetArrayIndex;\n"); + out.Write("};\n"); + out.Write("[maxvertexcount(%d)]\n", vertex_out); if (g_ActiveConfig.backend_info.bSupportsGSInstancing) { - out.Write("[maxvertexcount(3)]\n[instance(%d)]\n", g_ActiveConfig.iStereoMode > 0 ? 2 : 1); - out.Write("void main(triangle VS_OUTPUT o[3], inout TriangleStream Output, in uint InstanceID : SV_GSInstanceID)\n{\n"); + 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); } else { - out.Write("[maxvertexcount(6)]\n"); - out.Write("void main(triangle VS_OUTPUT o[3], inout TriangleStream Output)\n{\n"); + 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"); @@ -91,29 +114,32 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("\tVS_OUTPUT f;\n"); - // If the GPU supports invocation we don't need a for loop and can simply use the - // invocation identifier to determine which layer we're rendering. - 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 i = 0; i < 3; ++i) {\n"); - - // Select the output layer - if (ApiType == API_OPENGL) + if (g_ActiveConfig.iStereoMode > 0) { - out.Write("\t\tgl_Layer = eye;\n"); - out.Write("\t\tlayer = eye;\n"); + // If the GPU supports invocation we don't need a for loop and can simply use the + // invocation identifier to determine which layer we're rendering. + 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); } - else - out.Write("\t\tgs.layer = 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"); 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"); + } + else + out.Write("\t\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 // vertex which contains the negated z-component of the original vertex. @@ -123,10 +149,9 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A // 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("\t\tf.pos.x = pos.x;\n"); - if (ApiType == API_OPENGL) out.Write("\t\tgl_Position = pos;\n"); From 275af9c5e44129db8d039a0a0a7c1a721d6ab05a Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 15 Dec 2014 21:09:25 +0100 Subject: [PATCH 06/24] VideoCommon: Assume we always use a geometry shader, not just for stereoscopy. --- Source/Core/VideoCommon/PixelShaderGen.cpp | 47 ++++++--------------- Source/Core/VideoCommon/VertexShaderGen.cpp | 45 +------------------- Source/Core/VideoCommon/VertexShaderGen.h | 2 +- 3 files changed, 15 insertions(+), 79 deletions(-) diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 48cd5b8fec..742f9c0a60 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -316,51 +316,30 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T // As a workaround, we interpolate at the centroid of the coveraged pixel, which // is always inside the primitive. // Without MSAA, this flag is defined to have no effect. + out.Write("centroid in VS_OUTPUT vs;\n"); + uid_data->stereo = g_ActiveConfig.iStereoMode > 0; if (g_ActiveConfig.iStereoMode > 0) - { - out.Write("centroid in VS_OUTPUT vs;\n"); out.Write("flat in int layer;\n"); - } - else - { - out.Write("centroid in float4 colors_02;\n"); - out.Write("centroid in float4 colors_12;\n"); - - // compute window position if needed because binding semantic WPOS is not widely supported - // Let's set up attributes - for (unsigned int i = 0; i < numTexgen; ++i) - { - out.Write("centroid in float3 uv%d;\n", i); - } - out.Write("centroid in float4 clipPos;\n"); - if (g_ActiveConfig.bEnablePixelLighting) - { - out.Write("centroid in float4 Normal;\n"); - } - } out.Write("void main()\n{\n"); - if (g_ActiveConfig.iStereoMode > 0) + // compute window position if needed because binding semantic WPOS is not widely supported + // Let's set up attributes + for (unsigned int i = 0; i < numTexgen; ++i) { - // compute window position if needed because binding semantic WPOS is not widely supported - // Let's set up attributes - for (unsigned int i = 0; i < numTexgen; ++i) - { - out.Write("\tfloat3 uv%d = vs.tex%d;\n", i, i); - } - out.Write("\tfloat4 clipPos = vs.clipPos;\n"); - if (g_ActiveConfig.bEnablePixelLighting) - { - out.Write("\tfloat4 Normal = vs.Normal;\n"); - } + out.Write("\tfloat3 uv%d = vs.tex%d;\n", i, i); + } + out.Write("\tfloat4 clipPos = vs.clipPos;\n"); + if (g_ActiveConfig.bEnablePixelLighting) + { + out.Write("\tfloat4 Normal = vs.Normal;\n"); } // On Mali, global variables must be initialized as constants. // This is why we initialize these variables locally instead. - out.Write("\tfloat4 colors_0 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "vs.colors_0" : "colors_02"); - out.Write("\tfloat4 colors_1 = %s;\n", (g_ActiveConfig.iStereoMode > 0) ? "vs.colors_1" : "colors_12"); + out.Write("\tfloat4 colors_0 = vs.colors_0;\n"); + out.Write("\tfloat4 colors_1 = vs.colors_1;\n"); out.Write("\tfloat4 rawpos = gl_FragCoord;\n"); } diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 00db2b0f02..80e025386f 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -72,33 +72,9 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ out.Write("in float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i); } - uid_data->stereo = g_ActiveConfig.iStereoMode > 0; - if (g_ActiveConfig.iStereoMode > 0) - { - out.Write("centroid out VS_OUTPUT o;\n"); - } - else - { - // Let's set up attributes - for (size_t i = 0; i < 8; ++i) - { - if (i < xfmem.numTexGen.numTexGens) - { - out.Write("centroid out float3 uv%d;\n", i); - } - } - - out.Write("centroid out float4 clipPos;\n"); - if (g_ActiveConfig.bEnablePixelLighting) - out.Write("centroid out float4 Normal;\n"); - out.Write("centroid out float4 colors_02;\n"); - out.Write("centroid out float4 colors_12;\n"); - } + out.Write("centroid out VS_OUTPUT o;\n"); out.Write("void main()\n{\n"); - - if (g_ActiveConfig.iStereoMode <= 0) - out.Write("VS_OUTPUT o;\n"); } else // D3D { @@ -384,25 +360,6 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ if (api_type == API_OPENGL) { - if (g_ActiveConfig.iStereoMode <= 0) - { - // Bit ugly here - // TODO: Make pretty - // Will look better when we bind uniforms in GLSL 1.3 - // clipPos/w needs to be done in pixel shader, not here - - for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i) - out.Write("uv%d.xyz = o.tex%d;\n", i, i); - - out.Write("clipPos = o.clipPos;\n"); - - if (g_ActiveConfig.bEnablePixelLighting) - out.Write("Normal = o.Normal;\n"); - - out.Write("colors_02 = o.colors_0;\n"); - out.Write("colors_12 = o.colors_1;\n"); - } - out.Write("gl_Position = o.pos;\n"); } else // D3D diff --git a/Source/Core/VideoCommon/VertexShaderGen.h b/Source/Core/VideoCommon/VertexShaderGen.h index 1f08c1963a..b97f577061 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.h +++ b/Source/Core/VideoCommon/VertexShaderGen.h @@ -37,7 +37,7 @@ struct vertex_shader_uid_data u32 numColorChans : 2; u32 dualTexTrans_enabled : 1; u32 pixel_lighting : 1; - u32 stereo : 1; + u32 pad : 1; u32 texMtxInfo_n_projection : 16; // Stored separately to guarantee that the texMtxInfo struct is 8 bits wide struct { From 55e60a9c2242713a93621ca1b618930e5c61aef0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 15 Dec 2014 22:12:17 +0100 Subject: [PATCH 07/24] VideoCommon: Merge LineGeometryShader into GeometryShaderGen. This adds line-width emulation support to OpenGL. --- Source/Core/VideoBackends/D3D/D3D.vcxproj | 2 - .../VideoBackends/D3D/D3D.vcxproj.filters | 6 - .../VideoBackends/D3D/LineGeometryShader.cpp | 239 ------------------ .../VideoBackends/D3D/LineGeometryShader.h | 42 --- Source/Core/VideoBackends/D3D/Render.cpp | 5 - Source/Core/VideoBackends/D3D/Render.h | 1 - .../Core/VideoBackends/D3D/VertexManager.cpp | 28 +- Source/Core/VideoBackends/D3D/VertexManager.h | 2 - Source/Core/VideoBackends/OGL/Render.cpp | 14 - Source/Core/VideoBackends/OGL/Render.h | 1 - Source/Core/VideoCommon/BPFunctions.cpp | 5 - Source/Core/VideoCommon/BPFunctions.h | 1 - Source/Core/VideoCommon/BPStructs.cpp | 1 - Source/Core/VideoCommon/GeometryShaderGen.cpp | 99 ++++++-- Source/Core/VideoCommon/RenderBase.h | 1 - 15 files changed, 81 insertions(+), 366 deletions(-) delete mode 100644 Source/Core/VideoBackends/D3D/LineGeometryShader.cpp delete mode 100644 Source/Core/VideoBackends/D3D/LineGeometryShader.h 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; From 8ae738ff3076aa2b4cec254f3d5dcfe2fea95d88 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 15 Dec 2014 22:29:56 +0100 Subject: [PATCH 08/24] VideoCommon: Merge PointGeometryShader into GeometryShaderGen. This adds point-width emulation support to OpenGL. --- Source/Core/VideoBackends/D3D/D3D.vcxproj | 2 - .../VideoBackends/D3D/D3D.vcxproj.filters | 6 - .../VideoBackends/D3D/PointGeometryShader.cpp | 233 ------------------ .../VideoBackends/D3D/PointGeometryShader.h | 42 ---- .../Core/VideoBackends/D3D/VertexManager.cpp | 30 +-- Source/Core/VideoBackends/D3D/VertexManager.h | 3 - Source/Core/VideoCommon/GeometryShaderGen.cpp | 34 ++- 7 files changed, 40 insertions(+), 310 deletions(-) delete mode 100644 Source/Core/VideoBackends/D3D/PointGeometryShader.cpp delete mode 100644 Source/Core/VideoBackends/D3D/PointGeometryShader.h diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj b/Source/Core/VideoBackends/D3D/D3D.vcxproj index f1334b8f8f..a83e265c34 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj @@ -48,7 +48,6 @@ - @@ -71,7 +70,6 @@ - diff --git a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters index d6f7331c37..e5f5baf882 100644 --- a/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters +++ b/Source/Core/VideoBackends/D3D/D3D.vcxproj.filters @@ -42,9 +42,6 @@ Render - - Render - Render @@ -102,9 +99,6 @@ Render - - Render - Render diff --git a/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp b/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp deleted file mode 100644 index 3f874b3915..0000000000 --- a/Source/Core/VideoBackends/D3D/PointGeometryShader.cpp +++ /dev/null @@ -1,233 +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/PointGeometryShader.h" -#include "VideoCommon/VertexShaderGen.h" - -namespace DX11 -{ - -struct PointGSParams -{ - 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[(sizeof(PointGSParams) + 15) & ~15]; -}; - -static const char POINT_GS_COMMON[] = -// The struct VS_OUTPUT used by the vertex shader goes here. -"// dolphin-emu point geometry shader common part\n" - -"cbuffer cbParams : register(b0)\n" -"{\n" - "struct\n" // Should match PointGSParams above - "{\n" - "float PointSize;\n" - "float TexOffset;\n" - "float VpWidth;\n" - "float VpHeight;\n" - "float TexOffsetEnable[8];\n" - "} Params;\n" -"}\n" - -"[maxvertexcount(4)]\n" -"void main(point VS_OUTPUT input[1], inout TriangleStream outStream)\n" -"{\n" - "VS_OUTPUT ptLL = input[0];\n" - "VS_OUTPUT ptLR = ptLL;\n" - "VS_OUTPUT ptUL = ptLL;\n" - "VS_OUTPUT ptUR = ptLL;\n" - - // Offset from center to upper right vertex - // Lerp Params.PointSize/2 from [0,0..VpWidth,VpHeight] to [-1,1..1,-1] - "float2 offset = float2(Params.PointSize/Params.VpWidth, -Params.PointSize/Params.VpHeight) * input[0].pos.w;\n" - - "ptLL.pos.xy += float2(-1,-1) * offset;\n" - "ptLR.pos.xy += float2(1,-1) * offset;\n" - "ptUL.pos.xy += float2(-1,1) * offset;\n" - "ptUR.pos.xy += offset;\n" - - "float2 texOffset = float2(Params.TexOffset, Params.TexOffset);\n" - -"#ifndef NUM_TEXCOORDS\n" -"#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? -"#if NUM_TEXCOORDS >= 1\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 * 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 * 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 * 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 * 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 * 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 * 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 * 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" - "outStream.Append(ptLR);\n" - "outStream.Append(ptUL);\n" - "outStream.Append(ptUR);\n" -"}\n" -; - -PointGeometryShader::PointGeometryShader() - : m_ready(false), m_paramsBuffer(nullptr) -{ } - -void PointGeometryShader::Init() -{ - m_ready = false; - - HRESULT hr; - - // Create constant buffer for uploading data to geometry shader - - D3D11_BUFFER_DESC bd = CD3D11_BUFFER_DESC(sizeof(PointGSParams_Padded), - D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); - hr = D3D::device->CreateBuffer(&bd, nullptr, &m_paramsBuffer); - CHECK(SUCCEEDED(hr), "create point geometry shader params buffer"); - D3D::SetDebugObjectName(m_paramsBuffer, "point geometry shader params buffer"); - - m_ready = true; -} - -void PointGeometryShader::Shutdown() -{ - m_ready = false; - - for (auto& it : m_shaders) - { - SAFE_RELEASE(it.second); - } - m_shaders.clear(); - - SAFE_RELEASE(m_paramsBuffer); -} - -bool PointGeometryShader::SetShader(u32 components, float pointSize, - 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", POINT_GS_COMMON); - - std::stringstream numTexCoordsStream; - numTexCoordsStream << xfmem.numTexGen.numTexGens; - - INFO_LOG(VIDEO, "Compiling point 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, "Point 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)) - { - 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::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); - - 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/PointGeometryShader.h b/Source/Core/VideoBackends/D3D/PointGeometryShader.h deleted file mode 100644 index b24f73d486..0000000000 --- a/Source/Core/VideoBackends/D3D/PointGeometryShader.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 point geometry shaders, one for each -// vertex format. -class PointGeometryShader -{ - -public: - - PointGeometryShader(); - - void Init(); - void Shutdown(); - // Returns true on success, false on failure - bool SetShader(u32 components, float pointSize, 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/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index dcd1ad1569..9f2b2ba318 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -48,14 +48,10 @@ void VertexManager::CreateDeviceObjects() m_currentBuffer = 0; m_bufferCursor = MAX_BUFFER_SIZE; - - m_pointShader.Init(); } void VertexManager::DestroyDeviceObjects() { - m_pointShader.Shutdown(); - for (int i = 0; i < MAX_BUFFER_COUNT; i++) { SAFE_RELEASE(m_buffers[i]); @@ -158,28 +154,16 @@ void VertexManager::Draw(u32 stride) } else //if (current_primitive_type == PRIMITIVE_POINTS) { - float pointSize = float(bpmem.lineptwidth.pointsize) / 6.f; - float texOffset = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff]; - float vpWidth = 2.0f * xfmem.viewport.wd; - float vpHeight = -2.0f * xfmem.viewport.ht; + D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + 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.point_offset; + INCSTAT(stats.thisFrame.numDrawCalls); - if (m_pointShader.SetShader(components, pointSize, - texOffset, vpWidth, vpHeight, texOffsetEnable)) - { - D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - - D3D::stateman->Apply(); - D3D::context->DrawIndexed(indices, startIndex, baseVertex); - - INCSTAT(stats.thisFrame.numDrawCalls); - - D3D::stateman->SetGeometryShader(nullptr); - } + D3D::stateman->SetGeometryShader(nullptr); } } diff --git a/Source/Core/VideoBackends/D3D/VertexManager.h b/Source/Core/VideoBackends/D3D/VertexManager.h index 12e3bf2d4b..0b124d7512 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.h +++ b/Source/Core/VideoBackends/D3D/VertexManager.h @@ -4,7 +4,6 @@ #pragma once -#include "VideoBackends/D3D/PointGeometryShader.h" #include "VideoCommon/VertexManagerBase.h" namespace DX11 @@ -39,8 +38,6 @@ private: enum { MAX_BUFFER_COUNT = 2 }; ID3D11Buffer* m_buffers[MAX_BUFFER_COUNT]; - PointGeometryShader m_pointShader; - std::vector LocalVBuffer; std::vector LocalIBuffer; }; diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index ee6da0fe4d..fabd883ded 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -140,6 +140,12 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("\t\toffset = float2(0, -" I_LINEPTWIDTH"[0] / " I_VIEWPORT".y);\n"); out.Write("\t}\n"); } + else if (primitive_type == PRIMITIVE_POINTS) + { + // Offset from center to upper right vertex + // Lerp PointSize/2 from [0,0..VpWidth,VpHeight] to [-1,1..1,-1] + out.Write("float2 offset = float2(" I_LINEPTWIDTH"[1] / " I_VIEWPORT".x, -" I_LINEPTWIDTH"[1] / " I_VIEWPORT".y) * o[0].pos.w;\n"); + } if (g_ActiveConfig.iStereoMode > 0) { @@ -186,12 +192,38 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A 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); + out.Write("\tr.tex%d.x += " I_LINEPTWIDTH"[2] * (" I_TEXOFFSETFLAGS"[%d] & 0x01);\n", i, i); } EmitVertex(out, "l", ApiType); EmitVertex(out, "r", ApiType); } + else if (primitive_type == PRIMITIVE_POINTS) + { + out.Write("VS_OUTPUT ll = f;\n"); + out.Write("VS_OUTPUT lr = f;\n"); + out.Write("VS_OUTPUT ul = f;\n"); + out.Write("VS_OUTPUT ur = f;\n"); + + out.Write("ll.pos.xy += float2(-1,-1) * offset;\n"); + out.Write("lr.pos.xy += float2(1,-1) * offset;\n"); + out.Write("ul.pos.xy += float2(-1,1) * offset;\n"); + out.Write("ur.pos.xy += offset;\n"); + + out.Write("float2 texOffset = float2(" I_LINEPTWIDTH"[3], " I_LINEPTWIDTH"[3]);\n"); + + for (unsigned int i = 0; i < bpmem.genMode.numtexgens; ++i) + { + out.Write("ll.tex%d.xy += float2(0,1) * texOffset * (" I_TEXOFFSETFLAGS"[%d] & 0x10);\n", i, i); + out.Write("lr.tex%d.xy += texOffset * (" I_TEXOFFSETFLAGS"[%d] & 0x10);\n", i, i); + out.Write("ur.tex%d.xy += float2(1,0) * texOffset * (" I_TEXOFFSETFLAGS"[%d] & 0x10);\n", i, i); + } + + EmitVertex(out, "ll", ApiType); + EmitVertex(out, "lr", ApiType); + EmitVertex(out, "ul", ApiType); + EmitVertex(out, "ur", ApiType); + } else { EmitVertex(out, "f", ApiType); From 861fa1af2387567a00c77db8b78a3ac376fef863 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 15 Dec 2014 22:39:03 +0100 Subject: [PATCH 09/24] GeometryShaderGen: Declare a prototype for EmitVertex(). --- Source/Core/VideoCommon/GeometryShaderGen.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index fabd883ded..37f75ad0d0 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -27,6 +27,8 @@ static const char* primitives_d3d[] = "triangle" }; +template static inline void EmitVertex(T& out, const char *vertex, API_TYPE ApiType); + template static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE ApiType) { From 16af00d51568ddcb4301bffd490d26d342314bd7 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 15 Dec 2014 23:05:16 +0100 Subject: [PATCH 10/24] GeometryShaderGen: Use signed integers for the texture offset flags. --- Source/Core/VideoCommon/ConstantManager.h | 2 +- Source/Core/VideoCommon/GeometryShaderGen.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoCommon/ConstantManager.h b/Source/Core/VideoCommon/ConstantManager.h index 00f82d681e..83c97b2598 100644 --- a/Source/Core/VideoCommon/ConstantManager.h +++ b/Source/Core/VideoCommon/ConstantManager.h @@ -50,5 +50,5 @@ struct GeometryShaderConstants float4 stereoparams; float4 lineptwidth; float4 viewport; - u32 texoffsetflags[8]; + s32 texoffsetflags[8]; }; diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 37f75ad0d0..a8bd784b1b 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -75,7 +75,7 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A "\tfloat4 " I_STEREOPARAMS";\n" "\tfloat4 " I_LINEPTWIDTH";\n" "\tfloat4 " I_VIEWPORT";\n" - "\tuint " I_TEXOFFSETFLAGS"[8];\n" + "\tint " I_TEXOFFSETFLAGS"[8];\n" "};\n"); uid_data->numTexGens = bpmem.genMode.numtexgens; From d115048615864591125cd1b918bdd923b5b63058 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 15 Dec 2014 23:20:56 +0100 Subject: [PATCH 11/24] GeometryShaderGen: Remove redundant declaration. --- Source/Core/VideoCommon/GeometryShaderGen.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index a8bd784b1b..7e989e7b17 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -120,8 +120,6 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("\tGS_OUTPUT gs;\n"); } - out.Write("\tVS_OUTPUT f;\n"); - if (primitive_type == PRIMITIVE_LINES) { // GameCube/Wii's line drawing algorithm is a little quirky. It does not From 0ac710339100dc6dc2f1f4c094b372846decdce5 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 16 Dec 2014 00:21:07 +0100 Subject: [PATCH 12/24] GeometryShaderGen: Pack uniforms more tightly. --- Source/Core/VideoCommon/ConstantManager.h | 5 +- Source/Core/VideoCommon/GeometryShaderGen.cpp | 48 +++++++++++-------- .../VideoCommon/GeometryShaderManager.cpp | 22 +++++---- Source/Core/VideoCommon/ShaderGenCommon.h | 7 ++- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/Source/Core/VideoCommon/ConstantManager.h b/Source/Core/VideoCommon/ConstantManager.h index 83c97b2598..9bfce8aac1 100644 --- a/Source/Core/VideoCommon/ConstantManager.h +++ b/Source/Core/VideoCommon/ConstantManager.h @@ -48,7 +48,6 @@ struct VertexShaderConstants struct GeometryShaderConstants { float4 stereoparams; - float4 lineptwidth; - float4 viewport; - s32 texoffsetflags[8]; + float4 lineptparams; + int4 texoffset; }; diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 7e989e7b17..e10b919dd4 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -73,9 +73,8 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("cbuffer GSBlock {\n"); out.Write( "\tfloat4 " I_STEREOPARAMS";\n" - "\tfloat4 " I_LINEPTWIDTH";\n" - "\tfloat4 " I_VIEWPORT";\n" - "\tint " I_TEXOFFSETFLAGS"[8];\n" + "\tfloat4 " I_LINEPTPARAMS";\n" + "\tint4 " I_TEXOFFSET";\n" "};\n"); uid_data->numTexGens = bpmem.genMode.numtexgens; @@ -130,21 +129,21 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A 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"); + out.Write("\tif (" I_LINEPTPARAMS".y * to.y > " I_LINEPTPARAMS".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\toffset = float2(" I_LINEPTPARAMS".z / " I_LINEPTPARAMS".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\toffset = float2(0, -" I_LINEPTPARAMS".z / " I_LINEPTPARAMS".y);\n"); out.Write("\t}\n"); } else if (primitive_type == PRIMITIVE_POINTS) { // Offset from center to upper right vertex // Lerp PointSize/2 from [0,0..VpWidth,VpHeight] to [-1,1..1,-1] - out.Write("float2 offset = float2(" I_LINEPTWIDTH"[1] / " I_VIEWPORT".x, -" I_LINEPTWIDTH"[1] / " I_VIEWPORT".y) * o[0].pos.w;\n"); + out.Write("float2 offset = float2(" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".x, -" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".y) * o[0].pos.w;\n"); } if (g_ActiveConfig.iStereoMode > 0) @@ -190,34 +189,43 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("\tl.pos.xy -= offset * l.pos.w;\n"); out.Write("\tr.pos.xy += offset * r.pos.w;\n"); + out.Write("\tif (" I_TEXOFFSET"[2] != 0) {\n"); + out.Write("\tfloat texOffset = 1.0 / float(" I_TEXOFFSET"[2]);\n"); + for (unsigned int i = 0; i < bpmem.genMode.numtexgens; ++i) { - out.Write("\tr.tex%d.x += " I_LINEPTWIDTH"[2] * (" I_TEXOFFSETFLAGS"[%d] & 0x01);\n", i, i); + out.Write("\tif (((" I_TEXOFFSET"[0] >> %d) & 0x1) != 0)\n", i); + out.Write("\t\tr.tex%d.x += texOffset;\n", i); } + out.Write("\t}\n"); EmitVertex(out, "l", ApiType); EmitVertex(out, "r", ApiType); } else if (primitive_type == PRIMITIVE_POINTS) { - out.Write("VS_OUTPUT ll = f;\n"); - out.Write("VS_OUTPUT lr = f;\n"); - out.Write("VS_OUTPUT ul = f;\n"); - out.Write("VS_OUTPUT ur = f;\n"); + out.Write("\tVS_OUTPUT ll = f;\n"); + out.Write("\tVS_OUTPUT lr = f;\n"); + out.Write("\tVS_OUTPUT ul = f;\n"); + out.Write("\tVS_OUTPUT ur = f;\n"); - out.Write("ll.pos.xy += float2(-1,-1) * offset;\n"); - out.Write("lr.pos.xy += float2(1,-1) * offset;\n"); - out.Write("ul.pos.xy += float2(-1,1) * offset;\n"); - out.Write("ur.pos.xy += offset;\n"); + out.Write("\tll.pos.xy += float2(-1,-1) * offset;\n"); + out.Write("\tlr.pos.xy += float2(1,-1) * offset;\n"); + out.Write("\tul.pos.xy += float2(-1,1) * offset;\n"); + out.Write("\tur.pos.xy += offset;\n"); - out.Write("float2 texOffset = float2(" I_LINEPTWIDTH"[3], " I_LINEPTWIDTH"[3]);\n"); + out.Write("\tif (" I_TEXOFFSET"[3] != 0) {\n"); + out.Write("\tfloat2 texOffset = float2(1.0 / float(" I_TEXOFFSET"[3]), 1.0 / float(" I_TEXOFFSET"[3]));\n"); for (unsigned int i = 0; i < bpmem.genMode.numtexgens; ++i) { - out.Write("ll.tex%d.xy += float2(0,1) * texOffset * (" I_TEXOFFSETFLAGS"[%d] & 0x10);\n", i, i); - out.Write("lr.tex%d.xy += texOffset * (" I_TEXOFFSETFLAGS"[%d] & 0x10);\n", i, i); - out.Write("ur.tex%d.xy += float2(1,0) * texOffset * (" I_TEXOFFSETFLAGS"[%d] & 0x10);\n", i, i); + out.Write("\tif (((" I_TEXOFFSET"[1] >> %d) & 0x1) != 0) {\n", i); + out.Write("\t\tll.tex%d.xy += float2(0,1) * texOffset;\n", i); + out.Write("\t\tlr.tex%d.xy += texOffset;\n", i); + out.Write("\t\tur.tex%d.xy += float2(1,0) * texOffset;\n", i); + out.Write("\t}\n"); } + out.Write("\t}\n"); EmitVertex(out, "ll", ApiType); EmitVertex(out, "lr", ApiType); diff --git a/Source/Core/VideoCommon/GeometryShaderManager.cpp b/Source/Core/VideoCommon/GeometryShaderManager.cpp index 70bb151666..3d05a7161c 100644 --- a/Source/Core/VideoCommon/GeometryShaderManager.cpp +++ b/Source/Core/VideoCommon/GeometryShaderManager.cpp @@ -15,8 +15,8 @@ // track changes static bool s_projection_changed, s_viewport_changed, s_lineptwidth_changed; -static const float LINE_PT_TEX_OFFSETS[8] = { - 0.f, 0.0625f, 0.125f, 0.25f, 0.5f, 1.f, 1.f, 1.f +static const int LINE_PT_TEX_OFFSETS[8] = { + 0, 16, 8, 4, 2, 1, 1, 1 }; GeometryShaderConstants GeometryShaderManager::constants; @@ -56,16 +56,16 @@ void GeometryShaderManager::SetConstants() { if (s_lineptwidth_changed) { - constants.lineptwidth[0] = bpmem.lineptwidth.linesize / 6.f; - constants.lineptwidth[1] = bpmem.lineptwidth.pointsize / 6.f; - constants.lineptwidth[2] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff]; - constants.lineptwidth[3] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff]; + constants.lineptparams[2] = bpmem.lineptwidth.linesize / 6.f; + constants.lineptparams[3] = bpmem.lineptwidth.pointsize / 6.f; + constants.texoffset[2] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff]; + constants.texoffset[3] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff]; } if (s_viewport_changed) { - constants.viewport[0] = 2.0f * xfmem.viewport.wd; - constants.viewport[1] = -2.0f * xfmem.viewport.ht; + constants.lineptparams[0] = 2.0f * xfmem.viewport.wd; + constants.lineptparams[1] = -2.0f * xfmem.viewport.ht; } if (s_projection_changed) @@ -106,7 +106,11 @@ void GeometryShaderManager::SetLinePtWidthChanged() void GeometryShaderManager::SetTexCoordChanged(u8 texmapid) { TCoordInfo& tc = bpmem.texcoords[texmapid]; - constants.texoffsetflags[texmapid] = tc.s.line_offset + tc.s.point_offset * 2; + int bitmask = 1 << texmapid; + constants.texoffset[0] &= ~bitmask; + constants.texoffset[0] |= tc.s.line_offset << texmapid; + constants.texoffset[1] &= ~bitmask; + constants.texoffset[1] |= tc.s.point_offset << texmapid; dirty = true; } diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index d5a2438316..444abad82c 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -280,10 +280,9 @@ static inline void GenerateVSOutputStruct(T& object, API_TYPE api_type) #define I_POSTTRANSFORMMATRICES "cpostmtx" #define I_PIXELCENTERCORRECTION "cpixelcenter" -#define I_STEREOPARAMS "cstereo" -#define I_LINEPTWIDTH "clinept" -#define I_VIEWPORT "cviewport" -#define I_TEXOFFSETFLAGS "ctexoffset" +#define I_STEREOPARAMS "cstereo" +#define I_LINEPTPARAMS "clinept" +#define I_TEXOFFSET "ctexoffset" static const char s_shader_uniforms[] = "\tfloat4 " I_POSNORMALMATRIX"[6];\n" From 2850c9a206fe69e569d3458f350045ca31a2ba97 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 16 Dec 2014 01:49:29 +0100 Subject: [PATCH 13/24] VertexManager: Disable culling for lines and points. --- Source/Core/VideoBackends/D3D/VertexManager.cpp | 4 ++++ Source/Core/VideoBackends/OGL/VertexManager.cpp | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index 9f2b2ba318..f51319bb73 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -141,6 +141,7 @@ void VertexManager::Draw(u32 stride) } else if (current_primitive_type == PRIMITIVE_LINES) { + ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); D3D::stateman->SetGeometryShader(GeometryShaderCache::GetActiveShader()); @@ -151,9 +152,11 @@ void VertexManager::Draw(u32 stride) INCSTAT(stats.thisFrame.numDrawCalls); D3D::stateman->SetGeometryShader(nullptr); + ((DX11::Renderer*)g_renderer)->RestoreCull(); } else //if (current_primitive_type == PRIMITIVE_POINTS) { + ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); D3D::stateman->SetGeometryShader(GeometryShaderCache::GetActiveShader()); @@ -164,6 +167,7 @@ void VertexManager::Draw(u32 stride) INCSTAT(stats.thisFrame.numDrawCalls); D3D::stateman->SetGeometryShader(nullptr); + ((DX11::Renderer*)g_renderer)->RestoreCull(); } } diff --git a/Source/Core/VideoBackends/OGL/VertexManager.cpp b/Source/Core/VideoBackends/OGL/VertexManager.cpp index d5ff396ba0..1a162b1cde 100644 --- a/Source/Core/VideoBackends/OGL/VertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/VertexManager.cpp @@ -101,9 +101,11 @@ void VertexManager::Draw(u32 stride) { case PRIMITIVE_POINTS: primitive_mode = GL_POINTS; + glDisable(GL_CULL_FACE); break; case PRIMITIVE_LINES: primitive_mode = GL_LINES; + glDisable(GL_CULL_FACE); break; case PRIMITIVE_TRIANGLES: primitive_mode = g_ActiveConfig.backend_info.bSupportsPrimitiveRestart ? GL_TRIANGLE_STRIP : GL_TRIANGLES; @@ -120,6 +122,9 @@ void VertexManager::Draw(u32 stride) } INCSTAT(stats.thisFrame.numDrawCalls); + + if (current_primitive_type != PRIMITIVE_TRIANGLES) + ((OGL::Renderer*)g_renderer)->SetGenerationMode(); } void VertexManager::vFlush(bool useDstAlpha) From f2e52b46c3293228759d2db373a6e11c5c4513cf Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 16 Dec 2014 16:53:49 +0100 Subject: [PATCH 14/24] GeometryShaderGen: Cosmetics. --- Source/Core/VideoCommon/GeometryShaderGen.cpp | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index e10b919dd4..bf40056a8d 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -27,7 +27,7 @@ static const char* primitives_d3d[] = "triangle" }; -template static inline void EmitVertex(T& out, const char *vertex, API_TYPE ApiType); +template static inline void EmitVertex(T& out, const char* vertex, API_TYPE ApiType); template static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE ApiType) @@ -124,20 +124,20 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A // 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_LINEPTPARAMS".y * to.y > " I_LINEPTPARAMS".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_LINEPTPARAMS".z / " I_LINEPTPARAMS".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_LINEPTPARAMS".z / " I_LINEPTPARAMS".y);\n"); - out.Write("\t}\n"); + out.Write( + "\tfloat2 offset;\n" + "\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. + "\tif (" I_LINEPTPARAMS".y * to.y > " I_LINEPTPARAMS".x * to.x) {\n" + // Line is more tall. Extend geometry left and right. + // Lerp LineWidth/2 from [0..VpWidth] to [-1..1] + "\t\toffset = float2(" I_LINEPTPARAMS".z / " I_LINEPTPARAMS".x, 0);\n" + "\t} else {\n" + // Line is more wide. Extend geometry up and down. + // Lerp LineWidth/2 from [0..VpHeight] to [1..-1] + "\t\toffset = float2(0, -" I_LINEPTPARAMS".z / " I_LINEPTPARAMS".y);\n" + "\t}\n"); } else if (primitive_type == PRIMITIVE_POINTS) { @@ -168,7 +168,9 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("\tlayer = eye;\n"); } else + { 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 @@ -183,11 +185,11 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A if (primitive_type == PRIMITIVE_LINES) { - out.Write("\tVS_OUTPUT l = f;\n"); - out.Write("\tVS_OUTPUT r = f;\n"); + out.Write("\tVS_OUTPUT l = f;\n" + "\tVS_OUTPUT r = f;\n"); - out.Write("\tl.pos.xy -= offset * l.pos.w;\n"); - out.Write("\tr.pos.xy += offset * r.pos.w;\n"); + out.Write("\tl.pos.xy -= offset * l.pos.w;\n" + "\tr.pos.xy += offset * r.pos.w;\n"); out.Write("\tif (" I_TEXOFFSET"[2] != 0) {\n"); out.Write("\tfloat texOffset = 1.0 / float(" I_TEXOFFSET"[2]);\n"); @@ -204,15 +206,15 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A } else if (primitive_type == PRIMITIVE_POINTS) { - out.Write("\tVS_OUTPUT ll = f;\n"); - out.Write("\tVS_OUTPUT lr = f;\n"); - out.Write("\tVS_OUTPUT ul = f;\n"); - out.Write("\tVS_OUTPUT ur = f;\n"); + out.Write("\tVS_OUTPUT ll = f;\n" + "\tVS_OUTPUT lr = f;\n" + "\tVS_OUTPUT ul = f;\n" + "\tVS_OUTPUT ur = f;\n"); - out.Write("\tll.pos.xy += float2(-1,-1) * offset;\n"); - out.Write("\tlr.pos.xy += float2(1,-1) * offset;\n"); - out.Write("\tul.pos.xy += float2(-1,1) * offset;\n"); - out.Write("\tur.pos.xy += offset;\n"); + out.Write("\tll.pos.xy += float2(-1,-1) * offset;\n" + "\tlr.pos.xy += float2(1,-1) * offset;\n" + "\tul.pos.xy += float2(-1,1) * offset;\n" + "\tur.pos.xy += offset;\n"); out.Write("\tif (" I_TEXOFFSET"[3] != 0) {\n"); out.Write("\tfloat2 texOffset = float2(1.0 / float(" I_TEXOFFSET"[3]), 1.0 / float(" I_TEXOFFSET"[3]));\n"); @@ -245,7 +247,7 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A out.Write("\toutput.RestartStrip();\n"); if (g_ActiveConfig.iStereoMode > 0 && !g_ActiveConfig.backend_info.bSupportsGSInstancing) - out.Write("\t}\n"); + out.Write("\t}\n"); out.Write("}\n"); @@ -257,7 +259,7 @@ 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) +static inline void EmitVertex(T& out, const char* vertex, API_TYPE ApiType) { if (ApiType == API_OPENGL) out.Write("\tgl_Position = %s.pos;\n", vertex); From bd6d22973381b43369670300a707e86084c040e0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 16 Dec 2014 17:28:35 +0100 Subject: [PATCH 15/24] GeometryShader: Disable the geometry shader stage if it is a pass-through shader. --- Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp | 11 ++++++++++- Source/Core/VideoBackends/D3D/GeometryShaderCache.h | 1 + Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp | 3 ++- Source/Core/VideoCommon/GeometryShaderGen.cpp | 6 ++++++ Source/Core/VideoCommon/GeometryShaderGen.h | 1 + 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp index bed0ff95b7..7088cd70f5 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -28,6 +28,7 @@ GeometryShaderCache::GSCache GeometryShaderCache::GeometryShaders; const GeometryShaderCache::GSCacheEntry* GeometryShaderCache::last_entry; GeometryShaderUid GeometryShaderCache::last_uid; UidChecker GeometryShaderCache::geometry_uid_checker; +const GeometryShaderCache::GSCacheEntry GeometryShaderCache::pass_entry; ID3D11GeometryShader* ClearGeometryShader = nullptr; ID3D11GeometryShader* CopyGeometryShader = nullptr; @@ -203,12 +204,20 @@ bool GeometryShaderCache::SetShader(u32 primitive_type) if (uid == last_uid) { GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE,true); - return (last_entry->shader != nullptr); + return true; } } last_uid = uid; + // Check if the shader is a pass-through shader + if (IsPassthroughGeometryShader(uid)) + { + // Return the default pass-through shader + last_entry = &pass_entry; + return true; + } + // Check if the shader is already in the cache GSCache::iterator iter; iter = GeometryShaders.find(uid); diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h index fe4aea4a36..d88b88f4ae 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.h +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.h @@ -43,6 +43,7 @@ private: static GSCache GeometryShaders; static const GSCacheEntry* last_entry; static GeometryShaderUid last_uid; + static const GSCacheEntry pass_entry; static UidChecker geometry_uid_checker; }; diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index d2ec0d049b..8f90aff28a 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -211,7 +211,8 @@ SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components ShaderCode gcode; GenerateVertexShaderCode(vcode, components, API_OPENGL); GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components); - GenerateGeometryShaderCode(gcode, primitive_type, API_OPENGL); + if (!IsPassthroughGeometryShader(uid.guid)) + GenerateGeometryShaderCode(gcode, primitive_type, API_OPENGL); if (g_ActiveConfig.bEnableShaderDebugging) { diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index bf40056a8d..3d478a6a4d 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -281,3 +281,9 @@ void GenerateGeometryShaderCode(ShaderCode& object, u32 primitive_type, API_TYPE { GenerateGeometryShader(object, primitive_type, ApiType); } + +bool IsPassthroughGeometryShader(GeometryShaderUid& object) +{ + geometry_shader_uid_data* uid_data = object.GetUidData(); + return uid_data->primitive_type == PRIMITIVE_TRIANGLES && !uid_data->stereo; +} diff --git a/Source/Core/VideoCommon/GeometryShaderGen.h b/Source/Core/VideoCommon/GeometryShaderGen.h index 93e222b25e..0f66f7a4f9 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.h +++ b/Source/Core/VideoCommon/GeometryShaderGen.h @@ -25,3 +25,4 @@ typedef ShaderUid GeometryShaderUid; void GenerateGeometryShaderCode(ShaderCode& object, u32 primitive_type, API_TYPE ApiType); void GetGeometryShaderUid(GeometryShaderUid& object, u32 primitive_type, API_TYPE ApiType); +bool IsPassthroughGeometryShader(GeometryShaderUid& object); From 782a5adb947ef5e4c961580047ff17aea70f3d0f Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 16 Dec 2014 23:52:42 +0100 Subject: [PATCH 16/24] VideoCommon: Pass interface blocks between shader stages to resolve naming conflicts. --- Source/Core/VideoCommon/GeometryShaderGen.cpp | 64 ++++++++++++------- Source/Core/VideoCommon/PixelShaderGen.cpp | 19 +++--- Source/Core/VideoCommon/VertexShaderGen.cpp | 4 +- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 3d478a6a4d..4a6b4dce55 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -87,18 +87,24 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A if (g_ActiveConfig.backend_info.bSupportsGSInstancing) out.Write("#define InstanceID gl_InvocationID\n"); - out.Write("centroid in VS_OUTPUT o[%d];\n", vertex_in); - out.Write("centroid out VS_OUTPUT vs;\n"); + out.Write("in VertexData {\n"); + out.Write("\tcentroid VS_OUTPUT o;\n"); + out.Write("} vs[%d];\n", vertex_in); + + out.Write("out VertexData {\n"); + out.Write("\tcentroid VS_OUTPUT o;\n"); if (g_ActiveConfig.iStereoMode > 0) - out.Write("flat out int layer;\n"); + out.Write("\tflat int layer;\n"); + + out.Write("} ps;\n"); out.Write("void main()\n{\n"); } else // D3D { - out.Write("struct GS_OUTPUT {\n"); - out.Write("\tVS_OUTPUT vs;\n"); + out.Write("struct VertexData {\n"); + out.Write("\tVS_OUTPUT o;\n"); if (g_ActiveConfig.iStereoMode > 0) out.Write("\tuint layer : SV_RenderTargetArrayIndex;\n"); @@ -108,25 +114,36 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A if (g_ActiveConfig.backend_info.bSupportsGSInstancing) { 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); + 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("[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("void main(%s VS_OUTPUT o[%d], inout TriangleStream output)\n{\n", primitives_d3d[primitive_type], vertex_in); } - out.Write("\tGS_OUTPUT gs;\n"); + out.Write("\tVertexData ps;\n"); } if (primitive_type == PRIMITIVE_LINES) { + if (ApiType == API_OPENGL) + { + out.Write("\tVS_OUTPUT start = vs[0].o;\n"); + out.Write("\tVS_OUTPUT end = vs[1].o;\n"); + } + else + { + out.Write("\tVS_OUTPUT start = o[0];\n"); + out.Write("\tVS_OUTPUT end = o[1];\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. out.Write( "\tfloat2 offset;\n" - "\tfloat2 to = abs(o[1].pos.xy - o[0].pos.xy);\n" + "\tfloat2 to = abs(end.pos.xy - start.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. "\tif (" I_LINEPTPARAMS".y * to.y > " I_LINEPTPARAMS".x * to.x) {\n" @@ -141,9 +158,14 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A } else if (primitive_type == PRIMITIVE_POINTS) { + if (ApiType == API_OPENGL) + out.Write("\tVS_OUTPUT point = vs[0].o;\n"); + else + out.Write("\tVS_OUTPUT point = o[0];\n"); + // Offset from center to upper right vertex // Lerp PointSize/2 from [0,0..VpWidth,VpHeight] to [-1,1..1,-1] - out.Write("float2 offset = float2(" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".x, -" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".y) * o[0].pos.w;\n"); + out.Write("float2 offset = float2(" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".x, -" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".y) * point.pos.w;\n"); } if (g_ActiveConfig.iStereoMode > 0) @@ -157,20 +179,18 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A } out.Write("\tfor (int i = 0; i < %d; ++i) {\n", vertex_in); - out.Write("\tVS_OUTPUT f = o[i];\n"); + + if (ApiType == API_OPENGL) + out.Write("\tVS_OUTPUT f = vs[i].o;\n"); + else + out.Write("\tVS_OUTPUT f = o[i];\n"); if (g_ActiveConfig.iStereoMode > 0) { // Select the output layer + out.Write("\tps.layer = eye;\n"); if (ApiType == API_OPENGL) - { out.Write("\tgl_Layer = eye;\n"); - out.Write("\tlayer = eye;\n"); - } - else - { - 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 @@ -179,8 +199,8 @@ 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("\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"); + out.Write("\tf.clipPos.x += " I_STEREOPARAMS"[eye] * (f.clipPos.w - " I_STEREOPARAMS"[2]);\n"); + out.Write("\tf.pos.x += " I_STEREOPARAMS"[eye] * (f.pos.w - " I_STEREOPARAMS"[2]);\n"); } if (primitive_type == PRIMITIVE_LINES) @@ -264,12 +284,12 @@ 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); + out.Write("\tps.o = %s;\n", vertex); if (ApiType == API_OPENGL) out.Write("\tEmitVertex();\n"); else - out.Write("\toutput.Append(gs);\n"); + out.Write("\toutput.Append(ps);\n"); } void GetGeometryShaderUid(GeometryShaderUid& object, u32 primitive_type, API_TYPE ApiType) diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 742f9c0a60..06d9893a71 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -316,11 +316,14 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T // As a workaround, we interpolate at the centroid of the coveraged pixel, which // is always inside the primitive. // Without MSAA, this flag is defined to have no effect. - out.Write("centroid in VS_OUTPUT vs;\n"); - uid_data->stereo = g_ActiveConfig.iStereoMode > 0; + out.Write("in VertexData {\n"); + out.Write("\tcentroid VS_OUTPUT o;\n"); + if (g_ActiveConfig.iStereoMode > 0) - out.Write("flat in int layer;\n"); + out.Write("\tflat int layer;\n"); + + out.Write("};\n"); out.Write("void main()\n{\n"); @@ -328,18 +331,18 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T // Let's set up attributes for (unsigned int i = 0; i < numTexgen; ++i) { - out.Write("\tfloat3 uv%d = vs.tex%d;\n", i, i); + out.Write("\tfloat3 uv%d = o.tex%d;\n", i, i); } - out.Write("\tfloat4 clipPos = vs.clipPos;\n"); + out.Write("\tfloat4 clipPos = o.clipPos;\n"); if (g_ActiveConfig.bEnablePixelLighting) { - out.Write("\tfloat4 Normal = vs.Normal;\n"); + out.Write("\tfloat4 Normal = o.Normal;\n"); } // On Mali, global variables must be initialized as constants. // This is why we initialize these variables locally instead. - out.Write("\tfloat4 colors_0 = vs.colors_0;\n"); - out.Write("\tfloat4 colors_1 = vs.colors_1;\n"); + out.Write("\tfloat4 colors_0 = o.colors_0;\n"); + out.Write("\tfloat4 colors_1 = o.colors_1;\n"); out.Write("\tfloat4 rawpos = gl_FragCoord;\n"); } diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 80e025386f..83fbddf2d9 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -72,7 +72,9 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ out.Write("in float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i); } - out.Write("centroid out VS_OUTPUT o;\n"); + out.Write("out VertexData {\n" + "\tcentroid VS_OUTPUT o;\n" + "};\n"); out.Write("void main()\n{\n"); } From 7e8f96f0d3649f20483a639ac37f489737cba500 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 17 Dec 2014 00:26:03 +0100 Subject: [PATCH 17/24] OGL: Don't generate a geometry shader if the backend doesn't support it. This commit repurposes the bSupportsStereoscopy flag as the bSupportsGeometryShaders flag. --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 2 +- Source/Core/VideoBackends/D3D/main.cpp | 2 +- Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp | 2 +- Source/Core/VideoBackends/OGL/Render.cpp | 10 +++++----- Source/Core/VideoBackends/OGL/main.cpp | 2 +- Source/Core/VideoCommon/VideoConfig.cpp | 2 +- Source/Core/VideoCommon/VideoConfig.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 6ccba4251d..c1a26c2387 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -449,7 +449,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con // - stereoscopy - if (vconfig.backend_info.bSupportsStereoscopy && vconfig.iStereoMode > 0) + if (vconfig.backend_info.bSupportsGeometryShaders && vconfig.iStereoMode > 0) { wxFlexGridSizer* const szr_stereo = new wxFlexGridSizer(2, 5, 5); diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 0126ab8b1d..6652d6bc57 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -80,7 +80,7 @@ void InitBackendInfo() g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsOversizedViewports = false; - g_Config.backend_info.bSupportsStereoscopy = true; + g_Config.backend_info.bSupportsGeometryShaders = true; g_Config.backend_info.bSupports3DVision = true; IDXGIFactory* factory; diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 8f90aff28a..14f5f94c82 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -211,7 +211,7 @@ SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components ShaderCode gcode; GenerateVertexShaderCode(vcode, components, API_OPENGL); GeneratePixelShaderCode(pcode, dstAlphaMode, API_OPENGL, components); - if (!IsPassthroughGeometryShader(uid.guid)) + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders && !IsPassthroughGeometryShader(uid.guid)) GenerateGeometryShaderCode(gcode, primitive_type, API_OPENGL); if (g_ActiveConfig.bEnableShaderDebugging) diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index b717e3cf35..8658f92894 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -498,7 +498,7 @@ Renderer::Renderer() { g_ogl_config.eSupportedGLSLVersion = GLSLES_300; g_ogl_config.bSupportsAEP = false; - g_Config.backend_info.bSupportsStereoscopy = false; + g_Config.backend_info.bSupportsGeometryShaders = false; } else { @@ -506,7 +506,7 @@ Renderer::Renderer() g_ogl_config.bSupportsAEP = GLExtensions::Supports("GL_ANDROID_extension_pack_es31a"); g_Config.backend_info.bSupportsBindingLayout = true; g_Config.backend_info.bSupportsEarlyZ = true; - g_Config.backend_info.bSupportsStereoscopy = g_ogl_config.bSupportsAEP; + g_Config.backend_info.bSupportsGeometryShaders = g_ogl_config.bSupportsAEP; } } else @@ -522,13 +522,13 @@ Renderer::Renderer() { g_ogl_config.eSupportedGLSLVersion = GLSL_130; g_Config.backend_info.bSupportsEarlyZ = false; // layout keyword is only supported on glsl150+ - g_Config.backend_info.bSupportsStereoscopy = false; // geometry shaders are only supported on glsl150+ + g_Config.backend_info.bSupportsGeometryShaders = false; // geometry shaders are only supported on glsl150+ } else if (strstr(g_ogl_config.glsl_version, "1.40")) { g_ogl_config.eSupportedGLSLVersion = GLSL_140; g_Config.backend_info.bSupportsEarlyZ = false; // layout keyword is only supported on glsl150+ - g_Config.backend_info.bSupportsStereoscopy = false; // geometry shaders are only supported on glsl150+ + g_Config.backend_info.bSupportsGeometryShaders = false; // geometry shaders are only supported on glsl150+ } else { @@ -565,7 +565,7 @@ Renderer::Renderer() bSuccess = false; } - if (g_Config.iStereoMode > 0 && !g_Config.backend_info.bSupportsStereoscopy) + if (g_Config.iStereoMode > 0 && !g_Config.backend_info.bSupportsGeometryShaders) OSD::AddMessage("Stereoscopic 3D isn't supported by your GPU, support for OpenGL 3.2 is required.", 10000); if (!bSuccess) diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index addfcf0533..c4c966458e 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -139,7 +139,7 @@ static void InitBackendInfo() //g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu dependent and must be set in renderer //g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer g_Config.backend_info.bSupportsOversizedViewports = true; - g_Config.backend_info.bSupportsStereoscopy = true; + g_Config.backend_info.bSupportsGeometryShaders = true; g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.Adapters.clear(); diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 2b6025f13e..d0f02dd327 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -214,7 +214,7 @@ void VideoConfig::VerifyValidity() // TODO: Check iMaxAnisotropy value if (iAdapter < 0 || iAdapter > ((int)backend_info.Adapters.size() - 1)) iAdapter = 0; if (iMultisampleMode < 0 || iMultisampleMode >= (int)backend_info.AAModes.size()) iMultisampleMode = 0; - if (!backend_info.bSupportsStereoscopy) iStereoMode = 0; + if (!backend_info.bSupportsGeometryShaders) iStereoMode = 0; } void VideoConfig::Save(const std::string& ini_file) diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index fa5a52772b..f27b1b2116 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -151,7 +151,7 @@ struct VideoConfig final bool bSupportsDualSourceBlend; bool bSupportsPrimitiveRestart; bool bSupportsOversizedViewports; - bool bSupportsStereoscopy; + bool bSupportsGeometryShaders; bool bSupports3DVision; bool bSupportsEarlyZ; // needed by PixelShaderGen, so must stay in VideoCommon bool bSupportsBindingLayout; // Needed by ShaderGen, so must stay in VideoCommon From 3d9dfad6a229f03948620b97f7e3b48e80784b3c Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 17 Dec 2014 03:05:23 +0100 Subject: [PATCH 18/24] D3D: Set the geometry shader before every draw call. And refactor the VertexManager draw call. --- Source/Core/VideoBackends/D3D/D3DUtil.cpp | 1 + .../VideoBackends/D3D/PSTextureEncoder.cpp | 1 + Source/Core/VideoBackends/D3D/Render.cpp | 5 +- .../Core/VideoBackends/D3D/VertexManager.cpp | 53 ++++++------------- Source/Core/VideoBackends/D3D/XFBEncoder.cpp | 1 + 5 files changed, 22 insertions(+), 39 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DUtil.cpp b/Source/Core/VideoBackends/D3D/D3DUtil.cpp index 50eac8665b..ad9acc809f 100644 --- a/Source/Core/VideoBackends/D3D/D3DUtil.cpp +++ b/Source/Core/VideoBackends/D3D/D3DUtil.cpp @@ -350,6 +350,7 @@ int CD3DFont::DrawTextScaled(float x, float y, float size, float spacing, u32 dw D3D::stateman->SetPixelShader(m_pshader); D3D::stateman->SetVertexShader(m_vshader); + D3D::stateman->SetGeometryShader(nullptr); D3D::stateman->SetInputLayout(m_InputLayout); D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); diff --git a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp index fcc40cc9e5..0ca9ee2211 100644 --- a/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/PSTextureEncoder.cpp @@ -1084,6 +1084,7 @@ size_t PSTextureEncoder::Encode(u8* dst, unsigned int dstFormat, #endif { D3D::stateman->SetVertexShader(m_vShader); + D3D::stateman->SetGeometryShader(nullptr); D3D::stateman->PushBlendState(m_efbEncodeBlendState); D3D::stateman->PushDepthState(m_efbEncodeDepthState); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 840725fb53..3c2712fbf7 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -1105,13 +1105,14 @@ void Renderer::ApplyState(bool bUseDstAlpha) } ID3D11Buffer* vertexConstants = VertexShaderCache::GetConstantBuffer(); - ID3D11Buffer* pixelConstants = PixelShaderCache::GetConstantBuffer(); - D3D::stateman->SetPixelConstants(pixelConstants, g_ActiveConfig.bEnablePixelLighting ? vertexConstants : nullptr); + D3D::stateman->SetPixelConstants(PixelShaderCache::GetConstantBuffer(), g_ActiveConfig.bEnablePixelLighting ? vertexConstants : nullptr); D3D::stateman->SetVertexConstants(vertexConstants); + D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); D3D::stateman->SetPixelShader(PixelShaderCache::GetActiveShader()); D3D::stateman->SetVertexShader(VertexShaderCache::GetActiveShader()); + D3D::stateman->SetGeometryShader(GeometryShaderCache::GetActiveShader()); } void Renderer::RestoreState() diff --git a/Source/Core/VideoBackends/D3D/VertexManager.cpp b/Source/Core/VideoBackends/D3D/VertexManager.cpp index f51319bb73..5a15ca2a0b 100644 --- a/Source/Core/VideoBackends/D3D/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/VertexManager.cpp @@ -126,49 +126,28 @@ void VertexManager::Draw(u32 stride) u32 baseVertex = m_vertexDrawOffset / stride; u32 startIndex = m_indexDrawOffset / sizeof(u16); - if (current_primitive_type == PRIMITIVE_TRIANGLES) + switch (current_primitive_type) { - D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); - D3D::stateman->SetGeometryShader(GeometryShaderCache::GetActiveShader()); - - D3D::stateman->Apply(); - D3D::context->DrawIndexed(indices, startIndex, baseVertex); - - INCSTAT(stats.thisFrame.numDrawCalls); - - D3D::stateman->SetGeometryShader(nullptr); + case PRIMITIVE_POINTS: + D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); + break; + case PRIMITIVE_LINES: + D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); + ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); + break; + case PRIMITIVE_TRIANGLES: + D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + break; } - else if (current_primitive_type == PRIMITIVE_LINES) - { - ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); - D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); - D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); - D3D::stateman->SetGeometryShader(GeometryShaderCache::GetActiveShader()); - D3D::stateman->Apply(); - D3D::context->DrawIndexed(indices, startIndex, baseVertex); + D3D::stateman->Apply(); + D3D::context->DrawIndexed(indices, startIndex, baseVertex); - INCSTAT(stats.thisFrame.numDrawCalls); + INCSTAT(stats.thisFrame.numDrawCalls); - D3D::stateman->SetGeometryShader(nullptr); + if (current_primitive_type != PRIMITIVE_TRIANGLES) ((DX11::Renderer*)g_renderer)->RestoreCull(); - } - else //if (current_primitive_type == PRIMITIVE_POINTS) - { - ((DX11::Renderer*)g_renderer)->ApplyCullDisable(); - D3D::stateman->SetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - D3D::stateman->SetGeometryConstants(GeometryShaderCache::GetConstantBuffer()); - D3D::stateman->SetGeometryShader(GeometryShaderCache::GetActiveShader()); - - D3D::stateman->Apply(); - D3D::context->DrawIndexed(indices, startIndex, baseVertex); - - INCSTAT(stats.thisFrame.numDrawCalls); - - D3D::stateman->SetGeometryShader(nullptr); - ((DX11::Renderer*)g_renderer)->RestoreCull(); - } } void VertexManager::vFlush(bool useDstAlpha) diff --git a/Source/Core/VideoBackends/D3D/XFBEncoder.cpp b/Source/Core/VideoBackends/D3D/XFBEncoder.cpp index fb56363e31..955fb38bc8 100644 --- a/Source/Core/VideoBackends/D3D/XFBEncoder.cpp +++ b/Source/Core/VideoBackends/D3D/XFBEncoder.cpp @@ -282,6 +282,7 @@ void XFBEncoder::Encode(u8* dst, u32 width, u32 height, const EFBRectangle& srcR D3D::stateman->SetPixelShader(m_pShader); D3D::stateman->SetVertexShader(m_vShader); + D3D::stateman->SetGeometryShader(nullptr); D3D::stateman->PushBlendState(m_xfbEncodeBlendState); D3D::stateman->PushDepthState(m_xfbEncodeDepthState); From 1af3d8447a47ea7a8be86060ca879cafe1c57824 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 17 Dec 2014 03:11:23 +0100 Subject: [PATCH 19/24] GeometryShaderManager: Set the constants within the callbacks. --- .../VideoCommon/GeometryShaderManager.cpp | 80 ++++++------------- .../Core/VideoCommon/GeometryShaderManager.h | 3 - Source/Core/VideoCommon/VertexManagerBase.cpp | 1 - 3 files changed, 26 insertions(+), 58 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderManager.cpp b/Source/Core/VideoCommon/GeometryShaderManager.cpp index 3d05a7161c..2ca0965343 100644 --- a/Source/Core/VideoCommon/GeometryShaderManager.cpp +++ b/Source/Core/VideoCommon/GeometryShaderManager.cpp @@ -12,9 +12,6 @@ #include "VideoCommon/VideoConfig.h" #include "VideoCommon/XFMemory.h" -// track changes -static bool s_projection_changed, s_viewport_changed, s_lineptwidth_changed; - static const int LINE_PT_TEX_OFFSETS[8] = { 0, 16, 8, 4, 2, 1, 1, 1 }; @@ -35,72 +32,47 @@ void GeometryShaderManager::Shutdown() void GeometryShaderManager::Dirty() { - s_projection_changed = true; - s_viewport_changed = true; - s_lineptwidth_changed = true; + SetViewportChanged(); + SetProjectionChanged(); + SetLinePtWidthChanged(); - SetTexCoordChanged(0); - SetTexCoordChanged(1); - SetTexCoordChanged(2); - SetTexCoordChanged(3); - SetTexCoordChanged(4); - SetTexCoordChanged(5); - SetTexCoordChanged(6); - SetTexCoordChanged(7); - - dirty = true; -} - -// Syncs the shader constant buffers with xfmem -void GeometryShaderManager::SetConstants() -{ - if (s_lineptwidth_changed) - { - constants.lineptparams[2] = bpmem.lineptwidth.linesize / 6.f; - constants.lineptparams[3] = bpmem.lineptwidth.pointsize / 6.f; - constants.texoffset[2] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff]; - constants.texoffset[3] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff]; - } - - if (s_viewport_changed) - { - constants.lineptparams[0] = 2.0f * xfmem.viewport.wd; - constants.lineptparams[1] = -2.0f * xfmem.viewport.ht; - } - - if (s_projection_changed) - { - s_projection_changed = false; - - if (g_ActiveConfig.iStereoMode > 0 && xfmem.projection.type == GX_PERSPECTIVE) - { - float offset = (g_ActiveConfig.iStereoSeparation / 1000.0f) * (g_ActiveConfig.iStereoSeparationPercent / 100.0f); - constants.stereoparams[0] = (g_ActiveConfig.bStereoSwapEyes) ? offset : -offset; - constants.stereoparams[1] = (g_ActiveConfig.bStereoSwapEyes) ? -offset : offset; - constants.stereoparams[2] = (g_ActiveConfig.iStereoConvergence / 10.0f) * (g_ActiveConfig.iStereoConvergencePercent / 100.0f); - } - else - { - constants.stereoparams[0] = constants.stereoparams[1] = 0; - } - } + for (int i = 0; i < 8; i++) + SetTexCoordChanged(i); dirty = true; } void GeometryShaderManager::SetViewportChanged() { - s_viewport_changed = true; + constants.lineptparams[0] = 2.0f * xfmem.viewport.wd; + constants.lineptparams[1] = -2.0f * xfmem.viewport.ht; + dirty = true; } void GeometryShaderManager::SetProjectionChanged() { - s_projection_changed = true; + if (g_ActiveConfig.iStereoMode > 0 && xfmem.projection.type == GX_PERSPECTIVE) + { + float offset = (g_ActiveConfig.iStereoSeparation / 1000.0f) * (g_ActiveConfig.iStereoSeparationPercent / 100.0f); + constants.stereoparams[0] = (g_ActiveConfig.bStereoSwapEyes) ? offset : -offset; + constants.stereoparams[1] = (g_ActiveConfig.bStereoSwapEyes) ? -offset : offset; + constants.stereoparams[2] = (g_ActiveConfig.iStereoConvergence / 10.0f) * (g_ActiveConfig.iStereoConvergencePercent / 100.0f); + } + else + { + constants.stereoparams[0] = constants.stereoparams[1] = 0; + } + + dirty = true; } void GeometryShaderManager::SetLinePtWidthChanged() { - s_lineptwidth_changed = true; + constants.lineptparams[2] = bpmem.lineptwidth.linesize / 6.f; + constants.lineptparams[3] = bpmem.lineptwidth.pointsize / 6.f; + constants.texoffset[2] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.lineoff]; + constants.texoffset[3] = LINE_PT_TEX_OFFSETS[bpmem.lineptwidth.pointoff]; + dirty = true; } void GeometryShaderManager::SetTexCoordChanged(u8 texmapid) diff --git a/Source/Core/VideoCommon/GeometryShaderManager.h b/Source/Core/VideoCommon/GeometryShaderManager.h index 86cd3ee2ea..eab036fd7e 100644 --- a/Source/Core/VideoCommon/GeometryShaderManager.h +++ b/Source/Core/VideoCommon/GeometryShaderManager.h @@ -18,9 +18,6 @@ public: static void Shutdown(); static void DoState(PointerWrap &p); - // constant management - static void SetConstants(); - static void SetViewportChanged(); static void SetProjectionChanged(); static void SetLinePtWidthChanged(); diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 7484039137..b1bc049fe5 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -224,7 +224,6 @@ void VertexManager::Flush() // set global constants VertexShaderManager::SetConstants(); PixelShaderManager::SetConstants(); - GeometryShaderManager::SetConstants(); bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && From 69df23f725205a4bcd10c6315f2421d3041e614e Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 17 Dec 2014 09:18:40 +0100 Subject: [PATCH 20/24] VideoCommon: Only use interface blocks when geometry shaders are supported. --- .../Core/VideoCommon/GeometryShaderManager.cpp | 2 -- Source/Core/VideoCommon/PixelShaderGen.cpp | 17 ++++++++++++----- Source/Core/VideoCommon/VertexShaderGen.cpp | 13 ++++++++++--- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderManager.cpp b/Source/Core/VideoCommon/GeometryShaderManager.cpp index 2ca0965343..09adad56c0 100644 --- a/Source/Core/VideoCommon/GeometryShaderManager.cpp +++ b/Source/Core/VideoCommon/GeometryShaderManager.cpp @@ -88,8 +88,6 @@ void GeometryShaderManager::SetTexCoordChanged(u8 texmapid) void GeometryShaderManager::DoState(PointerWrap &p) { - p.Do(dirty); - if (p.GetMode() == PointerWrap::MODE_READ) { // Reload current state from global GPU state diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 06d9893a71..8557f9e98b 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -317,13 +317,20 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T // is always inside the primitive. // Without MSAA, this flag is defined to have no effect. uid_data->stereo = g_ActiveConfig.iStereoMode > 0; - out.Write("in VertexData {\n"); - out.Write("\tcentroid VS_OUTPUT o;\n"); + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + out.Write("in VertexData {\n"); + out.Write("\tcentroid VS_OUTPUT o;\n"); - if (g_ActiveConfig.iStereoMode > 0) - out.Write("\tflat int layer;\n"); + if (g_ActiveConfig.iStereoMode > 0) + out.Write("\tflat int layer;\n"); - out.Write("};\n"); + out.Write("};\n"); + } + else + { + out.Write("centroid in VS_OUTPUT o;\n"); + } out.Write("void main()\n{\n"); diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 83fbddf2d9..bd033967ee 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -72,9 +72,16 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ out.Write("in float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i); } - out.Write("out VertexData {\n" - "\tcentroid VS_OUTPUT o;\n" - "};\n"); + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + out.Write("out VertexData {\n" + "\tcentroid VS_OUTPUT o;\n" + "};\n"); + } + else + { + out.Write("centroid out VS_OUTPUT o; \n"); + } out.Write("void main()\n{\n"); } From 93ce95b48ea0eab19725335c449722d142551d63 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 17 Dec 2014 09:37:29 +0100 Subject: [PATCH 21/24] D3D: Use ROUND_UP macro for rounding buffer sizes. --- Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp | 2 +- Source/Core/VideoBackends/D3D/PixelShaderCache.cpp | 2 +- Source/Core/VideoBackends/D3D/VertexShaderCache.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp index 7088cd70f5..9a9da67b63 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -132,7 +132,7 @@ const char copy_shader_code[] = { void GeometryShaderCache::Init() { - unsigned int gbsize = ((sizeof(GeometryShaderConstants))&(~0xf)) + 0x10; // must be a multiple of 16 + unsigned int gbsize = ROUND_UP(sizeof(GeometryShaderConstants), 16); // must be a multiple of 16 D3D11_BUFFER_DESC gbdesc = CD3D11_BUFFER_DESC(gbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); HRESULT hr = D3D::device->CreateBuffer(&gbdesc, nullptr, &gscbuf); CHECK(hr == S_OK, "Create geometry shader constant buffer (size=%u)", gbsize); diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp index d8fbd62158..ae1919c91e 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp @@ -432,7 +432,7 @@ public: void PixelShaderCache::Init() { - unsigned int cbsize = ((sizeof(PixelShaderConstants))&(~0xf))+0x10; // must be a multiple of 16 + unsigned int cbsize = ROUND_UP(sizeof(PixelShaderConstants), 16); // must be a multiple of 16 D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); D3D::device->CreateBuffer(&cbdesc, nullptr, &pscbuf); CHECK(pscbuf!=nullptr, "Create pixel shader constant buffer"); diff --git a/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp b/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp index 9dfd87691e..54c103c36f 100644 --- a/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/VertexShaderCache.cpp @@ -115,7 +115,7 @@ void VertexShaderCache::Init() { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - unsigned int cbsize = ((sizeof(VertexShaderConstants))&(~0xf))+0x10; // must be a multiple of 16 + unsigned int cbsize = ROUND_UP(sizeof(VertexShaderConstants), 16); // must be a multiple of 16 D3D11_BUFFER_DESC cbdesc = CD3D11_BUFFER_DESC(cbsize, D3D11_BIND_CONSTANT_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE); HRESULT hr = D3D::device->CreateBuffer(&cbdesc, nullptr, &vscbuf); CHECK(hr==S_OK, "Create vertex shader constant buffer (size=%u)", cbsize); From 1f84f4632d161a798e7408e8ca28b1f58ef75e60 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 17 Dec 2014 23:33:54 +0100 Subject: [PATCH 22/24] OGL: Check OpenGL version for geometry shader support. --- Source/Core/VideoBackends/OGL/Render.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 8658f92894..571f3edd87 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -476,6 +476,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsEarlyZ = GLExtensions::Supports("GL_ARB_shader_image_load_store"); g_Config.backend_info.bSupportsBBox = GLExtensions::Supports("GL_ARB_shader_storage_buffer_object"); g_Config.backend_info.bSupportsGSInstancing = GLExtensions::Supports("GL_ARB_gpu_shader5"); + g_Config.backend_info.bSupportsGeometryShaders = (GLExtensions::Version() >= 320); // Desktop OpenGL supports the binding layout if it supports 420pack // OpenGL ES 3.1 supports it implicitly without an extension From 8dc3653ac9ec07040c8bcd0748c8040cf831d632 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 17 Dec 2014 23:44:05 +0100 Subject: [PATCH 23/24] VideoCommon: Don't pass structs between shader stages when geometry shaders are unsupported. --- Source/Core/VideoCommon/PixelShaderGen.cpp | 39 ++++++++++++++------- Source/Core/VideoCommon/VertexShaderGen.cpp | 30 +++++++++++++++- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 8557f9e98b..77f24d115c 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -329,27 +329,42 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T } else { - out.Write("centroid in VS_OUTPUT o;\n"); + out.Write("centroid in float4 colors_02;\n"); + out.Write("centroid in float4 colors_12;\n"); + // compute window position if needed because binding semantic WPOS is not widely supported + // Let's set up attributes + for (unsigned int i = 0; i < numTexgen; ++i) + { + out.Write("centroid in float3 uv%d;\n", i); + } + out.Write("centroid in float4 clipPos;\n"); + if (g_ActiveConfig.bEnablePixelLighting) + { + out.Write("centroid in float4 Normal;\n"); + } } out.Write("void main()\n{\n"); - // compute window position if needed because binding semantic WPOS is not widely supported - // Let's set up attributes - for (unsigned int i = 0; i < numTexgen; ++i) + if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) { - out.Write("\tfloat3 uv%d = o.tex%d;\n", i, i); - } - out.Write("\tfloat4 clipPos = o.clipPos;\n"); - if (g_ActiveConfig.bEnablePixelLighting) - { - out.Write("\tfloat4 Normal = o.Normal;\n"); + // compute window position if needed because binding semantic WPOS is not widely supported + // Let's set up attributes + for (unsigned int i = 0; i < numTexgen; ++i) + { + out.Write("\tfloat3 uv%d = o.tex%d;\n", i, i); + } + out.Write("\tfloat4 clipPos = o.clipPos;\n"); + if (g_ActiveConfig.bEnablePixelLighting) + { + out.Write("\tfloat4 Normal = o.Normal;\n"); + } } // On Mali, global variables must be initialized as constants. // This is why we initialize these variables locally instead. - out.Write("\tfloat4 colors_0 = o.colors_0;\n"); - out.Write("\tfloat4 colors_1 = o.colors_1;\n"); + out.Write("\tfloat4 colors_0 = %s;\n", g_ActiveConfig.backend_info.bSupportsGeometryShaders ? "o.colors_0" : "colors_02"); + out.Write("\tfloat4 colors_1 = %s;\n", g_ActiveConfig.backend_info.bSupportsGeometryShaders ? "o.colors_1" : "colors_12"); out.Write("\tfloat4 rawpos = gl_FragCoord;\n"); } diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index bd033967ee..123f137ff2 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -80,10 +80,25 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ } else { - out.Write("centroid out VS_OUTPUT o; \n"); + // Let's set up attributes + for (size_t i = 0; i < 8; ++i) + { + if (i < xfmem.numTexGen.numTexGens) + { + out.Write("centroid out float3 uv%d;\n", i); + } + } + out.Write("centroid out float4 clipPos;\n"); + if (g_ActiveConfig.bEnablePixelLighting) + out.Write("centroid out float4 Normal;\n"); + out.Write("centroid out float4 colors_02;\n"); + out.Write("centroid out float4 colors_12;\n"); } out.Write("void main()\n{\n"); + + if (!g_ActiveConfig.backend_info.bSupportsGeometryShaders) + out.Write("VS_OUTPUT o;\n"); } else // D3D { @@ -369,6 +384,19 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ if (api_type == API_OPENGL) { + if (!g_ActiveConfig.backend_info.bSupportsGeometryShaders) + { + // TODO: Pass structs between shader stages even if geometry shaders + // are not supported, however that will break GL 3.0 and 3.1 support. + for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i) + out.Write("uv%d.xyz = o.tex%d;\n", i, i); + out.Write("clipPos = o.clipPos;\n"); + if (g_ActiveConfig.bEnablePixelLighting) + out.Write("Normal = o.Normal;\n"); + out.Write("colors_02 = o.colors_0;\n"); + out.Write("colors_12 = o.colors_1;\n"); + } + out.Write("gl_Position = o.pos;\n"); } else // D3D From e7e8a4f1cb3d1c7801c18f4d3ff5cae797d5f5b3 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Thu, 18 Dec 2014 19:53:53 +0100 Subject: [PATCH 24/24] GeometryShaderGen: Don't use the reserved keyword "point" in D3D. --- Source/Core/VideoCommon/GeometryShaderGen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 4a6b4dce55..cabdfea191 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -159,13 +159,13 @@ static inline void GenerateGeometryShader(T& out, u32 primitive_type, API_TYPE A else if (primitive_type == PRIMITIVE_POINTS) { if (ApiType == API_OPENGL) - out.Write("\tVS_OUTPUT point = vs[0].o;\n"); + out.Write("\tVS_OUTPUT center = vs[0].o;\n"); else - out.Write("\tVS_OUTPUT point = o[0];\n"); + out.Write("\tVS_OUTPUT center = o[0];\n"); // Offset from center to upper right vertex // Lerp PointSize/2 from [0,0..VpWidth,VpHeight] to [-1,1..1,-1] - out.Write("float2 offset = float2(" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".x, -" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".y) * point.pos.w;\n"); + out.Write("\tfloat2 offset = float2(" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".x, -" I_LINEPTPARAMS".w / " I_LINEPTPARAMS".y) * center.pos.w;\n"); } if (g_ActiveConfig.iStereoMode > 0)