buffer_cache: Return handles instead of pointer to handles
The original idea of returning pointers is that handles can be moved. The problem is that the implementation didn't take that in mind and made everything harder to work with. This commit drops pointer to handles and returns the handles themselves. While it is still true that handles can be invalidated, this way we get an old handle instead of a dangling pointer. This problem can be solved in the future with sparse buffers.
This commit is contained in:
parent
7e4a132a77
commit
090fd3fefa
14 changed files with 90 additions and 228 deletions
|
@ -55,33 +55,31 @@ void OGLBufferCache::WriteBarrier() {
|
|||
glMemoryBarrier(GL_ALL_BARRIER_BITS);
|
||||
}
|
||||
|
||||
const GLuint* OGLBufferCache::ToHandle(const Buffer& buffer) {
|
||||
GLuint OGLBufferCache::ToHandle(const Buffer& buffer) {
|
||||
return buffer->GetHandle();
|
||||
}
|
||||
|
||||
const GLuint* OGLBufferCache::GetEmptyBuffer(std::size_t) {
|
||||
static const GLuint null_buffer = 0;
|
||||
return &null_buffer;
|
||||
GLuint OGLBufferCache::GetEmptyBuffer(std::size_t) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OGLBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
|
||||
const u8* data) {
|
||||
glNamedBufferSubData(*buffer->GetHandle(), static_cast<GLintptr>(offset),
|
||||
glNamedBufferSubData(buffer->GetHandle(), static_cast<GLintptr>(offset),
|
||||
static_cast<GLsizeiptr>(size), data);
|
||||
}
|
||||
|
||||
void OGLBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
|
||||
u8* data) {
|
||||
MICROPROFILE_SCOPE(OpenGL_Buffer_Download);
|
||||
glGetNamedBufferSubData(*buffer->GetHandle(), static_cast<GLintptr>(offset),
|
||||
glGetNamedBufferSubData(buffer->GetHandle(), static_cast<GLintptr>(offset),
|
||||
static_cast<GLsizeiptr>(size), data);
|
||||
}
|
||||
|
||||
void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
|
||||
std::size_t dst_offset, std::size_t size) {
|
||||
glCopyNamedBufferSubData(*src->GetHandle(), *dst->GetHandle(),
|
||||
static_cast<GLintptr>(src_offset), static_cast<GLintptr>(dst_offset),
|
||||
static_cast<GLsizeiptr>(size));
|
||||
glCopyNamedBufferSubData(src->GetHandle(), dst->GetHandle(), static_cast<GLintptr>(src_offset),
|
||||
static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size));
|
||||
}
|
||||
|
||||
OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer,
|
||||
|
@ -89,7 +87,7 @@ OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_poi
|
|||
DEBUG_ASSERT(cbuf_cursor < std::size(cbufs));
|
||||
const GLuint& cbuf = cbufs[cbuf_cursor++];
|
||||
glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer);
|
||||
return {&cbuf, 0};
|
||||
return {cbuf, 0};
|
||||
}
|
||||
|
||||
} // namespace OpenGL
|
||||
|
|
|
@ -34,12 +34,12 @@ public:
|
|||
explicit CachedBufferBlock(VAddr cpu_addr, const std::size_t size);
|
||||
~CachedBufferBlock();
|
||||
|
||||
const GLuint* GetHandle() const {
|
||||
return &gl_buffer.handle;
|
||||
GLuint GetHandle() const {
|
||||
return gl_buffer.handle;
|
||||
}
|
||||
|
||||
private:
|
||||
OGLBuffer gl_buffer{};
|
||||
OGLBuffer gl_buffer;
|
||||
};
|
||||
|
||||
class OGLBufferCache final : public GenericBufferCache {
|
||||
|
@ -48,7 +48,7 @@ public:
|
|||
const Device& device, std::size_t stream_size);
|
||||
~OGLBufferCache();
|
||||
|
||||
const GLuint* GetEmptyBuffer(std::size_t) override;
|
||||
GLuint GetEmptyBuffer(std::size_t) override;
|
||||
|
||||
void Acquire() noexcept {
|
||||
cbuf_cursor = 0;
|
||||
|
@ -57,9 +57,9 @@ public:
|
|||
protected:
|
||||
Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override;
|
||||
|
||||
void WriteBarrier() override;
|
||||
GLuint ToHandle(const Buffer& buffer) override;
|
||||
|
||||
const GLuint* ToHandle(const Buffer& buffer) override;
|
||||
void WriteBarrier() override;
|
||||
|
||||
void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
|
||||
const u8* data) override;
|
||||
|
|
|
@ -188,10 +188,8 @@ void RasterizerOpenGL::SetupVertexBuffer() {
|
|||
ASSERT(end > start);
|
||||
const u64 size = end - start + 1;
|
||||
const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size);
|
||||
|
||||
// Bind the vertex array to the buffer at the current offset.
|
||||
vertex_array_pushbuffer.SetVertexBuffer(static_cast<GLuint>(index), vertex_buffer,
|
||||
vertex_buffer_offset, vertex_array.stride);
|
||||
glBindVertexBuffer(static_cast<GLuint>(index), vertex_buffer, vertex_buffer_offset,
|
||||
vertex_array.stride);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,7 +220,7 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer() {
|
|||
const auto& regs = system.GPU().Maxwell3D().regs;
|
||||
const std::size_t size = CalculateIndexBufferSize();
|
||||
const auto [buffer, offset] = buffer_cache.UploadMemory(regs.index_array.IndexStart(), size);
|
||||
vertex_array_pushbuffer.SetIndexBuffer(buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -524,7 +522,6 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
|
|||
|
||||
// Prepare vertex array format.
|
||||
SetupVertexFormat();
|
||||
vertex_array_pushbuffer.Setup();
|
||||
|
||||
// Upload vertex and index data.
|
||||
SetupVertexBuffer();
|
||||
|
@ -534,17 +531,13 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
|
|||
index_buffer_offset = SetupIndexBuffer();
|
||||
}
|
||||
|
||||
// Prepare packed bindings.
|
||||
bind_ubo_pushbuffer.Setup();
|
||||
bind_ssbo_pushbuffer.Setup();
|
||||
|
||||
// Setup emulation uniform buffer.
|
||||
GLShader::MaxwellUniformData ubo;
|
||||
ubo.SetFromRegs(gpu);
|
||||
const auto [buffer, offset] =
|
||||
buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment());
|
||||
bind_ubo_pushbuffer.Push(EmulationUniformBlockBinding, buffer, offset,
|
||||
static_cast<GLsizeiptr>(sizeof(ubo)));
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, EmulationUniformBlockBinding, buffer, offset,
|
||||
static_cast<GLsizeiptr>(sizeof(ubo)));
|
||||
|
||||
// Setup shaders and their used resources.
|
||||
texture_cache.GuardSamplers(true);
|
||||
|
@ -557,11 +550,6 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
|
|||
// Signal the buffer cache that we are not going to upload more things.
|
||||
buffer_cache.Unmap();
|
||||
|
||||
// Now that we are no longer uploading data, we can safely bind the buffers to OpenGL.
|
||||
vertex_array_pushbuffer.Bind();
|
||||
bind_ubo_pushbuffer.Bind();
|
||||
bind_ssbo_pushbuffer.Bind();
|
||||
|
||||
program_manager.BindGraphicsPipeline();
|
||||
|
||||
if (texture_cache.TextureBarrier()) {
|
||||
|
@ -630,17 +618,11 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
|
|||
(Maxwell::MaxConstBufferSize + device.GetUniformBufferAlignment());
|
||||
buffer_cache.Map(buffer_size);
|
||||
|
||||
bind_ubo_pushbuffer.Setup();
|
||||
bind_ssbo_pushbuffer.Setup();
|
||||
|
||||
SetupComputeConstBuffers(kernel);
|
||||
SetupComputeGlobalMemory(kernel);
|
||||
|
||||
buffer_cache.Unmap();
|
||||
|
||||
bind_ubo_pushbuffer.Bind();
|
||||
bind_ssbo_pushbuffer.Bind();
|
||||
|
||||
const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
|
||||
glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z);
|
||||
++num_queued_commands;
|
||||
|
@ -771,8 +753,8 @@ void RasterizerOpenGL::SetupConstBuffer(u32 binding, const Tegra::Engines::Const
|
|||
const ConstBufferEntry& entry) {
|
||||
if (!buffer.enabled) {
|
||||
// Set values to zero to unbind buffers
|
||||
bind_ubo_pushbuffer.Push(binding, buffer_cache.GetEmptyBuffer(sizeof(float)), 0,
|
||||
sizeof(float));
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, binding, buffer_cache.GetEmptyBuffer(sizeof(float)), 0,
|
||||
sizeof(float));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -783,7 +765,7 @@ void RasterizerOpenGL::SetupConstBuffer(u32 binding, const Tegra::Engines::Const
|
|||
const auto alignment = device.GetUniformBufferAlignment();
|
||||
const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment, false,
|
||||
device.HasFastBufferSubData());
|
||||
bind_ubo_pushbuffer.Push(binding, cbuf, offset, size);
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, binding, cbuf, offset, size);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, const Shader& shader) {
|
||||
|
@ -819,7 +801,8 @@ void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& e
|
|||
const auto alignment{device.GetShaderStorageBufferAlignment()};
|
||||
const auto [ssbo, buffer_offset] =
|
||||
buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.IsWritten());
|
||||
bind_ssbo_pushbuffer.Push(binding, ssbo, buffer_offset, static_cast<GLsizeiptr>(size));
|
||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, ssbo, buffer_offset,
|
||||
static_cast<GLsizeiptr>(size));
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, const Shader& shader) {
|
||||
|
@ -1432,7 +1415,7 @@ void RasterizerOpenGL::EndTransformFeedback() {
|
|||
const GPUVAddr gpu_addr = binding.Address();
|
||||
const std::size_t size = binding.buffer_size;
|
||||
const auto [dest_buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true);
|
||||
glCopyNamedBufferSubData(handle, *dest_buffer, 0, offset, static_cast<GLsizeiptr>(size));
|
||||
glCopyNamedBufferSubData(handle, dest_buffer, 0, offset, static_cast<GLsizeiptr>(size));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -231,9 +231,7 @@ private:
|
|||
static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
|
||||
OGLBufferCache buffer_cache;
|
||||
|
||||
VertexArrayPushBuffer vertex_array_pushbuffer{state_tracker};
|
||||
BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER};
|
||||
BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER};
|
||||
GLint vertex_binding = 0;
|
||||
|
||||
std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers>
|
||||
transform_feedback_buffers;
|
||||
|
|
|
@ -14,68 +14,6 @@
|
|||
|
||||
namespace OpenGL {
|
||||
|
||||
struct VertexArrayPushBuffer::Entry {
|
||||
GLuint binding_index{};
|
||||
const GLuint* buffer{};
|
||||
GLintptr offset{};
|
||||
GLsizei stride{};
|
||||
};
|
||||
|
||||
VertexArrayPushBuffer::VertexArrayPushBuffer(StateTracker& state_tracker)
|
||||
: state_tracker{state_tracker} {}
|
||||
|
||||
VertexArrayPushBuffer::~VertexArrayPushBuffer() = default;
|
||||
|
||||
void VertexArrayPushBuffer::Setup() {
|
||||
index_buffer = nullptr;
|
||||
vertex_buffers.clear();
|
||||
}
|
||||
|
||||
void VertexArrayPushBuffer::SetIndexBuffer(const GLuint* buffer) {
|
||||
index_buffer = buffer;
|
||||
}
|
||||
|
||||
void VertexArrayPushBuffer::SetVertexBuffer(GLuint binding_index, const GLuint* buffer,
|
||||
GLintptr offset, GLsizei stride) {
|
||||
vertex_buffers.push_back(Entry{binding_index, buffer, offset, stride});
|
||||
}
|
||||
|
||||
void VertexArrayPushBuffer::Bind() {
|
||||
if (index_buffer) {
|
||||
state_tracker.BindIndexBuffer(*index_buffer);
|
||||
}
|
||||
|
||||
for (const auto& entry : vertex_buffers) {
|
||||
glBindVertexBuffer(entry.binding_index, *entry.buffer, entry.offset, entry.stride);
|
||||
}
|
||||
}
|
||||
|
||||
struct BindBuffersRangePushBuffer::Entry {
|
||||
GLuint binding;
|
||||
const GLuint* buffer;
|
||||
GLintptr offset;
|
||||
GLsizeiptr size;
|
||||
};
|
||||
|
||||
BindBuffersRangePushBuffer::BindBuffersRangePushBuffer(GLenum target) : target{target} {}
|
||||
|
||||
BindBuffersRangePushBuffer::~BindBuffersRangePushBuffer() = default;
|
||||
|
||||
void BindBuffersRangePushBuffer::Setup() {
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
void BindBuffersRangePushBuffer::Push(GLuint binding, const GLuint* buffer, GLintptr offset,
|
||||
GLsizeiptr size) {
|
||||
entries.push_back(Entry{binding, buffer, offset, size});
|
||||
}
|
||||
|
||||
void BindBuffersRangePushBuffer::Bind() {
|
||||
for (const Entry& entry : entries) {
|
||||
glBindBufferRange(target, entry.binding, *entry.buffer, entry.offset, entry.size);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info) {
|
||||
if (!GLAD_GL_KHR_debug) {
|
||||
// We don't need to throw an error as this is just for debugging
|
||||
|
|
|
@ -11,49 +11,6 @@
|
|||
|
||||
namespace OpenGL {
|
||||
|
||||
class StateTracker;
|
||||
|
||||
class VertexArrayPushBuffer final {
|
||||
public:
|
||||
explicit VertexArrayPushBuffer(StateTracker& state_tracker);
|
||||
~VertexArrayPushBuffer();
|
||||
|
||||
void Setup();
|
||||
|
||||
void SetIndexBuffer(const GLuint* buffer);
|
||||
|
||||
void SetVertexBuffer(GLuint binding_index, const GLuint* buffer, GLintptr offset,
|
||||
GLsizei stride);
|
||||
|
||||
void Bind();
|
||||
|
||||
private:
|
||||
struct Entry;
|
||||
|
||||
StateTracker& state_tracker;
|
||||
|
||||
const GLuint* index_buffer{};
|
||||
std::vector<Entry> vertex_buffers;
|
||||
};
|
||||
|
||||
class BindBuffersRangePushBuffer final {
|
||||
public:
|
||||
explicit BindBuffersRangePushBuffer(GLenum target);
|
||||
~BindBuffersRangePushBuffer();
|
||||
|
||||
void Setup();
|
||||
|
||||
void Push(GLuint binding, const GLuint* buffer, GLintptr offset, GLsizeiptr size);
|
||||
|
||||
void Bind();
|
||||
|
||||
private:
|
||||
struct Entry;
|
||||
|
||||
GLenum target;
|
||||
std::vector<Entry> entries;
|
||||
};
|
||||
|
||||
void LabelGLObject(GLenum identifier, GLuint handle, VAddr addr, std::string_view extra_info = {});
|
||||
|
||||
} // namespace OpenGL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue