struct nir_to_dxil_options opts = {};
opts.interpolate_at_vertex = screen->have_load_at_vertex;
opts.lower_int16 = !screen->opts4.Native16BitShaderOpsSupported;
- opts.ubo_binding_offset = shader->has_default_ubo0 ? 0 : 1;
+ opts.no_ubo0 = !shader->has_default_ubo0;
+ opts.last_ubo_is_not_arrayed = shader->num_state_vars > 0;
opts.provoking_vertex = key->fs.provoking_vertex;
opts.environment = DXIL_ENVIRONMENT_GL;
if(nir->info.num_ubos) {
// Ignore state_vars ubo as it is bound as root constants
unsigned num_ubo_bindings = nir->info.num_ubos - (shader->state_vars_used ? 1 : 0);
- for(unsigned i = opts.ubo_binding_offset; i < num_ubo_bindings; ++i) {
+ for(unsigned i = shader->has_default_ubo0 ? 0 : 1; i < num_ubo_bindings; ++i) {
shader->cb_bindings[shader->num_cb_bindings++].binding = i;
}
}
}
static inline void
-init_range_root_param(D3D12_ROOT_PARAMETER1 *param,
- D3D12_DESCRIPTOR_RANGE1 *range,
- D3D12_DESCRIPTOR_RANGE_TYPE type,
- uint32_t num_descs,
- D3D12_SHADER_VISIBILITY visibility,
- uint32_t base_shader_register,
- uint32_t register_space)
+init_range(D3D12_DESCRIPTOR_RANGE1 *range,
+ D3D12_DESCRIPTOR_RANGE_TYPE type,
+ uint32_t num_descs,
+ uint32_t base_shader_register,
+ uint32_t register_space,
+ uint32_t offset_from_start)
{
range->RangeType = type;
range->NumDescriptors = num_descs;
range->Flags = D3D12_DESCRIPTOR_RANGE_FLAG_NONE;
else
range->Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS;
- range->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+ range->OffsetInDescriptorsFromTableStart = offset_from_start;
+}
+static inline void
+init_range_root_param(D3D12_ROOT_PARAMETER1 *param,
+ D3D12_DESCRIPTOR_RANGE1 *range,
+ D3D12_DESCRIPTOR_RANGE_TYPE type,
+ uint32_t num_descs,
+ D3D12_SHADER_VISIBILITY visibility,
+ uint32_t base_shader_register,
+ uint32_t register_space)
+{
+ init_range(range, type, num_descs, base_shader_register, register_space, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND);
param->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
param->DescriptorTable.NumDescriptorRanges = 1;
param->DescriptorTable.pDescriptorRanges = range;
{
struct d3d12_screen *screen = d3d12_screen(ctx->base.screen);
D3D12_ROOT_PARAMETER1 root_params[D3D12_GFX_SHADER_STAGES * D3D12_NUM_BINDING_TYPES];
- D3D12_DESCRIPTOR_RANGE1 desc_ranges[D3D12_GFX_SHADER_STAGES * D3D12_NUM_BINDING_TYPES];
+ D3D12_DESCRIPTOR_RANGE1 desc_ranges[D3D12_GFX_SHADER_STAGES * (D3D12_NUM_BINDING_TYPES + 1)];
unsigned num_params = 0;
unsigned num_ranges = 0;
}
if (key->stages[i].num_ssbos > 0) {
- init_range_root_param(&root_params[num_params++],
+ init_range_root_param(&root_params[num_params],
&desc_ranges[num_ranges++],
D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
key->stages[i].num_ssbos,
visibility,
0,
0);
+
+ /* To work around a WARP bug, bind these descriptors a second time in descriptor
+ * space 2. Space 0 will be used for static indexing, while space 2 will be used
+ * for dynamic indexing. Space 0 will be individual SSBOs in the DXIL shader, while
+ * space 2 will be a single array.
+ */
+ root_params[num_params++].DescriptorTable.NumDescriptorRanges++;
+ init_range(&desc_ranges[num_ranges++],
+ D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
+ key->stages[i].num_ssbos,
+ 0,
+ 2,
+ 0);
}
if (key->stages[i].num_images > 0) {
visibility);
}
assert(num_params < PIPE_SHADER_TYPES * D3D12_NUM_BINDING_TYPES);
- assert(num_ranges < PIPE_SHADER_TYPES * D3D12_NUM_BINDING_TYPES);
+ assert(num_ranges < PIPE_SHADER_TYPES * (D3D12_NUM_BINDING_TYPES + 1));
}
D3D12_VERSIONED_ROOT_SIGNATURE_DESC root_sig_desc;
struct nir_to_dxil_options opts = {
.interpolate_at_vertex = false,
.lower_int16 = (conf && (conf->lower_bit_size & 16) != 0),
- .ubo_binding_offset = 0,
.disable_math_refactoring = true,
.num_kernel_globals = num_global_inputs,
.environment = DXIL_ENVIRONMENT_CL,
ctx->mod.shader_kind != DXIL_COMPUTE_SHADER)
ctx->mod.feats.uavs_at_every_stage = true;
- if (ctx->opts->environment != DXIL_ENVIRONMENT_VULKAN) {
+ if (ctx->opts->environment != DXIL_ENVIRONMENT_VULKAN && space <= 1) {
for (unsigned i = 0; i < count; ++i) {
const struct dxil_value *handle = emit_createhandle_call_const_index(ctx, DXIL_RESOURCE_CLASS_UAV,
id, binding + i, false);
unsigned space = 0;
if (ctx->opts->environment == DXIL_ENVIRONMENT_GL &&
- class == DXIL_RESOURCE_CLASS_UAV &&
- kind != DXIL_RESOURCE_KIND_RAW_BUFFER) {
- space = 1;
+ class == DXIL_RESOURCE_CLASS_UAV) {
+ if (kind == DXIL_RESOURCE_KIND_RAW_BUFFER)
+ space = 2;
+ else
+ space = 1;
}
- /* TODO: Figure out how to find this */
+ /* The base binding here will almost always be zero. The only cases where we end
+ * up in this type of dynamic indexing are:
+ * 1. GL UBOs
+ * 2. GL SSBOs
+ * 2. CL SSBOs
+ * In all cases except GL UBOs, the resources are a single zero-based array.
+ * In that case, the base is 1, because uniforms use 0 and cannot by dynamically
+ * indexed. All other cases should either fall into static indexing (first early return),
+ * deref-based dynamic handle creation (images, or Vulkan textures/samplers), or
+ * load_vulkan_descriptor handle creation.
+ */
unsigned base_binding = 0;
+ if (ctx->opts->environment == DXIL_ENVIRONMENT_GL &&
+ class == DXIL_RESOURCE_CLASS_CBV)
+ base_binding = 1;
const struct dxil_value *handle = emit_createhandle_call(ctx, class,
get_resource_id(ctx, class, space, base_binding), value, !const_block_index);
return false;
}
} else {
- for (int i = ctx->opts->ubo_binding_offset; i < ctx->shader->info.num_ubos; ++i) {
- char name[64];
- snprintf(name, sizeof(name), "__ubo%d", i);
- if (!emit_cbv(ctx, i, 0, 16384 /*4096 vec4's*/, 1, name))
+ if (ctx->shader->info.num_ubos) {
+ const unsigned ubo_size = 16384 /*4096 vec4's*/;
+ bool has_ubo0 = !ctx->opts->no_ubo0;
+ bool has_state_vars = ctx->opts->last_ubo_is_not_arrayed;
+ unsigned ubo1_array_size = ctx->shader->info.num_ubos -
+ (has_state_vars ? 2 : 1);
+
+ if (has_ubo0 &&
+ !emit_cbv(ctx, 0, 0, ubo_size, 1, "__ubo_uniforms"))
+ return false;
+ if (ubo1_array_size &&
+ !emit_cbv(ctx, 1, 0, ubo_size, ubo1_array_size, "__ubos"))
+ return false;
+ if (has_state_vars &&
+ !emit_cbv(ctx, ctx->shader->info.num_ubos - 1, 0, ubo_size, 1, "__ubo_state_vars"))
return false;
}
}
DXIL_RESOURCE_KIND_RAW_BUFFER, name))
return false;
}
+ /* To work around a WARP bug, bind these descriptors a second time in descriptor
+ * space 2. Space 0 will be used for static indexing, while space 2 will be used
+ * for dynamic indexing. Space 0 will be individual SSBOs in the DXIL shader, while
+ * space 2 will be a single array.
+ */
+ if (ctx->shader->info.num_ssbos &&
+ !emit_uav(ctx, 0, 2, ctx->shader->info.num_ssbos, DXIL_COMP_TYPE_INVALID,
+ DXIL_RESOURCE_KIND_RAW_BUFFER, "__ssbo_dynamic"))
+ return false;
}
nir_foreach_image_variable(var, ctx->shader) {
bool interpolate_at_vertex;
bool lower_int16;
bool disable_math_refactoring;
- unsigned ubo_binding_offset;
+ bool no_ubo0;
+ bool last_ubo_is_not_arrayed;
unsigned provoking_vertex;
unsigned num_kernel_globals;
enum dxil_environment environment;