From ec9fa0ed134a13dcbfa5983993595390c90ef634 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Fri, 16 Apr 2021 11:40:35 -0700 Subject: [PATCH] d3d12, microsoft/compiler: Use SRV/sampler variable binding data For GL, we've previously mostly ignored the binding property for sampler variables during the shader compilation step. For CL, our image bindings were always 0-based as well. Now, for Vulkan, we are going to be getting explicit bindings and need to emit DXIL that respects those bindings. Since Vulkan can also have both split and combined images and samplers, we now need to be smarter about recognizing when NIR is trying to use a "sampler" as *both* an image and sampler (in deref mode, the same variable will be deref'd as both image and sampler). That "being smarter" bit comes next, but first, let's prep GL for building correct root signatures and binding the resources correctly. Reviewed-By: Bill Kristiansen Part-of: --- src/gallium/drivers/d3d12/d3d12_compiler.cpp | 9 ++--- src/gallium/drivers/d3d12/d3d12_compiler.h | 4 +-- src/gallium/drivers/d3d12/d3d12_draw.cpp | 36 +++++++++---------- .../drivers/d3d12/d3d12_root_signature.cpp | 15 ++++---- .../drivers/d3d12/d3d12_root_signature.h | 3 +- src/microsoft/compiler/nir_to_dxil.c | 16 ++++----- 6 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.cpp b/src/gallium/drivers/d3d12/d3d12_compiler.cpp index efb30710381..a2979435b96 100644 --- a/src/gallium/drivers/d3d12/d3d12_compiler.cpp +++ b/src/gallium/drivers/d3d12/d3d12_compiler.cpp @@ -175,16 +175,17 @@ compile_nir(struct d3d12_context *ctx, struct d3d12_shader_selector *sel, } // Non-ubo variables + shader->begin_srv_binding = (UINT_MAX); nir_foreach_variable_with_modes(var, nir, nir_var_uniform) { auto type = glsl_without_array(var->type); if (glsl_type_is_sampler(type) && glsl_get_sampler_result_type(type) != GLSL_TYPE_VOID) { unsigned count = glsl_type_is_array(var->type) ? glsl_get_aoa_size(var->type) : 1; for (unsigned i = 0; i < count; ++i) { - shader->srv_bindings[shader->num_srv_bindings].index = var->data.binding + i; - shader->srv_bindings[shader->num_srv_bindings].binding = var->data.binding; - shader->srv_bindings[shader->num_srv_bindings].dimension = resource_dimension(glsl_get_sampler_dim(type)); - shader->num_srv_bindings++; + shader->srv_bindings[var->data.binding + i].binding = var->data.binding; + shader->srv_bindings[var->data.binding + i].dimension = resource_dimension(glsl_get_sampler_dim(type)); } + shader->begin_srv_binding = MIN2(var->data.binding, shader->begin_srv_binding); + shader->end_srv_binding = MAX2(var->data.binding + count, shader->end_srv_binding); } } diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.h b/src/gallium/drivers/d3d12/d3d12_compiler.h index e1bb14412db..535ba5196c2 100644 --- a/src/gallium/drivers/d3d12/d3d12_compiler.h +++ b/src/gallium/drivers/d3d12/d3d12_compiler.h @@ -136,11 +136,11 @@ struct d3d12_shader { bool state_vars_used; struct { - int index; int binding; uint32_t dimension; } srv_bindings[PIPE_MAX_SHADER_SAMPLER_VIEWS]; - size_t num_srv_bindings; + size_t begin_srv_binding; + size_t end_srv_binding; bool has_default_ubo0; unsigned pstipple_binding; diff --git a/src/gallium/drivers/d3d12/d3d12_draw.cpp b/src/gallium/drivers/d3d12/d3d12_draw.cpp index 309a870160f..b46f2de7813 100644 --- a/src/gallium/drivers/d3d12/d3d12_draw.cpp +++ b/src/gallium/drivers/d3d12/d3d12_draw.cpp @@ -90,19 +90,19 @@ fill_srv_descriptors(struct d3d12_context *ctx, d2d12_descriptor_heap_get_next_handle(batch->view_heap, &table_start); - for (unsigned i = 0; i < shader->num_srv_bindings; i++) + for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++) { struct d3d12_sampler_view *view; - if ((unsigned)shader->srv_bindings[i].binding == shader->pstipple_binding) { + if (i == shader->pstipple_binding) { view = (struct d3d12_sampler_view*)ctx->pstipple.sampler_view; } else { - int index = shader->srv_bindings[i].index; - view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][index]; + view = (struct d3d12_sampler_view*)ctx->sampler_views[stage][i]; } + unsigned desc_idx = i - shader->begin_srv_binding; if (view != NULL) { - descs[i] = view->handle.cpu_handle ; + descs[desc_idx] = view->handle.cpu_handle; d3d12_batch_reference_sampler_view(batch, view); D3D12_RESOURCE_STATES state = (stage == PIPE_SHADER_FRAGMENT) ? @@ -120,11 +120,11 @@ fill_srv_descriptors(struct d3d12_context *ctx, state); } } else { - descs[i] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle; + descs[desc_idx] = screen->null_srvs[shader->srv_bindings[i].dimension].cpu_handle; } } - d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->num_srv_bindings); + d3d12_descriptor_heap_append_handles(batch->view_heap, descs, shader->end_srv_binding - shader->begin_srv_binding); return table_start.gpu_handle; } @@ -141,27 +141,27 @@ fill_sampler_descriptors(struct d3d12_context *ctx, d2d12_descriptor_heap_get_next_handle(batch->sampler_heap, &table_start); - for (unsigned i = 0; i < shader->num_srv_bindings; i++) + for (unsigned i = shader->begin_srv_binding; i < shader->end_srv_binding; i++) { struct d3d12_sampler_state *sampler; - if ((unsigned)shader->srv_bindings[i].binding == shader->pstipple_binding) { + if (i == shader->pstipple_binding) { sampler = ctx->pstipple.sampler_cso; } else { - int index = shader->srv_bindings[i].index; - sampler = ctx->samplers[stage][index]; + sampler = ctx->samplers[stage][i]; } + unsigned desc_idx = i - shader->begin_srv_binding; if (sampler != NULL) { if (sampler->is_shadow_sampler && shader_sel->compare_with_lod_bias_grad) - descs[i] = sampler->handle_without_shadow.cpu_handle; + descs[desc_idx] = sampler->handle_without_shadow.cpu_handle; else - descs[i] = sampler->handle.cpu_handle; + descs[desc_idx] = sampler->handle.cpu_handle; } else - descs[i] = ctx->null_sampler.cpu_handle; + descs[desc_idx] = ctx->null_sampler.cpu_handle; } - d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->num_srv_bindings); + d3d12_descriptor_heap_append_handles(batch->sampler_heap, descs, shader->end_srv_binding - shader->begin_srv_binding); return table_start.gpu_handle; } @@ -219,7 +219,7 @@ check_descriptors_left(struct d3d12_context *ctx) continue; needed_descs += shader->current->num_cb_bindings; - needed_descs += shader->current->num_srv_bindings; + needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; } if (d3d12_descriptor_heap_get_remaining_handles(batch->view_heap) < needed_descs) @@ -232,7 +232,7 @@ check_descriptors_left(struct d3d12_context *ctx) if (!shader) continue; - needed_descs += shader->current->num_srv_bindings; + needed_descs += shader->current->end_srv_binding - shader->current->begin_srv_binding; } if (d3d12_descriptor_heap_get_remaining_handles(batch->sampler_heap) < needed_descs) @@ -262,7 +262,7 @@ set_graphics_root_parameters(struct d3d12_context *ctx, ctx->cmdlist->SetGraphicsRootDescriptorTable(num_params, fill_cbv_descriptors(ctx, shader, i)); num_params++; } - if (shader->num_srv_bindings > 0) { + if (shader->end_srv_binding > 0) { if (dirty & D3D12_SHADER_DIRTY_SAMPLER_VIEWS) ctx->cmdlist->SetGraphicsRootDescriptorTable(num_params, fill_srv_descriptors(ctx, shader, i)); num_params++; diff --git a/src/gallium/drivers/d3d12/d3d12_root_signature.cpp b/src/gallium/drivers/d3d12/d3d12_root_signature.cpp index be050140e66..14a03b39a31 100644 --- a/src/gallium/drivers/d3d12/d3d12_root_signature.cpp +++ b/src/gallium/drivers/d3d12/d3d12_root_signature.cpp @@ -115,23 +115,23 @@ create_root_signature(struct d3d12_context *ctx, struct d3d12_root_signature_key num_params++; } - if (key->stages[i].num_srv_bindings > 0) { + if (key->stages[i].end_srv_binding > 0) { init_range_root_param(&root_params[num_params], &desc_ranges[num_params], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, - key->stages[i].num_srv_bindings, + key->stages[i].end_srv_binding - key->stages[i].begin_srv_binding, visibility, - 0); + key->stages[i].begin_srv_binding); num_params++; } - if (key->stages[i].num_srv_bindings > 0) { + if (key->stages[i].end_srv_binding > 0) { init_range_root_param(&root_params[num_params], &desc_ranges[num_params], D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, - key->stages[i].num_srv_bindings, + key->stages[i].end_srv_binding - key->stages[i].begin_srv_binding, visibility, - 0); + key->stages[i].begin_srv_binding); num_params++; } @@ -186,7 +186,8 @@ fill_key(struct d3d12_context *ctx, struct d3d12_root_signature_key *key) if (shader) { key->stages[i].num_cb_bindings = shader->num_cb_bindings; - key->stages[i].num_srv_bindings = shader->num_srv_bindings; + key->stages[i].end_srv_binding = shader->end_srv_binding; + key->stages[i].begin_srv_binding = shader->begin_srv_binding; key->stages[i].state_vars_size = shader->state_vars_size; key->stages[i].has_default_ubo0 = shader->has_default_ubo0; diff --git a/src/gallium/drivers/d3d12/d3d12_root_signature.h b/src/gallium/drivers/d3d12/d3d12_root_signature.h index 1a821a5b28f..93a60ba54a2 100644 --- a/src/gallium/drivers/d3d12/d3d12_root_signature.h +++ b/src/gallium/drivers/d3d12/d3d12_root_signature.h @@ -30,7 +30,8 @@ struct d3d12_root_signature_key { bool has_stream_output; struct { unsigned num_cb_bindings; - unsigned num_srv_bindings; + unsigned end_srv_binding; + unsigned begin_srv_binding; unsigned state_vars_size; bool has_default_ubo0; } stages[D3D12_GFX_SHADER_STAGES]; diff --git a/src/microsoft/compiler/nir_to_dxil.c b/src/microsoft/compiler/nir_to_dxil.c index 206c84d407f..dc3606c5c59 100644 --- a/src/microsoft/compiler/nir_to_dxil.c +++ b/src/microsoft/compiler/nir_to_dxil.c @@ -793,9 +793,10 @@ get_resource_id(struct ntd_context *ctx, enum dxil_resource_class class, } static bool -emit_srv(struct ntd_context *ctx, nir_variable *var, unsigned binding, unsigned count) +emit_srv(struct ntd_context *ctx, nir_variable *var, unsigned count) { unsigned id = util_dynarray_num_elements(&ctx->srv_metadata_nodes, const struct dxil_mdnode *); + unsigned binding = var->data.binding; resource_array_layout layout = {id, binding, count}; enum dxil_component_type comp_type; @@ -1099,9 +1100,10 @@ emit_ubo_var(struct ntd_context *ctx, nir_variable *var) } static bool -emit_sampler(struct ntd_context *ctx, nir_variable *var, unsigned binding, unsigned count) +emit_sampler(struct ntd_context *ctx, nir_variable *var, unsigned count) { unsigned id = util_dynarray_num_elements(&ctx->sampler_metadata_nodes, const struct dxil_mdnode *); + unsigned binding = var->data.binding; resource_array_layout layout = {id, binding, count}; const struct dxil_type *int32_type = dxil_module_get_int_type(&ctx->mod, 32); const struct dxil_type *sampler_type = dxil_module_get_struct_type(&ctx->mod, "struct.SamplerState", &int32_type, 1); @@ -4287,8 +4289,6 @@ shader_has_shared_ops(struct nir_shader *s) static bool emit_module(struct ntd_context *ctx, const struct nir_to_dxil_options *opts) { - unsigned binding; - /* The validator forces us to emit resources in a specific order: * CBVs, Samplers, SRVs, UAVs. While we are at it also remove * stale struct uniforms, they are lowered but might not have been removed */ @@ -4299,26 +4299,22 @@ emit_module(struct ntd_context *ctx, const struct nir_to_dxil_options *opts) return false; /* Samplers */ - binding = 0; nir_foreach_variable_with_modes(var, ctx->shader, nir_var_uniform) { unsigned count = glsl_type_get_sampler_count(var->type); if (var->data.mode == nir_var_uniform && count && glsl_get_sampler_result_type(glsl_without_array(var->type)) == GLSL_TYPE_VOID) { - if (!emit_sampler(ctx, var, binding, count)) + if (!emit_sampler(ctx, var, count)) return false; - binding += count; } } /* SRVs */ - binding = 0; nir_foreach_variable_with_modes(var, ctx->shader, nir_var_uniform) { unsigned count = glsl_type_get_sampler_count(var->type); if (var->data.mode == nir_var_uniform && count && glsl_get_sampler_result_type(glsl_without_array(var->type)) != GLSL_TYPE_VOID) { - if (!emit_srv(ctx, var, binding, count)) + if (!emit_srv(ctx, var, count)) return false; - binding += count; } }