summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_opengl
diff options
context:
space:
mode:
authorGravatar Ameer J2023-12-19 15:53:36 -0500
committerGravatar Ameer J2023-12-19 17:13:23 -0500
commit372bca5945bc455e12bb9d309679e0bb8c00283d (patch)
tree6d8d5623c8d00bff1946534f3dd9bb9b0d369880 /src/video_core/renderer_opengl
parentMerge pull request #12382 from liamwhite/image-limit (diff)
downloadyuzu-372bca5945bc455e12bb9d309679e0bb8c00283d.tar.gz
yuzu-372bca5945bc455e12bb9d309679e0bb8c00283d.tar.xz
yuzu-372bca5945bc455e12bb9d309679e0bb8c00283d.zip
gl_buffer_cache: Reintroduce NV_vertex_buffer_unified_memory
Workaround Nvidia drivers complaining when a buffer is bound as both a vertex buffer and transform feedback buffer
Diffstat (limited to 'src/video_core/renderer_opengl')
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp45
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h1
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_device.h5
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp16
5 files changed, 60 insertions, 8 deletions
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index a71866b75..b787b6994 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -58,6 +58,9 @@ Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rast
58 glObjectLabel(GL_BUFFER, buffer.handle, static_cast<GLsizei>(name.size()), name.data()); 58 glObjectLabel(GL_BUFFER, buffer.handle, static_cast<GLsizei>(name.size()), name.data());
59 } 59 }
60 glNamedBufferData(buffer.handle, SizeBytes(), nullptr, GL_DYNAMIC_DRAW); 60 glNamedBufferData(buffer.handle, SizeBytes(), nullptr, GL_DYNAMIC_DRAW);
61 if (runtime.has_unified_vertex_buffers) {
62 glGetNamedBufferParameterui64vNV(buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &address);
63 }
61} 64}
62 65
63void Buffer::ImmediateUpload(size_t offset, std::span<const u8> data) noexcept { 66void Buffer::ImmediateUpload(size_t offset, std::span<const u8> data) noexcept {
@@ -109,6 +112,7 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_,
109 : device{device_}, staging_buffer_pool{staging_buffer_pool_}, 112 : device{device_}, staging_buffer_pool{staging_buffer_pool_},
110 has_fast_buffer_sub_data{device.HasFastBufferSubData()}, 113 has_fast_buffer_sub_data{device.HasFastBufferSubData()},
111 use_assembly_shaders{device.UseAssemblyShaders()}, 114 use_assembly_shaders{device.UseAssemblyShaders()},
115 has_unified_vertex_buffers{device.HasVertexBufferUnifiedMemory()},
112 stream_buffer{has_fast_buffer_sub_data ? std::nullopt : std::make_optional<StreamBuffer>()} { 116 stream_buffer{has_fast_buffer_sub_data ? std::nullopt : std::make_optional<StreamBuffer>()} {
113 GLint gl_max_attributes; 117 GLint gl_max_attributes;
114 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_attributes); 118 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_attributes);
@@ -210,8 +214,14 @@ void BufferCacheRuntime::ClearBuffer(Buffer& dest_buffer, u32 offset, size_t siz
210} 214}
211 215
212void BufferCacheRuntime::BindIndexBuffer(Buffer& buffer, u32 offset, u32 size) { 216void BufferCacheRuntime::BindIndexBuffer(Buffer& buffer, u32 offset, u32 size) {
213 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.Handle()); 217 if (has_unified_vertex_buffers) {
214 index_buffer_offset = offset; 218 buffer.MakeResident(GL_READ_ONLY);
219 glBufferAddressRangeNV(GL_ELEMENT_ARRAY_ADDRESS_NV, 0, buffer.HostGpuAddr() + offset,
220 static_cast<GLsizeiptr>(Common::AlignUp(size, 4)));
221 } else {
222 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.Handle());
223 index_buffer_offset = offset;
224 }
215} 225}
216 226
217void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, 227void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size,
@@ -219,8 +229,15 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset,
219 if (index >= max_attributes) { 229 if (index >= max_attributes) {
220 return; 230 return;
221 } 231 }
222 glBindVertexBuffer(index, buffer.Handle(), static_cast<GLintptr>(offset), 232 if (has_unified_vertex_buffers) {
223 static_cast<GLsizei>(stride)); 233 buffer.MakeResident(GL_READ_ONLY);
234 glBindVertexBuffer(index, 0, 0, static_cast<GLsizei>(stride));
235 glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, index,
236 buffer.HostGpuAddr() + offset, static_cast<GLsizeiptr>(size));
237 } else {
238 glBindVertexBuffer(index, buffer.Handle(), static_cast<GLintptr>(offset),
239 static_cast<GLsizei>(stride));
240 }
224} 241}
225 242
226void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) { 243void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) {
@@ -233,9 +250,23 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi
233 [](u64 stride) { return static_cast<GLsizei>(stride); }); 250 [](u64 stride) { return static_cast<GLsizei>(stride); });
234 const u32 count = 251 const u32 count =
235 std::min(static_cast<u32>(bindings.buffers.size()), max_attributes - bindings.min_index); 252 std::min(static_cast<u32>(bindings.buffers.size()), max_attributes - bindings.min_index);
236 glBindVertexBuffers(bindings.min_index, static_cast<GLsizei>(count), buffer_handles.data(), 253 if (has_unified_vertex_buffers) {
237 reinterpret_cast<const GLintptr*>(bindings.offsets.data()), 254 for (u32 index = 0; index < count; ++index) {
238 buffer_strides.data()); 255 Buffer& buffer = *bindings.buffers[index];
256 buffer.MakeResident(GL_READ_ONLY);
257 glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, bindings.min_index + index,
258 buffer.HostGpuAddr() + bindings.offsets[index],
259 static_cast<GLsizeiptr>(bindings.sizes[index]));
260 }
261 static constexpr std::array<size_t, 32> ZEROS{};
262 glBindVertexBuffers(bindings.min_index, static_cast<GLsizei>(count),
263 reinterpret_cast<const GLuint*>(ZEROS.data()),
264 reinterpret_cast<const GLintptr*>(ZEROS.data()), buffer_strides.data());
265 } else {
266 glBindVertexBuffers(bindings.min_index, static_cast<GLsizei>(count), buffer_handles.data(),
267 reinterpret_cast<const GLintptr*>(bindings.offsets.data()),
268 buffer_strides.data());
269 }
239} 270}
240 271
241void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, 272void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer,
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index 71cd45d35..1e8708f59 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -209,6 +209,7 @@ private:
209 209
210 bool has_fast_buffer_sub_data = false; 210 bool has_fast_buffer_sub_data = false;
211 bool use_assembly_shaders = false; 211 bool use_assembly_shaders = false;
212 bool has_unified_vertex_buffers = false;
212 213
213 bool use_storage_buffers = false; 214 bool use_storage_buffers = false;
214 215
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index a6c93068f..993438a27 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -200,6 +200,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
200 has_broken_texture_view_formats = is_amd || (!is_linux && is_intel); 200 has_broken_texture_view_formats = is_amd || (!is_linux && is_intel);
201 has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; 201 has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2;
202 has_derivative_control = GLAD_GL_ARB_derivative_control; 202 has_derivative_control = GLAD_GL_ARB_derivative_control;
203 has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory;
203 has_debugging_tool_attached = IsDebugToolAttached(extensions); 204 has_debugging_tool_attached = IsDebugToolAttached(extensions);
204 has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float"); 205 has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float");
205 has_geometry_shader_passthrough = GLAD_GL_NV_geometry_shader_passthrough; 206 has_geometry_shader_passthrough = GLAD_GL_NV_geometry_shader_passthrough;
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 96034ea4a..a5a6bbbba 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -72,6 +72,10 @@ public:
72 return has_texture_shadow_lod; 72 return has_texture_shadow_lod;
73 } 73 }
74 74
75 bool HasVertexBufferUnifiedMemory() const {
76 return has_vertex_buffer_unified_memory;
77 }
78
75 bool HasASTC() const { 79 bool HasASTC() const {
76 return has_astc; 80 return has_astc;
77 } 81 }
@@ -211,6 +215,7 @@ private:
211 bool has_vertex_viewport_layer{}; 215 bool has_vertex_viewport_layer{};
212 bool has_image_load_formatted{}; 216 bool has_image_load_formatted{};
213 bool has_texture_shadow_lod{}; 217 bool has_texture_shadow_lod{};
218 bool has_vertex_buffer_unified_memory{};
214 bool has_astc{}; 219 bool has_astc{};
215 bool has_variable_aoffi{}; 220 bool has_variable_aoffi{};
216 bool has_component_indexing_bug{}; 221 bool has_component_indexing_bug{};
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 7a4f0c5c1..2933718b6 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -168,6 +168,14 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
168 if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) { 168 if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) {
169 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); 169 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
170 } 170 }
171 // Enable unified vertex attributes and query vertex buffer address when the driver supports it
172 if (device.HasVertexBufferUnifiedMemory()) {
173 glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
174 glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
175 glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY);
176 glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV,
177 &vertex_buffer_address);
178 }
171} 179}
172 180
173RendererOpenGL::~RendererOpenGL() = default; 181RendererOpenGL::~RendererOpenGL() = default;
@@ -667,7 +675,13 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
667 offsetof(ScreenRectVertex, tex_coord)); 675 offsetof(ScreenRectVertex, tex_coord));
668 glVertexAttribBinding(PositionLocation, 0); 676 glVertexAttribBinding(PositionLocation, 0);
669 glVertexAttribBinding(TexCoordLocation, 0); 677 glVertexAttribBinding(TexCoordLocation, 0);
670 glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); 678 if (device.HasVertexBufferUnifiedMemory()) {
679 glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex));
680 glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address,
681 sizeof(vertices));
682 } else {
683 glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
684 }
671 685
672 if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) { 686 if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
673 glBindSampler(0, present_sampler.handle); 687 glBindSampler(0, present_sampler.handle);