libs/vkd3d-shader: Implement arbitrary mappings from D3D shader register to Vulkan descriptors.

An arbitrary mapping can be passed to vkd3d_shader_compile_dxbc().
This commit is contained in:
Józef Kucia 2017-07-26 13:45:25 +02:00
parent d39d0e4c9f
commit edd1e9602d
6 changed files with 118 additions and 35 deletions

View File

@ -38,8 +38,27 @@ struct vkd3d_shader_code
size_t size; size_t size;
}; };
enum vkd3d_descriptor_type
{
VKD3D_DESCRIPTOR_TYPE_UNKNOWN,
VKD3D_DESCRIPTOR_TYPE_CBV, /* cb# */
VKD3D_DESCRIPTOR_TYPE_SRV, /* t# */
VKD3D_DESCRIPTOR_TYPE_UAV, /* u# */
VKD3D_DESCRIPTOR_TYPE_SAMPLER, /* s# */
};
struct vkd3d_shader_resource_binding
{
enum vkd3d_descriptor_type type;
unsigned int index;
uint32_t descriptor_set;
uint32_t binding;
};
HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_code *spirv, uint32_t compiler_options); struct vkd3d_shader_code *spirv, uint32_t compiler_options,
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count);
void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code); void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code);
HRESULT vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc, HRESULT vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,

View File

@ -1365,6 +1365,9 @@ struct vkd3d_dxbc_compiler
struct vkd3d_control_flow_info *control_flow_info; struct vkd3d_control_flow_info *control_flow_info;
size_t control_flow_info_size; size_t control_flow_info_size;
unsigned int binding_count;
const struct vkd3d_shader_resource_binding *bindings;
const struct vkd3d_shader_signature *input_signature; const struct vkd3d_shader_signature *input_signature;
const struct vkd3d_shader_signature *output_signature; const struct vkd3d_shader_signature *output_signature;
struct struct
@ -1377,7 +1380,8 @@ struct vkd3d_dxbc_compiler
}; };
struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version, struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
const struct vkd3d_shader_desc *shader_desc, uint32_t compiler_options) const struct vkd3d_shader_desc *shader_desc, uint32_t compiler_options,
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count)
{ {
const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature; const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature;
struct vkd3d_dxbc_compiler *compiler; struct vkd3d_dxbc_compiler *compiler;
@ -1427,9 +1431,74 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
compiler->input_signature = &shader_desc->input_signature; compiler->input_signature = &shader_desc->input_signature;
compiler->output_signature = &shader_desc->output_signature; compiler->output_signature = &shader_desc->output_signature;
if (binding_count)
{
compiler->binding_count = binding_count;
compiler->bindings = bindings;
}
return compiler; return compiler;
} }
struct vkd3d_descriptor_binding
{
uint32_t set;
uint32_t binding;
};
static struct vkd3d_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_binding(
struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg)
{
enum vkd3d_descriptor_type descriptor_type;
struct vkd3d_descriptor_binding vk_binding;
unsigned int reg_idx = reg->idx[0].offset;
unsigned int i;
descriptor_type = VKD3D_DESCRIPTOR_TYPE_UNKNOWN;
if (reg->type == VKD3DSPR_CONSTBUFFER)
descriptor_type = VKD3D_DESCRIPTOR_TYPE_CBV;
else if (reg->type == VKD3DSPR_RESOURCE)
descriptor_type = VKD3D_DESCRIPTOR_TYPE_SRV;
else if (reg->type == VKD3DSPR_UAV)
descriptor_type = VKD3D_DESCRIPTOR_TYPE_UAV;
else if (reg->type == VKD3DSPR_SAMPLER)
descriptor_type = VKD3D_DESCRIPTOR_TYPE_SAMPLER;
else
FIXME("Unhandled register type %#x.\n", reg->type);
if (descriptor_type != VKD3D_DESCRIPTOR_TYPE_UNKNOWN)
{
for (i = 0; i < compiler->binding_count; ++i)
{
const struct vkd3d_shader_resource_binding *current = &compiler->bindings[i];
if (current->type == descriptor_type && current->index == reg_idx)
{
vk_binding.set = current->descriptor_set;
vk_binding.binding = current->binding;
return vk_binding;
}
}
if (compiler->binding_count)
FIXME("Could not find descriptor binding for %#x, %u.\n", descriptor_type, reg_idx);
}
vk_binding.set = 0;
vk_binding.binding = reg_idx;
return vk_binding;
}
static void vkd3d_dxbc_compiler_emit_descriptor_binding(struct vkd3d_dxbc_compiler *compiler,
uint32_t variable_id, const struct vkd3d_shader_register *reg)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
struct vkd3d_descriptor_binding vk_binding;
vk_binding = vkd3d_dxbc_compiler_get_descriptor_binding(compiler, reg);
vkd3d_spirv_build_op_decorate1(builder, variable_id, SpvDecorationDescriptorSet, vk_binding.set);
vkd3d_spirv_build_op_decorate1(builder, variable_id, SpvDecorationBinding, vk_binding.binding);
}
static void vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler, static void vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_symbol *symbol) const struct vkd3d_symbol *symbol)
{ {
@ -2291,18 +2360,17 @@ static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compi
const struct vkd3d_shader_instruction *instruction) 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, pointer_type_id, var_id;
const struct vkd3d_shader_src_param *src = &instruction->declaration.src; const struct vkd3d_shader_register *reg = &instruction->declaration.src.reg;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
struct vkd3d_symbol reg_symbol; struct vkd3d_symbol reg_symbol;
unsigned int cb_idx, cb_size; unsigned int cb_size;
assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC)); assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC));
if (instruction->flags & VKD3DSI_INDEXED_DYNAMIC) if (instruction->flags & VKD3DSI_INDEXED_DYNAMIC)
vkd3d_spirv_enable_capability(builder, SpvCapabilityUniformBufferArrayDynamicIndexing); vkd3d_spirv_enable_capability(builder, SpvCapabilityUniformBufferArrayDynamicIndexing);
cb_idx = src->reg.idx[0].offset; cb_size = reg->idx[1].offset;
cb_size = src->reg.idx[1].offset;
vec4_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE); vec4_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, cb_size); length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, cb_size);
@ -2318,12 +2386,11 @@ static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compi
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
pointer_type_id, SpvStorageClassUniform, 0); pointer_type_id, SpvStorageClassUniform, 0);
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, 0); vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, cb_idx);
vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, &src->reg); vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
vkd3d_symbol_make_register(&reg_symbol, &src->reg); vkd3d_symbol_make_register(&reg_symbol, reg);
reg_symbol.id = var_id; reg_symbol.id = var_id;
reg_symbol.info.storage_class = SpvStorageClassUniform; reg_symbol.info.storage_class = SpvStorageClassUniform;
vkd3d_dxbc_compiler_put_symbol(compiler, &reg_symbol); vkd3d_dxbc_compiler_put_symbol(compiler, &reg_symbol);
@ -2370,17 +2437,13 @@ static void vkd3d_dxbc_compiler_emit_dcl_sampler(struct vkd3d_dxbc_compiler *com
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
uint32_t type_id, ptr_type_id, var_id; uint32_t type_id, ptr_type_id, var_id;
struct vkd3d_symbol reg_symbol; struct vkd3d_symbol reg_symbol;
unsigned int sampler_idx;
sampler_idx = reg->idx[0].offset;
type_id = vkd3d_spirv_get_op_type_sampler(builder); type_id = vkd3d_spirv_get_op_type_sampler(builder);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, storage_class, type_id); 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, var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, storage_class, 0); ptr_type_id, storage_class, 0);
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, 0); vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, sampler_idx);
vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg); vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
@ -2455,16 +2518,18 @@ static const struct vkd3d_spirv_resource_type *vkd3d_dxbc_compiler_enable_resour
} }
static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_compiler *compiler, static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_semantic *semantic, bool is_uav) const struct vkd3d_shader_semantic *semantic)
{ {
const SpvStorageClass storage_class = SpvStorageClassUniformConstant; const SpvStorageClass storage_class = SpvStorageClassUniformConstant;
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
const struct vkd3d_shader_register *reg = &semantic->reg.reg;
const struct vkd3d_spirv_resource_type *resource_type_info; const struct vkd3d_spirv_resource_type *resource_type_info;
uint32_t sampled_type_id, type_id, ptr_type_id, var_id; uint32_t sampled_type_id, type_id, ptr_type_id, var_id;
enum vkd3d_component_type sampled_type; enum vkd3d_component_type sampled_type;
struct vkd3d_symbol resource_symbol; struct vkd3d_symbol resource_symbol;
unsigned int reg_idx; bool is_uav;
is_uav = reg->type == VKD3DSPR_UAV;
if (!(resource_type_info = vkd3d_dxbc_compiler_enable_resource_type(compiler, if (!(resource_type_info = vkd3d_dxbc_compiler_enable_resource_type(compiler,
semantic->resource_type, is_uav))) semantic->resource_type, is_uav)))
{ {
@ -2472,8 +2537,6 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
return; return;
} }
reg_idx = semantic->reg.reg.idx[0].offset;
sampled_type = vkd3d_component_type_from_data_type(semantic->resource_data_type); sampled_type = vkd3d_component_type_from_data_type(semantic->resource_data_type);
sampled_type_id = vkd3d_spirv_get_type_id(builder, sampled_type, 1); sampled_type_id = vkd3d_spirv_get_type_id(builder, sampled_type, 1);
@ -2484,12 +2547,11 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream, var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, storage_class, 0); ptr_type_id, storage_class, 0);
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, 0); vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, reg_idx);
vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, &semantic->reg.reg); vkd3d_dxbc_compiler_emit_register_debug_name(builder, var_id, reg);
vkd3d_symbol_make_resource(&resource_symbol, &semantic->reg.reg); vkd3d_symbol_make_resource(&resource_symbol, reg);
resource_symbol.id = var_id; resource_symbol.id = var_id;
resource_symbol.info.resource.sampled_type = sampled_type; resource_symbol.info.resource.sampled_type = sampled_type;
resource_symbol.info.resource.type_id = type_id; resource_symbol.info.resource.type_id = type_id;
@ -2500,7 +2562,7 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
static void vkd3d_dxbc_compiler_emit_dcl_resource(struct vkd3d_dxbc_compiler *compiler, static void vkd3d_dxbc_compiler_emit_dcl_resource(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction) const struct vkd3d_shader_instruction *instruction)
{ {
vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &instruction->declaration.semantic, false); vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &instruction->declaration.semantic);
} }
static void vkd3d_dxbc_compiler_emit_dcl_uav_typed(struct vkd3d_dxbc_compiler *compiler, static void vkd3d_dxbc_compiler_emit_dcl_uav_typed(struct vkd3d_dxbc_compiler *compiler,
@ -2509,7 +2571,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_uav_typed(struct vkd3d_dxbc_compiler *c
if (instruction->flags) if (instruction->flags)
FIXME("Unhandled flags %#x.\n", instruction->flags); FIXME("Unhandled flags %#x.\n", instruction->flags);
vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &instruction->declaration.semantic, true); vkd3d_dxbc_compiler_emit_resource_declaration(compiler, &instruction->declaration.semantic);
} }
static void vkd3d_dxbc_compiler_emit_dcl_input(struct vkd3d_dxbc_compiler *compiler, static void vkd3d_dxbc_compiler_emit_dcl_input(struct vkd3d_dxbc_compiler *compiler,

View File

@ -19,7 +19,8 @@
#include "vkd3d_shader_private.h" #include "vkd3d_shader_private.h"
HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
struct vkd3d_shader_code *spirv, uint32_t compiler_options) struct vkd3d_shader_code *spirv, uint32_t compiler_options,
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count)
{ {
struct vkd3d_dxbc_compiler *spirv_compiler; struct vkd3d_dxbc_compiler *spirv_compiler;
struct vkd3d_shader_version shader_version; struct vkd3d_shader_version shader_version;
@ -30,8 +31,8 @@ HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
HRESULT hr; HRESULT hr;
bool ret; bool ret;
TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x.\n", TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x, bindings %p, binding_count %u.\n",
dxbc->code, dxbc->size, spirv, compiler_options); dxbc->code, dxbc->size, spirv, compiler_options, bindings, binding_count);
if (FAILED(hr = shader_extract_from_dxbc(dxbc->code, dxbc->size, &shader_desc))) if (FAILED(hr = shader_extract_from_dxbc(dxbc->code, dxbc->size, &shader_desc)))
{ {
@ -50,7 +51,7 @@ HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
shader_sm4_read_header(parser_data, &ptr, &shader_version); shader_sm4_read_header(parser_data, &ptr, &shader_version);
if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&shader_version, if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&shader_version,
&shader_desc, compiler_options))) &shader_desc, compiler_options, bindings, binding_count)))
{ {
ERR("Failed to create DXBC compiler.\n"); ERR("Failed to create DXBC compiler.\n");
shader_sm4_free(parser_data); shader_sm4_free(parser_data);

View File

@ -822,7 +822,8 @@ void free_shader_desc(struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN;
struct vkd3d_dxbc_compiler; struct vkd3d_dxbc_compiler;
struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version, struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version,
const struct vkd3d_shader_desc *shader_desc, uint32_t compiler_options) DECLSPEC_HIDDEN; const struct vkd3d_shader_desc *shader_desc, uint32_t compiler_options,
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count) DECLSPEC_HIDDEN;
void vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, void vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN; const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN;
bool vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler, bool vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,

View File

@ -701,7 +701,7 @@ static bool d3d12_shader_bytecode_is_spirv(const D3D12_SHADER_BYTECODE *code)
} }
static HRESULT create_shader_stage(struct d3d12_device *device, struct VkPipelineShaderStageCreateInfo *stage_desc, static HRESULT create_shader_stage(struct d3d12_device *device, struct VkPipelineShaderStageCreateInfo *stage_desc,
enum VkShaderStageFlagBits stage, const D3D12_SHADER_BYTECODE *code, uint32_t compiler_options) enum VkShaderStageFlagBits stage, const D3D12_SHADER_BYTECODE *code)
{ {
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct VkShaderModuleCreateInfo shader_desc; struct VkShaderModuleCreateInfo shader_desc;
@ -728,7 +728,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, struct VkPipelin
else else
{ {
struct vkd3d_shader_code dxbc = {code->pShaderBytecode, code->BytecodeLength}; struct vkd3d_shader_code dxbc = {code->pShaderBytecode, code->BytecodeLength};
if (FAILED(hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, compiler_options))) if (FAILED(hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, 0, NULL, 0)))
{ {
WARN("Failed to compile shader, hr %#x.\n", hr); WARN("Failed to compile shader, hr %#x.\n", hr);
return hr; return hr;
@ -769,7 +769,7 @@ static HRESULT d3d12_pipeline_state_init_compute(struct d3d12_pipeline_state *st
pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
pipeline_info.pNext = NULL; pipeline_info.pNext = NULL;
pipeline_info.flags = 0; pipeline_info.flags = 0;
if (FAILED(hr = create_shader_stage(device, &pipeline_info.stage, VK_SHADER_STAGE_COMPUTE_BIT, &desc->CS, 0))) if (FAILED(hr = create_shader_stage(device, &pipeline_info.stage, VK_SHADER_STAGE_COMPUTE_BIT, &desc->CS)))
return hr; return hr;
pipeline_info.layout = root_signature->vk_pipeline_layout; pipeline_info.layout = root_signature->vk_pipeline_layout;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE; pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
@ -1108,7 +1108,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
continue; continue;
if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count], if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count],
shader_stages[i].stage, b, 0))) shader_stages[i].stage, b)))
goto fail; goto fail;
++graphics->stage_count; ++graphics->stage_count;

View File

@ -162,7 +162,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, options.compiler_options); hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, options.compiler_options, NULL, 0);
vkd3d_shader_free_shader_code(&dxbc); vkd3d_shader_free_shader_code(&dxbc);
if (FAILED(hr)) if (FAILED(hr))
{ {