diff options
| author | 2019-04-10 11:23:19 -0400 | |
|---|---|---|
| committer | 2019-04-10 11:23:19 -0400 | |
| commit | 97648f48418c4d37c91f91b4c36689d4d86d501c (patch) | |
| tree | 843f53aabde61418c2b1590e6ab4c2a466aaa92e /src | |
| parent | Merge pull request #2377 from lioncash/todo (diff) | |
| parent | renderer_opengl/utils: Skip empty binds (diff) | |
| download | yuzu-97648f48418c4d37c91f91b4c36689d4d86d501c.tar.gz yuzu-97648f48418c4d37c91f91b4c36689d4d86d501c.tar.xz yuzu-97648f48418c4d37c91f91b4c36689d4d86d501c.zip | |
Merge pull request #2345 from ReinUsesLisp/multibind
gl_rasterizer: Use ARB_multi_bind to update buffers with a single call per drawcall
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 47 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/utils.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/utils.h | 20 |
4 files changed, 69 insertions, 30 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 7ff1e6737..d250d5cbb 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -299,6 +299,10 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 299 | BaseBindings base_bindings; | 299 | BaseBindings base_bindings; |
| 300 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | 300 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; |
| 301 | 301 | ||
| 302 | // Prepare packed bindings | ||
| 303 | bind_ubo_pushbuffer.Setup(base_bindings.cbuf); | ||
| 304 | bind_ssbo_pushbuffer.Setup(base_bindings.gmem); | ||
| 305 | |||
| 302 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 306 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| 303 | const auto& shader_config = gpu.regs.shader_config[index]; | 307 | const auto& shader_config = gpu.regs.shader_config[index]; |
| 304 | const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)}; | 308 | const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)}; |
| @@ -321,8 +325,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 321 | &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment)); | 325 | &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment)); |
| 322 | 326 | ||
| 323 | // Bind the emulation info buffer | 327 | // Bind the emulation info buffer |
| 324 | glBindBufferRange(GL_UNIFORM_BUFFER, base_bindings.cbuf, buffer_cache.GetHandle(), offset, | 328 | bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), offset, |
| 325 | static_cast<GLsizeiptr>(sizeof(ubo))); | 329 | static_cast<GLsizeiptr>(sizeof(ubo))); |
| 326 | 330 | ||
| 327 | Shader shader{shader_cache.GetStageProgram(program)}; | 331 | Shader shader{shader_cache.GetStageProgram(program)}; |
| 328 | const auto [program_handle, next_bindings] = | 332 | const auto [program_handle, next_bindings] = |
| @@ -366,6 +370,9 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 366 | base_bindings = next_bindings; | 370 | base_bindings = next_bindings; |
| 367 | } | 371 | } |
| 368 | 372 | ||
| 373 | bind_ubo_pushbuffer.Bind(); | ||
| 374 | bind_ssbo_pushbuffer.Bind(); | ||
| 375 | |||
| 369 | SyncClipEnabled(clip_distances); | 376 | SyncClipEnabled(clip_distances); |
| 370 | 377 | ||
| 371 | gpu.dirty_flags.shaders = false; | 378 | gpu.dirty_flags.shaders = false; |
| @@ -900,23 +907,14 @@ void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::Shader | |||
| 900 | const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)]; | 907 | const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)]; |
| 901 | const auto& entries = shader->GetShaderEntries().const_buffers; | 908 | const auto& entries = shader->GetShaderEntries().const_buffers; |
| 902 | 909 | ||
| 903 | constexpr u64 max_binds = Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers; | ||
| 904 | std::array<GLuint, max_binds> bind_buffers; | ||
| 905 | std::array<GLintptr, max_binds> bind_offsets; | ||
| 906 | std::array<GLsizeiptr, max_binds> bind_sizes; | ||
| 907 | |||
| 908 | ASSERT_MSG(entries.size() <= max_binds, "Exceeded expected number of binding points."); | ||
| 909 | |||
| 910 | // Upload only the enabled buffers from the 16 constbuffers of each shader stage | 910 | // Upload only the enabled buffers from the 16 constbuffers of each shader stage |
| 911 | for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { | 911 | for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { |
| 912 | const auto& used_buffer = entries[bindpoint]; | 912 | const auto& used_buffer = entries[bindpoint]; |
| 913 | const auto& buffer = shader_stage.const_buffers[used_buffer.GetIndex()]; | 913 | const auto& buffer = shader_stage.const_buffers[used_buffer.GetIndex()]; |
| 914 | 914 | ||
| 915 | if (!buffer.enabled) { | 915 | if (!buffer.enabled) { |
| 916 | // With disabled buffers set values as zero to unbind them | 916 | // Set values to zero to unbind buffers |
| 917 | bind_buffers[bindpoint] = 0; | 917 | bind_ubo_pushbuffer.Push(0, 0, 0); |
| 918 | bind_offsets[bindpoint] = 0; | ||
| 919 | bind_sizes[bindpoint] = 0; | ||
| 920 | continue; | 918 | continue; |
| 921 | } | 919 | } |
| 922 | 920 | ||
| @@ -944,30 +942,19 @@ void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::Shader | |||
| 944 | const GLintptr const_buffer_offset = buffer_cache.UploadMemory( | 942 | const GLintptr const_buffer_offset = buffer_cache.UploadMemory( |
| 945 | buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment)); | 943 | buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment)); |
| 946 | 944 | ||
| 947 | // Prepare values for multibind | 945 | bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), const_buffer_offset, size); |
| 948 | bind_buffers[bindpoint] = buffer_cache.GetHandle(); | ||
| 949 | bind_offsets[bindpoint] = const_buffer_offset; | ||
| 950 | bind_sizes[bindpoint] = size; | ||
| 951 | } | 946 | } |
| 952 | |||
| 953 | // The first binding is reserved for emulation values | ||
| 954 | const GLuint ubo_base_binding = base_bindings.cbuf + 1; | ||
| 955 | glBindBuffersRange(GL_UNIFORM_BUFFER, ubo_base_binding, static_cast<GLsizei>(entries.size()), | ||
| 956 | bind_buffers.data(), bind_offsets.data(), bind_sizes.data()); | ||
| 957 | } | 947 | } |
| 958 | 948 | ||
| 959 | void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, | 949 | void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, |
| 960 | const Shader& shader, GLenum primitive_mode, | 950 | const Shader& shader, GLenum primitive_mode, |
| 961 | BaseBindings base_bindings) { | 951 | BaseBindings base_bindings) { |
| 962 | // TODO(Rodrigo): Use ARB_multi_bind here | ||
| 963 | const auto& entries = shader->GetShaderEntries().global_memory_entries; | 952 | const auto& entries = shader->GetShaderEntries().global_memory_entries; |
| 964 | 953 | for (std::size_t bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { | |
| 965 | for (u32 bindpoint = 0; bindpoint < static_cast<u32>(entries.size()); ++bindpoint) { | 954 | const auto& entry{entries[bindpoint]}; |
| 966 | const auto& entry = entries[bindpoint]; | 955 | const auto& region{global_cache.GetGlobalRegion(entry, stage)}; |
| 967 | const u32 current_bindpoint = base_bindings.gmem + bindpoint; | 956 | bind_ssbo_pushbuffer.Push(region->GetBufferHandle(), 0, |
| 968 | const auto& region = global_cache.GetGlobalRegion(entry, stage); | 957 | static_cast<GLsizeiptr>(region->GetSizeInBytes())); |
| 969 | |||
| 970 | glBindBufferBase(GL_SHADER_STORAGE_BUFFER, current_bindpoint, region->GetBufferHandle()); | ||
| 971 | } | 958 | } |
| 972 | } | 959 | } |
| 973 | 960 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 54fbf48aa..e4c64ae71 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "video_core/renderer_opengl/gl_shader_cache.h" | 28 | #include "video_core/renderer_opengl/gl_shader_cache.h" |
| 29 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 29 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| 30 | #include "video_core/renderer_opengl/gl_state.h" | 30 | #include "video_core/renderer_opengl/gl_state.h" |
| 31 | #include "video_core/renderer_opengl/utils.h" | ||
| 31 | 32 | ||
| 32 | namespace Core { | 33 | namespace Core { |
| 33 | class System; | 34 | class System; |
| @@ -229,6 +230,9 @@ private: | |||
| 229 | PrimitiveAssembler primitive_assembler{buffer_cache}; | 230 | PrimitiveAssembler primitive_assembler{buffer_cache}; |
| 230 | GLint uniform_buffer_alignment; | 231 | GLint uniform_buffer_alignment; |
| 231 | 232 | ||
| 233 | BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER}; | ||
| 234 | BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER}; | ||
| 235 | |||
| 232 | std::size_t CalculateVertexArraysSize() const; | 236 | std::size_t CalculateVertexArraysSize() const; |
| 233 | 237 | ||
| 234 | std::size_t CalculateIndexBufferSize() const; | 238 | std::size_t CalculateIndexBufferSize() const; |
diff --git a/src/video_core/renderer_opengl/utils.cpp b/src/video_core/renderer_opengl/utils.cpp index d84634cb3..84a987371 100644 --- a/src/video_core/renderer_opengl/utils.cpp +++ b/src/video_core/renderer_opengl/utils.cpp | |||
| @@ -5,11 +5,39 @@ | |||
| 5 | #include <string> | 5 | #include <string> |
| 6 | #include <fmt/format.h> | 6 | #include <fmt/format.h> |
| 7 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 8 | #include "common/assert.h" | ||
| 8 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 9 | #include "video_core/renderer_opengl/utils.h" | 10 | #include "video_core/renderer_opengl/utils.h" |
| 10 | 11 | ||
| 11 | namespace OpenGL { | 12 | namespace OpenGL { |
| 12 | 13 | ||
| 14 | BindBuffersRangePushBuffer::BindBuffersRangePushBuffer(GLenum target) : target{target} {} | ||
| 15 | |||
| 16 | BindBuffersRangePushBuffer::~BindBuffersRangePushBuffer() = default; | ||
| 17 | |||
| 18 | void BindBuffersRangePushBuffer::Setup(GLuint first_) { | ||
| 19 | first = first_; | ||
| 20 | buffers.clear(); | ||
| 21 | offsets.clear(); | ||
| 22 | sizes.clear(); | ||
| 23 | } | ||
| 24 | |||
| 25 | void BindBuffersRangePushBuffer::Push(GLuint buffer, GLintptr offset, GLsizeiptr size) { | ||
| 26 | buffers.push_back(buffer); | ||
| 27 | offsets.push_back(offset); | ||
| 28 | sizes.push_back(size); | ||
| 29 | } | ||
| 30 | |||
| 31 | void BindBuffersRangePushBuffer::Bind() const { | ||
| 32 | const std::size_t count{buffers.size()}; | ||
| 33 | DEBUG_ASSERT(count == offsets.size() && count == sizes.size()); | ||
| 34 | if (count == 0) { | ||
| 35 | return; | ||
| 36 | } | ||
| 37 | glBindBuffersRange(target, first, static_cast<GLsizei>(count), buffers.data(), offsets.data(), | ||
| 38 | sizes.data()); | ||
| 39 | } | ||
| 40 | |||
| 13 | void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info) { | 41 | void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info) { |
| 14 | if (!GLAD_GL_KHR_debug) { | 42 | if (!GLAD_GL_KHR_debug) { |
| 15 | return; // We don't need to throw an error as this is just for debugging | 43 | return; // We don't need to throw an error as this is just for debugging |
diff --git a/src/video_core/renderer_opengl/utils.h b/src/video_core/renderer_opengl/utils.h index 1fcb6fc11..aef45c9dc 100644 --- a/src/video_core/renderer_opengl/utils.h +++ b/src/video_core/renderer_opengl/utils.h | |||
| @@ -5,11 +5,31 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <vector> | ||
| 8 | #include <glad/glad.h> | 9 | #include <glad/glad.h> |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | 11 | ||
| 11 | namespace OpenGL { | 12 | namespace OpenGL { |
| 12 | 13 | ||
| 14 | class BindBuffersRangePushBuffer { | ||
| 15 | public: | ||
| 16 | BindBuffersRangePushBuffer(GLenum target); | ||
| 17 | ~BindBuffersRangePushBuffer(); | ||
| 18 | |||
| 19 | void Setup(GLuint first_); | ||
| 20 | |||
| 21 | void Push(GLuint buffer, GLintptr offset, GLsizeiptr size); | ||
| 22 | |||
| 23 | void Bind() const; | ||
| 24 | |||
| 25 | private: | ||
| 26 | GLenum target; | ||
| 27 | GLuint first; | ||
| 28 | std::vector<GLuint> buffers; | ||
| 29 | std::vector<GLintptr> offsets; | ||
| 30 | std::vector<GLsizeiptr> sizes; | ||
| 31 | }; | ||
| 32 | |||
| 13 | void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info = ""); | 33 | void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info = ""); |
| 14 | 34 | ||
| 15 | } // namespace OpenGL \ No newline at end of file | 35 | } // namespace OpenGL \ No newline at end of file |