mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
libs/vkd3d-shader: Add support for push constants.
This commit is contained in:
parent
7aaa801768
commit
92fcb9ffa2
@ -50,15 +50,24 @@ enum vkd3d_descriptor_type
|
||||
struct vkd3d_shader_resource_binding
|
||||
{
|
||||
enum vkd3d_descriptor_type type;
|
||||
unsigned int index;
|
||||
unsigned int register_index;
|
||||
|
||||
uint32_t descriptor_set;
|
||||
uint32_t binding;
|
||||
};
|
||||
|
||||
struct vkd3d_shader_push_constant
|
||||
{
|
||||
unsigned int register_index;
|
||||
|
||||
unsigned int offset;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
|
||||
struct vkd3d_shader_code *spirv, uint32_t compiler_options,
|
||||
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count);
|
||||
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count,
|
||||
const struct vkd3d_shader_push_constant *push_constants, unsigned int push_constant_count);
|
||||
void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code);
|
||||
|
||||
HRESULT vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc,
|
||||
|
@ -631,6 +631,26 @@ static void vkd3d_spirv_build_op_name(struct vkd3d_spirv_builder *builder,
|
||||
vkd3d_spirv_build_string(stream, name, name_size);
|
||||
}
|
||||
|
||||
static void vkd3d_spirv_build_op_member_name(struct vkd3d_spirv_builder *builder,
|
||||
uint32_t type_id, uint32_t member, const char *fmt, ...)
|
||||
{
|
||||
struct vkd3d_spirv_stream *stream = &builder->debug_stream;
|
||||
unsigned int name_size;
|
||||
char name[1024];
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(name, ARRAY_SIZE(name), fmt, args);
|
||||
name[ARRAY_SIZE(name) - 1] = '\0';
|
||||
va_end(args);
|
||||
|
||||
name_size = vkd3d_spirv_string_word_count(name);
|
||||
vkd3d_spirv_build_word(stream, vkd3d_spirv_opcode_word(SpvOpMemberName, 3 + name_size));
|
||||
vkd3d_spirv_build_word(stream, type_id);
|
||||
vkd3d_spirv_build_word(stream, member);
|
||||
vkd3d_spirv_build_string(stream, name, name_size);
|
||||
}
|
||||
|
||||
static void vkd3d_spirv_build_op_decorate(struct vkd3d_spirv_builder *builder,
|
||||
uint32_t target_id, SpvDecoration decoration,
|
||||
uint32_t *literals, uint32_t literal_count)
|
||||
@ -1347,6 +1367,12 @@ struct vkd3d_control_flow_info
|
||||
} current_block;
|
||||
};
|
||||
|
||||
struct vkd3d_push_constant_buffer
|
||||
{
|
||||
struct vkd3d_shader_register reg;
|
||||
struct vkd3d_shader_push_constant pc;
|
||||
};
|
||||
|
||||
struct vkd3d_dxbc_compiler
|
||||
{
|
||||
struct vkd3d_spirv_builder spirv_builder;
|
||||
@ -1367,7 +1393,10 @@ struct vkd3d_dxbc_compiler
|
||||
|
||||
unsigned int binding_count;
|
||||
const struct vkd3d_shader_resource_binding *bindings;
|
||||
unsigned int push_constant_count;
|
||||
struct vkd3d_push_constant_buffer *push_constants;
|
||||
|
||||
bool after_declarations_section;
|
||||
const struct vkd3d_shader_signature *input_signature;
|
||||
const struct vkd3d_shader_signature *output_signature;
|
||||
struct
|
||||
@ -1381,10 +1410,12 @@ 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_resource_binding *bindings, unsigned int binding_count)
|
||||
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count,
|
||||
const struct vkd3d_shader_push_constant *constants, unsigned int constant_count)
|
||||
{
|
||||
const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature;
|
||||
struct vkd3d_dxbc_compiler *compiler;
|
||||
unsigned int i;
|
||||
|
||||
if (!(compiler = vkd3d_malloc(sizeof(*compiler))))
|
||||
return NULL;
|
||||
@ -1437,9 +1468,38 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
|
||||
compiler->bindings = bindings;
|
||||
}
|
||||
|
||||
if (constant_count)
|
||||
{
|
||||
compiler->push_constant_count = constant_count;
|
||||
if (!(compiler->push_constants = vkd3d_calloc(constant_count, sizeof(*compiler->push_constants))))
|
||||
{
|
||||
vkd3d_dxbc_compiler_destroy(compiler);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < compiler->push_constant_count; ++i)
|
||||
compiler->push_constants[i].pc = constants[i];
|
||||
}
|
||||
|
||||
return compiler;
|
||||
}
|
||||
|
||||
static struct vkd3d_push_constant_buffer *vkd3d_dxbc_compiler_find_push_constant(
|
||||
struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_register *reg)
|
||||
{
|
||||
unsigned int reg_idx = reg->idx[0].offset;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < compiler->push_constant_count; ++i)
|
||||
{
|
||||
struct vkd3d_push_constant_buffer *current = &compiler->push_constants[i];
|
||||
|
||||
if (current->pc.register_index == reg_idx)
|
||||
return current;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct vkd3d_descriptor_binding
|
||||
{
|
||||
uint32_t set;
|
||||
@ -1472,7 +1532,7 @@ static struct vkd3d_descriptor_binding vkd3d_dxbc_compiler_get_descriptor_bindin
|
||||
{
|
||||
const struct vkd3d_shader_resource_binding *current = &compiler->bindings[i];
|
||||
|
||||
if (current->type == descriptor_type && current->index == reg_idx)
|
||||
if (current->type == descriptor_type && current->register_index == reg_idx)
|
||||
{
|
||||
vk_binding.set = current->descriptor_set;
|
||||
vk_binding.binding = current->binding;
|
||||
@ -2356,12 +2416,84 @@ static void vkd3d_dxbc_compiler_emit_dcl_temps(struct vkd3d_dxbc_compiler *compi
|
||||
}
|
||||
}
|
||||
|
||||
static void vkd3d_dxbc_compiler_emit_push_constants(struct vkd3d_dxbc_compiler *compiler)
|
||||
{
|
||||
const SpvStorageClass storage_class = SpvStorageClassPushConstant;
|
||||
uint32_t vec4_id, length_id, struct_id, pointer_type_id, var_id;
|
||||
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||||
unsigned int i, j, count, reg_idx, cb_size;
|
||||
struct vkd3d_symbol reg_symbol;
|
||||
uint32_t *member_ids;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < compiler->push_constant_count; ++i)
|
||||
{
|
||||
const struct vkd3d_push_constant_buffer *cb = &compiler->push_constants[i];
|
||||
|
||||
if (cb->reg.type)
|
||||
++count;
|
||||
}
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
if (!(member_ids = vkd3d_calloc(count, sizeof(*member_ids))))
|
||||
return;
|
||||
|
||||
vec4_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_FLOAT, VKD3D_VEC4_SIZE);
|
||||
|
||||
for (i = 0, j = 0; i < compiler->push_constant_count; ++i)
|
||||
{
|
||||
const struct vkd3d_push_constant_buffer *cb = &compiler->push_constants[i];
|
||||
if (!cb->reg.type)
|
||||
continue;
|
||||
|
||||
cb_size = cb->reg.idx[1].offset;
|
||||
length_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, cb_size);
|
||||
member_ids[j] = vkd3d_spirv_build_op_type_array(builder, vec4_id, length_id);
|
||||
vkd3d_spirv_build_op_decorate1(builder, member_ids[j], SpvDecorationArrayStride, 16);
|
||||
|
||||
++j;
|
||||
}
|
||||
|
||||
struct_id = vkd3d_spirv_build_op_type_struct(builder, member_ids, count);
|
||||
vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0);
|
||||
vkd3d_spirv_build_op_name(builder, struct_id, "push_cb");
|
||||
vkd3d_free(member_ids);
|
||||
|
||||
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);
|
||||
|
||||
for (i = 0, j = 0; i < compiler->push_constant_count; ++i)
|
||||
{
|
||||
const struct vkd3d_push_constant_buffer *cb = &compiler->push_constants[i];
|
||||
if (!cb->reg.type)
|
||||
continue;
|
||||
|
||||
reg_idx = cb->reg.idx[0].offset;
|
||||
vkd3d_spirv_build_op_member_decorate1(builder, struct_id, j,
|
||||
SpvDecorationOffset, cb->pc.offset * sizeof(uint32_t));
|
||||
vkd3d_spirv_build_op_member_name(builder, struct_id, j, "cb%u", reg_idx);
|
||||
|
||||
vkd3d_symbol_make_register(®_symbol, &cb->reg);
|
||||
reg_symbol.id = var_id;
|
||||
reg_symbol.info.storage_class = storage_class;
|
||||
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
|
||||
if (j)
|
||||
FIXME("Multiple push constant buffers not supported yet.\n");
|
||||
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
const struct vkd3d_shader_register *reg = &instruction->declaration.src.reg;
|
||||
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
|
||||
const SpvStorageClass storage_class = SpvStorageClassUniform;
|
||||
struct vkd3d_push_constant_buffer *push_cb;
|
||||
struct vkd3d_symbol reg_symbol;
|
||||
unsigned int cb_size;
|
||||
|
||||
@ -2372,6 +2504,15 @@ static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compi
|
||||
|
||||
cb_size = reg->idx[1].offset;
|
||||
|
||||
if ((push_cb = vkd3d_dxbc_compiler_find_push_constant(compiler, reg)))
|
||||
{
|
||||
push_cb->reg = *reg;
|
||||
if (cb_size * VKD3D_VEC4_SIZE != push_cb->pc.count)
|
||||
FIXME("Push constant size do not match (cb size %u, constant count %u).\n",
|
||||
cb_size, push_cb->pc.count);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
array_type_id = vkd3d_spirv_build_op_type_array(builder, vec4_id, length_id);
|
||||
@ -2382,9 +2523,9 @@ 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, SpvStorageClassUniform, struct_id);
|
||||
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, SpvStorageClassUniform, 0);
|
||||
pointer_type_id, storage_class, 0);
|
||||
|
||||
vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, var_id, reg);
|
||||
|
||||
@ -2392,7 +2533,7 @@ static void vkd3d_dxbc_compiler_emit_dcl_constant_buffer(struct vkd3d_dxbc_compi
|
||||
|
||||
vkd3d_symbol_make_register(®_symbol, reg);
|
||||
reg_symbol.id = var_id;
|
||||
reg_symbol.info.storage_class = SpvStorageClassUniform;
|
||||
reg_symbol.info.storage_class = storage_class;
|
||||
vkd3d_dxbc_compiler_put_symbol(compiler, ®_symbol);
|
||||
}
|
||||
|
||||
@ -3574,9 +3715,26 @@ static void vkd3d_dxbc_compiler_emit_store_uav_typed(struct vkd3d_dxbc_compiler
|
||||
SpvImageOperandsMaskNone, NULL, 0);
|
||||
}
|
||||
|
||||
/* This function is called after declarations are processed. */
|
||||
static void vkd3d_dxbc_compiler_emit_main_prolog(struct vkd3d_dxbc_compiler *compiler)
|
||||
{
|
||||
vkd3d_dxbc_compiler_emit_push_constants(compiler);
|
||||
}
|
||||
|
||||
static bool is_dcl_instruction(enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx)
|
||||
{
|
||||
return VKD3DSIH_DCL <= handler_idx && handler_idx <= VKD3DSIH_DCL_VERTICES_OUT;
|
||||
}
|
||||
|
||||
void vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler,
|
||||
const struct vkd3d_shader_instruction *instruction)
|
||||
{
|
||||
if (!is_dcl_instruction(instruction->handler_idx) && !compiler->after_declarations_section)
|
||||
{
|
||||
compiler->after_declarations_section = true;
|
||||
vkd3d_dxbc_compiler_emit_main_prolog(compiler);
|
||||
}
|
||||
|
||||
switch (instruction->handler_idx)
|
||||
{
|
||||
case VKD3DSIH_DCL_GLOBAL_FLAGS:
|
||||
|
@ -20,7 +20,8 @@
|
||||
|
||||
HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
|
||||
struct vkd3d_shader_code *spirv, uint32_t compiler_options,
|
||||
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count)
|
||||
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count,
|
||||
const struct vkd3d_shader_push_constant *push_constants, unsigned int push_constant_count)
|
||||
{
|
||||
struct vkd3d_dxbc_compiler *spirv_compiler;
|
||||
struct vkd3d_shader_version shader_version;
|
||||
@ -31,8 +32,10 @@ HRESULT vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc,
|
||||
HRESULT hr;
|
||||
bool ret;
|
||||
|
||||
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);
|
||||
TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x, bindings %p, binding_count %u, "
|
||||
"push_constants %p, push_constant_count %u.\n",
|
||||
dxbc->code, dxbc->size, spirv, compiler_options, bindings, binding_count,
|
||||
push_constants, push_constant_count);
|
||||
|
||||
if (FAILED(hr = shader_extract_from_dxbc(dxbc->code, dxbc->size, &shader_desc)))
|
||||
{
|
||||
@ -50,8 +53,8 @@ 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, bindings, binding_count)))
|
||||
if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&shader_version, &shader_desc,
|
||||
compiler_options, bindings, binding_count, push_constants, push_constant_count)))
|
||||
{
|
||||
ERR("Failed to create DXBC compiler.\n");
|
||||
shader_sm4_free(parser_data);
|
||||
|
@ -823,7 +823,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_resource_binding *bindings, unsigned int binding_count) DECLSPEC_HIDDEN;
|
||||
const struct vkd3d_shader_resource_binding *bindings, unsigned int binding_count,
|
||||
const struct vkd3d_shader_push_constant *constants, unsigned int constant_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,
|
||||
|
@ -305,7 +305,7 @@ static uint32_t d3d12_root_signature_assign_vk_binding(struct d3d12_root_signatu
|
||||
uint32_t binding = *descriptor_idx;
|
||||
|
||||
root_signature->descriptor_mapping[binding].type = descriptor_type;
|
||||
root_signature->descriptor_mapping[binding].index = register_idx;
|
||||
root_signature->descriptor_mapping[binding].register_index = register_idx;
|
||||
root_signature->descriptor_mapping[binding].descriptor_set = 0;
|
||||
root_signature->descriptor_mapping[binding].binding = binding;
|
||||
|
||||
@ -816,7 +816,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device,
|
||||
{
|
||||
struct vkd3d_shader_code dxbc = {code->pShaderBytecode, code->BytecodeLength};
|
||||
if (FAILED(hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, 0,
|
||||
root_signature->descriptor_mapping, root_signature->descriptor_count)))
|
||||
root_signature->descriptor_mapping, root_signature->descriptor_count, NULL, 0)))
|
||||
{
|
||||
WARN("Failed to compile shader, hr %#x.\n", hr);
|
||||
return hr;
|
||||
|
@ -162,7 +162,7 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, options.compiler_options, NULL, 0);
|
||||
hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, options.compiler_options, NULL, 0, NULL, 0);
|
||||
vkd3d_shader_free_shader_code(&dxbc);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user