summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_buffer_cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl/gl_buffer_cache.cpp')
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp90
1 files changed, 77 insertions, 13 deletions
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index c225d1fc9..07a995f7d 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -2,14 +2,18 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
#include <span>
#include "video_core/buffer_cache/buffer_cache.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_device.h"
+#include "video_core/renderer_opengl/maxwell_to_gl.h"
namespace OpenGL {
namespace {
+using VideoCore::Surface::PixelFormat;
+
struct BindlessSSBO {
GLuint64EXT address;
GLsizei length;
@@ -21,6 +25,25 @@ constexpr std::array PROGRAM_LUT{
GL_VERTEX_PROGRAM_NV, GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV,
GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV,
};
+
+[[nodiscard]] GLenum GetTextureBufferFormat(GLenum gl_format) {
+ switch (gl_format) {
+ case GL_RGBA8_SNORM:
+ return GL_RGBA8;
+ case GL_R8_SNORM:
+ return GL_R8;
+ case GL_RGBA16_SNORM:
+ return GL_RGBA16;
+ case GL_R16_SNORM:
+ return GL_R16;
+ case GL_RG16_SNORM:
+ return GL_RG16;
+ case GL_RG8_SNORM:
+ return GL_RG8;
+ default:
+ return gl_format;
+ }
+}
} // Anonymous namespace
Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params)
@@ -62,6 +85,30 @@ void Buffer::MakeResident(GLenum access) noexcept {
glMakeNamedBufferResidentNV(buffer.handle, access);
}
+GLuint Buffer::View(u32 offset, u32 size, PixelFormat format) {
+ const auto it{std::ranges::find_if(views, [offset, size, format](const BufferView& view) {
+ return offset == view.offset && size == view.size && format == view.format;
+ })};
+ if (it != views.end()) {
+ return it->texture.handle;
+ }
+ OGLTexture texture;
+ texture.Create(GL_TEXTURE_BUFFER);
+ const GLenum gl_format{MaxwellToGL::GetFormatTuple(format).internal_format};
+ const GLenum texture_format{GetTextureBufferFormat(gl_format)};
+ if (texture_format != gl_format) {
+ LOG_WARNING(Render_OpenGL, "Emulating SNORM texture buffer with UNORM.");
+ }
+ glTextureBufferRange(texture.handle, texture_format, buffer.handle, offset, size);
+ views.push_back({
+ .offset = offset,
+ .size = size,
+ .format = format,
+ .texture = std::move(texture),
+ });
+ return views.back().texture.handle;
+}
+
BufferCacheRuntime::BufferCacheRuntime(const Device& device_)
: device{device_}, has_fast_buffer_sub_data{device.HasFastBufferSubData()},
use_assembly_shaders{device.UseAssemblyShaders()},
@@ -98,6 +145,12 @@ void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer,
}
}
+void BufferCacheRuntime::ClearBuffer(Buffer& dest_buffer, u32 offset, size_t size, u32 value) {
+ glClearNamedBufferSubData(dest_buffer.Handle(), GL_R32UI, static_cast<GLintptr>(offset),
+ static_cast<GLsizeiptr>(size / sizeof(u32)), GL_RED, GL_UNSIGNED_INT,
+ &value);
+}
+
void BufferCacheRuntime::BindIndexBuffer(Buffer& buffer, u32 offset, u32 size) {
if (has_unified_vertex_buffers) {
buffer.MakeResident(GL_READ_ONLY);
@@ -138,7 +191,7 @@ void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buff
glBindBufferRangeNV(PABO_LUT[stage], binding_index, handle, 0,
static_cast<GLsizeiptr>(size));
} else {
- const GLuint base_binding = device.GetBaseBindings(stage).uniform_buffer;
+ const GLuint base_binding = graphics_base_uniform_bindings[stage];
const GLuint binding = base_binding + binding_index;
glBindBufferRange(GL_UNIFORM_BUFFER, binding, buffer.Handle(),
static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
@@ -165,7 +218,12 @@ void BufferCacheRuntime::BindComputeUniformBuffer(u32 binding_index, Buffer& buf
void BufferCacheRuntime::BindStorageBuffer(size_t stage, u32 binding_index, Buffer& buffer,
u32 offset, u32 size, bool is_written) {
- if (use_assembly_shaders) {
+ if (use_storage_buffers) {
+ const GLuint base_binding = graphics_base_storage_bindings[stage];
+ const GLuint binding = base_binding + binding_index;
+ glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, buffer.Handle(),
+ static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
+ } else {
const BindlessSSBO ssbo{
.address = buffer.HostGpuAddr() + offset,
.length = static_cast<GLsizei>(size),
@@ -174,17 +232,19 @@ void BufferCacheRuntime::BindStorageBuffer(size_t stage, u32 binding_index, Buff
buffer.MakeResident(is_written ? GL_READ_WRITE : GL_READ_ONLY);
glProgramLocalParametersI4uivNV(PROGRAM_LUT[stage], binding_index, 1,
reinterpret_cast<const GLuint*>(&ssbo));
- } else {
- const GLuint base_binding = device.GetBaseBindings(stage).shader_storage_buffer;
- const GLuint binding = base_binding + binding_index;
- glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, buffer.Handle(),
- static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
}
}
void BufferCacheRuntime::BindComputeStorageBuffer(u32 binding_index, Buffer& buffer, u32 offset,
u32 size, bool is_written) {
- if (use_assembly_shaders) {
+ if (use_storage_buffers) {
+ if (size != 0) {
+ glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding_index, buffer.Handle(),
+ static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
+ } else {
+ glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding_index, 0, 0, 0);
+ }
+ } else {
const BindlessSSBO ssbo{
.address = buffer.HostGpuAddr() + offset,
.length = static_cast<GLsizei>(size),
@@ -193,11 +253,6 @@ void BufferCacheRuntime::BindComputeStorageBuffer(u32 binding_index, Buffer& buf
buffer.MakeResident(is_written ? GL_READ_WRITE : GL_READ_ONLY);
glProgramLocalParametersI4uivNV(GL_COMPUTE_PROGRAM_NV, binding_index, 1,
reinterpret_cast<const GLuint*>(&ssbo));
- } else if (size == 0) {
- glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding_index, 0, 0, 0);
- } else {
- glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding_index, buffer.Handle(),
- static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
}
}
@@ -207,4 +262,13 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, Buffer& buffer,
static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
}
+void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
+ PixelFormat format) {
+ *texture_handles++ = buffer.View(offset, size, format);
+}
+
+void BufferCacheRuntime::BindImageBuffer(Buffer& buffer, u32 offset, u32 size, PixelFormat format) {
+ *image_handles++ = buffer.View(offset, size, format);
+}
+
} // namespace OpenGL