diff options
| author | 2018-04-14 11:50:15 -0500 | |
|---|---|---|
| committer | 2018-04-14 23:02:05 -0500 | |
| commit | c9b511da084bcf1655a7e844ee0d80e46ce681c9 (patch) | |
| tree | f0c06f5bbcc0f8e7ea6d3681060c12936e887359 /src | |
| parent | GPU: Allow configuring ssbos in the opengl state manager. (diff) | |
| download | yuzu-c9b511da084bcf1655a7e844ee0d80e46ce681c9.tar.gz yuzu-c9b511da084bcf1655a7e844ee0d80e46ce681c9.tar.xz yuzu-c9b511da084bcf1655a7e844ee0d80e46ce681c9.zip | |
GPU: Upload the entirety of each constbuffer for each shader stage as SSBOs.
We're going to need the shader generator to give us a mapping of the actual used const buffers to properly bind them to the shader.
Diffstat (limited to 'src')
4 files changed, 48 insertions, 14 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 71b862114..2a2268c20 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -306,6 +306,8 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 306 | 306 | ||
| 307 | // Sync and bind the texture surfaces | 307 | // Sync and bind the texture surfaces |
| 308 | BindTextures(); | 308 | BindTextures(); |
| 309 | // Configure the constant buffer objects | ||
| 310 | SetupConstBuffers(); | ||
| 309 | 311 | ||
| 310 | // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable | 312 | // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable |
| 311 | // scissor test to prevent drawing outside of the framebuffer region | 313 | // scissor test to prevent drawing outside of the framebuffer region |
| @@ -388,7 +390,7 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 388 | 390 | ||
| 389 | void RasterizerOpenGL::BindTextures() { | 391 | void RasterizerOpenGL::BindTextures() { |
| 390 | using Regs = Tegra::Engines::Maxwell3D::Regs; | 392 | using Regs = Tegra::Engines::Maxwell3D::Regs; |
| 391 | auto maxwell3d = Core::System::GetInstance().GPU().Get3DEngine(); | 393 | auto& maxwell3d = Core::System::GetInstance().GPU().Get3DEngine(); |
| 392 | 394 | ||
| 393 | // Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a | 395 | // Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a |
| 394 | // certain number in OpenGL. We try to only use the minimum amount of host textures by not | 396 | // certain number in OpenGL. We try to only use the minimum amount of host textures by not |
| @@ -535,6 +537,41 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr | |||
| 535 | } | 537 | } |
| 536 | } | 538 | } |
| 537 | 539 | ||
| 540 | void RasterizerOpenGL::SetupConstBuffers() { | ||
| 541 | using Regs = Tegra::Engines::Maxwell3D::Regs; | ||
| 542 | auto& gpu = Core::System::GetInstance().GPU(); | ||
| 543 | auto& maxwell3d = gpu.Get3DEngine(); | ||
| 544 | |||
| 545 | // Upload only the enabled buffers from the 16 constbuffers of each shader stage | ||
| 546 | u32 current_bindpoint = 0; | ||
| 547 | for (u32 stage = 0; stage < Regs::MaxShaderStage; ++stage) { | ||
| 548 | auto& shader_stage = maxwell3d.state.shader_stages[stage]; | ||
| 549 | bool stage_enabled = maxwell3d.IsShaderStageEnabled(static_cast<Regs::ShaderStage>(stage)); | ||
| 550 | |||
| 551 | for (u32 buffer_id = 0; buffer_id < Regs::MaxConstBuffers; ++buffer_id) { | ||
| 552 | const auto& buffer = shader_stage.const_buffers[buffer_id]; | ||
| 553 | |||
| 554 | state.draw.const_buffers[stage][buffer_id].enabled = buffer.enabled && stage_enabled; | ||
| 555 | |||
| 556 | if (buffer.enabled && stage_enabled) { | ||
| 557 | state.draw.const_buffers[stage][buffer_id].bindpoint = current_bindpoint; | ||
| 558 | current_bindpoint++; | ||
| 559 | |||
| 560 | VAddr addr = gpu.memory_manager->PhysicalToVirtualAddress(buffer.address); | ||
| 561 | const u8* data = Memory::GetPointer(addr); | ||
| 562 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, | ||
| 563 | state.draw.const_buffers[stage][buffer_id].ssbo); | ||
| 564 | glBufferData(GL_SHADER_STORAGE_BUFFER, buffer.size, data, GL_DYNAMIC_DRAW); | ||
| 565 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); | ||
| 566 | } else { | ||
| 567 | state.draw.const_buffers[stage][buffer_id].bindpoint = -1; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | state.Apply(); | ||
| 573 | } | ||
| 574 | |||
| 538 | void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, | 575 | void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, |
| 539 | const Surface& depth_surface, bool has_stencil) { | 576 | const Surface& depth_surface, bool has_stencil) { |
| 540 | state.draw.draw_framebuffer = framebuffer.handle; | 577 | state.draw.draw_framebuffer = framebuffer.handle; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 527866e8a..bf3308aef 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -87,6 +87,9 @@ private: | |||
| 87 | /// Binds the required textures to OpenGL before drawing a batch. | 87 | /// Binds the required textures to OpenGL before drawing a batch. |
| 88 | void BindTextures(); | 88 | void BindTextures(); |
| 89 | 89 | ||
| 90 | /// Configures the current constbuffers to use for the draw command. | ||
| 91 | void SetupConstBuffers(); | ||
| 92 | |||
| 90 | /// Syncs the viewport to match the guest state | 93 | /// Syncs the viewport to match the guest state |
| 91 | void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale); | 94 | void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale); |
| 92 | 95 | ||
| @@ -129,7 +132,9 @@ private: | |||
| 129 | std::array<bool, 16> hw_vao_enabled_attributes; | 132 | std::array<bool, 16> hw_vao_enabled_attributes; |
| 130 | 133 | ||
| 131 | std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers; | 134 | std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers; |
| 132 | std::array<std::array<OGLBuffer, 16>, 5> ssbos; | 135 | std::array<std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers>, |
| 136 | Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> | ||
| 137 | ssbos; | ||
| 133 | 138 | ||
| 134 | static constexpr size_t VERTEX_BUFFER_SIZE = 128 * 1024 * 1024; | 139 | static constexpr size_t VERTEX_BUFFER_SIZE = 128 * 1024 * 1024; |
| 135 | std::unique_ptr<OGLStreamBuffer> vertex_buffer; | 140 | std::unique_ptr<OGLStreamBuffer> vertex_buffer; |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 7fceedce8..85b838faa 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp | |||
| @@ -53,13 +53,6 @@ void SetShaderSamplerBindings(GLuint shader) { | |||
| 53 | 53 | ||
| 54 | } // namespace Impl | 54 | } // namespace Impl |
| 55 | 55 | ||
| 56 | void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) { | 56 | void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {} |
| 57 | const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; | ||
| 58 | for (unsigned index = 0; index < shader_stage.const_buffers.size(); ++index) { | ||
| 59 | const auto& const_buffer = shader_stage.const_buffers[index]; | ||
| 60 | const VAddr vaddr = memory_manager->PhysicalToVirtualAddress(const_buffer.address); | ||
| 61 | Memory::ReadBlock(vaddr, const_buffers[index].data(), sizeof(ConstBuffer)); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | 57 | ||
| 65 | } // namespace GLShader | 58 | } // namespace GLShader |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 5c8560cf5..f003ce532 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -30,11 +30,10 @@ void SetShaderSamplerBindings(GLuint shader); | |||
| 30 | // Not following that rule will cause problems on some AMD drivers. | 30 | // Not following that rule will cause problems on some AMD drivers. |
| 31 | struct MaxwellUniformData { | 31 | struct MaxwellUniformData { |
| 32 | void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); | 32 | void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); |
| 33 | 33 | // TODO(Subv): Use this for something. | |
| 34 | using ConstBuffer = std::array<GLvec4, 4>; | ||
| 35 | alignas(16) std::array<ConstBuffer, Maxwell3D::Regs::MaxConstBuffers> const_buffers; | ||
| 36 | }; | 34 | }; |
| 37 | static_assert(sizeof(MaxwellUniformData) == 1024, "MaxwellUniformData structure size is incorrect"); | 35 | // static_assert(sizeof(MaxwellUniformData) == 1024, "MaxwellUniformData structure size is |
| 36 | // incorrect"); | ||
| 38 | static_assert(sizeof(MaxwellUniformData) < 16384, | 37 | static_assert(sizeof(MaxwellUniformData) < 16384, |
| 39 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); | 38 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); |
| 40 | 39 | ||