mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader: Implement remapping shader output registers to match the next shader's semantics.
This commit is contained in:
committed by
Alexandre Julliard
parent
cb96482500
commit
11475ef62a
Notes:
Alexandre Julliard
2023-08-03 21:25:28 +09:00
Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/280
@ -90,6 +90,11 @@ enum vkd3d_shader_structure_type
|
|||||||
* \since 1.9
|
* \since 1.9
|
||||||
*/
|
*/
|
||||||
VKD3D_SHADER_STRUCTURE_TYPE_SCAN_SIGNATURE_INFO,
|
VKD3D_SHADER_STRUCTURE_TYPE_SCAN_SIGNATURE_INFO,
|
||||||
|
/**
|
||||||
|
* The structure is a vkd3d_shader_next_stage_info structure.
|
||||||
|
* \since 1.9
|
||||||
|
*/
|
||||||
|
VKD3D_SHADER_STRUCTURE_TYPE_NEXT_STAGE_INFO,
|
||||||
|
|
||||||
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
|
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_STRUCTURE_TYPE),
|
||||||
};
|
};
|
||||||
@ -1676,6 +1681,74 @@ struct vkd3d_shader_scan_signature_info
|
|||||||
struct vkd3d_shader_signature patch_constant;
|
struct vkd3d_shader_signature patch_constant;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the mapping of a output varying register in a shader stage,
|
||||||
|
* to an input varying register in the following shader stage.
|
||||||
|
*
|
||||||
|
* This structure is used in struct vkd3d_shader_next_stage_info.
|
||||||
|
*/
|
||||||
|
struct vkd3d_shader_varying_map
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The signature index (in the output signature) of the output varying.
|
||||||
|
* If greater than or equal to the number of elements in the output
|
||||||
|
* signature, signifies that the varying is consumed by the next stage but
|
||||||
|
* not written by this one.
|
||||||
|
*/
|
||||||
|
unsigned int output_signature_index;
|
||||||
|
/** The register index of the input varying to map this register to. */
|
||||||
|
unsigned int input_register_index;
|
||||||
|
/** The mask consumed by the destination register. */
|
||||||
|
unsigned int input_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A chained structure which describes the next shader in the pipeline.
|
||||||
|
*
|
||||||
|
* This structure is optional, and should only be provided if there is in fact
|
||||||
|
* another shader in the pipeline.
|
||||||
|
* However, depending on the input and output formats, this structure may be
|
||||||
|
* necessary in order to generate shaders which correctly match each other.
|
||||||
|
* If the structure or its individual fields are not provided, vkd3d-shader
|
||||||
|
* will generate shaders which may be correct in isolation, but are not
|
||||||
|
* guaranteed to correctly match each other.
|
||||||
|
*
|
||||||
|
* This structure is passed to vkd3d_shader_compile() and extends
|
||||||
|
* vkd3d_shader_compile_info.
|
||||||
|
*
|
||||||
|
* This structure contains only input parameters.
|
||||||
|
*
|
||||||
|
* \since 1.9
|
||||||
|
*/
|
||||||
|
struct vkd3d_shader_next_stage_info
|
||||||
|
{
|
||||||
|
/** Must be set to VKD3D_SHADER_STRUCTURE_TYPE_NEXT_STAGE_INFO. */
|
||||||
|
enum vkd3d_shader_structure_type type;
|
||||||
|
/** Optional pointer to a structure containing further parameters. */
|
||||||
|
const void *next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mapping of output varyings in this shader stage to input varyings
|
||||||
|
* in the next shader stage.
|
||||||
|
*
|
||||||
|
* This mapping should include exactly one element for each varying
|
||||||
|
* consumed by the next shader stage.
|
||||||
|
* If this shader stage outputs a varying that is not consumed by the next
|
||||||
|
* shader stage, that varying should be absent from this array.
|
||||||
|
*
|
||||||
|
* If this field is absent, vkd3d-shader will map varyings from one stage
|
||||||
|
* to another based on their register index.
|
||||||
|
* For Direct3D shader model 3.0, such a default mapping will be incorrect
|
||||||
|
* unless the registers are allocated in the same order, and hence this
|
||||||
|
* field is necessary to correctly match inter-stage varyings.
|
||||||
|
* This mapping may also be necessary under other circumstances where the
|
||||||
|
* varying interface does not match exactly.
|
||||||
|
*/
|
||||||
|
const struct vkd3d_shader_varying_map *varying_map;
|
||||||
|
/** The number of registers provided in \ref varying_map. */
|
||||||
|
unsigned int varying_count;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef LIBVKD3D_SHADER_SOURCE
|
#ifdef LIBVKD3D_SHADER_SOURCE
|
||||||
# define VKD3D_SHADER_API VKD3D_EXPORT
|
# define VKD3D_SHADER_API VKD3D_EXPORT
|
||||||
#else
|
#else
|
||||||
@ -1748,13 +1821,14 @@ VKD3D_SHADER_API const enum vkd3d_shader_target_type *vkd3d_shader_get_supported
|
|||||||
*
|
*
|
||||||
* Depending on the source and target types, this function may support the
|
* Depending on the source and target types, this function may support the
|
||||||
* following chained structures:
|
* following chained structures:
|
||||||
|
* - vkd3d_shader_hlsl_source_info
|
||||||
* - vkd3d_shader_interface_info
|
* - vkd3d_shader_interface_info
|
||||||
|
* - vkd3d_shader_next_stage_info
|
||||||
* - vkd3d_shader_scan_descriptor_info
|
* - vkd3d_shader_scan_descriptor_info
|
||||||
* - vkd3d_shader_scan_signature_info
|
* - vkd3d_shader_scan_signature_info
|
||||||
* - vkd3d_shader_spirv_domain_shader_target_info
|
* - vkd3d_shader_spirv_domain_shader_target_info
|
||||||
* - vkd3d_shader_spirv_target_info
|
* - vkd3d_shader_spirv_target_info
|
||||||
* - vkd3d_shader_transform_feedback_info
|
* - vkd3d_shader_transform_feedback_info
|
||||||
* - vkd3d_shader_hlsl_source_info
|
|
||||||
*
|
*
|
||||||
* \param compile_info A chained structure containing compilation parameters.
|
* \param compile_info A chained structure containing compilation parameters.
|
||||||
*
|
*
|
||||||
|
@ -85,6 +85,75 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i
|
|||||||
shader_register_eliminate_phase_addressing((struct vkd3d_shader_register *)&ins->dst[i].reg, instance_id);
|
shader_register_eliminate_phase_addressing((struct vkd3d_shader_register *)&ins->dst[i].reg, instance_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct vkd3d_shader_varying_map *find_varying_map(
|
||||||
|
const struct vkd3d_shader_next_stage_info *next_stage, unsigned int signature_idx)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < next_stage->varying_count; ++i)
|
||||||
|
{
|
||||||
|
if (next_stage->varying_map[i].output_signature_index == signature_idx)
|
||||||
|
return &next_stage->varying_map[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum vkd3d_result remap_output_signature(struct vkd3d_shader_parser *parser,
|
||||||
|
const struct vkd3d_shader_compile_info *compile_info)
|
||||||
|
{
|
||||||
|
struct shader_signature *signature = &parser->shader_desc.output_signature;
|
||||||
|
const struct vkd3d_shader_next_stage_info *next_stage;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!(next_stage = vkd3d_find_struct(compile_info->next, NEXT_STAGE_INFO)))
|
||||||
|
return VKD3D_OK;
|
||||||
|
|
||||||
|
for (i = 0; i < signature->element_count; ++i)
|
||||||
|
{
|
||||||
|
const struct vkd3d_shader_varying_map *map = find_varying_map(next_stage, i);
|
||||||
|
struct signature_element *e = &signature->elements[i];
|
||||||
|
|
||||||
|
if (map)
|
||||||
|
{
|
||||||
|
unsigned int input_mask = map->input_mask;
|
||||||
|
|
||||||
|
e->target_location = map->input_register_index;
|
||||||
|
|
||||||
|
/* It is illegal in Vulkan if the next shader uses the same varying
|
||||||
|
* location with a different mask. */
|
||||||
|
if (input_mask && input_mask != e->mask)
|
||||||
|
{
|
||||||
|
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
|
||||||
|
"Aborting due to not yet implemented feature: "
|
||||||
|
"Output mask %#x does not match input mask %#x.",
|
||||||
|
e->mask, input_mask);
|
||||||
|
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
|
||||||
|
"Aborting due to not yet implemented feature: "
|
||||||
|
"This stage outputs varyings not consumed by the next stage.");
|
||||||
|
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < next_stage->varying_count; ++i)
|
||||||
|
{
|
||||||
|
if (next_stage->varying_map[i].output_signature_index >= signature->element_count)
|
||||||
|
{
|
||||||
|
vkd3d_shader_parser_error(parser, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
|
||||||
|
"Aborting due to not yet implemented feature: "
|
||||||
|
"The next stage consumes varyings not written by this stage.");
|
||||||
|
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VKD3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
struct hull_flattener
|
struct hull_flattener
|
||||||
{
|
{
|
||||||
struct vkd3d_shader_instruction_array instructions;
|
struct vkd3d_shader_instruction_array instructions;
|
||||||
@ -1194,7 +1263,8 @@ static enum vkd3d_result instruction_array_normalise_flat_constants(struct vkd3d
|
|||||||
return VKD3D_OK;
|
return VKD3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser)
|
enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
|
||||||
|
const struct vkd3d_shader_compile_info *compile_info)
|
||||||
{
|
{
|
||||||
struct vkd3d_shader_instruction_array *instructions = &parser->instructions;
|
struct vkd3d_shader_instruction_array *instructions = &parser->instructions;
|
||||||
enum vkd3d_result result = VKD3D_OK;
|
enum vkd3d_result result = VKD3D_OK;
|
||||||
@ -1202,6 +1272,10 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser)
|
|||||||
if (parser->shader_desc.is_dxil)
|
if (parser->shader_desc.is_dxil)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
if (parser->shader_version.type != VKD3D_SHADER_TYPE_PIXEL
|
||||||
|
&& (result = remap_output_signature(parser, compile_info)) < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
if (parser->shader_version.type == VKD3D_SHADER_TYPE_HULL
|
if (parser->shader_version.type == VKD3D_SHADER_TYPE_HULL
|
||||||
&& (result = instruction_array_flatten_hull_shader_phases(instructions)) >= 0)
|
&& (result = instruction_array_flatten_hull_shader_phases(instructions)) >= 0)
|
||||||
{
|
{
|
||||||
|
@ -9542,7 +9542,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler,
|
|||||||
compiler->location.column = 0;
|
compiler->location.column = 0;
|
||||||
compiler->location.line = 1;
|
compiler->location.line = 1;
|
||||||
|
|
||||||
if ((result = vkd3d_shader_normalise(parser)) < 0)
|
if ((result = vkd3d_shader_normalise(parser, compile_info)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
instructions = parser->instructions;
|
instructions = parser->instructions;
|
||||||
|
@ -168,6 +168,8 @@ enum vkd3d_shader_error
|
|||||||
VKD3D_SHADER_WARNING_DXIL_INVALID_BLOCK_LENGTH = 8302,
|
VKD3D_SHADER_WARNING_DXIL_INVALID_BLOCK_LENGTH = 8302,
|
||||||
VKD3D_SHADER_WARNING_DXIL_INVALID_MODULE_LENGTH = 8303,
|
VKD3D_SHADER_WARNING_DXIL_INVALID_MODULE_LENGTH = 8303,
|
||||||
VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS = 8304,
|
VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS = 8304,
|
||||||
|
|
||||||
|
VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum vkd3d_shader_opcode
|
enum vkd3d_shader_opcode
|
||||||
@ -1409,6 +1411,7 @@ void dxbc_writer_add_section(struct dxbc_writer *dxbc, uint32_t tag, const void
|
|||||||
void dxbc_writer_init(struct dxbc_writer *dxbc);
|
void dxbc_writer_init(struct dxbc_writer *dxbc);
|
||||||
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *code);
|
int dxbc_writer_write(struct dxbc_writer *dxbc, struct vkd3d_shader_code *code);
|
||||||
|
|
||||||
enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser);
|
enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
|
||||||
|
const struct vkd3d_shader_compile_info *compile_info);
|
||||||
|
|
||||||
#endif /* __VKD3D_SHADER_PRIVATE_H */
|
#endif /* __VKD3D_SHADER_PRIVATE_H */
|
||||||
|
Reference in New Issue
Block a user