mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
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:
parent
d39d0e4c9f
commit
edd1e9602d
@ -38,8 +38,27 @@ struct vkd3d_shader_code
|
||||
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,
|
||||
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);
|
||||
|
||||
HRESULT vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
|
||||
|
@ -1365,6 +1365,9 @@ struct vkd3d_dxbc_compiler
|
||||
struct vkd3d_control_flow_info *control_flow_info;
|
||||
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 *output_signature;
|
||||
struct
|
||||
@ -1377,7 +1380,8 @@ struct vkd3d_dxbc_compiler
|
||||
};
|
||||
|
||||
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;
|
||||
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->output_signature = &shader_desc->output_signature;
|
||||
|
||||
if (binding_count)
|
||||
{
|
||||
compiler->binding_count = binding_count;
|
||||
compiler->bindings = bindings;
|
||||
}
|
||||
|
||||
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,
|
||||
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)
|
||||
{
|
||||
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_symbol reg_symbol;
|
||||
unsigned int cb_idx, cb_size;
|
||||
unsigned int cb_size;
|
||||
|
||||
assert(!(instruction->flags & ~VKD3DSI_INDEXED_DYNAMIC));
|
||||
|
||||
if (instruction->flags & VKD3DSI_INDEXED_DYNAMIC)
|
||||
vkd3d_spirv_enable_capability(builder, SpvCapabilityUniformBufferArrayDynamicIndexing);
|
||||
|
||||
cb_idx = src->reg.idx[0].offset;
|
||||
cb_size = src->reg.idx[1].offset;
|
||||
cb_size = reg->idx[1].offset;
|
||||
|
||||
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);
|
||||
@ -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,
|
||||
pointer_type_id, SpvStorageClassUniform, 0);
|
||||
|
||||
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, 0);
|
||||
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, cb_idx);
|
||||
vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
|
||||
|
||||
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(®_symbol, &src->reg);
|
||||
vkd3d_symbol_make_register(®_symbol, reg);
|
||||
reg_symbol.id = var_id;
|
||||
reg_symbol.info.storage_class = SpvStorageClassUniform;
|
||||
vkd3d_dxbc_compiler_put_symbol(compiler, ®_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;
|
||||
uint32_t type_id, ptr_type_id, var_id;
|
||||
struct vkd3d_symbol reg_symbol;
|
||||
unsigned int sampler_idx;
|
||||
|
||||
sampler_idx = reg->idx[0].offset;
|
||||
|
||||
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_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, 0);
|
||||
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, sampler_idx);
|
||||
vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, 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,
|
||||
const struct vkd3d_shader_semantic *semantic, bool is_uav)
|
||||
const struct vkd3d_shader_semantic *semantic)
|
||||
{
|
||||
const SpvStorageClass storage_class = SpvStorageClassUniformConstant;
|
||||
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;
|
||||
uint32_t sampled_type_id, type_id, ptr_type_id, var_id;
|
||||
enum vkd3d_component_type sampled_type;
|
||||
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,
|
||||
semantic->resource_type, is_uav)))
|
||||
{
|
||||
@ -2472,8 +2537,6 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp
|
||||
return;
|
||||
}
|
||||
|
||||
reg_idx = semantic->reg.reg.idx[0].offset;
|
||||
|
||||
sampled_type = vkd3d_component_type_from_data_type(semantic->resource_data_type);
|
||||
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,
|
||||
ptr_type_id, storage_class, 0);
|
||||
|
||||
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, 0);
|
||||
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, reg_idx);
|
||||
vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
|
||||
|
||||
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.info.resource.sampled_type = sampled_type;
|
||||
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,
|
||||
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,
|
||||
@ -2509,7 +2571,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_uav_typed(struct vkd3d_dxbc_compiler *c
|
||||
if (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,
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include "vkd3d_shader_private.h"
|
||||
|
||||
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_shader_version shader_version;
|
||||
@ -30,8 +31,8 @@ HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
|
||||
HRESULT hr;
|
||||
bool ret;
|
||||
|
||||
TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x.\n",
|
||||
dxbc->code, dxbc->size, spirv, compiler_options);
|
||||
TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x, bindings %p, binding_count %u.\n",
|
||||
dxbc->code, dxbc->size, spirv, compiler_options, bindings, binding_count);
|
||||
|
||||
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);
|
||||
|
||||
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");
|
||||
shader_sm4_free(parser_data);
|
||||
|
@ -822,7 +822,8 @@ void free_shader_desc(struct vkd3d_shader_desc *desc) DECLSPEC_HIDDEN;
|
||||
struct vkd3d_dxbc_compiler;
|
||||
|
||||
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,
|
||||
const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN;
|
||||
bool vkd3d_dxbc_compiler_generate_spirv(struct vkd3d_dxbc_compiler *compiler,
|
||||
|
@ -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,
|
||||
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;
|
||||
struct VkShaderModuleCreateInfo shader_desc;
|
||||
@ -728,7 +728,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, struct VkPipelin
|
||||
else
|
||||
{
|
||||
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);
|
||||
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.pNext = NULL;
|
||||
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;
|
||||
pipeline_info.layout = root_signature->vk_pipeline_layout;
|
||||
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
@ -1108,7 +1108,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
++graphics->stage_count;
|
||||
|
@ -162,7 +162,7 @@ int main(int argc, char **argv)
|
||||
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);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user