vkd3d-shader/spirv: Support passing shader parameters through uniform buffers.

This commit is contained in:
Elizabeth Figura 2024-06-10 12:36:58 -05:00 committed by Henri Verbeet
parent 3dff608bf8
commit e8bdac8147
Notes: Henri Verbeet 2024-07-11 17:16:48 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/870
2 changed files with 77 additions and 0 deletions

View File

@ -472,6 +472,13 @@ enum vkd3d_shader_parameter_type
* constant. This value is only supported for the SPIR-V target type.
*/
VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT,
/**
* The parameter value is provided to the shader as part of a uniform
* buffer.
*
* \since 1.13
*/
VKD3D_SHADER_PARAMETER_TYPE_BUFFER,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_TYPE),
};
@ -536,6 +543,23 @@ struct vkd3d_shader_parameter_specialization_constant
uint32_t id;
};
/**
* The linkage of a parameter specified through a uniform buffer, used in
* struct vkd3d_shader_parameter1.
*/
struct vkd3d_shader_parameter_buffer
{
/**
* The set of the uniform buffer descriptor. If the target environment does
* not support descriptor sets, this value must be set to 0.
*/
unsigned int set;
/** The binding index of the uniform buffer descriptor. */
unsigned int binding;
/** The byte offset of the parameter within the buffer. */
uint32_t offset;
};
/**
* An individual shader parameter.
*
@ -600,6 +624,11 @@ struct vkd3d_shader_parameter1
* VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT.
*/
struct vkd3d_shader_parameter_specialization_constant specialization_constant;
/**
* Additional information if \a type is
* VKD3D_SHADER_PARAMETER_TYPE_BUFFER.
*/
struct vkd3d_shader_parameter_buffer buffer;
void *_pointer_pad;
uint32_t _pad[4];
} u;

View File

@ -2421,6 +2421,11 @@ struct spirv_compiler
const struct vkd3d_shader_parameter1 *parameters;
unsigned int parameter_count;
struct
{
uint32_t buffer_id;
} *spirv_parameter_info;
bool prolog_emitted;
struct shader_signature input_signature;
struct shader_signature output_signature;
@ -3394,6 +3399,21 @@ static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler
return spirv_compiler_emit_spec_constant(compiler, name, spec_id);
}
static uint32_t spirv_compiler_get_buffer_parameter(struct spirv_compiler *compiler,
const struct vkd3d_shader_parameter1 *parameter)
{
struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
unsigned int index = parameter - compiler->parameters;
uint32_t type_id, ptr_id, ptr_type_id;
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, type_id);
ptr_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id,
compiler->spirv_parameter_info[index].buffer_id,
spirv_compiler_get_constant_uint(compiler, 0));
return vkd3d_spirv_build_op_load(builder, type_id, ptr_id, SpvMemoryAccessMaskNone);
}
static uint32_t spirv_compiler_emit_uint_shader_parameter(struct spirv_compiler *compiler,
enum vkd3d_shader_parameter_name name)
{
@ -3409,6 +3429,8 @@ static uint32_t spirv_compiler_emit_uint_shader_parameter(struct spirv_compiler
return spirv_compiler_get_constant_uint(compiler, parameter->u.immediate_constant.u.u32);
if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT)
return spirv_compiler_get_spec_constant(compiler, name, parameter->u.specialization_constant.id);
if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_BUFFER)
return spirv_compiler_get_buffer_parameter(compiler, parameter);
FIXME("Unhandled parameter type %#x.\n", parameter->type);
@ -10573,6 +10595,32 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct
compiler->parameter_count = program->parameter_count;
compiler->parameters = program->parameters;
compiler->spirv_parameter_info = vkd3d_calloc(compiler->parameter_count, sizeof(*compiler->spirv_parameter_info));
for (i = 0; i < compiler->parameter_count; ++i)
{
const struct vkd3d_shader_parameter1 *parameter = &compiler->parameters[i];
if (parameter->type == VKD3D_SHADER_PARAMETER_TYPE_BUFFER)
{
uint32_t type_id, struct_id, ptr_type_id, var_id;
type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
struct_id = vkd3d_spirv_build_op_type_struct(builder, &type_id, 1);
vkd3d_spirv_build_op_decorate(builder, struct_id, SpvDecorationBlock, NULL, 0);
vkd3d_spirv_build_op_member_decorate1(builder, struct_id, 0,
SpvDecorationOffset, parameter->u.buffer.offset);
ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassUniform, struct_id);
var_id = vkd3d_spirv_build_op_variable(builder, &builder->global_stream,
ptr_type_id, SpvStorageClassUniform, 0);
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationDescriptorSet, parameter->u.buffer.set);
vkd3d_spirv_build_op_decorate1(builder, var_id, SpvDecorationBinding, parameter->u.buffer.binding);
compiler->spirv_parameter_info[i].buffer_id = var_id;
}
}
if (program->block_count && !spirv_compiler_init_blocks(compiler, program->block_count))
return VKD3D_ERROR_OUT_OF_MEMORY;