Просмотр исходного кода

shader/other: Implement MEMBAR.CTS

This silences an assertion we were hitting and uses workgroup memory
barriers when the game requests it.
ReinUsesLisp 6 лет назад
Родитель
Сommit
32e6727dae

+ 8 - 2
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -2344,7 +2344,12 @@ private:
         return {};
     }
 
-    Expression MemoryBarrierGL(Operation) {
+    Expression MemoryBarrierGroup(Operation) {
+        code.AddLine("groupMemoryBarrier();");
+        return {};
+    }
+
+    Expression MemoryBarrierGlobal(Operation) {
         code.AddLine("memoryBarrier();");
         return {};
     }
@@ -2591,7 +2596,8 @@ private:
         &GLSLDecompiler::ShuffleIndexed,
 
         &GLSLDecompiler::Barrier,
-        &GLSLDecompiler::MemoryBarrierGL,
+        &GLSLDecompiler::MemoryBarrierGroup,
+        &GLSLDecompiler::MemoryBarrierGlobal,
     };
     static_assert(operation_decompilers.size() == static_cast<std::size_t>(OperationCode::Amount));
 

+ 4 - 3
src/video_core/renderer_vulkan/vk_shader_decompiler.cpp

@@ -2215,8 +2215,8 @@ private:
         return {};
     }
 
-    Expression MemoryBarrierGL(Operation) {
-        const auto scope = spv::Scope::Device;
+    template <spv::Scope scope>
+    Expression MemoryBarrier(Operation) {
         const auto semantics =
             spv::MemorySemanticsMask::AcquireRelease | spv::MemorySemanticsMask::UniformMemory |
             spv::MemorySemanticsMask::WorkgroupMemory |
@@ -2681,7 +2681,8 @@ private:
         &SPIRVDecompiler::ShuffleIndexed,
 
         &SPIRVDecompiler::Barrier,
-        &SPIRVDecompiler::MemoryBarrierGL,
+        &SPIRVDecompiler::MemoryBarrier<spv::Scope::Workgroup>,
+        &SPIRVDecompiler::MemoryBarrier<spv::Scope::Device>,
     };
     static_assert(operation_decompilers.size() == static_cast<std::size_t>(OperationCode::Amount));
 

+ 12 - 2
src/video_core/shader/decode/other.cpp

@@ -299,9 +299,19 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
         break;
     }
     case OpCode::Id::MEMBAR: {
-        UNIMPLEMENTED_IF(instr.membar.type != Tegra::Shader::MembarType::GL);
         UNIMPLEMENTED_IF(instr.membar.unknown != Tegra::Shader::MembarUnknown::Default);
-        bb.push_back(Operation(OperationCode::MemoryBarrierGL));
+        const OperationCode type = [instr] {
+            switch (instr.membar.type) {
+            case Tegra::Shader::MembarType::CTA:
+                return OperationCode::MemoryBarrierGroup;
+            case Tegra::Shader::MembarType::GL:
+                return OperationCode::MemoryBarrierGlobal;
+            default:
+                UNIMPLEMENTED_MSG("MEMBAR type={}", static_cast<int>(instr.membar.type.Value()));
+                return OperationCode::MemoryBarrierGlobal;
+            }
+        }();
+        bb.push_back(Operation(type));
         break;
     }
     case OpCode::Id::DEPBAR: {

+ 3 - 2
src/video_core/shader/node.h

@@ -233,8 +233,9 @@ enum class OperationCode {
     ThreadLtMask,   /// () -> uint
     ShuffleIndexed, /// (uint value, uint index) -> uint
 
-    Barrier,         /// () -> void
-    MemoryBarrierGL, /// () -> void
+    Barrier,             /// () -> void
+    MemoryBarrierGroup,  /// () -> void
+    MemoryBarrierGlobal, /// () -> void
 
     Amount,
 };