gl_buffer_cache: Batch vertex/tfb buffer binding
This commit is contained in:
parent
5f945e2fcd
commit
a595ed499d
|
@ -53,13 +53,11 @@ Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rast
|
||||||
VAddr cpu_addr_, u64 size_bytes_)
|
VAddr cpu_addr_, u64 size_bytes_)
|
||||||
: VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) {
|
: VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) {
|
||||||
buffer.Create();
|
buffer.Create();
|
||||||
|
if (runtime.device.HasDebuggingToolAttached()) {
|
||||||
const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr());
|
const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr());
|
||||||
glObjectLabel(GL_BUFFER, buffer.handle, static_cast<GLsizei>(name.size()), name.data());
|
glObjectLabel(GL_BUFFER, buffer.handle, static_cast<GLsizei>(name.size()), name.data());
|
||||||
glNamedBufferData(buffer.handle, SizeBytes(), nullptr, GL_DYNAMIC_DRAW);
|
|
||||||
|
|
||||||
if (runtime.has_unified_vertex_buffers) {
|
|
||||||
glGetNamedBufferParameterui64vNV(buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &address);
|
|
||||||
}
|
}
|
||||||
|
glNamedBufferData(buffer.handle, SizeBytes(), nullptr, GL_DYNAMIC_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::ImmediateUpload(size_t offset, std::span<const u8> data) noexcept {
|
void Buffer::ImmediateUpload(size_t offset, std::span<const u8> data) noexcept {
|
||||||
|
@ -111,7 +109,6 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_,
|
||||||
: device{device_}, staging_buffer_pool{staging_buffer_pool_},
|
: device{device_}, staging_buffer_pool{staging_buffer_pool_},
|
||||||
has_fast_buffer_sub_data{device.HasFastBufferSubData()},
|
has_fast_buffer_sub_data{device.HasFastBufferSubData()},
|
||||||
use_assembly_shaders{device.UseAssemblyShaders()},
|
use_assembly_shaders{device.UseAssemblyShaders()},
|
||||||
has_unified_vertex_buffers{device.HasVertexBufferUnifiedMemory()},
|
|
||||||
stream_buffer{has_fast_buffer_sub_data ? std::nullopt : std::make_optional<StreamBuffer>()} {
|
stream_buffer{has_fast_buffer_sub_data ? std::nullopt : std::make_optional<StreamBuffer>()} {
|
||||||
GLint gl_max_attributes;
|
GLint gl_max_attributes;
|
||||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_attributes);
|
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &gl_max_attributes);
|
||||||
|
@ -123,6 +120,7 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_,
|
||||||
GL_STREAM_DRAW);
|
GL_STREAM_DRAW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (use_assembly_shaders) {
|
||||||
for (auto& stage_uniforms : copy_uniforms) {
|
for (auto& stage_uniforms : copy_uniforms) {
|
||||||
for (OGLBuffer& buffer : stage_uniforms) {
|
for (OGLBuffer& buffer : stage_uniforms) {
|
||||||
buffer.Create();
|
buffer.Create();
|
||||||
|
@ -133,6 +131,7 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_,
|
||||||
buffer.Create();
|
buffer.Create();
|
||||||
glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY);
|
glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
device_access_memory = [this]() -> u64 {
|
device_access_memory = [this]() -> u64 {
|
||||||
if (device.CanReportMemoryUsage()) {
|
if (device.CanReportMemoryUsage()) {
|
||||||
|
@ -206,39 +205,32 @@ void BufferCacheRuntime::ClearBuffer(Buffer& dest_buffer, u32 offset, size_t siz
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::BindIndexBuffer(Buffer& buffer, u32 offset, u32 size) {
|
void BufferCacheRuntime::BindIndexBuffer(Buffer& buffer, u32 offset, u32 size) {
|
||||||
if (has_unified_vertex_buffers) {
|
|
||||||
buffer.MakeResident(GL_READ_ONLY);
|
|
||||||
glBufferAddressRangeNV(GL_ELEMENT_ARRAY_ADDRESS_NV, 0, buffer.HostGpuAddr() + offset,
|
|
||||||
static_cast<GLsizeiptr>(Common::AlignUp(size, 4)));
|
|
||||||
} else {
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.Handle());
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.Handle());
|
||||||
index_buffer_offset = offset;
|
index_buffer_offset = offset;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size,
|
void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size,
|
||||||
u32 stride) {
|
u32 stride) {
|
||||||
if (index >= max_attributes) {
|
if (index >= max_attributes) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (has_unified_vertex_buffers) {
|
|
||||||
buffer.MakeResident(GL_READ_ONLY);
|
|
||||||
glBindVertexBuffer(index, 0, 0, static_cast<GLsizei>(stride));
|
|
||||||
glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, index,
|
|
||||||
buffer.HostGpuAddr() + offset, static_cast<GLsizeiptr>(size));
|
|
||||||
} else {
|
|
||||||
glBindVertexBuffer(index, buffer.Handle(), static_cast<GLintptr>(offset),
|
glBindVertexBuffer(index, buffer.Handle(), static_cast<GLintptr>(offset),
|
||||||
static_cast<GLsizei>(stride));
|
static_cast<GLsizei>(stride));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) {
|
void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) {
|
||||||
for (u32 index = 0; index < bindings.buffers.size(); ++index) {
|
// TODO: Should HostBindings provide the correct runtime types to avoid these transforms?
|
||||||
BindVertexBuffer(bindings.min_index + index, *bindings.buffers[index],
|
std::array<GLuint, 32> buffer_handles;
|
||||||
static_cast<u32>(bindings.offsets[index]),
|
std::array<GLsizei, 32> buffer_strides;
|
||||||
static_cast<u32>(bindings.sizes[index]),
|
std::ranges::transform(bindings.buffers, buffer_handles.begin(),
|
||||||
static_cast<u32>(bindings.strides[index]));
|
[](const Buffer* const buffer) { return buffer->Handle(); });
|
||||||
}
|
std::ranges::transform(bindings.strides, buffer_strides.begin(),
|
||||||
|
[](u64 stride) { return static_cast<GLsizei>(stride); });
|
||||||
|
const u32 count =
|
||||||
|
std::min(static_cast<u32>(bindings.buffers.size()), max_attributes - bindings.min_index);
|
||||||
|
glBindVertexBuffers(bindings.min_index, static_cast<GLsizei>(count), buffer_handles.data(),
|
||||||
|
reinterpret_cast<const GLintptr*>(bindings.offsets.data()),
|
||||||
|
buffer_strides.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer,
|
void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer,
|
||||||
|
@ -330,11 +322,13 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, Buffer& buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings) {
|
void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings) {
|
||||||
for (u32 index = 0; index < bindings.buffers.size(); ++index) {
|
std::array<GLuint, 4> buffer_handles;
|
||||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index, bindings.buffers[index]->Handle(),
|
std::ranges::transform(bindings.buffers, buffer_handles.begin(),
|
||||||
static_cast<GLintptr>(bindings.offsets[index]),
|
[](const Buffer* const buffer) { return buffer->Handle(); });
|
||||||
static_cast<GLsizeiptr>(bindings.sizes[index]));
|
glBindBuffersRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0,
|
||||||
}
|
static_cast<GLsizei>(bindings.buffers.size()), buffer_handles.data(),
|
||||||
|
reinterpret_cast<const GLintptr*>(bindings.offsets.data()),
|
||||||
|
reinterpret_cast<const GLsizeiptr*>(bindings.strides.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
|
void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
|
||||||
|
|
|
@ -194,7 +194,6 @@ private:
|
||||||
|
|
||||||
bool has_fast_buffer_sub_data = false;
|
bool has_fast_buffer_sub_data = false;
|
||||||
bool use_assembly_shaders = false;
|
bool use_assembly_shaders = false;
|
||||||
bool has_unified_vertex_buffers = false;
|
|
||||||
|
|
||||||
bool use_storage_buffers = false;
|
bool use_storage_buffers = false;
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,6 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
|
||||||
has_broken_texture_view_formats = is_amd || (!is_linux && is_intel);
|
has_broken_texture_view_formats = is_amd || (!is_linux && is_intel);
|
||||||
has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2;
|
has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2;
|
||||||
has_derivative_control = GLAD_GL_ARB_derivative_control;
|
has_derivative_control = GLAD_GL_ARB_derivative_control;
|
||||||
has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory;
|
|
||||||
has_debugging_tool_attached = IsDebugToolAttached(extensions);
|
has_debugging_tool_attached = IsDebugToolAttached(extensions);
|
||||||
has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float");
|
has_depth_buffer_float = HasExtension(extensions, "GL_NV_depth_buffer_float");
|
||||||
has_geometry_shader_passthrough = GLAD_GL_NV_geometry_shader_passthrough;
|
has_geometry_shader_passthrough = GLAD_GL_NV_geometry_shader_passthrough;
|
||||||
|
|
|
@ -72,10 +72,6 @@ public:
|
||||||
return has_texture_shadow_lod;
|
return has_texture_shadow_lod;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasVertexBufferUnifiedMemory() const {
|
|
||||||
return has_vertex_buffer_unified_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasASTC() const {
|
bool HasASTC() const {
|
||||||
return has_astc;
|
return has_astc;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +211,6 @@ private:
|
||||||
bool has_vertex_viewport_layer{};
|
bool has_vertex_viewport_layer{};
|
||||||
bool has_image_load_formatted{};
|
bool has_image_load_formatted{};
|
||||||
bool has_texture_shadow_lod{};
|
bool has_texture_shadow_lod{};
|
||||||
bool has_vertex_buffer_unified_memory{};
|
|
||||||
bool has_astc{};
|
bool has_astc{};
|
||||||
bool has_variable_aoffi{};
|
bool has_variable_aoffi{};
|
||||||
bool has_component_indexing_bug{};
|
bool has_component_indexing_bug{};
|
||||||
|
|
|
@ -168,15 +168,6 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
|
||||||
if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) {
|
if (!GLAD_GL_ARB_seamless_cubemap_per_texture && !GLAD_GL_AMD_seamless_cubemap_per_texture) {
|
||||||
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||||
}
|
}
|
||||||
// Enable unified vertex attributes and query vertex buffer address when the driver supports it
|
|
||||||
if (device.HasVertexBufferUnifiedMemory()) {
|
|
||||||
glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV);
|
|
||||||
glEnableClientState(GL_ELEMENT_ARRAY_UNIFIED_NV);
|
|
||||||
|
|
||||||
glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY);
|
|
||||||
glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV,
|
|
||||||
&vertex_buffer_address);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RendererOpenGL::~RendererOpenGL() = default;
|
RendererOpenGL::~RendererOpenGL() = default;
|
||||||
|
@ -680,13 +671,7 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
||||||
offsetof(ScreenRectVertex, tex_coord));
|
offsetof(ScreenRectVertex, tex_coord));
|
||||||
glVertexAttribBinding(PositionLocation, 0);
|
glVertexAttribBinding(PositionLocation, 0);
|
||||||
glVertexAttribBinding(TexCoordLocation, 0);
|
glVertexAttribBinding(TexCoordLocation, 0);
|
||||||
if (device.HasVertexBufferUnifiedMemory()) {
|
|
||||||
glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex));
|
|
||||||
glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address,
|
|
||||||
sizeof(vertices));
|
|
||||||
} else {
|
|
||||||
glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
|
glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
|
||||||
}
|
|
||||||
|
|
||||||
if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
|
if (Settings::values.scaling_filter.GetValue() != Settings::ScalingFilter::NearestNeighbor) {
|
||||||
glBindSampler(0, present_sampler.handle);
|
glBindSampler(0, present_sampler.handle);
|
||||||
|
|
Reference in New Issue