[buffer_cache] guards against non contiguous allocations

This commit is contained in:
xbzk 2026-05-16 10:16:44 -03:00
parent 59671fceaa
commit ea190464f1
2 changed files with 24 additions and 7 deletions

View file

@ -324,6 +324,7 @@ void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr
const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
const Binding binding{
.device_addr = *device_addr,
.gpu_addr = gpu_addr,
.size = size,
.buffer_id = BufferId{},
};
@ -940,12 +941,23 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
return alignment > 1 && (offset % alignment) != 0;
}
}();
const bool use_fast_buffer = needs_alignment_stream
|| (has_host_buffer && size <= channel_state->uniform_buffer_skip_cache_size
&& !memory_tracker.IsRegionGpuModified(device_addr, size));
const bool has_gpu_range = binding.gpu_addr != 0 && size != 0;
const bool gpu_fully_mapped =
has_gpu_range && gpu_memory->IsFullyMappedRange(binding.gpu_addr, size);
const bool gpu_continuous =
gpu_fully_mapped && gpu_memory->IsContinuousRange(binding.gpu_addr, size);
const bool needs_virtual_uniform_stream =
has_gpu_range && (!gpu_fully_mapped || !gpu_continuous);
const bool region_gpu_modified =
has_host_buffer && memory_tracker.IsRegionGpuModified(device_addr, size);
const bool use_fast_buffer = needs_alignment_stream ||
needs_virtual_uniform_stream ||
(has_host_buffer &&
size <= channel_state->uniform_buffer_skip_cache_size &&
!region_gpu_modified);
if (use_fast_buffer) {
if constexpr (IS_OPENGL) {
if (runtime.HasFastBufferSubData()) {
if (!needs_virtual_uniform_stream && runtime.HasFastBufferSubData()) {
// Fast path for Nvidia
const bool should_fast_bind =
!HasFastUniformBufferBound(stage, binding_index) ||
@ -1254,11 +1266,16 @@ void BufferCache<P>::UpdateIndexBuffer() {
const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin);
const u32 draw_size =
(index_buffer_ref.count + index_buffer_ref.first) * index_buffer_ref.FormatSizeInBytes();
const u32 size = (std::min)(address_size, draw_size);
u32 size = (std::min)(address_size, draw_size);
if (size == 0 || !device_addr) {
channel_state->index_buffer = NULL_BINDING;
return;
}
size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size));
if (size == 0) {
channel_state->index_buffer = NULL_BINDING;
return;
}
channel_state->index_buffer = Binding{
.device_addr = *device_addr,
.size = size,
@ -1296,9 +1313,7 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
UpdateVertexBufferSlot(index, NULL_BINDING);
return;
}
if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end) || size >= 64_MiB) {
size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size));
}
const BufferId buffer_id = FindBuffer(*device_addr, size);
const Binding binding{
.device_addr = *device_addr,

View file

@ -81,6 +81,7 @@ static constexpr u32 DEFAULT_SKIP_CACHE_SIZE = static_cast<u32>(4_KiB);
struct Binding {
DAddr device_addr{};
GPUVAddr gpu_addr{};
u32 size{};
BufferId buffer_id;
};
@ -91,6 +92,7 @@ struct TextureBufferBinding : Binding {
static constexpr Binding NULL_BINDING{
.device_addr = 0,
.gpu_addr = 0,
.size = 0,
.buffer_id = NULL_BUFFER_ID,
};