diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 9985e0d50c..3a4e88e4e1 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -13,6 +13,7 @@ constexpr u32 MacroRegistersStart = 0xE00; const std::unordered_map Maxwell3D::method_handlers = { {0xE24, {"SetShader", 5, &Maxwell3D::SetShader}}, + {0xE2A, {"BindStorageBuffer", 1, &Maxwell3D::BindStorageBuffer}}, }; Maxwell3D::Maxwell3D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} @@ -200,6 +201,26 @@ void Maxwell3D::SetShader(const std::vector& parameters) { ProcessCBBind(shader_stage); } +void Maxwell3D::BindStorageBuffer(const std::vector& parameters) { + /** + * Parameters description: + * [0] = Buffer offset >> 2 + */ + + u32 buffer_offset = parameters[0] << 2; + + // Perform the same operations as the real macro code. + // Note: This value is hardcoded in the macro's code. + static constexpr u32 DefaultCBSize = 0x5F00; + regs.const_buffer.cb_size = DefaultCBSize; + + GPUVAddr address = regs.ssbo_info.BufferAddress(); + regs.const_buffer.cb_address_high = address >> 32; + regs.const_buffer.cb_address_low = address & 0xFFFFFFFF; + + regs.const_buffer.cb_pos = buffer_offset; +} + void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { // Bind the buffer currently in CB_ADDRESS to the specified index in the desired shader stage. auto& shader = state.shader_stages[static_cast(stage)]; diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 93b42b53c1..3e97d9045c 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -166,7 +166,19 @@ public: u32 tex_cb_index; - INSERT_PADDING_WORDS(0x4B3); + INSERT_PADDING_WORDS(0x395); + + struct { + /// Compressed address of a buffer that holds information about bound SSBOs. + /// This address is usually bound to c0 in the shaders. + u32 buffer_address; + + GPUVAddr BufferAddress() const { + return static_cast(buffer_address) << 8; + } + } ssbo_info; + + INSERT_PADDING_WORDS(0x11D); }; std::array reg_array; }; @@ -229,6 +241,7 @@ private: /// Method call handlers void SetShader(const std::vector& parameters); + void BindStorageBuffer(const std::vector& parameters); struct MethodInfo { const char* name; @@ -252,6 +265,7 @@ ASSERT_REG_POSITION(shader_config[0], 0x800); ASSERT_REG_POSITION(const_buffer, 0x8E0); ASSERT_REG_POSITION(cb_bind[0], 0x904); ASSERT_REG_POSITION(tex_cb_index, 0x982); +ASSERT_REG_POSITION(ssbo_info, 0xD18); #undef ASSERT_REG_POSITION