diff options
| author | 2019-07-07 20:36:42 -0300 | |
|---|---|---|
| committer | 2019-07-07 20:42:55 -0300 | |
| commit | c9d886c84e4102f7b9c464c704eecb61d37b3df4 (patch) | |
| tree | c26dadd5ead8fb3d9b8241cc8b9d6f97dd9d98f4 | |
| parent | Merge pull request #2694 from FearlessTobi/patch-1 (diff) | |
| download | yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.tar.gz yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.tar.xz yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.zip | |
gl_shader_decompiler: Implement gl_ViewportIndex and gl_Layer in vertex shaders
This commit implements gl_ViewportIndex and gl_Layer in vertex and
geometry shaders. In the case it's used in a vertex shader, it requires
ARB_shader_viewport_layer_array. This extension is available on AMD and
Nvidia devices (mesa and proprietary drivers), but not available on
Intel on any platform. At the moment of writing this description I don't
know if this is a hardware limitation or a driver limitation.
In the case that ARB_shader_viewport_layer_array is not available,
writes to these registers on a vertex shader are ignored, with the
appropriate logging.
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.h | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 104 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 15 |
10 files changed, 136 insertions, 40 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 404d4f5aa..b92921d0f 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -78,7 +78,7 @@ union Attribute { | |||
| 78 | constexpr explicit Attribute(u64 value) : value(value) {} | 78 | constexpr explicit Attribute(u64 value) : value(value) {} |
| 79 | 79 | ||
| 80 | enum class Index : u64 { | 80 | enum class Index : u64 { |
| 81 | PointSize = 6, | 81 | LayerViewportPointSize = 6, |
| 82 | Position = 7, | 82 | Position = 7, |
| 83 | Attribute_0 = 8, | 83 | Attribute_0 = 8, |
| 84 | Attribute_31 = 39, | 84 | Attribute_31 = 39, |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index a48e14d2e..4b1f22f7a 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -26,6 +26,7 @@ Device::Device() { | |||
| 26 | uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); | 26 | uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); |
| 27 | max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); | 27 | max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); |
| 28 | max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); | 28 | max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); |
| 29 | has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; | ||
| 29 | has_variable_aoffi = TestVariableAoffi(); | 30 | has_variable_aoffi = TestVariableAoffi(); |
| 30 | has_component_indexing_bug = TestComponentIndexingBug(); | 31 | has_component_indexing_bug = TestComponentIndexingBug(); |
| 31 | } | 32 | } |
| @@ -34,6 +35,7 @@ Device::Device(std::nullptr_t) { | |||
| 34 | uniform_buffer_alignment = 0; | 35 | uniform_buffer_alignment = 0; |
| 35 | max_vertex_attributes = 16; | 36 | max_vertex_attributes = 16; |
| 36 | max_varyings = 15; | 37 | max_varyings = 15; |
| 38 | has_vertex_viewport_layer = true; | ||
| 37 | has_variable_aoffi = true; | 39 | has_variable_aoffi = true; |
| 38 | has_component_indexing_bug = false; | 40 | has_component_indexing_bug = false; |
| 39 | } | 41 | } |
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 8c8c93760..7a3a0675b 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -26,6 +26,10 @@ public: | |||
| 26 | return max_varyings; | 26 | return max_varyings; |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | bool HasVertexViewportLayer() const { | ||
| 30 | return has_vertex_viewport_layer; | ||
| 31 | } | ||
| 32 | |||
| 29 | bool HasVariableAoffi() const { | 33 | bool HasVariableAoffi() const { |
| 30 | return has_variable_aoffi; | 34 | return has_variable_aoffi; |
| 31 | } | 35 | } |
| @@ -41,6 +45,7 @@ private: | |||
| 41 | std::size_t uniform_buffer_alignment{}; | 45 | std::size_t uniform_buffer_alignment{}; |
| 42 | u32 max_vertex_attributes{}; | 46 | u32 max_vertex_attributes{}; |
| 43 | u32 max_varyings{}; | 47 | u32 max_varyings{}; |
| 48 | bool has_vertex_viewport_layer{}; | ||
| 44 | bool has_variable_aoffi{}; | 49 | bool has_variable_aoffi{}; |
| 45 | bool has_component_indexing_bug{}; | 50 | bool has_component_indexing_bug{}; |
| 46 | }; | 51 | }; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index f9b2b03a0..7fea92713 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -182,8 +182,11 @@ CachedProgram SpecializeShader(const std::string& code, const GLShader::ShaderEn | |||
| 182 | const auto texture_buffer_usage{variant.texture_buffer_usage}; | 182 | const auto texture_buffer_usage{variant.texture_buffer_usage}; |
| 183 | 183 | ||
| 184 | std::string source = "#version 430 core\n" | 184 | std::string source = "#version 430 core\n" |
| 185 | "#extension GL_ARB_separate_shader_objects : enable\n\n"; | 185 | "#extension GL_ARB_separate_shader_objects : enable\n"; |
| 186 | source += fmt::format("#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++); | 186 | if (entries.shader_viewport_layer_array) { |
| 187 | source += "#extension GL_ARB_shader_viewport_layer_array : enable\n"; | ||
| 188 | } | ||
| 189 | source += fmt::format("\n#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++); | ||
| 187 | 190 | ||
| 188 | for (const auto& cbuf : entries.const_buffers) { | 191 | for (const auto& cbuf : entries.const_buffers) { |
| 189 | source += | 192 | source += |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 5f2f1510c..a4451dd2f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/alignment.h" | 14 | #include "common/alignment.h" |
| 15 | #include "common/assert.h" | 15 | #include "common/assert.h" |
| 16 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 17 | #include "common/logging/log.h" | ||
| 17 | #include "video_core/engines/maxwell_3d.h" | 18 | #include "video_core/engines/maxwell_3d.h" |
| 18 | #include "video_core/renderer_opengl/gl_device.h" | 19 | #include "video_core/renderer_opengl/gl_device.h" |
| 19 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 20 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| @@ -244,6 +245,8 @@ public: | |||
| 244 | usage.is_read, usage.is_written); | 245 | usage.is_read, usage.is_written); |
| 245 | } | 246 | } |
| 246 | entries.clip_distances = ir.GetClipDistances(); | 247 | entries.clip_distances = ir.GetClipDistances(); |
| 248 | entries.shader_viewport_layer_array = | ||
| 249 | stage == ShaderStage::Vertex && (ir.UsesLayer() || ir.UsesPointSize()); | ||
| 247 | entries.shader_length = ir.GetLength(); | 250 | entries.shader_length = ir.GetLength(); |
| 248 | return entries; | 251 | return entries; |
| 249 | } | 252 | } |
| @@ -280,22 +283,34 @@ private: | |||
| 280 | } | 283 | } |
| 281 | 284 | ||
| 282 | void DeclareVertexRedeclarations() { | 285 | void DeclareVertexRedeclarations() { |
| 283 | bool clip_distances_declared = false; | ||
| 284 | |||
| 285 | code.AddLine("out gl_PerVertex {{"); | 286 | code.AddLine("out gl_PerVertex {{"); |
| 286 | ++code.scope; | 287 | ++code.scope; |
| 287 | 288 | ||
| 288 | code.AddLine("vec4 gl_Position;"); | 289 | code.AddLine("vec4 gl_Position;"); |
| 289 | 290 | ||
| 290 | for (const auto o : ir.GetOutputAttributes()) { | 291 | for (const auto attribute : ir.GetOutputAttributes()) { |
| 291 | if (o == Attribute::Index::PointSize) | 292 | if (attribute == Attribute::Index::ClipDistances0123 || |
| 292 | code.AddLine("float gl_PointSize;"); | 293 | attribute == Attribute::Index::ClipDistances4567) { |
| 293 | if (!clip_distances_declared && (o == Attribute::Index::ClipDistances0123 || | ||
| 294 | o == Attribute::Index::ClipDistances4567)) { | ||
| 295 | code.AddLine("float gl_ClipDistance[];"); | 294 | code.AddLine("float gl_ClipDistance[];"); |
| 296 | clip_distances_declared = true; | 295 | break; |
| 297 | } | 296 | } |
| 298 | } | 297 | } |
| 298 | if (stage != ShaderStage::Vertex || device.HasVertexViewportLayer()) { | ||
| 299 | if (ir.UsesLayer()) { | ||
| 300 | code.AddLine("int gl_Layer;"); | ||
| 301 | } | ||
| 302 | if (ir.UsesViewportIndex()) { | ||
| 303 | code.AddLine("int gl_ViewportIndex;"); | ||
| 304 | } | ||
| 305 | } else if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) { | ||
| 306 | LOG_ERROR( | ||
| 307 | Render_OpenGL, | ||
| 308 | "GL_ARB_shader_viewport_layer_array is not available and its required by a shader"); | ||
| 309 | } | ||
| 310 | |||
| 311 | if (ir.UsesPointSize()) { | ||
| 312 | code.AddLine("int gl_PointSize;"); | ||
| 313 | } | ||
| 299 | 314 | ||
| 300 | --code.scope; | 315 | --code.scope; |
| 301 | code.AddLine("}};"); | 316 | code.AddLine("}};"); |
| @@ -803,6 +818,45 @@ private: | |||
| 803 | return CastOperand(VisitOperand(operation, operand_index), type); | 818 | return CastOperand(VisitOperand(operation, operand_index), type); |
| 804 | } | 819 | } |
| 805 | 820 | ||
| 821 | std::optional<std::pair<std::string, bool>> GetOutputAttribute(const AbufNode* abuf) { | ||
| 822 | switch (const auto attribute = abuf->GetIndex()) { | ||
| 823 | case Attribute::Index::Position: | ||
| 824 | return std::make_pair("gl_Position"s + GetSwizzle(abuf->GetElement()), false); | ||
| 825 | case Attribute::Index::LayerViewportPointSize: | ||
| 826 | switch (abuf->GetElement()) { | ||
| 827 | case 0: | ||
| 828 | UNIMPLEMENTED(); | ||
| 829 | return {}; | ||
| 830 | case 1: | ||
| 831 | if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) { | ||
| 832 | return {}; | ||
| 833 | } | ||
| 834 | return std::make_pair("gl_Layer", true); | ||
| 835 | case 2: | ||
| 836 | if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) { | ||
| 837 | return {}; | ||
| 838 | } | ||
| 839 | return std::make_pair("gl_ViewportIndex", true); | ||
| 840 | case 3: | ||
| 841 | UNIMPLEMENTED_MSG("Requires some state changes for gl_PointSize to work in shader"); | ||
| 842 | return std::make_pair("gl_PointSize", false); | ||
| 843 | } | ||
| 844 | return {}; | ||
| 845 | case Attribute::Index::ClipDistances0123: | ||
| 846 | return std::make_pair(fmt::format("gl_ClipDistance[{}]", abuf->GetElement()), false); | ||
| 847 | case Attribute::Index::ClipDistances4567: | ||
| 848 | return std::make_pair(fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), | ||
| 849 | false); | ||
| 850 | default: | ||
| 851 | if (IsGenericAttribute(attribute)) { | ||
| 852 | return std::make_pair( | ||
| 853 | GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement()), false); | ||
| 854 | } | ||
| 855 | UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute)); | ||
| 856 | return {}; | ||
| 857 | } | ||
| 858 | } | ||
| 859 | |||
| 806 | std::string CastOperand(const std::string& value, Type type) const { | 860 | std::string CastOperand(const std::string& value, Type type) const { |
| 807 | switch (type) { | 861 | switch (type) { |
| 808 | case Type::Bool: | 862 | case Type::Bool: |
| @@ -999,6 +1053,8 @@ private: | |||
| 999 | const Node& src = operation[1]; | 1053 | const Node& src = operation[1]; |
| 1000 | 1054 | ||
| 1001 | std::string target; | 1055 | std::string target; |
| 1056 | bool is_integer = false; | ||
| 1057 | |||
| 1002 | if (const auto gpr = std::get_if<GprNode>(&*dest)) { | 1058 | if (const auto gpr = std::get_if<GprNode>(&*dest)) { |
| 1003 | if (gpr->GetIndex() == Register::ZeroIndex) { | 1059 | if (gpr->GetIndex() == Register::ZeroIndex) { |
| 1004 | // Writing to Register::ZeroIndex is a no op | 1060 | // Writing to Register::ZeroIndex is a no op |
| @@ -1007,26 +1063,12 @@ private: | |||
| 1007 | target = GetRegister(gpr->GetIndex()); | 1063 | target = GetRegister(gpr->GetIndex()); |
| 1008 | } else if (const auto abuf = std::get_if<AbufNode>(&*dest)) { | 1064 | } else if (const auto abuf = std::get_if<AbufNode>(&*dest)) { |
| 1009 | UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer()); | 1065 | UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer()); |
| 1010 | 1066 | const auto result = GetOutputAttribute(abuf); | |
| 1011 | target = [&]() -> std::string { | 1067 | if (!result) { |
| 1012 | switch (const auto attribute = abuf->GetIndex(); abuf->GetIndex()) { | 1068 | return {}; |
| 1013 | case Attribute::Index::Position: | 1069 | } |
| 1014 | return "gl_Position"s + GetSwizzle(abuf->GetElement()); | 1070 | target = result->first; |
| 1015 | case Attribute::Index::PointSize: | 1071 | is_integer = result->second; |
| 1016 | return "gl_PointSize"; | ||
| 1017 | case Attribute::Index::ClipDistances0123: | ||
| 1018 | return fmt::format("gl_ClipDistance[{}]", abuf->GetElement()); | ||
| 1019 | case Attribute::Index::ClipDistances4567: | ||
| 1020 | return fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4); | ||
| 1021 | default: | ||
| 1022 | if (IsGenericAttribute(attribute)) { | ||
| 1023 | return GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement()); | ||
| 1024 | } | ||
| 1025 | UNIMPLEMENTED_MSG("Unhandled output attribute: {}", | ||
| 1026 | static_cast<u32>(attribute)); | ||
| 1027 | return "0"; | ||
| 1028 | } | ||
| 1029 | }(); | ||
| 1030 | } else if (const auto lmem = std::get_if<LmemNode>(&*dest)) { | 1072 | } else if (const auto lmem = std::get_if<LmemNode>(&*dest)) { |
| 1031 | target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); | 1073 | target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); |
| 1032 | } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { | 1074 | } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { |
| @@ -1038,7 +1080,11 @@ private: | |||
| 1038 | UNREACHABLE_MSG("Assign called without a proper target"); | 1080 | UNREACHABLE_MSG("Assign called without a proper target"); |
| 1039 | } | 1081 | } |
| 1040 | 1082 | ||
| 1041 | code.AddLine("{} = {};", target, Visit(src)); | 1083 | if (is_integer) { |
| 1084 | code.AddLine("{} = ftoi({});", target, Visit(src)); | ||
| 1085 | } else { | ||
| 1086 | code.AddLine("{} = {};", target, Visit(src)); | ||
| 1087 | } | ||
| 1042 | return {}; | 1088 | return {}; |
| 1043 | } | 1089 | } |
| 1044 | 1090 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h index 14d11c7fc..02586736d 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.h +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h | |||
| @@ -78,6 +78,7 @@ struct ShaderEntries { | |||
| 78 | std::vector<ImageEntry> images; | 78 | std::vector<ImageEntry> images; |
| 79 | std::vector<GlobalMemoryEntry> global_memory_entries; | 79 | std::vector<GlobalMemoryEntry> global_memory_entries; |
| 80 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | 80 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; |
| 81 | bool shader_viewport_layer_array{}; | ||
| 81 | std::size_t shader_length{}; | 82 | std::size_t shader_length{}; |
| 82 | }; | 83 | }; |
| 83 | 84 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 10688397b..7893d1e26 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | |||
| @@ -373,6 +373,12 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn | |||
| 373 | } | 373 | } |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | bool shader_viewport_layer_array{}; | ||
| 377 | if (!LoadObjectFromPrecompiled(shader_viewport_layer_array)) { | ||
| 378 | return {}; | ||
| 379 | } | ||
| 380 | entry.entries.shader_viewport_layer_array = shader_viewport_layer_array; | ||
| 381 | |||
| 376 | u64 shader_length{}; | 382 | u64 shader_length{}; |
| 377 | if (!LoadObjectFromPrecompiled(shader_length)) { | 383 | if (!LoadObjectFromPrecompiled(shader_length)) { |
| 378 | return {}; | 384 | return {}; |
| @@ -445,6 +451,10 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(u64 unique_identifier, const std: | |||
| 445 | } | 451 | } |
| 446 | } | 452 | } |
| 447 | 453 | ||
| 454 | if (!SaveObjectToPrecompiled(entries.shader_viewport_layer_array)) { | ||
| 455 | return false; | ||
| 456 | } | ||
| 457 | |||
| 448 | if (!SaveObjectToPrecompiled(static_cast<u64>(entries.shader_length))) { | 458 | if (!SaveObjectToPrecompiled(static_cast<u64>(entries.shader_length))) { |
| 449 | return false; | 459 | return false; |
| 450 | } | 460 | } |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 97ce214b1..6071c6d99 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -430,20 +430,17 @@ private: | |||
| 430 | instance_index = DeclareBuiltIn(spv::BuiltIn::InstanceIndex, spv::StorageClass::Input, | 430 | instance_index = DeclareBuiltIn(spv::BuiltIn::InstanceIndex, spv::StorageClass::Input, |
| 431 | t_in_uint, "instance_index"); | 431 | t_in_uint, "instance_index"); |
| 432 | 432 | ||
| 433 | bool is_point_size_declared = false; | ||
| 434 | bool is_clip_distances_declared = false; | 433 | bool is_clip_distances_declared = false; |
| 435 | for (const auto index : ir.GetOutputAttributes()) { | 434 | for (const auto index : ir.GetOutputAttributes()) { |
| 436 | if (index == Attribute::Index::PointSize) { | 435 | if (index == Attribute::Index::ClipDistances0123 || |
| 437 | is_point_size_declared = true; | 436 | index == Attribute::Index::ClipDistances4567) { |
| 438 | } else if (index == Attribute::Index::ClipDistances0123 || | ||
| 439 | index == Attribute::Index::ClipDistances4567) { | ||
| 440 | is_clip_distances_declared = true; | 437 | is_clip_distances_declared = true; |
| 441 | } | 438 | } |
| 442 | } | 439 | } |
| 443 | 440 | ||
| 444 | std::vector<Id> members; | 441 | std::vector<Id> members; |
| 445 | members.push_back(t_float4); | 442 | members.push_back(t_float4); |
| 446 | if (is_point_size_declared) { | 443 | if (ir.UsesPointSize()) { |
| 447 | members.push_back(t_float); | 444 | members.push_back(t_float); |
| 448 | } | 445 | } |
| 449 | if (is_clip_distances_declared) { | 446 | if (is_clip_distances_declared) { |
| @@ -466,7 +463,7 @@ private: | |||
| 466 | 463 | ||
| 467 | position_index = MemberDecorateBuiltIn(spv::BuiltIn::Position, "position", true); | 464 | position_index = MemberDecorateBuiltIn(spv::BuiltIn::Position, "position", true); |
| 468 | point_size_index = | 465 | point_size_index = |
| 469 | MemberDecorateBuiltIn(spv::BuiltIn::PointSize, "point_size", is_point_size_declared); | 466 | MemberDecorateBuiltIn(spv::BuiltIn::PointSize, "point_size", ir.UsesPointSize()); |
| 470 | clip_distances_index = MemberDecorateBuiltIn(spv::BuiltIn::ClipDistance, "clip_distances", | 467 | clip_distances_index = MemberDecorateBuiltIn(spv::BuiltIn::ClipDistance, "clip_distances", |
| 471 | is_clip_distances_declared); | 468 | is_clip_distances_declared); |
| 472 | 469 | ||
| @@ -712,7 +709,8 @@ private: | |||
| 712 | case Attribute::Index::Position: | 709 | case Attribute::Index::Position: |
| 713 | return AccessElement(t_out_float, per_vertex, position_index, | 710 | return AccessElement(t_out_float, per_vertex, position_index, |
| 714 | abuf->GetElement()); | 711 | abuf->GetElement()); |
| 715 | case Attribute::Index::PointSize: | 712 | case Attribute::Index::LayerViewportPointSize: |
| 713 | UNIMPLEMENTED_IF(abuf->GetElement() != 3); | ||
| 716 | return AccessElement(t_out_float, per_vertex, point_size_index); | 714 | return AccessElement(t_out_float, per_vertex, point_size_index); |
| 717 | case Attribute::Index::ClipDistances0123: | 715 | case Attribute::Index::ClipDistances0123: |
| 718 | return AccessElement(t_out_float, per_vertex, clip_distances_index, | 716 | return AccessElement(t_out_float, per_vertex, clip_distances_index, |
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 11b545cca..fd80dd116 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp | |||
| @@ -89,6 +89,22 @@ Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_addres | |||
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { | 91 | Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { |
| 92 | if (index == Attribute::Index::LayerViewportPointSize) { | ||
| 93 | switch (element) { | ||
| 94 | case 0: | ||
| 95 | UNIMPLEMENTED(); | ||
| 96 | break; | ||
| 97 | case 1: | ||
| 98 | uses_layer = true; | ||
| 99 | break; | ||
| 100 | case 2: | ||
| 101 | uses_viewport_index = true; | ||
| 102 | break; | ||
| 103 | case 3: | ||
| 104 | uses_point_size = true; | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | } | ||
| 92 | if (index == Attribute::Index::ClipDistances0123 || | 108 | if (index == Attribute::Index::ClipDistances0123 || |
| 93 | index == Attribute::Index::ClipDistances4567) { | 109 | index == Attribute::Index::ClipDistances4567) { |
| 94 | const auto clip_index = | 110 | const auto clip_index = |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index e22548208..a656761ea 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -121,6 +121,18 @@ public: | |||
| 121 | return static_cast<std::size_t>(coverage_end * sizeof(u64)); | 121 | return static_cast<std::size_t>(coverage_end * sizeof(u64)); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | bool UsesLayer() const { | ||
| 125 | return uses_layer; | ||
| 126 | } | ||
| 127 | |||
| 128 | bool UsesViewportIndex() const { | ||
| 129 | return uses_viewport_index; | ||
| 130 | } | ||
| 131 | |||
| 132 | bool UsesPointSize() const { | ||
| 133 | return uses_point_size; | ||
| 134 | } | ||
| 135 | |||
| 124 | bool HasPhysicalAttributes() const { | 136 | bool HasPhysicalAttributes() const { |
| 125 | return uses_physical_attributes; | 137 | return uses_physical_attributes; |
| 126 | } | 138 | } |
| @@ -343,6 +355,9 @@ private: | |||
| 343 | std::set<Image> used_images; | 355 | std::set<Image> used_images; |
| 344 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; | 356 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; |
| 345 | std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; | 357 | std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; |
| 358 | bool uses_layer{}; | ||
| 359 | bool uses_viewport_index{}; | ||
| 360 | bool uses_point_size{}; | ||
| 346 | bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes | 361 | bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes |
| 347 | 362 | ||
| 348 | Tegra::Shader::Header header; | 363 | Tegra::Shader::Header header; |