Module: vkd3d Branch: master Commit: e8bdac814730fbcda582873ef3a1072fb59987c8 URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/e8bdac814730fbcda582873ef3a107...
Author: Elizabeth Figura zfigura@codeweavers.com Date: Mon Jun 10 12:36:58 2024 -0500
vkd3d-shader/spirv: Support passing shader parameters through uniform buffers.
---
include/vkd3d_shader.h | 29 ++++++++++++++++++++++++++++ libs/vkd3d-shader/spirv.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index d37b0f18..ceee4b86 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -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; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index d5a3bafd..92130ff3 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -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;