Merge pull request #2345 from ReinUsesLisp/multibind
gl_rasterizer: Use ARB_multi_bind to update buffers with a single call per drawcall
This commit is contained in:
		
						commit
						97648f4841
					
				@ -299,6 +299,10 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
 | 
				
			|||||||
    BaseBindings base_bindings;
 | 
					    BaseBindings base_bindings;
 | 
				
			||||||
    std::array<bool, Maxwell::NumClipDistances> clip_distances{};
 | 
					    std::array<bool, Maxwell::NumClipDistances> clip_distances{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Prepare packed bindings
 | 
				
			||||||
 | 
					    bind_ubo_pushbuffer.Setup(base_bindings.cbuf);
 | 
				
			||||||
 | 
					    bind_ssbo_pushbuffer.Setup(base_bindings.gmem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
 | 
					    for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
 | 
				
			||||||
        const auto& shader_config = gpu.regs.shader_config[index];
 | 
					        const auto& shader_config = gpu.regs.shader_config[index];
 | 
				
			||||||
        const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)};
 | 
					        const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)};
 | 
				
			||||||
@ -321,7 +325,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
 | 
				
			|||||||
            &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment));
 | 
					            &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Bind the emulation info buffer
 | 
					        // Bind the emulation info buffer
 | 
				
			||||||
        glBindBufferRange(GL_UNIFORM_BUFFER, base_bindings.cbuf, buffer_cache.GetHandle(), offset,
 | 
					        bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), offset,
 | 
				
			||||||
                                 static_cast<GLsizeiptr>(sizeof(ubo)));
 | 
					                                 static_cast<GLsizeiptr>(sizeof(ubo)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Shader shader{shader_cache.GetStageProgram(program)};
 | 
					        Shader shader{shader_cache.GetStageProgram(program)};
 | 
				
			||||||
@ -366,6 +370,9 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
 | 
				
			|||||||
        base_bindings = next_bindings;
 | 
					        base_bindings = next_bindings;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bind_ubo_pushbuffer.Bind();
 | 
				
			||||||
 | 
					    bind_ssbo_pushbuffer.Bind();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SyncClipEnabled(clip_distances);
 | 
					    SyncClipEnabled(clip_distances);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gpu.dirty_flags.shaders = false;
 | 
					    gpu.dirty_flags.shaders = false;
 | 
				
			||||||
@ -900,23 +907,14 @@ void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::Shader
 | 
				
			|||||||
    const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)];
 | 
					    const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)];
 | 
				
			||||||
    const auto& entries = shader->GetShaderEntries().const_buffers;
 | 
					    const auto& entries = shader->GetShaderEntries().const_buffers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constexpr u64 max_binds = Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers;
 | 
					 | 
				
			||||||
    std::array<GLuint, max_binds> bind_buffers;
 | 
					 | 
				
			||||||
    std::array<GLintptr, max_binds> bind_offsets;
 | 
					 | 
				
			||||||
    std::array<GLsizeiptr, max_binds> bind_sizes;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ASSERT_MSG(entries.size() <= max_binds, "Exceeded expected number of binding points.");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Upload only the enabled buffers from the 16 constbuffers of each shader stage
 | 
					    // Upload only the enabled buffers from the 16 constbuffers of each shader stage
 | 
				
			||||||
    for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
 | 
					    for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
 | 
				
			||||||
        const auto& used_buffer = entries[bindpoint];
 | 
					        const auto& used_buffer = entries[bindpoint];
 | 
				
			||||||
        const auto& buffer = shader_stage.const_buffers[used_buffer.GetIndex()];
 | 
					        const auto& buffer = shader_stage.const_buffers[used_buffer.GetIndex()];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!buffer.enabled) {
 | 
					        if (!buffer.enabled) {
 | 
				
			||||||
            // With disabled buffers set values as zero to unbind them
 | 
					            // Set values to zero to unbind buffers
 | 
				
			||||||
            bind_buffers[bindpoint] = 0;
 | 
					            bind_ubo_pushbuffer.Push(0, 0, 0);
 | 
				
			||||||
            bind_offsets[bindpoint] = 0;
 | 
					 | 
				
			||||||
            bind_sizes[bindpoint] = 0;
 | 
					 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -944,30 +942,19 @@ void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::Shader
 | 
				
			|||||||
        const GLintptr const_buffer_offset = buffer_cache.UploadMemory(
 | 
					        const GLintptr const_buffer_offset = buffer_cache.UploadMemory(
 | 
				
			||||||
            buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment));
 | 
					            buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Prepare values for multibind
 | 
					        bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), const_buffer_offset, size);
 | 
				
			||||||
        bind_buffers[bindpoint] = buffer_cache.GetHandle();
 | 
					 | 
				
			||||||
        bind_offsets[bindpoint] = const_buffer_offset;
 | 
					 | 
				
			||||||
        bind_sizes[bindpoint] = size;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // The first binding is reserved for emulation values
 | 
					 | 
				
			||||||
    const GLuint ubo_base_binding = base_bindings.cbuf + 1;
 | 
					 | 
				
			||||||
    glBindBuffersRange(GL_UNIFORM_BUFFER, ubo_base_binding, static_cast<GLsizei>(entries.size()),
 | 
					 | 
				
			||||||
                       bind_buffers.data(), bind_offsets.data(), bind_sizes.data());
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
 | 
					void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
 | 
				
			||||||
                                          const Shader& shader, GLenum primitive_mode,
 | 
					                                          const Shader& shader, GLenum primitive_mode,
 | 
				
			||||||
                                          BaseBindings base_bindings) {
 | 
					                                          BaseBindings base_bindings) {
 | 
				
			||||||
    // TODO(Rodrigo): Use ARB_multi_bind here
 | 
					 | 
				
			||||||
    const auto& entries = shader->GetShaderEntries().global_memory_entries;
 | 
					    const auto& entries = shader->GetShaderEntries().global_memory_entries;
 | 
				
			||||||
 | 
					    for (std::size_t bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
 | 
				
			||||||
    for (u32 bindpoint = 0; bindpoint < static_cast<u32>(entries.size()); ++bindpoint) {
 | 
					        const auto& entry{entries[bindpoint]};
 | 
				
			||||||
        const auto& entry = entries[bindpoint];
 | 
					        const auto& region{global_cache.GetGlobalRegion(entry, stage)};
 | 
				
			||||||
        const u32 current_bindpoint = base_bindings.gmem + bindpoint;
 | 
					        bind_ssbo_pushbuffer.Push(region->GetBufferHandle(), 0,
 | 
				
			||||||
        const auto& region = global_cache.GetGlobalRegion(entry, stage);
 | 
					                                  static_cast<GLsizeiptr>(region->GetSizeInBytes()));
 | 
				
			||||||
 | 
					 | 
				
			||||||
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, current_bindpoint, region->GetBufferHandle());
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,7 @@
 | 
				
			|||||||
#include "video_core/renderer_opengl/gl_shader_cache.h"
 | 
					#include "video_core/renderer_opengl/gl_shader_cache.h"
 | 
				
			||||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
 | 
					#include "video_core/renderer_opengl/gl_shader_manager.h"
 | 
				
			||||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
					#include "video_core/renderer_opengl/gl_state.h"
 | 
				
			||||||
 | 
					#include "video_core/renderer_opengl/utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Core {
 | 
					namespace Core {
 | 
				
			||||||
class System;
 | 
					class System;
 | 
				
			||||||
@ -229,6 +230,9 @@ private:
 | 
				
			|||||||
    PrimitiveAssembler primitive_assembler{buffer_cache};
 | 
					    PrimitiveAssembler primitive_assembler{buffer_cache};
 | 
				
			||||||
    GLint uniform_buffer_alignment;
 | 
					    GLint uniform_buffer_alignment;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER};
 | 
				
			||||||
 | 
					    BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::size_t CalculateVertexArraysSize() const;
 | 
					    std::size_t CalculateVertexArraysSize() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::size_t CalculateIndexBufferSize() const;
 | 
					    std::size_t CalculateIndexBufferSize() const;
 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,39 @@
 | 
				
			|||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <fmt/format.h>
 | 
					#include <fmt/format.h>
 | 
				
			||||||
#include <glad/glad.h>
 | 
					#include <glad/glad.h>
 | 
				
			||||||
 | 
					#include "common/assert.h"
 | 
				
			||||||
#include "common/common_types.h"
 | 
					#include "common/common_types.h"
 | 
				
			||||||
#include "video_core/renderer_opengl/utils.h"
 | 
					#include "video_core/renderer_opengl/utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenGL {
 | 
					namespace OpenGL {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BindBuffersRangePushBuffer::BindBuffersRangePushBuffer(GLenum target) : target{target} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BindBuffersRangePushBuffer::~BindBuffersRangePushBuffer() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BindBuffersRangePushBuffer::Setup(GLuint first_) {
 | 
				
			||||||
 | 
					    first = first_;
 | 
				
			||||||
 | 
					    buffers.clear();
 | 
				
			||||||
 | 
					    offsets.clear();
 | 
				
			||||||
 | 
					    sizes.clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BindBuffersRangePushBuffer::Push(GLuint buffer, GLintptr offset, GLsizeiptr size) {
 | 
				
			||||||
 | 
					    buffers.push_back(buffer);
 | 
				
			||||||
 | 
					    offsets.push_back(offset);
 | 
				
			||||||
 | 
					    sizes.push_back(size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void BindBuffersRangePushBuffer::Bind() const {
 | 
				
			||||||
 | 
					    const std::size_t count{buffers.size()};
 | 
				
			||||||
 | 
					    DEBUG_ASSERT(count == offsets.size() && count == sizes.size());
 | 
				
			||||||
 | 
					    if (count == 0) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glBindBuffersRange(target, first, static_cast<GLsizei>(count), buffers.data(), offsets.data(),
 | 
				
			||||||
 | 
					                       sizes.data());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info) {
 | 
					void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info) {
 | 
				
			||||||
    if (!GLAD_GL_KHR_debug) {
 | 
					    if (!GLAD_GL_KHR_debug) {
 | 
				
			||||||
        return; // We don't need to throw an error as this is just for debugging
 | 
					        return; // We don't need to throw an error as this is just for debugging
 | 
				
			||||||
 | 
				
			|||||||
@ -5,11 +5,31 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
#include <glad/glad.h>
 | 
					#include <glad/glad.h>
 | 
				
			||||||
#include "common/common_types.h"
 | 
					#include "common/common_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenGL {
 | 
					namespace OpenGL {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BindBuffersRangePushBuffer {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    BindBuffersRangePushBuffer(GLenum target);
 | 
				
			||||||
 | 
					    ~BindBuffersRangePushBuffer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Setup(GLuint first_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Push(GLuint buffer, GLintptr offset, GLsizeiptr size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Bind() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    GLenum target;
 | 
				
			||||||
 | 
					    GLuint first;
 | 
				
			||||||
 | 
					    std::vector<GLuint> buffers;
 | 
				
			||||||
 | 
					    std::vector<GLintptr> offsets;
 | 
				
			||||||
 | 
					    std::vector<GLsizeiptr> sizes;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info = "");
 | 
					void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string extra_info = "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace OpenGL
 | 
					} // namespace OpenGL
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user