Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- include/vkd3d_shader.h | 13 ++++ libs/vkd3d-shader/vkd3d_shader.map | 1 + libs/vkd3d-shader/vkd3d_shader_main.c | 130 +++++++++++++++++++++++++++++++--- libs/vkd3d/state.c | 2 + 4 files changed, 137 insertions(+), 9 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 358e90d..b2fa499 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -585,11 +585,22 @@ struct vkd3d_versioned_root_signature_desc /* FIXME: Add support for 64 UAV bind slots. */ #define VKD3D_SHADER_MAX_UNORDERED_ACCESS_VIEWS 8
+struct vkd3d_shader_descriptor_info +{ + enum vkd3d_shader_descriptor_type type; + unsigned int register_space; + unsigned int register_index; + unsigned int count; +}; + struct vkd3d_shader_scan_info { enum vkd3d_shader_structure_type type; void *next;
+ struct vkd3d_shader_descriptor_info *descriptors; + unsigned int descriptor_count; + unsigned int uav_read_mask; /* VKD3D_SHADER_MAX_UNORDERED_ACCESS_VIEWS */ unsigned int uav_counter_mask; /* VKD3D_SHADER_MAX_UNORDERED_ACCESS_VIEWS */ unsigned int sampler_comparison_mode_mask; /* 16 */ @@ -694,6 +705,7 @@ int vkd3d_shader_convert_root_signature(struct vkd3d_versioned_root_signature_de
int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_scan_info *scan_info); +void vkd3d_shader_free_scan_info(struct vkd3d_shader_scan_info *scan_info);
int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_signature *signature); @@ -723,6 +735,7 @@ typedef int (*PFN_vkd3d_shader_convert_root_signature)(struct vkd3d_versioned_ro
typedef int (*PFN_vkd3d_shader_scan_dxbc)(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_scan_info *scan_info); +typedef void (*PFN_vkd3d_shader_free_scan_info)(struct vkd3d_shader_scan_info *scan_info);
typedef int (*PFN_vkd3d_shader_parse_input_signature)(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_signature *signature); diff --git a/libs/vkd3d-shader/vkd3d_shader.map b/libs/vkd3d-shader/vkd3d_shader.map index a8c73b6..13bebde 100644 --- a/libs/vkd3d-shader/vkd3d_shader.map +++ b/libs/vkd3d-shader/vkd3d_shader.map @@ -5,6 +5,7 @@ global: vkd3d_shader_convert_root_signature; vkd3d_shader_find_signature_element; vkd3d_shader_free_root_signature; + vkd3d_shader_free_scan_info; vkd3d_shader_free_shader_code; vkd3d_shader_free_shader_signature; vkd3d_shader_parse_input_signature; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 3255094..45a7a80 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -187,9 +187,16 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, s
vkd3d_dxbc_compiler_destroy(spirv_compiler); vkd3d_shader_parser_destroy(&parser); + vkd3d_shader_free_scan_info(&scan_info); return ret; }
+struct vkd3d_shader_scan_context +{ + struct vkd3d_shader_scan_info *scan_info; + size_t descriptors_size; +}; + static bool vkd3d_shader_instruction_is_uav_read(const struct vkd3d_shader_instruction *instruction) { enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx; @@ -221,6 +228,38 @@ static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_info * scan_info->uav_counter_mask |= 1u << reg->idx[0].offset; }
+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) +{ + struct vkd3d_shader_scan_info *scan_info = context->scan_info; + struct vkd3d_shader_descriptor_info *d; + + if (!vkd3d_array_reserve((void **)&scan_info->descriptors, &context->descriptors_size, + scan_info->descriptor_count + 1, sizeof(*scan_info->descriptors))) + { + ERR("Failed to allocate descriptor info.\n"); + return false; + } + + d = &scan_info->descriptors[scan_info->descriptor_count]; + d->type = type; + d->register_space = register_space; + d->register_index = register_index; + d->count = 1; + ++scan_info->descriptor_count; + + return true; +} + +static void vkd3d_shader_scan_constant_buffer_declaration(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_instruction *instruction) +{ + const struct vkd3d_shader_constant_buffer *cb = &instruction->declaration.cb; + + vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, + cb->register_space, cb->register_index); +} + static void vkd3d_shader_scan_input_declaration(struct vkd3d_shader_scan_info *scan_info, const struct vkd3d_shader_instruction *instruction) { @@ -230,29 +269,89 @@ static void vkd3d_shader_scan_input_declaration(struct vkd3d_shader_scan_info *s scan_info->use_vocp = true; }
-static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_info *scan_info, +static void vkd3d_shader_scan_sampler_declaration(struct vkd3d_shader_scan_context *context, const struct vkd3d_shader_instruction *instruction) { - unsigned int sampler_index = instruction->declaration.dst.reg.idx[0].offset; + const struct vkd3d_shader_sampler *sampler = &instruction->declaration.sampler; + struct vkd3d_shader_scan_info *scan_info = context->scan_info; + unsigned int sampler_index = sampler->register_index; + if (instruction->flags & VKD3DSI_SAMPLER_COMPARISON_MODE) { assert(sampler_index < CHAR_BIT * sizeof(scan_info->sampler_comparison_mode_mask)); scan_info->sampler_comparison_mode_mask |= 1u << sampler_index; } + + vkd3d_shader_scan_add_descriptor(context, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, + sampler->register_space, sampler->register_index); +} + +static void vkd3d_shader_scan_resource_declaration(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_instruction *instruction) +{ + const struct vkd3d_shader_semantic *semantic = &instruction->declaration.semantic; + enum vkd3d_shader_descriptor_type type; + + if (semantic->reg.reg.type == VKD3DSPR_UAV) + type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; + else + type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV; + vkd3d_shader_scan_add_descriptor(context, type, semantic->register_space, semantic->register_index); +} + +static void vkd3d_shader_scan_resource_declaration_raw(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_instruction *instruction) +{ + const struct vkd3d_shader_raw_resource *resource = &instruction->declaration.raw_resource; + enum vkd3d_shader_descriptor_type type; + + if (resource->dst.reg.type == VKD3DSPR_UAV) + type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; + else + type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV; + vkd3d_shader_scan_add_descriptor(context, type, resource->register_space, resource->register_index); }
-static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_info, +static void vkd3d_shader_scan_resource_declaration_structured(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_instruction *instruction) +{ + const struct vkd3d_shader_structured_resource *resource = &instruction->declaration.structured_resource; + enum vkd3d_shader_descriptor_type type; + + if (resource->reg.reg.type == VKD3DSPR_UAV) + type = VKD3D_SHADER_DESCRIPTOR_TYPE_UAV; + else + type = VKD3D_SHADER_DESCRIPTOR_TYPE_SRV; + vkd3d_shader_scan_add_descriptor(context, type, resource->register_space, resource->register_index); +} + +static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *context, const struct vkd3d_shader_instruction *instruction) { unsigned int i;
switch (instruction->handler_idx) { + case VKD3DSIH_DCL_CONSTANT_BUFFER: + vkd3d_shader_scan_constant_buffer_declaration(context, instruction); + break; case VKD3DSIH_DCL_INPUT: - vkd3d_shader_scan_input_declaration(scan_info, instruction); + vkd3d_shader_scan_input_declaration(context->scan_info, instruction); break; case VKD3DSIH_DCL_SAMPLER: - vkd3d_shader_scan_sampler_declaration(scan_info, instruction); + vkd3d_shader_scan_sampler_declaration(context, instruction); + break; + case VKD3DSIH_DCL: + case VKD3DSIH_DCL_UAV_TYPED: + vkd3d_shader_scan_resource_declaration(context, instruction); + break; + case VKD3DSIH_DCL_RESOURCE_RAW: + case VKD3DSIH_DCL_UAV_RAW: + vkd3d_shader_scan_resource_declaration_raw(context, instruction); + break; + case VKD3DSIH_DCL_RESOURCE_STRUCTURED: + case VKD3DSIH_DCL_UAV_STRUCTURED: + vkd3d_shader_scan_resource_declaration_structured(context, instruction); break; default: break; @@ -263,23 +362,24 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_in for (i = 0; i < instruction->dst_count; ++i) { if (instruction->dst[i].reg.type == VKD3DSPR_UAV) - vkd3d_shader_scan_record_uav_read(scan_info, &instruction->dst[i].reg); + vkd3d_shader_scan_record_uav_read(context->scan_info, &instruction->dst[i].reg); } for (i = 0; i < instruction->src_count; ++i) { if (instruction->src[i].reg.type == VKD3DSPR_UAV) - vkd3d_shader_scan_record_uav_read(scan_info, &instruction->src[i].reg); + vkd3d_shader_scan_record_uav_read(context->scan_info, &instruction->src[i].reg); } }
if (vkd3d_shader_instruction_is_uav_counter(instruction)) - vkd3d_shader_scan_record_uav_counter(scan_info, &instruction->src[0].reg); + vkd3d_shader_scan_record_uav_counter(context->scan_info, &instruction->src[0].reg); }
int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_scan_info *scan_info) { struct vkd3d_shader_instruction instruction; + struct vkd3d_shader_scan_context context; struct vkd3d_shader_parser parser; int ret;
@@ -296,6 +396,9 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc,
memset(scan_info, 0, sizeof(*scan_info));
+ memset(&context, 0, sizeof(context)); + context.scan_info = scan_info; + while (!shader_sm4_is_end(parser.data, &parser.ptr)) { shader_sm4_read_instruction(parser.data, &parser.ptr, &instruction); @@ -303,17 +406,26 @@ int vkd3d_shader_scan_dxbc(const struct vkd3d_shader_code *dxbc, if (instruction.handler_idx == VKD3DSIH_INVALID) { WARN("Encountered unrecognized or invalid instruction.\n"); + vkd3d_shader_free_scan_info(scan_info); vkd3d_shader_parser_destroy(&parser); return VKD3D_ERROR_INVALID_ARGUMENT; }
- vkd3d_shader_scan_instruction(scan_info, &instruction); + vkd3d_shader_scan_instruction(&context, &instruction); }
vkd3d_shader_parser_destroy(&parser); return VKD3D_OK; }
+void vkd3d_shader_free_scan_info(struct vkd3d_shader_scan_info *scan_info) +{ + if (!scan_info) + return; + + vkd3d_free(scan_info->descriptors); +} + void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *shader_code) { if (!shader_code) diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index db342df..501afc6 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1528,6 +1528,7 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st WARN("Failed to create descriptor set layout for UAV counters, hr %#x.\n", hr); return hr; } + vkd3d_shader_free_scan_info(&shader_info);
shader_interface.type = VKD3D_SHADER_STRUCTURE_TYPE_INTERFACE_INFO; shader_interface.next = NULL; @@ -2267,6 +2268,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s } if (shader_info.uav_counter_mask) FIXME("UAV counters not implemented for graphics pipelines.\n"); + vkd3d_shader_free_scan_info(&shader_info);
target_info = NULL; switch (shader_stages[i].stage)