diff options
author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2019-07-08 01:36:42 +0200 |
---|---|---|
committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2019-07-08 01:42:55 +0200 |
commit | c9d886c84e4102f7b9c464c704eecb61d37b3df4 (patch) | |
tree | c26dadd5ead8fb3d9b8241cc8b9d6f97dd9d98f4 /src/video_core | |
parent | Merge pull request #2694 from FearlessTobi/patch-1 (diff) | |
download | yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.tar yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.tar.gz yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.tar.bz2 yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.tar.lz yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.tar.xz yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.tar.zst yuzu-c9d886c84e4102f7b9c464c704eecb61d37b3df4.zip |
Diffstat (limited to 'src/video_core')
-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 { constexpr explicit Attribute(u64 value) : value(value) {} enum class Index : u64 { - PointSize = 6, + LayerViewportPointSize = 6, Position = 7, Attribute_0 = 8, 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() { uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); + has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; has_variable_aoffi = TestVariableAoffi(); has_component_indexing_bug = TestComponentIndexingBug(); } @@ -34,6 +35,7 @@ Device::Device(std::nullptr_t) { uniform_buffer_alignment = 0; max_vertex_attributes = 16; max_varyings = 15; + has_vertex_viewport_layer = true; has_variable_aoffi = true; has_component_indexing_bug = false; } 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: return max_varyings; } + bool HasVertexViewportLayer() const { + return has_vertex_viewport_layer; + } + bool HasVariableAoffi() const { return has_variable_aoffi; } @@ -41,6 +45,7 @@ private: std::size_t uniform_buffer_alignment{}; u32 max_vertex_attributes{}; u32 max_varyings{}; + bool has_vertex_viewport_layer{}; bool has_variable_aoffi{}; bool has_component_indexing_bug{}; }; 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 const auto texture_buffer_usage{variant.texture_buffer_usage}; std::string source = "#version 430 core\n" - "#extension GL_ARB_separate_shader_objects : enable\n\n"; - source += fmt::format("#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++); + "#extension GL_ARB_separate_shader_objects : enable\n"; + if (entries.shader_viewport_layer_array) { + source += "#extension GL_ARB_shader_viewport_layer_array : enable\n"; + } + source += fmt::format("\n#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++); for (const auto& cbuf : entries.const_buffers) { 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 @@ #include "common/alignment.h" #include "common/assert.h" #include "common/common_types.h" +#include "common/logging/log.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/renderer_opengl/gl_device.h" #include "video_core/renderer_opengl/gl_rasterizer.h" @@ -244,6 +245,8 @@ public: usage.is_read, usage.is_written); } entries.clip_distances = ir.GetClipDistances(); + entries.shader_viewport_layer_array = + stage == ShaderStage::Vertex && (ir.UsesLayer() || ir.UsesPointSize()); entries.shader_length = ir.GetLength(); return entries; } @@ -280,22 +283,34 @@ private: } void DeclareVertexRedeclarations() { - bool clip_distances_declared = false; - code.AddLine("out gl_PerVertex {{"); ++code.scope; code.AddLine("vec4 gl_Position;"); - for (const auto o : ir.GetOutputAttributes()) { - if (o == Attribute::Index::PointSize) - code.AddLine("float gl_PointSize;"); - if (!clip_distances_declared && (o == Attribute::Index::ClipDistances0123 || - o == Attribute::Index::ClipDistances4567)) { + for (const auto attribute : ir.GetOutputAttributes()) { + if (attribute == Attribute::Index::ClipDistances0123 || + attribute == Attribute::Index::ClipDistances4567) { code.AddLine("float gl_ClipDistance[];"); - clip_distances_declared = true; + break; } } + if (stage != ShaderStage::Vertex || device.HasVertexViewportLayer()) { + if (ir.UsesLayer()) { + code.AddLine("int gl_Layer;"); + } + if (ir.UsesViewportIndex()) { + code.AddLine("int gl_ViewportIndex;"); + } + } else if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) { + LOG_ERROR( + Render_OpenGL, + "GL_ARB_shader_viewport_layer_array is not available and its required by a shader"); + } + + if (ir.UsesPointSize()) { + code.AddLine("int gl_PointSize;"); + } --code.scope; code.AddLine("}};"); @@ -803,6 +818,45 @@ private: return CastOperand(VisitOperand(operation, operand_index), type); } + std::optional<std::pair<std::string, bool>> GetOutputAttribute(const AbufNode* abuf) { + switch (const auto attribute = abuf->GetIndex()) { + case Attribute::Index::Position: + return std::make_pair("gl_Position"s + GetSwizzle(abuf->GetElement()), false); + case Attribute::Index::LayerViewportPointSize: + switch (abuf->GetElement()) { + case 0: + UNIMPLEMENTED(); + return {}; + case 1: + if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) { + return {}; + } + return std::make_pair("gl_Layer", true); + case 2: + if (stage == ShaderStage::Vertex && !device.HasVertexViewportLayer()) { + return {}; + } + return std::make_pair("gl_ViewportIndex", true); + case 3: + UNIMPLEMENTED_MSG("Requires some state changes for gl_PointSize to work in shader"); + return std::make_pair("gl_PointSize", false); + } + return {}; + case Attribute::Index::ClipDistances0123: + return std::make_pair(fmt::format("gl_ClipDistance[{}]", abuf->GetElement()), false); + case Attribute::Index::ClipDistances4567: + return std::make_pair(fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), + false); + default: + if (IsGenericAttribute(attribute)) { + return std::make_pair( + GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement()), false); + } + UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute)); + return {}; + } + } + std::string CastOperand(const std::string& value, Type type) const { switch (type) { case Type::Bool: @@ -999,6 +1053,8 @@ private: const Node& src = operation[1]; std::string target; + bool is_integer = false; + if (const auto gpr = std::get_if<GprNode>(&*dest)) { if (gpr->GetIndex() == Register::ZeroIndex) { // Writing to Register::ZeroIndex is a no op @@ -1007,26 +1063,12 @@ private: target = GetRegister(gpr->GetIndex()); } else if (const auto abuf = std::get_if<AbufNode>(&*dest)) { UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer()); - - target = [&]() -> std::string { - switch (const auto attribute = abuf->GetIndex(); abuf->GetIndex()) { - case Attribute::Index::Position: - return "gl_Position"s + GetSwizzle(abuf->GetElement()); - case Attribute::Index::PointSize: - return "gl_PointSize"; - case Attribute::Index::ClipDistances0123: - return fmt::format("gl_ClipDistance[{}]", abuf->GetElement()); - case Attribute::Index::ClipDistances4567: - return fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4); - default: - if (IsGenericAttribute(attribute)) { - return GetOutputAttribute(attribute) + GetSwizzle(abuf->GetElement()); - } - UNIMPLEMENTED_MSG("Unhandled output attribute: {}", - static_cast<u32>(attribute)); - return "0"; - } - }(); + const auto result = GetOutputAttribute(abuf); + if (!result) { + return {}; + } + target = result->first; + is_integer = result->second; } else if (const auto lmem = std::get_if<LmemNode>(&*dest)) { target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { @@ -1038,7 +1080,11 @@ private: UNREACHABLE_MSG("Assign called without a proper target"); } - code.AddLine("{} = {};", target, Visit(src)); + if (is_integer) { + code.AddLine("{} = ftoi({});", target, Visit(src)); + } else { + code.AddLine("{} = {};", target, Visit(src)); + } return {}; } 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 { std::vector<ImageEntry> images; std::vector<GlobalMemoryEntry> global_memory_entries; std::array<bool, Maxwell::NumClipDistances> clip_distances{}; + bool shader_viewport_layer_array{}; std::size_t shader_length{}; }; 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 } } + bool shader_viewport_layer_array{}; + if (!LoadObjectFromPrecompiled(shader_viewport_layer_array)) { + return {}; + } + entry.entries.shader_viewport_layer_array = shader_viewport_layer_array; + u64 shader_length{}; if (!LoadObjectFromPrecompiled(shader_length)) { return {}; @@ -445,6 +451,10 @@ bool ShaderDiskCacheOpenGL::SaveDecompiledFile(u64 unique_identifier, const std: } } + if (!SaveObjectToPrecompiled(entries.shader_viewport_layer_array)) { + return false; + } + if (!SaveObjectToPrecompiled(static_cast<u64>(entries.shader_length))) { return false; } 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: instance_index = DeclareBuiltIn(spv::BuiltIn::InstanceIndex, spv::StorageClass::Input, t_in_uint, "instance_index"); - bool is_point_size_declared = false; bool is_clip_distances_declared = false; for (const auto index : ir.GetOutputAttributes()) { - if (index == Attribute::Index::PointSize) { - is_point_size_declared = true; - } else if (index == Attribute::Index::ClipDistances0123 || - index == Attribute::Index::ClipDistances4567) { + if (index == Attribute::Index::ClipDistances0123 || + index == Attribute::Index::ClipDistances4567) { is_clip_distances_declared = true; } } std::vector<Id> members; members.push_back(t_float4); - if (is_point_size_declared) { + if (ir.UsesPointSize()) { members.push_back(t_float); } if (is_clip_distances_declared) { @@ -466,7 +463,7 @@ private: position_index = MemberDecorateBuiltIn(spv::BuiltIn::Position, "position", true); point_size_index = - MemberDecorateBuiltIn(spv::BuiltIn::PointSize, "point_size", is_point_size_declared); + MemberDecorateBuiltIn(spv::BuiltIn::PointSize, "point_size", ir.UsesPointSize()); clip_distances_index = MemberDecorateBuiltIn(spv::BuiltIn::ClipDistance, "clip_distances", is_clip_distances_declared); @@ -712,7 +709,8 @@ private: case Attribute::Index::Position: return AccessElement(t_out_float, per_vertex, position_index, abuf->GetElement()); - case Attribute::Index::PointSize: + case Attribute::Index::LayerViewportPointSize: + UNIMPLEMENTED_IF(abuf->GetElement() != 3); return AccessElement(t_out_float, per_vertex, point_size_index); case Attribute::Index::ClipDistances0123: 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 } Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { + if (index == Attribute::Index::LayerViewportPointSize) { + switch (element) { + case 0: + UNIMPLEMENTED(); + break; + case 1: + uses_layer = true; + break; + case 2: + uses_viewport_index = true; + break; + case 3: + uses_point_size = true; + break; + } + } if (index == Attribute::Index::ClipDistances0123 || index == Attribute::Index::ClipDistances4567) { 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: return static_cast<std::size_t>(coverage_end * sizeof(u64)); } + bool UsesLayer() const { + return uses_layer; + } + + bool UsesViewportIndex() const { + return uses_viewport_index; + } + + bool UsesPointSize() const { + return uses_point_size; + } + bool HasPhysicalAttributes() const { return uses_physical_attributes; } @@ -343,6 +355,9 @@ private: std::set<Image> used_images; std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; + bool uses_layer{}; + bool uses_viewport_index{}; + bool uses_point_size{}; bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes Tegra::Shader::Header header; |