d3d12: Reuse sampler tables inside of a batch
If a shader's sampler state is dirty often, the sampler descriptor heap can get used up quickly, forcing flushing. If that happens quickly, we run out of batches and have to wait for batches to finish on the GPU. When this happens, it is often because the sampler state is switching, not because it's truly unique. This change hashes and saves sampler descriptor tables that can be reused in subsequent draws in the same batch, instead of re-copying the same descriptors and consuming the heap. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20618>
This commit is contained in:
committed by
Marge Bot
parent
32b23d8fb2
commit
54088f4bb5
@@ -37,6 +37,20 @@
|
||||
|
||||
#include <dxguids/dxguids.h>
|
||||
|
||||
|
||||
unsigned d3d12_sampler_desc_table_key_hash(const void* key)
|
||||
{
|
||||
const d3d12_sampler_desc_table_key* table = (d3d12_sampler_desc_table_key*)key;
|
||||
|
||||
return _mesa_hash_data(table->descs, sizeof(table->descs[0]) * table->count);
|
||||
}
|
||||
bool d3d12_sampler_desc_table_key_equals(const void* a, const void* b)
|
||||
{
|
||||
const d3d12_sampler_desc_table_key* table_a = (d3d12_sampler_desc_table_key*)a;
|
||||
const d3d12_sampler_desc_table_key* table_b = (d3d12_sampler_desc_table_key*)b;
|
||||
return table_a->count == table_b->count && memcmp(table_a->descs, table_b->descs, sizeof(table_a->descs[0]) * table_a->count) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
d3d12_init_batch(struct d3d12_context *ctx, struct d3d12_batch *batch)
|
||||
{
|
||||
@@ -44,6 +58,8 @@ d3d12_init_batch(struct d3d12_context *ctx, struct d3d12_batch *batch)
|
||||
|
||||
batch->bos = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
|
||||
_mesa_key_pointer_equal);
|
||||
batch->sampler_tables = _mesa_hash_table_create(NULL, d3d12_sampler_desc_table_key_hash,
|
||||
d3d12_sampler_desc_table_key_equals);
|
||||
batch->sampler_views = _mesa_set_create(NULL, _mesa_hash_pointer,
|
||||
_mesa_key_pointer_equal);
|
||||
batch->surfaces = _mesa_set_create(NULL, _mesa_hash_pointer,
|
||||
@@ -52,7 +68,7 @@ d3d12_init_batch(struct d3d12_context *ctx, struct d3d12_batch *batch)
|
||||
_mesa_hash_pointer,
|
||||
_mesa_key_pointer_equal);
|
||||
|
||||
if (!batch->bos || !batch->sampler_views || !batch->surfaces || !batch->objects)
|
||||
if (!batch->bos || !batch->sampler_tables || !batch->sampler_views || !batch->surfaces || !batch->objects)
|
||||
return false;
|
||||
|
||||
util_dynarray_init(&batch->zombie_samplers, NULL);
|
||||
@@ -86,6 +102,13 @@ delete_bo(hash_entry *entry)
|
||||
d3d12_bo_unreference(bo);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_sampler_view_table(hash_entry *entry)
|
||||
{
|
||||
FREE((void*)entry->key);
|
||||
FREE(entry->data);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_sampler_view(set_entry *entry)
|
||||
{
|
||||
@@ -121,6 +144,7 @@ d3d12_reset_batch(struct d3d12_context *ctx, struct d3d12_batch *batch, uint64_t
|
||||
}
|
||||
|
||||
_mesa_hash_table_clear(batch->bos, delete_bo);
|
||||
_mesa_hash_table_clear(batch->sampler_tables, delete_sampler_view_table);
|
||||
_mesa_set_clear(batch->sampler_views, delete_sampler_view);
|
||||
_mesa_set_clear(batch->surfaces, delete_surface);
|
||||
_mesa_set_clear(batch->objects, delete_object);
|
||||
@@ -149,6 +173,7 @@ d3d12_destroy_batch(struct d3d12_context *ctx, struct d3d12_batch *batch)
|
||||
d3d12_descriptor_heap_free(batch->sampler_heap);
|
||||
d3d12_descriptor_heap_free(batch->view_heap);
|
||||
_mesa_hash_table_destroy(batch->bos, NULL);
|
||||
_mesa_hash_table_destroy(batch->sampler_tables, NULL);
|
||||
_mesa_set_destroy(batch->sampler_views, NULL);
|
||||
_mesa_set_destroy(batch->surfaces, NULL);
|
||||
_mesa_set_destroy(batch->objects, NULL);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "util/u_dynarray.h"
|
||||
#include "util/hash_table.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "d3d12_common.h"
|
||||
@@ -34,10 +35,18 @@ struct d3d12_bo;
|
||||
struct d3d12_descriptor_heap;
|
||||
struct d3d12_fence;
|
||||
|
||||
|
||||
struct d3d12_sampler_desc_table_key
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
struct d3d12_batch {
|
||||
struct d3d12_fence *fence;
|
||||
|
||||
struct hash_table *bos;
|
||||
struct hash_table *sampler_tables;
|
||||
struct set *sampler_views;
|
||||
struct set *surfaces;
|
||||
struct set *objects;
|
||||
|
||||
@@ -191,13 +191,10 @@ fill_sampler_descriptors(struct d3d12_context *ctx,
|
||||
{
|
||||
const struct d3d12_shader *shader = shader_sel->current;
|
||||
struct d3d12_batch *batch = d3d12_current_batch(ctx);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE descs[PIPE_MAX_SHADER_SAMPLER_VIEWS];
|
||||
struct d3d12_descriptor_handle table_start;
|
||||
struct d3d12_sampler_desc_table_key view;
|
||||
|
||||
d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start);
|
||||
|
||||
for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++)
|
||||
{
|
||||
view.count = 0;
|
||||
for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++, view.count++) {
|
||||
struct d3d12_sampler_state *sampler;
|
||||
|
||||
if (i == shader->pstipple_binding) {
|
||||
@@ -209,15 +206,32 @@ fill_sampler_descriptors(struct d3d12_context *ctx,
|
||||
unsigned desc_idx = i - shader->begin_srv_binding;
|
||||
if (sampler != NULL) {
|
||||
if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad)
|
||||
descs[desc_idx] = sampler->handle_without_shadow.cpu_handle;
|
||||
view.descs[desc_idx] = sampler->handle_without_shadow.cpu_handle;
|
||||
else
|
||||
descs[desc_idx] = sampler->handle.cpu_handle;
|
||||
view.descs[desc_idx] = sampler->handle.cpu_handle;
|
||||
} else
|
||||
descs[desc_idx] = ctx->null_sampler.cpu_handle;
|
||||
view.descs[desc_idx] = ctx->null_sampler.cpu_handle;
|
||||
}
|
||||
|
||||
d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding);
|
||||
return table_start.gpu_handle;
|
||||
hash_entry* sampler_entry =
|
||||
(hash_entry*)_mesa_hash_table_search(batch->sampler_tables, &view);
|
||||
|
||||
if (!sampler_entry) {
|
||||
d3d12_sampler_desc_table_key* sampler_table_key = MALLOC_STRUCT(d3d12_sampler_desc_table_key);
|
||||
sampler_table_key->count = view.count;
|
||||
memcpy(sampler_table_key->descs, &view.descs, view.count * sizeof(view.descs[0]));
|
||||
|
||||
d3d12_descriptor_handle* sampler_table_data = MALLOC_STRUCT(d3d12_descriptor_handle);
|
||||
d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, sampler_table_data);
|
||||
|
||||
d3d12_descriptor_heap_append_handles(batch->sampler_heap, view.descs, shader->end_srv_binding - shader->begin_srv_binding);
|
||||
|
||||
_mesa_hash_table_insert(batch->sampler_tables, sampler_table_key, sampler_table_data);
|
||||
|
||||
return sampler_table_data->gpu_handle;
|
||||
} else
|
||||
return ((d3d12_descriptor_handle*)sampler_entry->data)->gpu_handle;
|
||||
|
||||
}
|
||||
|
||||
static D3D12_UAV_DIMENSION
|
||||
|
||||
Reference in New Issue
Block a user