Based on register loading code from Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/dxbc.c | 121 ++++++++++++++++------- libs/vkd3d-shader/spirv.c | 86 +++++++++++----- libs/vkd3d-shader/vkd3d_shader_main.c | 17 ++-- libs/vkd3d-shader/vkd3d_shader_private.h | 8 +- 4 files changed, 157 insertions(+), 75 deletions(-)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index d2cf87e3..ad1db82a 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -622,12 +622,24 @@ static void shader_sm4_read_shader_data(struct vkd3d_shader_instruction *ins, ins->declaration.icb = &priv->icb; }
-static unsigned int shader_sm4_map_resource_idx(struct vkd3d_shader_register *reg, const struct vkd3d_sm4_data *priv) +static void shader_sm4_read_register_indices(struct vkd3d_shader_resource *resource, + struct vkd3d_shader_instruction *ins, struct vkd3d_sm4_data *priv) { if (shader_is_sm_5_1(priv)) - return reg->idx[1].offset; + { + resource->register_first = resource->reg.reg.idx[1].offset; + resource->register_last = resource->reg.reg.idx[2].offset; + if (resource->register_last < resource->register_first) + { + FIXME("Invalid register range [%u:%u].\n", resource->register_first, resource->register_last); + ins->handler_idx = VKD3DSIH_INVALID; + } + } else - return reg->idx[0].offset; + { + resource->register_first = resource->reg.reg.idx[0].offset; + resource->register_last = resource->register_first; + } }
static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, @@ -635,6 +647,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, struct vkd3d_sm4_data *priv) { struct vkd3d_shader_semantic *semantic = &ins->declaration.semantic; + struct vkd3d_shader_resource *resource = &semantic->resource; enum vkd3d_sm4_resource_type resource_type; const DWORD *end = &tokens[token_count]; enum vkd3d_sm4_data_type data_type; @@ -653,8 +666,7 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, semantic->resource_type = resource_type_table[resource_type]; } reg_data_type = opcode == VKD3D_SM4_OP_DCL_RESOURCE ? VKD3D_DATA_RESOURCE : VKD3D_DATA_UAV; - shader_sm4_read_dst_param(priv, &tokens, end, reg_data_type, &semantic->resource.reg); - semantic->resource.register_index = shader_sm4_map_resource_idx(&semantic->resource.reg.reg, priv); + shader_sm4_read_dst_param(priv, &tokens, end, reg_data_type, &resource->reg);
components = *tokens++; for (i = 0; i < VKD3D_VEC4_SIZE; i++) @@ -675,23 +687,21 @@ static void shader_sm4_read_dcl_resource(struct vkd3d_shader_instruction *ins, if (reg_data_type == VKD3D_DATA_UAV) ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT;
- shader_sm4_read_register_space(priv, &tokens, end, &semantic->resource.register_space); + shader_sm4_read_register_space(priv, &tokens, end, &resource->register_space); + shader_sm4_read_register_indices(resource, ins, priv); }
static void shader_sm4_read_dcl_constant_buffer(struct vkd3d_shader_instruction *ins, DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count, struct vkd3d_sm4_data *priv) { + struct vkd3d_shader_constant_buffer *cb = &ins->declaration.cb; const DWORD *end = &tokens[token_count];
- shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_FLOAT, &ins->declaration.cb.src); - ins->declaration.cb.register_index = shader_sm4_map_resource_idx(&ins->declaration.cb.src.reg, priv); if (opcode_token & VKD3D_SM4_INDEX_TYPE_MASK) ins->flags |= VKD3DSI_INDEXED_DYNAMIC;
- ins->declaration.cb.size = ins->declaration.cb.src.reg.idx[2].offset; - ins->declaration.cb.register_space = 0; - + shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_FLOAT, &cb->src); if (shader_is_sm_5_1(priv)) { if (tokens >= end) @@ -700,8 +710,22 @@ static void shader_sm4_read_dcl_constant_buffer(struct vkd3d_shader_instruction return; }
- ins->declaration.cb.size = *tokens++; - shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.cb.register_space); + cb->size = *tokens++; + shader_sm4_read_register_space(priv, &tokens, end, &cb->register_space); + cb->register_first = cb->src.reg.idx[1].offset; + cb->register_last = cb->src.reg.idx[2].offset; + if (cb->register_last < cb->register_first) + { + FIXME("Invalid register range [%u:%u].\n", cb->register_first, cb->register_last); + ins->handler_idx = VKD3DSIH_INVALID; + } + } + else + { + cb->size = cb->src.reg.idx[2].offset; + cb->register_space = 0; + cb->register_first = cb->src.reg.idx[0].offset; + cb->register_last = cb->register_first; } }
@@ -709,14 +733,31 @@ static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins, DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count, struct vkd3d_sm4_data *priv) { + struct vkd3d_shader_sampler *sampler = &ins->declaration.sampler; const DWORD *end = &tokens[token_count];
ins->flags = (opcode_token & VKD3D_SM4_SAMPLER_MODE_MASK) >> VKD3D_SM4_SAMPLER_MODE_SHIFT; if (ins->flags & ~VKD3D_SM4_SAMPLER_COMPARISON) FIXME("Unhandled sampler mode %#x.\n", ins->flags); - shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_SAMPLER, &ins->declaration.sampler.src); - ins->declaration.sampler.register_index = shader_sm4_map_resource_idx(&ins->declaration.sampler.src.reg, priv); - shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.sampler.register_space); + + shader_sm4_read_src_param(priv, &tokens, end, VKD3D_DATA_SAMPLER, &sampler->src); + if (shader_is_sm_5_1(priv)) + { + shader_sm4_read_register_space(priv, &tokens, end, &sampler->register_space); + sampler->register_first = sampler->src.reg.idx[1].offset; + sampler->register_last = sampler->src.reg.idx[2].offset; + if (sampler->register_last < sampler->register_first) + { + FIXME("Invalid register range [%u:%u].\n", sampler->register_first, sampler->register_last); + ins->handler_idx = VKD3DSIH_INVALID; + } + } + else + { + sampler->register_space = 0; + sampler->register_first = sampler->src.reg.idx[0].offset; + sampler->register_last = sampler->register_first; + } }
static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins, @@ -912,29 +953,32 @@ static void shader_sm5_read_dcl_uav_raw(struct vkd3d_shader_instruction *ins, DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count, struct vkd3d_sm4_data *priv) { - struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource; + struct vkd3d_shader_resource *resource = &ins->declaration.raw_resource.resource; const DWORD *end = &tokens[token_count];
- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->resource.reg); - resource->resource.register_index = shader_sm4_map_resource_idx(&resource->resource.reg.reg, priv); ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; - shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.register_space); + + shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->reg); + shader_sm4_read_register_space(priv, &tokens, end, &resource->register_space); + shader_sm4_read_register_indices(resource, ins, priv); }
static void shader_sm5_read_dcl_uav_structured(struct vkd3d_shader_instruction *ins, DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count, struct vkd3d_sm4_data *priv) { - struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource; + struct vkd3d_shader_structured_resource *structured = &ins->declaration.structured_resource; + struct vkd3d_shader_resource *resource = &structured->resource; const DWORD *end = &tokens[token_count];
- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->resource.reg); - resource->resource.register_index = shader_sm4_map_resource_idx(&resource->resource.reg.reg, priv); ins->flags = (opcode_token & VKD3D_SM5_UAV_FLAGS_MASK) >> VKD3D_SM5_UAV_FLAGS_SHIFT; - resource->byte_stride = *tokens++; - if (resource->byte_stride % 4) - FIXME("Byte stride %u is not multiple of 4.\n", resource->byte_stride); - shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.register_space); + + shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_UAV, &resource->reg); + structured->byte_stride = *tokens++; + if (structured->byte_stride % 4) + FIXME("Byte stride %u is not multiple of 4.\n", structured->byte_stride); + shader_sm4_read_register_space(priv, &tokens, end, &resource->register_space); + shader_sm4_read_register_indices(resource, ins, priv); }
static void shader_sm5_read_dcl_tgsm_raw(struct vkd3d_shader_instruction *ins, @@ -963,27 +1007,28 @@ static void shader_sm5_read_dcl_resource_structured(struct vkd3d_shader_instruct DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count, struct vkd3d_sm4_data *priv) { - struct vkd3d_shader_structured_resource *resource = &ins->declaration.structured_resource; + struct vkd3d_shader_structured_resource *structured = &ins->declaration.structured_resource; + struct vkd3d_shader_resource *resource = &structured->resource; const DWORD *end = &tokens[token_count];
- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->resource.reg); - resource->resource.register_index = shader_sm4_map_resource_idx(&resource->resource.reg.reg, priv); - resource->byte_stride = *tokens++; - if (resource->byte_stride % 4) - FIXME("Byte stride %u is not multiple of 4.\n", resource->byte_stride); - shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.register_space); + shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->reg); + structured->byte_stride = *tokens++; + if (structured->byte_stride % 4) + FIXME("Byte stride %u is not multiple of 4.\n", structured->byte_stride); + shader_sm4_read_register_space(priv, &tokens, end, &resource->register_space); + shader_sm4_read_register_indices(resource, ins, priv); }
static void shader_sm5_read_dcl_resource_raw(struct vkd3d_shader_instruction *ins, DWORD opcode, DWORD opcode_token, const DWORD *tokens, unsigned int token_count, struct vkd3d_sm4_data *priv) { - struct vkd3d_shader_raw_resource *resource = &ins->declaration.raw_resource; + struct vkd3d_shader_resource *resource = &ins->declaration.raw_resource.resource; const DWORD *end = &tokens[token_count];
- shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->resource.reg); - resource->resource.register_index = shader_sm4_map_resource_idx(&resource->resource.reg.reg, priv); - shader_sm4_read_register_space(priv, &tokens, end, &resource->resource.register_space); + shader_sm4_read_dst_param(priv, &tokens, end, VKD3D_DATA_RESOURCE, &resource->reg); + shader_sm4_read_register_space(priv, &tokens, end, &resource->register_space); + shader_sm4_read_register_indices(resource, ins, priv); }
static void shader_sm5_read_sync(struct vkd3d_shader_instruction *ins, diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index d477b384..0342efa3 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2077,6 +2077,14 @@ static const char *debug_vkd3d_symbol(const struct vkd3d_symbol *symbol) } }
+static const char *debug_register_range(unsigned int register_first, unsigned int register_last, bool bounded) +{ + if (bounded) + return vkd3d_dbg_sprintf("[%u:%u]", register_first, register_last); + else + return vkd3d_dbg_sprintf("[%u:*]", register_first); +} + struct vkd3d_if_cf_info { size_t stream_location; @@ -2404,9 +2412,12 @@ static struct vkd3d_push_constant_buffer_binding *vkd3d_dxbc_compiler_find_push_ const struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_constant_buffer *cb) { unsigned int register_space = cb->register_space; - unsigned int reg_idx = cb->register_index; + unsigned int reg_idx = cb->register_first; unsigned int i;
+ if (cb->register_first != cb->register_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]; @@ -2431,7 +2442,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->register_last != resource->register_first)) + return false; + + if (sampler && sampler->register_first != sampler->register_last) return false;
for (i = 0; i < shader_interface->combined_sampler_count; ++i) @@ -2442,9 +2456,9 @@ static bool vkd3d_dxbc_compiler_has_combined_sampler(const struct vkd3d_dxbc_com continue;
if ((!resource || (combined_sampler->resource_space == resource->register_space - && combined_sampler->resource_index == resource->register_index)) + && combined_sampler->resource_index == resource->register_first)) && (!sampler || (combined_sampler->sampler_space == sampler->register_space - && combined_sampler->sampler_index == sampler->register_index))) + && combined_sampler->sampler_index == sampler->register_first))) return true; }
@@ -2464,12 +2478,14 @@ static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_dxbc_compiler_error(struct vkd3d_dxbc_
static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding( struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, unsigned int register_space, - unsigned int reg_idx, enum vkd3d_shader_resource_type resource_type, bool is_uav_counter) + unsigned int register_first, unsigned int register_last, enum vkd3d_shader_resource_type resource_type, + bool is_uav_counter) { const struct vkd3d_shader_interface_info *shader_interface = &compiler->shader_interface; enum vkd3d_shader_descriptor_type descriptor_type; enum vkd3d_shader_binding_flag resource_type_flag; struct vkd3d_shader_descriptor_binding binding; + bool bounded = true; unsigned int i;
if (reg->type == VKD3DSPR_CONSTBUFFER) @@ -2491,6 +2507,12 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE;
+ if (register_last == ~0u) + { + bounded = false; + register_last = register_first; + } + if (is_uav_counter) { assert(descriptor_type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV); @@ -2501,15 +2523,17 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor if (!vkd3d_dxbc_compiler_check_shader_visibility(compiler, current->shader_visibility)) continue;
- if (current->register_space != register_space || current->register_index != reg_idx) + if (current->register_space != register_space || current->register_index > register_first + || current->register_index + current->binding.count <= register_last) continue;
if (current->offset) { FIXME("Atomic counter offsets are not supported yet.\n"); vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING, - "Descriptor binding for UAV counter %u, space %u has unsupported ‘offset’ %u.", - reg_idx, register_space, current->offset); + "Descriptor binding for UAV counter %s, space %u has unsupported ‘offset’ %u.", + debug_register_range(register_first, register_last, bounded), + register_space, current->offset); }
if (current->binding.count != 1) @@ -2517,16 +2541,18 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor FIXME("Descriptor arrays are not supported.\n"); vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING, "Descriptor binding for UAV counter %u, space %u has unsupported ‘count’ %u.", - reg_idx, register_space, current->binding.count); + register_first, register_space, current->binding.count); }
return current->binding; } if (shader_interface->uav_counter_count) { - FIXME("Could not find descriptor binding for UAV counter %u, space %u.\n", reg_idx, register_space); + FIXME("Could not find descriptor binding for UAV counters %s, space %u.\n", + debug_register_range(register_first, register_last, bounded), register_space); vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND, - "Could not find descriptor binding for UAV counter %u, space %u.", reg_idx, register_space); + "Could not find descriptor binding for UAV counters %s, space %u.", + debug_register_range(register_first, register_last, bounded), register_space); } } else @@ -2542,7 +2568,8 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor continue;
if (current->type != descriptor_type || current->register_space != register_space - || current->register_index != reg_idx) + || current->register_index > register_first + || current->register_index + current->binding.count <= register_last) continue;
if (current->binding.count != 1) @@ -2558,11 +2585,13 @@ 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, register_space, reg_idx, compiler->shader_type); + FIXME("Could not find binding for type %#x, space %u, registers %s, shader type %#x.\n", + descriptor_type, register_space, debug_register_range(register_first, register_last, bounded), + 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, register_space, reg_idx, compiler->shader_type); + "Could not find descriptor binding for type %#x, space %u, registers %s, shader type %#x.", + descriptor_type, register_space, debug_register_range(register_first, register_last, bounded), + compiler->shader_type); } }
@@ -2585,12 +2614,13 @@ static void vkd3d_dxbc_compiler_emit_descriptor_binding(struct vkd3d_dxbc_compil
static void vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(struct vkd3d_dxbc_compiler *compiler, uint32_t variable_id, const struct vkd3d_shader_register *reg, unsigned int register_space, - unsigned int register_index, enum vkd3d_shader_resource_type resource_type, bool is_uav_counter) + unsigned int register_first, unsigned int register_last, enum vkd3d_shader_resource_type resource_type, + bool is_uav_counter) { struct vkd3d_shader_descriptor_binding binding;
binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, register_space, - register_index, resource_type, is_uav_counter); + register_first, register_last, resource_type, is_uav_counter); vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, variable_id, &binding); }
@@ -5365,7 +5395,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com
vkd3d_symbol_make_sampler(®_symbol, reg); reg_symbol.info.sampler.register_space = sampler->register_space; - reg_symbol.info.sampler.register_index = sampler->register_index; + reg_symbol.info.sampler.register_index = sampler->register_first; vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
if (vkd3d_dxbc_compiler_has_combined_sampler(compiler, NULL, sampler)) @@ -5435,7 +5465,8 @@ static const struct vkd3d_shader_descriptor_info *vkd3d_dxbc_compiler_get_descri for (i = 0; i < descriptor_info->descriptor_count; ++i) { d = &descriptor_info->descriptors[i]; - if (d->type == type && d->register_space == register_space && d->register_index == register_index) + if (d->type == type && d->register_space == register_space && d->register_index <= register_index + && (d->count == ~0u || d->register_index + d->count > register_index)) return d; }
@@ -5556,7 +5587,9 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp const struct vkd3d_shader_register *reg = &resource->reg.reg; const struct vkd3d_spirv_resource_type *resource_type_info; unsigned int register_space = resource->register_space; - unsigned int register_index = resource->register_index; + unsigned int register_first = resource->register_first; + unsigned int register_last = resource->register_last; + struct vkd3d_shader_descriptor_binding binding; enum vkd3d_shader_component_type sampled_type; struct vkd3d_symbol resource_symbol; bool is_uav; @@ -5574,7 +5607,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp if (vkd3d_dxbc_compiler_has_combined_sampler(compiler, resource, NULL)) { vkd3d_dxbc_compiler_emit_combined_sampler_declarations(compiler, reg, register_space, - register_index, resource_type, sampled_type, structure_stride, raw, resource_type_info); + register_first, resource_type, sampled_type, structure_stride, raw, resource_type_info); return; }
@@ -5597,7 +5630,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp else { type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, reg, register_space, - register_index, resource_type_info, sampled_type, structure_stride || raw, 0); + register_first, resource_type_info, sampled_type, structure_stride || raw, 0); }
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); @@ -5614,7 +5647,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp const struct vkd3d_shader_descriptor_info *d;
d = vkd3d_dxbc_compiler_get_descriptor_info(compiler, - VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, register_space, register_index); + VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, register_space, register_first);
if (!(d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ)) vkd3d_spirv_build_op_decorate(builder, var_id, SpvDecorationNonReadable, NULL, 0); @@ -5650,7 +5683,8 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp ptr_type_id, storage_class, 0);
vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler, - counter_var_id, reg, register_space, register_index, resource_type, true); + counter_var_id, reg, register_space, register_first, register_last, + resource_type, true);
vkd3d_spirv_build_op_name(builder, counter_var_id, "u%u_counter", reg->idx[0].offset); } @@ -5659,7 +5693,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp vkd3d_symbol_make_resource(&resource_symbol, reg); resource_symbol.id = var_id; resource_symbol.info.resource.register_space = register_space; - resource_symbol.info.resource.register_index = register_index; + resource_symbol.info.resource.register_index = register_first; resource_symbol.info.resource.sampled_type = sampled_type; resource_symbol.info.resource.type_id = type_id; resource_symbol.info.resource.resource_type_info = resource_type_info; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 2308b894..31029ad9 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -580,9 +580,9 @@ static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_contex }
static bool vkd3d_shader_scan_add_descriptor(struct vkd3d_shader_scan_context *context, - enum vkd3d_shader_descriptor_type type, unsigned int register_space, unsigned int register_index, - enum vkd3d_shader_resource_type resource_type, enum vkd3d_shader_resource_data_type resource_data_type, - unsigned int flags) + enum vkd3d_shader_descriptor_type type, unsigned int register_space, unsigned int register_first, + unsigned int register_last, enum vkd3d_shader_resource_type resource_type, + enum vkd3d_shader_resource_data_type resource_data_type, unsigned int flags) { struct vkd3d_shader_scan_descriptor_info *info = context->scan_descriptor_info; struct vkd3d_shader_descriptor_info *d; @@ -597,11 +597,11 @@ static bool vkd3d_shader_scan_add_descriptor(struct vkd3d_shader_scan_context *c d = &info->descriptors[info->descriptor_count]; d->type = type; d->register_space = register_space; - d->register_index = register_index; + d->register_index = register_first; d->resource_type = resource_type; d->resource_data_type = resource_data_type; d->flags = flags; - d->count = 1; + d->count = (register_last == ~0u) ? ~0u : register_last - register_first + 1; ++info->descriptor_count;
return true; @@ -633,7 +633,7 @@ static void vkd3d_shader_scan_constant_buffer_declaration(struct vkd3d_shader_sc return;
vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, cb->register_space, - cb->register_index, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0); + cb->register_first, cb->register_last, VKD3D_SHADER_RESOURCE_BUFFER, VKD3D_SHADER_RESOURCE_DATA_UINT, 0); }
static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_context *context, @@ -650,7 +650,8 @@ static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_conte else flags = 0; vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler->register_space, - sampler->register_index, VKD3D_SHADER_RESOURCE_NONE, VKD3D_SHADER_RESOURCE_DATA_UINT, flags); + sampler->register_first, sampler->register_last, VKD3D_SHADER_RESOURCE_NONE, + VKD3D_SHADER_RESOURCE_DATA_UINT, flags); }
static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_context *context, @@ -667,7 +668,7 @@ static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_cont else type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV; vkd3d_shader_scan_add_descriptor(context, type, resource->register_space, - resource->register_index, resource_type, resource_data_type, 0); + resource->register_first, resource->register_last, resource_type, resource_data_type, 0); if (type == VKD3D_SHADER_DESCRIPTOR_TYPE_UAV) vkd3d_shader_scan_add_uav_range(context, resource->reg.reg.idx[0].offset, context->scan_descriptor_info->descriptor_count - 1); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 6d756e40..54930fa2 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -640,7 +640,7 @@ struct vkd3d_shader_resource { struct vkd3d_shader_dst_param reg; unsigned int register_space; - unsigned int register_index; + unsigned int register_first, register_last; };
enum vkd3d_decl_usage @@ -715,14 +715,16 @@ struct vkd3d_shader_register_semantic struct vkd3d_shader_sampler { struct vkd3d_shader_src_param src; - unsigned int register_space, register_index; + unsigned int register_space; + unsigned int register_first, register_last; };
struct vkd3d_shader_constant_buffer { struct vkd3d_shader_src_param src; unsigned int size; - unsigned int register_space, register_index; + unsigned int register_space; + unsigned int register_first, register_last; };
struct vkd3d_shader_structured_resource
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/spirv.c | 294 +++++++++++++++++++++++++++++++++----- 1 file changed, 257 insertions(+), 37 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 0342efa3..b99615f4 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1,5 +1,6 @@ /* * Copyright 2017 Józef Kucia for CodeWeavers + * Copyright 2021 Conor McCarthy for Codeweavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -335,6 +336,7 @@ struct vkd3d_spirv_builder uint64_t capability_mask; uint64_t capability_draw_parameters : 1; uint64_t capability_demote_to_helper_invocation : 1; + uint64_t capability_descriptor_indexing : 1; uint32_t ext_instr_set_glsl_450; uint32_t invocation_count; SpvExecutionModel execution_model; @@ -391,6 +393,11 @@ static void vkd3d_spirv_enable_capability(struct vkd3d_spirv_builder *builder, } }
+static void vkd3d_spirv_enable_descriptor_indexing(struct vkd3d_spirv_builder *builder) +{ + builder->capability_descriptor_indexing = 1; +} + static uint32_t vkd3d_spirv_get_glsl_std450_instr_set(struct vkd3d_spirv_builder *builder) { if (!builder->ext_instr_set_glsl_450) @@ -1808,6 +1815,8 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, vkd3d_spirv_build_op_extension(&stream, "SPV_KHR_shader_draw_parameters"); if (builder->capability_demote_to_helper_invocation) vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_demote_to_helper_invocation"); + if (builder->capability_descriptor_indexing || builder->capability_non_uniform) + 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"); @@ -1921,6 +1930,7 @@ struct vkd3d_symbol_combined_sampler struct vkd3d_symbol_register_data { SpvStorageClass storage_class; + int binding_offset; /* Offset within a merged array binding. */ uint32_t member_idx; enum vkd3d_shader_component_type component_type; unsigned int write_mask; @@ -1934,8 +1944,11 @@ struct vkd3d_symbol_resource_data { unsigned int register_space; unsigned int register_index; + int binding_offset; /* Offset within a merged array binding. */ + SpvStorageClass storage_class; enum vkd3d_shader_component_type sampled_type; uint32_t type_id; + uint32_t contained_type_id; const struct vkd3d_spirv_resource_type *resource_type_info; unsigned int structure_stride; bool raw; @@ -1977,6 +1990,35 @@ struct vkd3d_symbol } info; };
+struct vkd3d_array_variable_key +{ + uint32_t ptr_type_id; + unsigned int set; + unsigned int binding; +}; + +struct vkd3d_array_variable +{ + struct rb_entry entry; + struct vkd3d_array_variable_key key; + uint32_t id; +}; + +static int vkd3d_array_variable_compare(const void *key, const struct rb_entry *entry) +{ + const struct vkd3d_array_variable *a = key; + const struct vkd3d_array_variable *b = RB_ENTRY_VALUE(entry, const struct vkd3d_array_variable, entry); + + return memcmp(&a->key, &b->key, sizeof(a->key)); +} + +static void vkd3d_array_variable_free(struct rb_entry *entry, void *context) +{ + struct vkd3d_array_variable *s = RB_ENTRY_VALUE(entry, struct vkd3d_array_variable, entry); + + vkd3d_free(s); +} + static int vkd3d_symbol_compare(const void *key, const struct rb_entry *entry) { const struct vkd3d_symbol *a = key; @@ -2012,6 +2054,7 @@ static void vkd3d_symbol_set_register_info(struct vkd3d_symbol *symbol, { symbol->id = val_id; symbol->info.reg.storage_class = storage_class; + symbol->info.reg.binding_offset = VKD3D_SHADER_SINGLE_BINDING; symbol->info.reg.member_idx = 0; symbol->info.reg.component_type = component_type; symbol->info.reg.write_mask = write_mask; @@ -2172,11 +2215,13 @@ struct vkd3d_dxbc_compiler bool ssbo_uavs;
struct rb_tree symbol_table; + struct rb_tree array_var_table; uint32_t temp_id; unsigned int temp_count; struct vkd3d_hull_shader_variables hs; uint32_t sample_positions_id;
+ struct vkd3d_shader_version shader_version; enum vkd3d_shader_type shader_type;
unsigned int branch_id; @@ -2224,6 +2269,11 @@ struct vkd3d_dxbc_compiler enum vkd3d_shader_compile_option_formatting_flags formatting; };
+static bool shader_is_sm_5_1(const struct vkd3d_dxbc_compiler *compiler) +{ + return (((unsigned int)compiler->shader_version.major << 8) + compiler->shader_version.minor) >= 0x501; +} + static bool is_control_point_phase(const struct vkd3d_shader_phase *phase) { return phase && phase->type == VKD3DSIH_HS_CONTROL_POINT_PHASE; @@ -2317,7 +2367,9 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader }
rb_init(&compiler->symbol_table, vkd3d_symbol_compare); + rb_init(&compiler->array_var_table, vkd3d_array_variable_compare);
+ compiler->shader_version = *shader_version; compiler->shader_type = shader_version->type;
compiler->input_signature = &shader_desc->input_signature; @@ -2572,14 +2624,8 @@ static struct vkd3d_shader_descriptor_binding vkd3d_dxbc_compiler_get_descriptor || current->register_index + current->binding.count <= register_last) continue;
- if (current->binding.count != 1) - { - FIXME("Descriptor arrays are not supported.\n"); - vkd3d_dxbc_compiler_error(compiler, VKD3D_SHADER_ERROR_SPV_INVALID_DESCRIPTOR_BINDING, - "Descriptor binding for type %#x, space %u, register %u, " - "shader type %#x has unsupported ‘count’ %u.", - descriptor_type, register_space, reg_idx, compiler->shader_type, current->binding.count); - } + if (current->binding.offset != VKD3D_SHADER_SINGLE_BINDING || !bounded) + vkd3d_spirv_enable_descriptor_indexing(&compiler->spirv_builder);
return current->binding; } @@ -2815,6 +2861,42 @@ static void vkd3d_dxbc_compiler_emit_register_debug_name(struct vkd3d_spirv_buil vkd3d_spirv_build_op_name(builder, id, "%s", debug_name); }
+static bool vkd3d_dxbc_compiler_get_range_binding_debug_name(char *buffer, unsigned int buffer_size, + const struct vkd3d_shader_register *reg, const struct vkd3d_shader_descriptor_binding *binding) +{ + char count[8] = "*"; + if (binding->count < 0x10000) + snprintf(count, ARRAY_SIZE(count), "%u", binding->count); + switch (reg->type) + { + case VKD3DSPR_RESOURCE: + snprintf(buffer, buffer_size, "t%u_%s", binding->offset, count); + break; + case VKD3DSPR_UAV: + snprintf(buffer, buffer_size, "u%u_%s", binding->offset, count); + break; + case VKD3DSPR_SAMPLER: + snprintf(buffer, buffer_size, "s%u_%s", binding->offset, count); + break; + case VKD3DSPR_CONSTBUFFER: + snprintf(buffer, buffer_size, "cb%u_%s_%u", binding->offset, count, reg->idx[1].offset); + break; + default: + FIXME("Unhandled register %#x.\n", reg->type); + return false; + } + + return true; +} + +static void vkd3d_dxbc_compiler_emit_range_binding_debug_name(struct vkd3d_spirv_builder *builder, + uint32_t id, const struct vkd3d_shader_register *reg, const struct vkd3d_shader_descriptor_binding *binding) +{ + char debug_name[256]; + if (vkd3d_dxbc_compiler_get_range_binding_debug_name(debug_name, ARRAY_SIZE(debug_name), reg, binding)) + vkd3d_spirv_build_op_name(builder, id, "%s", debug_name); +} + static uint32_t vkd3d_dxbc_compiler_emit_variable(struct vkd3d_dxbc_compiler *compiler, struct vkd3d_spirv_stream *stream, SpvStorageClass storage_class, enum vkd3d_shader_component_type component_type, unsigned int component_count) @@ -2845,6 +2927,66 @@ static uint32_t vkd3d_dxbc_compiler_emit_array_variable(struct vkd3d_dxbc_compil return vkd3d_spirv_build_op_variable(builder, stream, ptr_type_id, storage_class, 0); }
+static uint32_t vkd3d_dxbc_compiler_get_resource_variable(struct vkd3d_dxbc_compiler *compiler, + SpvStorageClass storage_class, uint32_t ptr_type_id, const struct vkd3d_shader_register *reg, + const struct vkd3d_shader_descriptor_binding *binding, bool unbounded) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + + if (binding->offset != VKD3D_SHADER_SINGLE_BINDING || unbounded) + { + struct vkd3d_array_variable *array_var_entry; + struct vkd3d_array_variable array_var; + struct rb_entry *entry; + + /* Declare one array variable per Vulkan binding, and use it for all array declarations + * which map to it. In this case ptr_type_id must point to an array type. */ + array_var.key.ptr_type_id = ptr_type_id; + array_var.key.set = binding->set; + array_var.key.binding = binding->binding; + if ((entry = rb_get(&compiler->array_var_table, &array_var))) + { + array_var_entry = RB_ENTRY_VALUE(entry, struct vkd3d_array_variable, entry); + return array_var_entry->id; + } + + array_var.id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, + ptr_type_id, storage_class, 0); + vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, array_var.id, binding); + vkd3d_dxbc_compiler_emit_range_binding_debug_name(builder, array_var.id, reg, binding); + + array_var_entry = vkd3d_malloc(sizeof(*array_var_entry)); + memcpy(array_var_entry, &array_var, sizeof(*array_var_entry)); + rb_put(&compiler->array_var_table, array_var_entry, &array_var_entry->entry); + + return array_var.id; + } + else + { + uint32_t var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, + ptr_type_id, storage_class, 0); + vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, binding); + vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + return var_id; + } +} + +static uint32_t vkd3d_dxbc_compiler_build_resource_variable(struct vkd3d_dxbc_compiler *compiler, + SpvStorageClass storage_class, uint32_t type_id, const struct vkd3d_shader_register *reg, + const struct vkd3d_shader_descriptor_binding *binding, bool unbounded) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + uint32_t ptr_type_id; + + if (binding->offset != VKD3D_SHADER_SINGLE_BINDING || unbounded) + type_id = vkd3d_spirv_get_op_type_array(builder, type_id, + vkd3d_dxbc_compiler_get_constant_uint(compiler, binding->count)); + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); + + return vkd3d_dxbc_compiler_get_resource_variable(compiler, storage_class, + ptr_type_id, reg, binding, unbounded); +} + static const struct vkd3d_shader_parameter *vkd3d_dxbc_compiler_get_shader_parameter( struct vkd3d_dxbc_compiler *compiler, enum vkd3d_shader_parameter_name name) { @@ -3028,6 +3170,7 @@ struct vkd3d_shader_register_info SpvStorageClass storage_class; enum vkd3d_shader_component_type component_type; unsigned int write_mask; + int binding_offset; uint32_t member_idx; unsigned int structure_stride; bool is_aggregate; @@ -3047,6 +3190,7 @@ static bool vkd3d_dxbc_compiler_get_register_info(const struct vkd3d_dxbc_compil assert(reg->idx[0].offset < compiler->temp_count); register_info->id = compiler->temp_id + reg->idx[0].offset; register_info->storage_class = SpvStorageClassFunction; + register_info->binding_offset = VKD3D_SHADER_SINGLE_BINDING; register_info->member_idx = 0; register_info->component_type = VKD3D_SHADER_COMPONENT_FLOAT; register_info->write_mask = VKD3DSP_WRITEMASK_ALL; @@ -3067,6 +3211,7 @@ static bool vkd3d_dxbc_compiler_get_register_info(const struct vkd3d_dxbc_compil symbol = RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); register_info->id = symbol->id; register_info->storage_class = symbol->info.reg.storage_class; + register_info->binding_offset = symbol->info.reg.binding_offset; register_info->member_idx = symbol->info.reg.member_idx; register_info->component_type = symbol->info.reg.component_type; register_info->write_mask = symbol->info.reg.write_mask; @@ -3092,17 +3237,38 @@ static bool register_is_descriptor(const struct vkd3d_shader_register *reg) } }
+static uint32_t vkd3d_dxbc_compiler_get_resource_index(struct vkd3d_dxbc_compiler *compiler, + const struct vkd3d_shader_register *reg, int binding_offset) +{ + uint32_t index_id; + + if (shader_is_sm_5_1(compiler)) + { + struct vkd3d_shader_register_index index = reg->idx[1]; + index.offset += binding_offset; + index_id = vkd3d_dxbc_compiler_emit_register_addressing(compiler, &index); + } + else + { + index_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, reg->idx[0].offset + binding_offset); + } + + return index_id; +} + static void vkd3d_dxbc_compiler_emit_dereference_register(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg, struct vkd3d_shader_register_info *register_info) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; unsigned int component_count, index_count = 0; uint32_t type_id, ptr_type_id; - uint32_t indexes[2]; + uint32_t indexes[3];
if (reg->type == VKD3DSPR_CONSTBUFFER) { assert(!reg->idx[0].rel_addr); + if (register_info->binding_offset != VKD3D_SHADER_SINGLE_BINDING) + indexes[index_count++] = vkd3d_dxbc_compiler_get_resource_index(compiler, reg, register_info->binding_offset); 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]); } @@ -5299,12 +5465,13 @@ static void vkd3d_dxbc_compiler_emit_push_constant_buffers(struct vkd3d_dxbc_com static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { - uint32_t vec4_id, array_type_id, length_id, struct_id, pointer_type_id, var_id; + uint32_t vec4_id, array_type_id, length_id, struct_id, var_id; const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const SpvStorageClass storage_class = SpvStorageClassUniform; const struct vkd3d_shader_register *reg = &cb->src.reg; struct vkd3d_push_constant_buffer_binding *push_cb; + struct vkd3d_shader_descriptor_binding binding; struct vkd3d_symbol reg_symbol;
assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC)); @@ -5335,18 +5502,16 @@ static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compi vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0, SpvDecorationOffset, 0); vkd3d_spirv_build_op_name(builder, struct_id, "cb%u_struct", cb->size);
- pointer_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id); - var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, - pointer_type_id, storage_class, 0); - - vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(compiler, - var_id, reg, cb->register_space, cb->register_index, VKD3D_SHADER_RESOURCE_BUFFER, false); + binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, cb->register_space, + cb->register_first, cb->register_last, VKD3D_SHADER_RESOURCE_BUFFER, false);
- vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + var_id = vkd3d_dxbc_compiler_build_resource_variable(compiler, storage_class, struct_id, + reg, &binding, cb->register_last == ~0u);
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.info.reg.binding_offset = binding.offset; vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol); }
@@ -5390,7 +5555,8 @@ 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; + struct vkd3d_shader_descriptor_binding binding; + uint32_t type_id, var_id; struct vkd3d_symbol reg_symbol;
vkd3d_symbol_make_sampler(®_symbol, reg); @@ -5401,19 +5567,17 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com if (vkd3d_dxbc_compiler_has_combined_sampler(compiler, NULL, sampler)) 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->register_space, sampler->register_index, VKD3D_SHADER_RESOURCE_NONE, false); + binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, sampler->register_space, + sampler->register_first, sampler->register_last, VKD3D_SHADER_RESOURCE_NONE, false);
- vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + type_id = vkd3d_spirv_get_op_type_sampler(builder); + var_id = vkd3d_dxbc_compiler_build_resource_variable(compiler, storage_class, + type_id, reg, &binding, sampler->register_last == ~0u);
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.info.reg.binding_offset = binding.offset; vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol); }
@@ -5567,8 +5731,11 @@ static void vkd3d_dxbc_compiler_emit_combined_sampler_declarations(struct vkd3d_ symbol.id = var_id; symbol.info.resource.register_space = resource_space; symbol.info.resource.register_index = resource_index; + symbol.info.resource.binding_offset = current->binding.offset; + symbol.info.resource.storage_class = storage_class; symbol.info.resource.sampled_type = sampled_type; symbol.info.resource.type_id = image_type_id; + symbol.info.resource.contained_type_id = 0; symbol.info.resource.resource_type_info = resource_type_info; symbol.info.resource.structure_stride = structure_stride; symbol.info.resource.raw = raw; @@ -5592,6 +5759,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp struct vkd3d_shader_descriptor_binding binding; enum vkd3d_shader_component_type sampled_type; struct vkd3d_symbol resource_symbol; + uint32_t contained_type_id = 0; bool is_uav;
is_uav = reg->type == VKD3DSPR_UAV; @@ -5611,6 +5779,9 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp return; }
+ binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg, register_space, + register_first, register_last, resource_type, false); + if (compiler->ssbo_uavs && is_uav && resource_type == VKD3D_SHADER_RESOURCE_BUFFER) { uint32_t array_type_id, struct_id; @@ -5631,16 +5802,19 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp { type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, reg, register_space, register_first, resource_type_info, sampled_type, structure_stride || raw, 0); + + if (binding.offset != VKD3D_SHADER_SINGLE_BINDING || register_last == ~0u) + { + contained_type_id = type_id; + type_id = vkd3d_spirv_get_op_type_array(builder, type_id, + vkd3d_dxbc_compiler_get_constant_uint(compiler, binding.count)); + } }
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, - register_space, register_index, resource_type, false);
- vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); + var_id = vkd3d_dxbc_compiler_get_resource_variable(compiler, storage_class, + ptr_type_id, reg, &binding, register_last == ~0u);
if (is_uav) { @@ -5678,6 +5852,11 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp storage_class = SpvStorageClassUniform; ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, struct_id); } + else if (contained_type_id) + { + /* TODO: UAV counter arrays. */ + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, contained_type_id); + }
counter_var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, ptr_type_id, storage_class, 0); @@ -5694,8 +5873,11 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp resource_symbol.id = var_id; resource_symbol.info.resource.register_space = register_space; resource_symbol.info.resource.register_index = register_first; + resource_symbol.info.resource.binding_offset = binding.offset; + resource_symbol.info.resource.storage_class = storage_class; resource_symbol.info.resource.sampled_type = sampled_type; resource_symbol.info.resource.type_id = type_id; + resource_symbol.info.resource.contained_type_id = contained_type_id; resource_symbol.info.resource.resource_type_info = resource_type_info; resource_symbol.info.resource.structure_stride = structure_stride; resource_symbol.info.resource.raw = raw; @@ -7687,9 +7869,27 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil if (!symbol) symbol = vkd3d_dxbc_compiler_find_resource(compiler, resource_reg);
- image->id = symbol->id; + if (symbol->info.resource.binding_offset != VKD3D_SHADER_SINGLE_BINDING) + { + uint32_t ptr_type_id, index_id; + + index_id = vkd3d_dxbc_compiler_get_resource_index(compiler, + resource_reg, symbol->info.resource.binding_offset); + + ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, + symbol->info.resource.storage_class, + symbol->info.resource.contained_type_id); + image->image_type_id = symbol->info.resource.contained_type_id; + + image->id = vkd3d_spirv_build_op_access_chain(builder, + ptr_type_id, symbol->id, &index_id, 1); + } + else + { + image->id = symbol->id; + image->image_type_id = symbol->info.resource.type_id; + } image->sampled_type = symbol->info.resource.sampled_type; - image->image_type_id = symbol->info.resource.type_id; image->resource_type_info = symbol->info.resource.resource_type_info; image->structure_stride = symbol->info.resource.structure_stride; image->raw = symbol->info.resource.raw; @@ -7704,8 +7904,15 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil return; }
- image->image_id = load ? vkd3d_spirv_build_op_load(builder, - image->image_type_id, image->id, SpvMemoryAccessMaskNone) : 0; + if (load) + { + image->image_id = vkd3d_spirv_build_op_load(builder, + image->image_type_id, image->id, SpvMemoryAccessMaskNone); + } + else + { + image->image_id = 0; + }
image->image_type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, resource_reg, symbol->info.resource.register_space, symbol->info.resource.register_index, image->resource_type_info, @@ -7713,10 +7920,22 @@ 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.binding_offset != VKD3D_SHADER_SINGLE_BINDING) + { + uint32_t ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, + register_info.storage_class, vkd3d_spirv_get_op_type_sampler(builder)); + uint32_t array_idx = vkd3d_dxbc_compiler_get_resource_index(compiler, + sampler_reg, register_info.binding_offset); + 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); @@ -9504,6 +9723,7 @@ void vkd3d_dxbc_compiler_destroy(struct vkd3d_dxbc_compiler *compiler) vkd3d_spirv_builder_free(&compiler->spirv_builder);
rb_destroy(&compiler->symbol_table, vkd3d_symbol_free, NULL); + rb_destroy(&compiler->array_var_table, vkd3d_array_variable_free, NULL);
vkd3d_free(compiler->shader_phases); vkd3d_free(compiler->spec_constants);
From: Philip Rebohle philip.rebohle@tu-dortmund.de
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/dxbc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index ad1db82a..60610f44 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -362,10 +362,10 @@ enum vkd3d_sm4_register_type
enum vkd3d_sm4_register_modifier { - VKD3D_SM4_REGISTER_MODIFIER_NONE = 0x01, - VKD3D_SM4_REGISTER_MODIFIER_NEGATE = 0x41, - VKD3D_SM4_REGISTER_MODIFIER_ABS = 0x81, - VKD3D_SM4_REGISTER_MODIFIER_ABS_NEGATE = 0xc1, + VKD3D_SM4_REGISTER_MODIFIER_NONE = 0x00, + VKD3D_SM4_REGISTER_MODIFIER_NEGATE = 0x40, + VKD3D_SM4_REGISTER_MODIFIER_ABS = 0x80, + VKD3D_SM4_REGISTER_MODIFIER_ABS_NEGATE = 0xc0, };
enum vkd3d_sm4_output_primitive_type @@ -1580,7 +1580,7 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr } m = *(*ptr)++;
- switch (m) + switch (m & 0xc0) { case VKD3D_SM4_REGISTER_MODIFIER_NEGATE: *modifier = VKD3DSPSM_NEG;
From: Philip Rebohle philip.rebohle@tu-dortmund.de From: Hans-Kristian Arntzen post@arntzen-software.no
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d-shader/dxbc.c | 6 ++++ libs/vkd3d-shader/spirv.c | 39 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 7 +++++ 3 files changed, 52 insertions(+)
diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c index 60610f44..644ee0d6 100644 --- a/libs/vkd3d-shader/dxbc.c +++ b/libs/vkd3d-shader/dxbc.c @@ -366,6 +366,7 @@ enum vkd3d_sm4_register_modifier VKD3D_SM4_REGISTER_MODIFIER_NEGATE = 0x40, VKD3D_SM4_REGISTER_MODIFIER_ABS = 0x80, VKD3D_SM4_REGISTER_MODIFIER_ABS_NEGATE = 0xc0, + VKD3D_SM4_REGISTER_MODIFIER_NONUNIFORM = 0x20000, };
enum vkd3d_sm4_output_primitive_type @@ -1567,6 +1568,7 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr { param->type = register_type_table[register_type]; } + param->modifier = VKD3DSPRM_NONE; param->data_type = data_type;
if (token & VKD3D_SM4_REGISTER_MODIFIER) @@ -1601,6 +1603,10 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr *modifier = VKD3DSPSM_NONE; break; } + + if (m & VKD3D_SM4_REGISTER_MODIFIER_NONUNIFORM) + param->modifier = VKD3DSPRM_NONUNIFORM; + } else { diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index b99615f4..f8c93a34 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -337,6 +337,7 @@ struct vkd3d_spirv_builder uint64_t capability_draw_parameters : 1; uint64_t capability_demote_to_helper_invocation : 1; uint64_t capability_descriptor_indexing : 1; + uint64_t capability_non_uniform : 1; uint32_t ext_instr_set_glsl_450; uint32_t invocation_count; SpvExecutionModel execution_model; @@ -387,6 +388,10 @@ static void vkd3d_spirv_enable_capability(struct vkd3d_spirv_builder *builder, { builder->capability_demote_to_helper_invocation = 1; } + else if (cap == SpvCapabilityShaderNonUniformEXT) + { + builder->capability_non_uniform = 1; + } else { FIXME("Unhandled capability %#x.\n", cap); @@ -1809,6 +1814,8 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder, vkd3d_spirv_build_op_capability(&stream, SpvCapabilityDrawParameters); if (builder->capability_demote_to_helper_invocation) vkd3d_spirv_build_op_capability(&stream, SpvCapabilityDemoteToHelperInvocationEXT); + if (builder->capability_non_uniform) + vkd3d_spirv_build_op_capability(&stream, SpvCapabilityShaderNonUniformEXT);
/* extensions */ if (builder->capability_draw_parameters) @@ -2670,6 +2677,15 @@ static void vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(struct vkd3d_dxb vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, variable_id, &binding); }
+static void vkd3d_dxbc_compiler_decorate_nonuniform(struct vkd3d_dxbc_compiler *compiler, + uint32_t expression_id) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + + vkd3d_spirv_enable_capability(builder, SpvCapabilityShaderNonUniformEXT); + vkd3d_spirv_build_op_decorate(builder, expression_id, SpvDecorationNonUniformEXT, NULL, 0); +} + static void vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_symbol *symbol) { @@ -3253,6 +3269,10 @@ static uint32_t vkd3d_dxbc_compiler_get_resource_index(struct vkd3d_dxbc_compile index_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, reg->idx[0].offset + binding_offset); }
+ /* AMD drivers rely on the index being marked as nonuniform */ + if (reg->modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, index_id); + return index_id; }
@@ -3327,6 +3347,8 @@ static void vkd3d_dxbc_compiler_emit_dereference_register(struct vkd3d_dxbc_comp ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id); register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, register_info->id, indexes, index_count); + if (reg->modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, register_info->id); } }
@@ -7908,6 +7930,8 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil { image->image_id = vkd3d_spirv_build_op_load(builder, image->image_type_id, image->id, SpvMemoryAccessMaskNone); + if (resource_reg->modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image->image_id); } else { @@ -7939,9 +7963,14 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
sampler_id = vkd3d_spirv_build_op_load(builder, vkd3d_spirv_get_op_type_sampler(builder), sampler_var_id, SpvMemoryAccessMaskNone); + if (sampler_reg->modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, sampler_id); + sampled_image_type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image->image_type_id); image->sampled_image_id = vkd3d_spirv_build_op_sampled_image(builder, sampled_image_type_id, image->image_id, sampler_id); + if (resource_reg->modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image->sampled_image_id); } else { @@ -8293,6 +8322,9 @@ static void vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(struct vkd3d_dxbc
ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2); constituents[j++] = vkd3d_spirv_build_op_load(builder, texel_type_id, ptr_id, SpvMemoryAccessMaskNone); + + if (resource->reg.modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id); } } else @@ -8435,6 +8467,9 @@ static void vkd3d_dxbc_compiler_emit_store_uav_raw_structured(struct vkd3d_dxbc_
ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2); vkd3d_spirv_build_op_store(builder, ptr_id, data_id, SpvMemoryAccessMaskNone); + + if (dst->reg.modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id); } } else @@ -8811,6 +8846,8 @@ static void vkd3d_dxbc_compiler_emit_atomic_instruction(struct vkd3d_dxbc_compil pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder, ptr_type_id, image.id, coordinate_id, sample_id); } + if (resource->reg.modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, pointer_id); }
val_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, component_type); @@ -8859,6 +8896,8 @@ static void vkd3d_dxbc_compiler_emit_bufinfo(struct vkd3d_dxbc_compiler *compile
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1); val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id); + if (src->reg.modifier == VKD3DSPRM_NONUNIFORM) + vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image.id); write_mask = VKD3DSP_WRITEMASK_0; }
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 54930fa2..453d3fb7 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -436,6 +436,12 @@ enum vkd3d_immconst_type VKD3D_IMMCONST_VEC4, };
+enum vkd3d_shader_register_modifier +{ + VKD3DSPRM_NONE = 0, + VKD3DSPRM_NONUNIFORM = 1, +}; + enum vkd3d_shader_src_modifier { VKD3DSPSM_NONE = 0, @@ -604,6 +610,7 @@ struct vkd3d_shader_register_index struct vkd3d_shader_register { enum vkd3d_shader_register_type type; + enum vkd3d_shader_register_modifier modifier; enum vkd3d_data_type data_type; struct vkd3d_shader_register_index idx[3]; enum vkd3d_immconst_type immconst_type;
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/device.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index a4c8bca8..88221406 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1423,7 +1423,17 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vulkan_info->EXT_shader_demote_to_helper_invocation = false; if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment) vulkan_info->EXT_texel_buffer_alignment = false; - vulkan_info->EXT_descriptor_indexing = false; + descriptor_indexing = &physical_device_info->descriptor_indexing_features; + if (!descriptor_indexing->descriptorBindingPartiallyBound + || !descriptor_indexing->descriptorBindingVariableDescriptorCount + || !physical_device_info->descriptor_indexing_features.shaderSampledImageArrayNonUniformIndexing + || !physical_device_info->descriptor_indexing_features.shaderUniformTexelBufferArrayDynamicIndexing + || !physical_device_info->descriptor_indexing_features.shaderUniformTexelBufferArrayNonUniformIndexing + || !physical_device_info->descriptor_indexing_features.shaderStorageImageArrayNonUniformIndexing + || !physical_device_info->descriptor_indexing_features.shaderStorageTexelBufferArrayDynamicIndexing + || !physical_device_info->descriptor_indexing_features.shaderStorageTexelBufferArrayNonUniformIndexing + || !physical_device_info->descriptor_indexing_features.shaderUniformBufferArrayNonUniformIndexing) + vulkan_info->EXT_descriptor_indexing = false;
vulkan_info->texel_buffer_alignment_properties = physical_device_info->texel_buffer_alignment_properties;
@@ -1461,7 +1471,6 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, /* Disable unused Vulkan features. */ features->shaderTessellationAndGeometryPointSize = VK_FALSE;
- descriptor_indexing = &physical_device_info->descriptor_indexing_features; if (descriptor_indexing) { descriptor_indexing->shaderInputAttachmentArrayDynamicIndexing = VK_FALSE;
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- libs/vkd3d/device.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 88221406..be6da6c0 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1471,18 +1471,15 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, /* Disable unused Vulkan features. */ features->shaderTessellationAndGeometryPointSize = VK_FALSE;
- if (descriptor_indexing) - { - descriptor_indexing->shaderInputAttachmentArrayDynamicIndexing = VK_FALSE; - descriptor_indexing->shaderInputAttachmentArrayNonUniformIndexing = VK_FALSE; + descriptor_indexing->shaderInputAttachmentArrayDynamicIndexing = VK_FALSE; + descriptor_indexing->shaderInputAttachmentArrayNonUniformIndexing = VK_FALSE;
- /* We do not use storage buffers currently. */ - features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE; - descriptor_indexing->shaderStorageBufferArrayNonUniformIndexing = VK_FALSE; - descriptor_indexing->descriptorBindingStorageBufferUpdateAfterBind = VK_FALSE; - } + /* We do not use storage buffers currently. */ + features->shaderStorageBufferArrayDynamicIndexing = VK_FALSE; + descriptor_indexing->shaderStorageBufferArrayNonUniformIndexing = VK_FALSE; + descriptor_indexing->descriptorBindingStorageBufferUpdateAfterBind = VK_FALSE;
- if (vulkan_info->EXT_descriptor_indexing && descriptor_indexing + if (vulkan_info->EXT_descriptor_indexing && (descriptor_indexing->descriptorBindingUniformBufferUpdateAfterBind || descriptor_indexing->descriptorBindingStorageBufferUpdateAfterBind || descriptor_indexing->descriptorBindingUniformTexelBufferUpdateAfterBind