vkd3d-shader: Introduce struct vkd3d_shader_parameter_info and struct vkd3d_shader_parameter1.

As the newly added documentation describes, this reroll serves two purposes:

* to allow shader parameters to be used for any target type (which allows using
  parameters for things like Direct3D 8-9 alpha test),

* to allow the union in struct vkd3d_shader_parameter to contain types larger
  than 32 bits (by specifying them indirectly through a pointer).
This commit is contained in:
Elizabeth Figura 2024-06-07 17:32:56 -05:00 committed by Henri Verbeet
parent bec4f413dc
commit 98def3214b
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
8 changed files with 153 additions and 19 deletions

View File

@ -105,6 +105,11 @@ enum vkd3d_shader_structure_type
* \since 1.10
*/
VKD3D_SHADER_STRUCTURE_TYPE_SCAN_COMBINED_RESOURCE_SAMPLER_INFO,
/**
* The structure is a vkd3d_shader_parameter_info structure.
* \since 1.13
*/
VKD3D_SHADER_STRUCTURE_TYPE_PARAMETER_INFO,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
};
@ -503,6 +508,20 @@ struct vkd3d_shader_parameter
} u;
};
struct vkd3d_shader_parameter1
{
enum vkd3d_shader_parameter_name name;
enum vkd3d_shader_parameter_type type;
enum vkd3d_shader_parameter_data_type data_type;
union
{
struct vkd3d_shader_parameter_immediate_constant immediate_constant;
struct vkd3d_shader_parameter_specialization_constant specialization_constant;
void *_pointer_pad;
uint32_t _pad[4];
} u;
};
/**
* Symbolic register indices for mapping uniform constant register sets in
* legacy Direct3D bytecode to constant buffer views in the target environment.
@ -1994,6 +2013,44 @@ struct vkd3d_shader_varying_map_info
unsigned int varying_count;
};
/**
* Interface information regarding a builtin shader parameter.
*
* Like compile options specified with struct vkd3d_shader_compile_option,
* parameters are used to specify certain values which are not part of the
* source shader bytecode but which need to be specified in the shader bytecode
* in the target format.
* Unlike struct vkd3d_shader_compile_option, however, this structure allows
* parameters to be specified in a variety of different ways, as described by
* enum vkd3d_shader_parameter_type.
*
* This structure is an extended version of struct vkd3d_shader_parameter as
* used in struct vkd3d_shader_spirv_target_info, which allows more parameter
* types to be used, and also allows specifying parameters when compiling
* shaders to target types other than SPIR-V. If this structure is chained
* along with vkd3d_shader_spirv_target_info, any parameters specified in the
* latter structure are ignored.
*
* This structure is passed to vkd3d_shader_compile() and extends
* vkd3d_shader_compile_info.
*
* This structure contains only input parameters.
*
* \since 1.13
*/
struct vkd3d_shader_parameter_info
{
/** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_PARAMETER_INFO. */
enum vkd3d_shader_structure_type type;
/** Optional pointer to a structure containing further parameters. */
const void *next;
/** Pointer to an array of dynamic parameters for this shader instance. */
const struct vkd3d_shader_parameter1 *parameters;
/** Size, in elements, of \ref parameters. */
unsigned int parameter_count;
};
#ifdef LIBVKD3D_SHADER_SOURCE
# define VKD3D_SHADER_API VKD3D_EXPORT
#else
@ -2077,6 +2134,7 @@ VKD3D_SHADER_API const enum vkd3d_shader_target_type *vkd3d_shader_get_supported
* - vkd3d_shader_descriptor_offset_info
* - vkd3d_shader_hlsl_source_info
* - vkd3d_shader_interface_info
* - vkd3d_shader_parameter_info
* - vkd3d_shader_preprocess_info
* - vkd3d_shader_scan_combined_resource_sampler_info
* - vkd3d_shader_scan_descriptor_info

View File

@ -1272,7 +1272,7 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, st
sm1->end = &code[token_count];
/* Estimate instruction count to avoid reallocation in most shaders. */
if (!vsir_program_init(program, &version, code_size != ~(size_t)0 ? token_count / 4u + 4 : 16))
if (!vsir_program_init(program, compile_info, &version, code_size != ~(size_t)0 ? token_count / 4u + 4 : 16))
return VKD3D_ERROR_OUT_OF_MEMORY;
vkd3d_shader_parser_init(&sm1->p, program, message_context, compile_info->source_name);

View File

@ -10206,12 +10206,13 @@ static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6
return NULL;
}
static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_program *program, const char *source_name,
static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_program *program,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context, struct dxbc_shader_desc *dxbc_desc)
{
size_t count, length, function_count, expected_function_count, byte_code_size = dxbc_desc->byte_code_size;
const struct vkd3d_shader_location location = {.source_name = compile_info->source_name};
struct shader_signature *patch_constant_signature, *output_signature, *input_signature;
const struct vkd3d_shader_location location = {.source_name = source_name};
uint32_t version_token, dxil_version, token_count, magic;
const uint32_t *byte_code = dxbc_desc->byte_code;
unsigned int chunk_offset, chunk_size;
@ -10302,9 +10303,9 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro
/* Estimate instruction count to avoid reallocation in most shaders. */
count = max(token_count, 400) - 400;
if (!vsir_program_init(program, &version, (count + (count >> 2)) / 2u + 10))
if (!vsir_program_init(program, compile_info, &version, (count + (count >> 2)) / 2u + 10))
return VKD3D_ERROR_OUT_OF_MEMORY;
vkd3d_shader_parser_init(&sm6->p, program, message_context, source_name);
vkd3d_shader_parser_init(&sm6->p, program, message_context, compile_info->source_name);
sm6->ptr = &sm6->start[1];
sm6->bitpos = 2;
@ -10565,7 +10566,7 @@ int dxil_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t co
dxbc_desc.byte_code = byte_code;
}
ret = sm6_parser_init(&sm6, program, compile_info->source_name, message_context, &dxbc_desc);
ret = sm6_parser_init(&sm6, program, compile_info, message_context, &dxbc_desc);
free_dxbc_shader_desc(&dxbc_desc);
vkd3d_free(byte_code);

View File

@ -5691,7 +5691,7 @@ static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl
version.major = ctx->profile->major_version;
version.minor = ctx->profile->minor_version;
version.type = ctx->profile->type;
if (!vsir_program_init(program, &version, 0))
if (!vsir_program_init(program, NULL, &version, 0))
{
ctx->result = VKD3D_ERROR_OUT_OF_MEMORY;
return;

View File

@ -19,9 +19,73 @@
#include "vkd3d_shader_private.h"
#include "vkd3d_types.h"
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve)
static int convert_parameter_info(const struct vkd3d_shader_compile_info *compile_info,
unsigned int *ret_count, const struct vkd3d_shader_parameter1 **ret_parameters)
{
const struct vkd3d_shader_spirv_target_info *spirv_info;
struct vkd3d_shader_parameter1 *parameters;
*ret_count = 0;
*ret_parameters = NULL;
if (!(spirv_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO)) || !spirv_info->parameter_count)
return VKD3D_OK;
if (!(parameters = vkd3d_calloc(spirv_info->parameter_count, sizeof(*parameters))))
return VKD3D_ERROR_OUT_OF_MEMORY;
for (unsigned int i = 0; i < spirv_info->parameter_count; ++i)
{
const struct vkd3d_shader_parameter *src = &spirv_info->parameters[i];
struct vkd3d_shader_parameter1 *dst = &parameters[i];
dst->name = src->name;
dst->type = src->type;
dst->data_type = src->data_type;
if (src->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT)
{
dst->u.immediate_constant = src->u.immediate_constant;
}
else if (src->type == VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT)
{
dst->u.specialization_constant = src->u.specialization_constant;
}
else
{
ERR("Invalid parameter type %#x.\n", src->type);
return VKD3D_ERROR_INVALID_ARGUMENT;
}
}
*ret_count = spirv_info->parameter_count;
*ret_parameters = parameters;
return VKD3D_OK;
}
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info,
const struct vkd3d_shader_version *version, unsigned int reserve)
{
memset(program, 0, sizeof(*program));
if (compile_info)
{
const struct vkd3d_shader_parameter_info *parameter_info;
if ((parameter_info = vkd3d_find_struct(compile_info->next, PARAMETER_INFO)))
{
program->parameter_count = parameter_info->parameter_count;
program->parameters = parameter_info->parameters;
}
else
{
if (convert_parameter_info(compile_info, &program->parameter_count, &program->parameters) < 0)
return false;
program->free_parameters = true;
}
}
program->shader_version = *version;
return shader_instruction_array_init(&program->instructions, reserve);
}
@ -30,6 +94,8 @@ void vsir_program_cleanup(struct vsir_program *program)
{
size_t i;
if (program->free_parameters)
vkd3d_free((void *)program->parameters);
for (i = 0; i < program->block_name_count; ++i)
vkd3d_free((void *)program->block_names[i]);
vkd3d_free(program->block_names);

View File

@ -2418,6 +2418,8 @@ struct spirv_compiler
uint32_t *descriptor_offset_ids;
struct vkd3d_push_constant_buffer_binding *push_constants;
const struct vkd3d_shader_spirv_target_info *spirv_target_info;
const struct vkd3d_shader_parameter1 *parameters;
unsigned int parameter_count;
bool prolog_emitted;
struct shader_signature input_signature;
@ -3290,16 +3292,15 @@ static uint32_t spirv_compiler_emit_array_variable(struct spirv_compiler *compil
return vkd3d_spirv_build_op_variable(builder, stream, ptr_type_id, storage_class, 0);
}
static const struct vkd3d_shader_parameter *spirv_compiler_get_shader_parameter(
static const struct vkd3d_shader_parameter1 *spirv_compiler_get_shader_parameter(
struct spirv_compiler *compiler, enum vkd3d_shader_parameter_name name)
{
const struct vkd3d_shader_spirv_target_info *info = compiler->spirv_target_info;
unsigned int i;
for (i = 0; info && i < info->parameter_count; ++i)
for (i = 0; i < compiler->parameter_count; ++i)
{
if (info->parameters[i].name == name)
return &info->parameters[i];
if (compiler->parameters[i].name == name)
return &compiler->parameters[i];
}
return NULL;
@ -3396,7 +3397,7 @@ static uint32_t spirv_compiler_get_spec_constant(struct spirv_compiler *compiler
static uint32_t spirv_compiler_emit_uint_shader_parameter(struct spirv_compiler *compiler,
enum vkd3d_shader_parameter_name name)
{
const struct vkd3d_shader_parameter *parameter;
const struct vkd3d_shader_parameter1 *parameter;
if (!(parameter = spirv_compiler_get_shader_parameter(compiler, name)))
{
@ -10570,6 +10571,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct
spirv_compiler_emit_descriptor_declarations(compiler);
compiler->parameter_count = program->parameter_count;
compiler->parameters = program->parameters;
if (program->block_count && !spirv_compiler_init_blocks(compiler, program->block_count))
return VKD3D_ERROR_OUT_OF_MEMORY;

View File

@ -2493,7 +2493,7 @@ fail:
}
static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_program *program,
const uint32_t *byte_code, size_t byte_code_size, const char *source_name,
const uint32_t *byte_code, size_t byte_code_size, const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_message_context *message_context)
{
struct vkd3d_shader_version version;
@ -2552,9 +2552,9 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro
version.minor = VKD3D_SM4_VERSION_MINOR(version_token);
/* Estimate instruction count to avoid reallocation in most shaders. */
if (!vsir_program_init(program, &version, token_count / 7u + 20))
if (!vsir_program_init(program, compile_info, &version, token_count / 7u + 20))
return false;
vkd3d_shader_parser_init(&sm4->p, program, message_context, source_name);
vkd3d_shader_parser_init(&sm4->p, program, message_context, compile_info->source_name);
sm4->ptr = sm4->start;
init_sm4_lookup_tables(&sm4->lookup);
@ -2651,7 +2651,7 @@ int tpf_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t con
}
if (!shader_sm4_init(&sm4, program, dxbc_desc.byte_code, dxbc_desc.byte_code_size,
compile_info->source_name, message_context))
compile_info, message_context))
{
WARN("Failed to initialise shader parser.\n");
free_dxbc_shader_desc(&dxbc_desc);

View File

@ -1362,6 +1362,10 @@ struct vsir_program
struct shader_signature output_signature;
struct shader_signature patch_constant_signature;
unsigned int parameter_count;
const struct vkd3d_shader_parameter1 *parameters;
bool free_parameters;
unsigned int input_control_point_count, output_control_point_count;
unsigned int flat_constant_count[3];
unsigned int block_count;
@ -1377,7 +1381,8 @@ void vsir_program_cleanup(struct vsir_program *program);
int vsir_program_compile(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out,
struct vkd3d_shader_message_context *message_context);
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve);
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info,
const struct vkd3d_shader_version *version, unsigned int reserve);
enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t config_flags,
const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context);
enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t config_flags,