Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 0407f501..23d1fcc7 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2236,6 +2236,8 @@ struct vkd3d_dxbc_compiler struct vkd3d_shader_spec_constant *spec_constants; size_t spec_constants_size; enum vkd3d_shader_compile_option_formatting_flags formatting; + + struct vkd3d_string_buffer_cache string_buffers; };
static bool is_control_point_phase(const struct vkd3d_shader_phase *phase) @@ -2358,6 +2360,8 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
compiler->scan_descriptor_info = scan_descriptor_info;
+ vkd3d_string_buffer_cache_init(&compiler->string_buffers); + vkd3d_dxbc_compiler_emit_initial_declarations(compiler);
return compiler; @@ -2484,6 +2488,22 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_dxbc_compiler_error(struct vkd3d_dxbc_ compiler->failed = true; }
+static struct vkd3d_string_buffer *vkd3d_shader_register_range_string(struct vkd3d_dxbc_compiler *compiler, + const struct vkd3d_shader_register_range *range) +{ + struct vkd3d_string_buffer *buffer = vkd3d_string_buffer_get(&compiler->string_buffers); + + if (!buffer) + return NULL; + + if (range->last != ~0u) + vkd3d_string_buffer_printf(buffer, "[%u:%u]", range->first, range->last); + else + vkd3d_string_buffer_printf(buffer, "[%u:*]", range->first); + + return buffer; +} + static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding( struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type, @@ -2576,11 +2596,14 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor } if (shader_interface->binding_count) { - FIXME("Could not find binding for type %#x, space %u, register %u, shader type %#x.\n", - descriptor_type, range->space, range->first, compiler->shader_type); + struct vkd3d_string_buffer *buffer = vkd3d_shader_register_range_string(compiler, range); + const char *range_str = buffer ? buffer->buffer : ""; + FIXME("Could not find descriptor binding for type %#x, space %u, registers %s, shader type %#x.\n", + descriptor_type, range->space, range_str, compiler->shader_type); vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND, - "Could not find descriptor binding for type %#x, space %u, register %u, shader type %#x.", - descriptor_type, range->space, range->first, compiler->shader_type); + "Could not find descriptor binding for type %#x, space %u, registers %s, shader type %#x.", + descriptor_type, range->space, range_str, compiler->shader_type); + vkd3d_string_buffer_release(&compiler->string_buffers, buffer); } }
@@ -9611,5 +9634,7 @@ void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler) vkd3d_free(compiler->shader_phases); vkd3d_free(compiler->spec_constants);
+ vkd3d_string_buffer_cache_cleanup(&compiler->string_buffers); + vkd3d_free(compiler); }
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 23d1fcc7..584f7c1a 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2457,7 +2457,10 @@ static bool vkd3d_dxbc_compiler_has_combined_sampler(const struct vkd3d_dxbc_com if (!shader_interface->combined_sampler_count) return false;
- if (resource && resource->reg.reg.type == VKD3DSPR_UAV) + if (resource && (resource->reg.reg.type == VKD3DSPR_UAV || resource->range.last != resource->range.first)) + return false; + + if (sampler && sampler->range.first != sampler->range.last) return false;
for (i = 0; i < shader_interface->combined_sampler_count; ++i)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 584f7c1a..2ea70463 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2433,6 +2433,9 @@ static struct vkd3d_push_constant_buffer_binding *vkd3d_dxbc_compiler_find_push_ unsigned int reg_idx = cb->range.first; unsigned int i;
+ if (cb->range.first != cb->range.last) + return NULL; + for (i = 0; i < compiler->shader_interface.push_constant_buffer_count; ++i) { struct vkd3d_push_constant_buffer_binding *current = &compiler->push_constants[i];
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 51 ++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 20 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 2ea70463..4fa94826 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -334,8 +334,9 @@ static bool vkd3d_spirv_stream_append(struct vkd3d_spirv_stream *dst_stream, struct vkd3d_spirv_builder { uint64_t capability_mask; - uint64_t capability_draw_parameters : 1; - uint64_t capability_demote_to_helper_invocation : 1; + SpvCapability *capabilities; + size_t capabilities_size; + size_t capabilities_count; uint32_t ext_instr_set_glsl_450; uint32_t invocation_count; SpvExecutionModel execution_model; @@ -371,25 +372,37 @@ static uint32_t vkd3d_spirv_alloc_id(struct vkd3d_spirv_builder *builder) return builder->current_id++; }
+static bool vkd3d_spirv_capability_is_enabled(struct vkd3d_spirv_builder *builder, + SpvCapability cap) +{ + size_t i; + + if (cap < sizeof(builder->capability_mask) * CHAR_BIT) + return (builder->capability_mask >> cap) & 1; + + for (i = 0; i < builder->capabilities_count; ++i) + if (builder->capabilities[i] == cap) + return true; + + return false; +} + static void vkd3d_spirv_enable_capability(struct vkd3d_spirv_builder *builder, SpvCapability cap) { if (cap < sizeof(builder->capability_mask) * CHAR_BIT) { builder->capability_mask |= 1ull << cap; + return; } - else if (cap == SpvCapabilityDrawParameters) - { - builder->capability_draw_parameters = 1; - } - else if (cap == SpvCapabilityDemoteToHelperInvocationEXT) - { - builder->capability_demote_to_helper_invocation = 1; - } - else - { - FIXME("Unhandled capability %#x.\n", cap); - } + + if (vkd3d_spirv_capability_is_enabled(builder, cap)) + return; + + vkd3d_array_reserve((void **)&builder->capabilities, &builder->capabilities_size, + builder->capabilities_count + 1, sizeof(*builder->capabilities)); + + builder->capabilities[builder->capabilities_count++] = cap; }
static uint32_t vkd3d_spirv_get_glsl_std450_instr_set(struct vkd3d_spirv_builder *builder) @@ -1801,15 +1814,13 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, vkd3d_spirv_build_op_capability(&stream, i); capability_mask >>= 1; } - if (builder->capability_draw_parameters) - vkd3d_spirv_build_op_capability(&stream, SpvCapabilityDrawParameters); - if (builder->capability_demote_to_helper_invocation) - vkd3d_spirv_build_op_capability(&stream, SpvCapabilityDemoteToHelperInvocationEXT); + for (i = 0; i < builder->capabilities_count; ++i) + vkd3d_spirv_build_op_capability(&stream, builder->capabilities[i]);
/* extensions */ - if (builder->capability_draw_parameters) + if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityDrawParameters)) vkd3d_spirv_build_op_extension(&stream, "SPV_KHR_shader_draw_parameters"); - if (builder->capability_demote_to_helper_invocation) + if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityDemoteToHelperInvocationEXT)) vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_demote_to_helper_invocation");
if (builder->ext_instr_set_glsl_450)
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 1 + libs/vkd3d-shader/spirv.c | 59 ++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 6cdbaf1e..b0412d30 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -573,6 +573,7 @@ enum vkd3d_shader_spirv_extension { VKD3D_SHADER_SPIRV_EXTENSION_NONE, VKD3D_SHADER_SPIRV_EXTENSION_EXT_DEMOTE_TO_HELPER_INVOCATION, + VKD3D_SHADER_SPIRV_EXTENSION_EXT_DESCRIPTOR_INDEXING,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SPIRV_EXTENSION), }; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 4fa94826..cd42eed0 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1822,6 +1822,12 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, vkd3d_spirv_build_op_extension(&stream, "SPV_KHR_shader_draw_parameters"); if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityDemoteToHelperInvocationEXT)) vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_demote_to_helper_invocation"); + if (vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityUniformBufferArrayDynamicIndexing) + || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT) + || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilitySampledImageArrayDynamicIndexing) + || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT) + || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStorageImageArrayDynamicIndexing)) + vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_descriptor_indexing");
if (builder->ext_instr_set_glsl_450) vkd3d_spirv_build_op_ext_inst_import(&stream, builder->ext_instr_set_glsl_450, "GLSL.std.450"); @@ -3126,18 +3132,56 @@ static bool register_is_descriptor(const struct vkd3d_shader_register *reg) } }
+static bool vkd3d_dxbc_compiler_enable_descriptor_indexing(struct vkd3d_dxbc_compiler *compiler, + enum vkd3d_shader_register_type reg_type, enum vkd3d_shader_resource_type resource_type) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + + if (!vkd3d_dxbc_compiler_is_target_extension_supported(compiler, + VKD3D_SHADER_SPIRV_EXTENSION_EXT_DESCRIPTOR_INDEXING)) + return false; + + switch (reg_type) + { + case VKD3DSPR_CONSTBUFFER: + vkd3d_spirv_enable_capability(builder, SpvCapabilityUniformBufferArrayDynamicIndexing); + break; + case VKD3DSPR_RESOURCE: + vkd3d_spirv_enable_capability(builder, resource_type == VKD3D_SHADER_RESOURCE_BUFFER + ? SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT + : SpvCapabilitySampledImageArrayDynamicIndexing); + break; + case VKD3DSPR_UAV: + vkd3d_spirv_enable_capability(builder, resource_type == VKD3D_SHADER_RESOURCE_BUFFER + ? SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT + : SpvCapabilityStorageImageArrayDynamicIndexing); + break; + case VKD3DSPR_SAMPLER: + break; + default: + ERR("Unhandled register type %#x.\n", reg_type); + break; + } + + return true; +} + static uint32_t vkd3d_dxbc_compiler_get_descriptor_index(struct vkd3d_dxbc_compiler *compiler, - const struct vkd3d_shader_register *reg, unsigned int binding_base_idx) + const struct vkd3d_shader_register *reg, unsigned int binding_base_idx, + enum vkd3d_shader_resource_type resource_type) { struct vkd3d_shader_register_index index = reg->idx[1]; uint32_t index_id;
if (index.rel_addr) { - FIXME("Descriptor dynamic indexing is not supported.\n"); - vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED, - "Cannot dynamically index a descriptor array of type %#x, id %u. " - "Dynamic indexing is not supported.", reg->type, reg->idx[0].offset); + if (!vkd3d_dxbc_compiler_enable_descriptor_indexing(compiler, reg->type, resource_type)) + { + FIXME("The device does not support descriptor indexing.\n"); + vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED, + "Cannot dynamically index a descriptor array of type %#x, id %u. " + "The device does not support descriptor indexing.", reg->type, reg->idx[0].offset); + } }
index.offset -= binding_base_idx; @@ -3159,7 +3203,8 @@ static void vkd3d_dxbc_compiler_emit_dereference_register(struct vkd3d_dxbc_comp assert(!reg->idx[0].rel_addr); if (register_info->descriptor_array) indexes[index_count++] = vkd3d_dxbc_compiler_get_descriptor_index(compiler, reg, - register_info->descriptor_array->info.descriptor_array.binding_base_idx); + register_info->descriptor_array->info.descriptor_array.binding_base_idx, + VKD3D_SHADER_RESOURCE_BUFFER); indexes[index_count++] = vkd3d_dxbc_compiler_get_constant_uint(compiler, register_info->member_idx); indexes[index_count++] = vkd3d_dxbc_compiler_emit_register_addressing(compiler, ®->idx[2]); } @@ -7818,7 +7863,7 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil uint32_t ptr_type_id, index_id;
index_id = vkd3d_dxbc_compiler_get_descriptor_index(compiler, resource_reg, - array_data->binding_base_idx); + array_data->binding_base_idx, symbol->info.resource.resource_type_info->resource_type);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, array_data->storage_class, array_data->contained_type_id);
On Tue, 27 Jul 2021 at 15:41, Conor McCarthy cmccarthy@codeweavers.com wrote:
+static bool vkd3d_dxbc_compiler_enable_descriptor_indexing(struct vkd3d_dxbc_compiler *compiler,
enum vkd3d_shader_register_type reg_type, enum vkd3d_shader_resource_type resource_type)
+{
- struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
- if (!vkd3d_dxbc_compiler_is_target_extension_supported(compiler,
VKD3D_SHADER_SPIRV_EXTENSION_EXT_DESCRIPTOR_INDEXING))
return false;
- switch (reg_type)
- {
case VKD3DSPR_CONSTBUFFER:
vkd3d_spirv_enable_capability(builder, SpvCapabilityUniformBufferArrayDynamicIndexing);
break;
case VKD3DSPR_RESOURCE:
vkd3d_spirv_enable_capability(builder, resource_type == VKD3D_SHADER_RESOURCE_BUFFER
? SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT
: SpvCapabilitySampledImageArrayDynamicIndexing);
break;
case VKD3DSPR_UAV:
vkd3d_spirv_enable_capability(builder, resource_type == VKD3D_SHADER_RESOURCE_BUFFER
? SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT
: SpvCapabilityStorageImageArrayDynamicIndexing);
break;
Yes, but when the application enabled "VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV_STORAGE_BUFFER", we use storage buffers for buffer UAVs. (See also vkd3d_dxbc_compiler_use_storage_buffer().)
static uint32_t vkd3d_dxbc_compiler_get_descriptor_index(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_register *reg, unsigned int binding_base_idx)
const struct vkd3d_shader_register *reg, unsigned int binding_base_idx,
enum vkd3d_shader_resource_type resource_type)
{ struct vkd3d_shader_register_index index = reg->idx[1]; uint32_t index_id;
if (index.rel_addr) {
FIXME("Descriptor dynamic indexing is not supported.\n");
vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED,
"Cannot dynamically index a descriptor array of type %#x, id %u. "
"Dynamic indexing is not supported.", reg->type, reg->idx[0].offset);
if (!vkd3d_dxbc_compiler_enable_descriptor_indexing(compiler, reg->type, resource_type))
{
FIXME("The device does not support descriptor indexing.\n");
vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_IDX_UNSUPPORTED,
"Cannot dynamically index a descriptor array of type %#x, id %u. "
"The device does not support descriptor indexing.", reg->type, reg->idx[0].offset);
}}
Using "The device" here is a little awkward. It makes sense when vkd3d-shader is used by libvkd3d or wined3d, but less so when used for offline compilation by e.g. vkd3d-compiler. Perhaps something like "The target environment" would be more appropriate.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index cd42eed0..36909c06 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5560,8 +5560,9 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com const SpvStorageClass storage_class = SpvStorageClassUniformConstant; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const struct vkd3d_shader_register *reg = &sampler->src.reg; - uint32_t type_id, ptr_type_id, var_id; + const struct vkd3d_symbol *array_symbol; struct vkd3d_symbol reg_symbol; + uint32_t type_id, var_id;
vkd3d_symbol_make_sampler(®_symbol, reg); reg_symbol.info.sampler.range = sampler->range; @@ -5571,18 +5572,13 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com return;
type_id = vkd3d_spirv_get_op_type_sampler(builder); - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); - var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, - ptr_type_id, storage_class, 0); - - vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler, var_id, reg, - &sampler->range, VKD3D_SHADER_RESOURCE_NONE, false); - - vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + var_id = vkd3d_dxbc_compiler_build_descriptor_variable(compiler, storage_class, type_id, reg, + &sampler->range, VKD3D_SHADER_RESOURCE_NONE, &array_symbol);
vkd3d_symbol_make_register(®_symbol, reg); vkd3d_symbol_set_register_info(®_symbol, var_id, storage_class, VKD3D_SHADER_COMPONENT_FLOAT, VKD3DSP_WRITEMASK_ALL); + reg_symbol.descriptor_array = array_symbol; vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol); }
@@ -7900,10 +7896,24 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
if (sampled) { + struct vkd3d_shader_register_info register_info; + assert(image->image_id); assert(sampler_reg);
- sampler_var_id = vkd3d_dxbc_compiler_get_register_id(compiler, sampler_reg); + if (!vkd3d_dxbc_compiler_get_register_info(compiler, sampler_reg, ®ister_info)) + ERR("Failed to get sampler register info.\n"); + sampler_var_id = register_info.id; + if (register_info.descriptor_array) + { + const struct vkd3d_symbol_descriptor_array_data *array_data + = ®ister_info.descriptor_array->info.descriptor_array; + uint32_t ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, + register_info.storage_class, array_data->contained_type_id); + uint32_t array_idx = vkd3d_dxbc_compiler_get_descriptor_index(compiler, + sampler_reg, array_data->binding_base_idx, VKD3D_SHADER_RESOURCE_NONE); + sampler_var_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, register_info.id, &array_idx, 1); + }
sampler_id = vkd3d_spirv_build_op_load(builder, vkd3d_spirv_get_op_type_sampler(builder), sampler_var_id, SpvMemoryAccessMaskNone);