summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h2
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.h5
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp105
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.h1
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp14
-rw-r--r--src/video_core/shader/shader_ir.cpp16
-rw-r--r--src/video_core/shader/shader_ir.h15
10 files changed, 137 insertions, 40 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 4aaad2979..79d469b88 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 6238ddaaa..85424a4c9 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -27,6 +27,7 @@ Device::Device() {
27 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT); 27 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
28 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); 28 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
29 max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); 29 max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
30 has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array;
30 has_variable_aoffi = TestVariableAoffi(); 31 has_variable_aoffi = TestVariableAoffi();
31 has_component_indexing_bug = TestComponentIndexingBug(); 32 has_component_indexing_bug = TestComponentIndexingBug();
32} 33}
@@ -35,6 +36,7 @@ Device::Device(std::nullptr_t) {
35 uniform_buffer_alignment = 0; 36 uniform_buffer_alignment = 0;
36 max_vertex_attributes = 16; 37 max_vertex_attributes = 16;
37 max_varyings = 15; 38 max_varyings = 15;
39 has_vertex_viewport_layer = true;
38 has_variable_aoffi = true; 40 has_variable_aoffi = true;
39 has_component_indexing_bug = false; 41 has_component_indexing_bug = false;
40} 42}
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 939edb440..dc883722d 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -30,6 +30,10 @@ public:
30 return max_varyings; 30 return max_varyings;
31 } 31 }
32 32
33 bool HasVertexViewportLayer() const {
34 return has_vertex_viewport_layer;
35 }
36
33 bool HasVariableAoffi() const { 37 bool HasVariableAoffi() const {
34 return has_variable_aoffi; 38 return has_variable_aoffi;
35 } 39 }
@@ -46,6 +50,7 @@ private:
46 std::size_t shader_storage_alignment{}; 50 std::size_t shader_storage_alignment{};
47 u32 max_vertex_attributes{}; 51 u32 max_vertex_attributes{};
48 u32 max_varyings{}; 52 u32 max_varyings{};
53 bool has_vertex_viewport_layer{};
49 bool has_variable_aoffi{}; 54 bool has_variable_aoffi{};
50 bool has_component_indexing_bug{}; 55 bool has_component_indexing_bug{};
51}; 56};
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 5d76ee12d..32dd9eae7 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -190,8 +190,11 @@ CachedProgram SpecializeShader(const std::string& code, const GLShader::ShaderEn
190 const auto texture_buffer_usage{variant.texture_buffer_usage}; 190 const auto texture_buffer_usage{variant.texture_buffer_usage};
191 191
192 std::string source = "#version 430 core\n" 192 std::string source = "#version 430 core\n"
193 "#extension GL_ARB_separate_shader_objects : enable\n\n"; 193 "#extension GL_ARB_separate_shader_objects : enable\n";
194 source += fmt::format("#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++); 194 if (entries.shader_viewport_layer_array) {
195 source += "#extension GL_ARB_shader_viewport_layer_array : enable\n";
196 }
197 source += fmt::format("\n#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++);
195 198
196 for (const auto& cbuf : entries.const_buffers) { 199 for (const auto& cbuf : entries.const_buffers) {
197 source += 200 source +=
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 47cc2011f..119073776 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"
@@ -246,6 +247,8 @@ public:
246 usage.is_read, usage.is_written); 247 usage.is_read, usage.is_written);
247 } 248 }
248 entries.clip_distances = ir.GetClipDistances(); 249 entries.clip_distances = ir.GetClipDistances();
250 entries.shader_viewport_layer_array =
251 stage == ShaderStage::Vertex && (ir.UsesLayer() || ir.UsesViewportIndex());
249 entries.shader_length = ir.GetLength(); 252 entries.shader_length = ir.GetLength();
250 return entries; 253 return entries;
251 } 254 }
@@ -282,22 +285,35 @@ private:
282 } 285 }
283 286
284 void DeclareVertexRedeclarations() { 287 void DeclareVertexRedeclarations() {
285 bool clip_distances_declared = false;
286
287 code.AddLine("out gl_PerVertex {{"); 288 code.AddLine("out gl_PerVertex {{");
288 ++code.scope; 289 ++code.scope;
289 290
290 code.AddLine("vec4 gl_Position;"); 291 code.AddLine("vec4 gl_Position;");
291 292
292 for (const auto o : ir.GetOutputAttributes()) { 293 for (const auto attribute : ir.GetOutputAttributes()) {
293 if (o == Attribute::Index::PointSize) 294 if (attribute == Attribute::Index::ClipDistances0123 ||
294 code.AddLine("float gl_PointSize;"); 295 attribute == Attribute::Index::ClipDistances4567) {
295 if (!clip_distances_declared && (o == Attribute::Index::ClipDistances0123 ||
296 o == Attribute::Index::ClipDistances4567)) {
297 code.AddLine("float gl_ClipDistance[];"); 296 code.AddLine("float gl_ClipDistance[];");
298 clip_distances_declared = true; 297 break;
299 } 298 }
300 } 299 }
300 if (stage != ShaderStage::Vertex || device.HasVertexViewportLayer()) {
301 if (ir.UsesLayer()) {
302 code.AddLine("int gl_Layer;");
303 }
304 if (ir.UsesViewportIndex()) {
305 code.AddLine("int gl_ViewportIndex;");
306 }
307 } else if ((ir.UsesLayer() || ir.UsesViewportIndex()) && stage == ShaderStage::Vertex &&
308 !device.HasVertexViewportLayer()) {
309 LOG_ERROR(
310 Render_OpenGL,
311 "GL_ARB_shader_viewport_layer_array is not available and its required by a shader");
312 }
313
314 if (ir.UsesPointSize()) {
315 code.AddLine("float gl_PointSize;");
316 }
301 317
302 --code.scope; 318 --code.scope;
303 code.AddLine("}};"); 319 code.AddLine("}};");
@@ -805,6 +821,45 @@ private:
805 return CastOperand(VisitOperand(operation, operand_index), type); 821 return CastOperand(VisitOperand(operation, operand_index), type);
806 } 822 }
807 823
824 std::optional<std::pair<std::string, bool>> GetOutputAttribute(const AbufNode* abuf) {
825 switch (const auto attribute = abuf->GetIndex()) {
826 case Attribute::Index::Position:
827 return std::make_pair("gl_Position"s + GetSwizzle(abuf->GetElement()), false);
828 case Attribute::Index::LayerViewportPointSize:
829 switch (abuf->GetElement()) {
830 case 0:
831 UNIMPLEMENTED();
832 return {};
833 case 1:
834 if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) {
835 return {};
836 }
837 return std::make_pair("gl_Layer", true);
838 case 2:
839 if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) {
840 return {};
841 }
842 return std::make_pair("gl_ViewportIndex", true);
843 case 3:
844 UNIMPLEMENTED_MSG("Requires some state changes for gl_PointSize to work in shader");
845 return std::make_pair("gl_PointSize", false);
846 }
847 return {};
848 case Attribute::Index::ClipDistances0123:
849 return std::make_pair(fmt::format("gl_ClipDistance[{}]", abuf->GetElement()), false);
850 case Attribute::Index::ClipDistances4567:
851 return std::make_pair(fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4),
852 false);
853 default:
854 if (IsGenericAttribute(attribute)) {
855 return std::make_pair(
856 GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement()), false);
857 }
858 UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute));
859 return {};
860 }
861 }
862
808 std::string CastOperand(const std::string& value, Type type) const { 863 std::string CastOperand(const std::string& value, Type type) const {
809 switch (type) { 864 switch (type) {
810 case Type::Bool: 865 case Type::Bool:
@@ -1001,6 +1056,8 @@ private:
1001 const Node& src = operation[1]; 1056 const Node& src = operation[1];
1002 1057
1003 std::string target; 1058 std::string target;
1059 bool is_integer = false;
1060
1004 if (const auto gpr = std::get_if<GprNode>(&*dest)) { 1061 if (const auto gpr = std::get_if<GprNode>(&*dest)) {
1005 if (gpr->GetIndex() == Register::ZeroIndex) { 1062 if (gpr->GetIndex() == Register::ZeroIndex) {
1006 // Writing to Register::ZeroIndex is a no op 1063 // Writing to Register::ZeroIndex is a no op
@@ -1009,26 +1066,12 @@ private:
1009 target = GetRegister(gpr->GetIndex()); 1066 target = GetRegister(gpr->GetIndex());
1010 } else if (const auto abuf = std::get_if<AbufNode>(&*dest)) { 1067 } else if (const auto abuf = std::get_if<AbufNode>(&*dest)) {
1011 UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer()); 1068 UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer());
1012 1069 const auto result = GetOutputAttribute(abuf);
1013 target = [&]() -> std::string { 1070 if (!result) {
1014 switch (const auto attribute = abuf->GetIndex(); abuf->GetIndex()) { 1071 return {};
1015 case Attribute::Index::Position: 1072 }
1016 return "gl_Position"s + GetSwizzle(abuf->GetElement()); 1073 target = result->first;
1017 case Attribute::Index::PointSize: 1074 is_integer = result->second;
1018 return "gl_PointSize";
1019 case Attribute::Index::ClipDistances0123:
1020 return fmt::format("gl_ClipDistance[{}]", abuf->GetElement());
1021 case Attribute::Index::ClipDistances4567:
1022 return fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4);
1023 default:
1024 if (IsGenericAttribute(attribute)) {
1025 return GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement());
1026 }
1027 UNIMPLEMENTED_MSG("Unhandled output attribute: {}",
1028 static_cast<u32>(attribute));
1029 return "0";
1030 }
1031 }();
1032 } else if (const auto lmem = std::get_if<LmemNode>(&*dest)) { 1075 } else if (const auto lmem = std::get_if<LmemNode>(&*dest)) {
1033 target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); 1076 target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress()));
1034 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { 1077 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
@@ -1040,7 +1083,11 @@ private:
1040 UNREACHABLE_MSG("Assign called without a proper target"); 1083 UNREACHABLE_MSG("Assign called without a proper target");
1041 } 1084 }
1042 1085
1043 code.AddLine("{} = {};", target, Visit(src)); 1086 if (is_integer) {
1087 code.AddLine("{} = ftoi({});", target, Visit(src));
1088 } else {
1089 code.AddLine("{} = {};", target, Visit(src));
1090 }
1044 return {}; 1091 return {};
1045 } 1092 }
1046 1093
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 1bb04607b..9b2d8e987 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 5994bfc4e..caa409788 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
91Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { 91Node 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 6145f0a70..03c888def 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -115,6 +115,18 @@ public:
115 return static_cast<std::size_t>(coverage_end * sizeof(u64)); 115 return static_cast<std::size_t>(coverage_end * sizeof(u64));
116 } 116 }
117 117
118 bool UsesLayer() const {
119 return uses_layer;
120 }
121
122 bool UsesViewportIndex() const {
123 return uses_viewport_index;
124 }
125
126 bool UsesPointSize() const {
127 return uses_point_size;
128 }
129
118 bool HasPhysicalAttributes() const { 130 bool HasPhysicalAttributes() const {
119 return uses_physical_attributes; 131 return uses_physical_attributes;
120 } 132 }
@@ -346,6 +358,9 @@ private:
346 std::set<Image> used_images; 358 std::set<Image> used_images;
347 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; 359 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{};
348 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; 360 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory;
361 bool uses_layer{};
362 bool uses_viewport_index{};
363 bool uses_point_size{};
349 bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes 364 bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes
350 365
351 Tegra::Shader::Header header; 366 Tegra::Shader::Header header;