mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader: Reduce masks to only read components in vsir_program_remap_output_signature().
This commit is contained in:
committed by
Henri Verbeet
parent
61bda1c054
commit
cc9fcee676
Notes:
Henri Verbeet
2024-11-04 17:11:05 +01:00
Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1236
@ -820,14 +820,84 @@ static const struct vkd3d_shader_varying_map *find_varying_map(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool target_allows_subset_masks(const struct vkd3d_shader_compile_info *info)
|
||||||
|
{
|
||||||
|
const struct vkd3d_shader_spirv_target_info *spirv_info;
|
||||||
|
enum vkd3d_shader_spirv_environment environment;
|
||||||
|
|
||||||
|
switch (info->target_type)
|
||||||
|
{
|
||||||
|
case VKD3D_SHADER_TARGET_SPIRV_BINARY:
|
||||||
|
spirv_info = vkd3d_find_struct(info->next, SPIRV_TARGET_INFO);
|
||||||
|
environment = spirv_info ? spirv_info->environment : VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0;
|
||||||
|
|
||||||
|
switch (environment)
|
||||||
|
{
|
||||||
|
case VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0:
|
||||||
|
case VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_1:
|
||||||
|
/* FIXME: Allow KHR_maintenance4. */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FIXME("Unrecognized environment %#x.\n", environment);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_unread_output_components(const struct shader_signature *signature,
|
||||||
|
struct vkd3d_shader_instruction *ins, struct vkd3d_shader_dst_param *dst)
|
||||||
|
{
|
||||||
|
const struct signature_element *e;
|
||||||
|
|
||||||
|
switch (dst->reg.type)
|
||||||
|
{
|
||||||
|
case VKD3DSPR_OUTPUT:
|
||||||
|
e = vsir_signature_find_element_for_reg(signature, dst->reg.idx[0].offset, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VKD3DSPR_ATTROUT:
|
||||||
|
e = vsir_signature_find_element_for_reg(signature,
|
||||||
|
SM1_COLOR_REGISTER_OFFSET + dst->reg.idx[0].offset, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VKD3DSPR_RASTOUT:
|
||||||
|
e = vsir_signature_find_element_for_reg(signature,
|
||||||
|
SM1_RASTOUT_REGISTER_OFFSET + dst->reg.idx[0].offset, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We already changed the mask earlier. */
|
||||||
|
dst->write_mask &= e->mask;
|
||||||
|
|
||||||
|
if (!dst->write_mask)
|
||||||
|
{
|
||||||
|
if (ins->dst_count == 1)
|
||||||
|
vkd3d_shader_instruction_make_nop(ins);
|
||||||
|
else
|
||||||
|
vsir_dst_param_init(dst, VKD3DSPR_NULL, VKD3D_DATA_UNUSED, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program *program,
|
static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program *program,
|
||||||
struct vsir_transformation_context *ctx)
|
struct vsir_transformation_context *ctx)
|
||||||
{
|
{
|
||||||
const struct vkd3d_shader_location location = {.source_name = ctx->compile_info->source_name};
|
const struct vkd3d_shader_location location = {.source_name = ctx->compile_info->source_name};
|
||||||
struct vkd3d_shader_message_context *message_context = ctx->message_context;
|
struct vkd3d_shader_message_context *message_context = ctx->message_context;
|
||||||
const struct vkd3d_shader_compile_info *compile_info = ctx->compile_info;
|
const struct vkd3d_shader_compile_info *compile_info = ctx->compile_info;
|
||||||
|
bool allows_subset_masks = target_allows_subset_masks(compile_info);
|
||||||
struct shader_signature *signature = &program->output_signature;
|
struct shader_signature *signature = &program->output_signature;
|
||||||
const struct vkd3d_shader_varying_map_info *varying_map;
|
const struct vkd3d_shader_varying_map_info *varying_map;
|
||||||
|
unsigned int subset_varying_count = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (!(varying_map = vkd3d_find_struct(compile_info->next, VARYING_MAP_INFO)))
|
if (!(varying_map = vkd3d_find_struct(compile_info->next, VARYING_MAP_INFO)))
|
||||||
@ -844,14 +914,21 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program
|
|||||||
|
|
||||||
e->target_location = map->input_register_index;
|
e->target_location = map->input_register_index;
|
||||||
|
|
||||||
/* It is illegal in Vulkan if the next shader uses the same varying
|
if ((input_mask & e->mask) == input_mask)
|
||||||
* location with a different mask. */
|
{
|
||||||
if (input_mask && input_mask != e->mask)
|
++subset_varying_count;
|
||||||
|
if (!allows_subset_masks)
|
||||||
|
{
|
||||||
|
e->mask = input_mask;
|
||||||
|
e->used_mask &= input_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input_mask && input_mask != e->mask)
|
||||||
{
|
{
|
||||||
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
|
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
|
||||||
"Aborting due to not yet implemented feature: "
|
"Aborting due to not yet implemented feature: "
|
||||||
"Output mask %#x does not match input mask %#x.",
|
"Input mask %#x reads components not written in output mask %#x.",
|
||||||
e->mask, input_mask);
|
input_mask, e->mask);
|
||||||
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -872,6 +949,22 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Vulkan (without KHR_maintenance4) disallows any mismatching masks,
|
||||||
|
* including when the input mask is a proper subset of the output mask.
|
||||||
|
* Resolve this by rewriting the shader to remove unread components from
|
||||||
|
* any writes to the output variable. */
|
||||||
|
|
||||||
|
if (!subset_varying_count || allows_subset_masks)
|
||||||
|
return VKD3D_OK;
|
||||||
|
|
||||||
|
for (i = 0; i < program->instructions.count; ++i)
|
||||||
|
{
|
||||||
|
struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < ins->dst_count; ++j)
|
||||||
|
remove_unread_output_components(signature, ins, &ins->dst[j]);
|
||||||
|
}
|
||||||
|
|
||||||
return VKD3D_OK;
|
return VKD3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ float4 main(in apple a) : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
[test]
|
[test]
|
||||||
todo(sm<4 | msl) draw quad
|
todo(msl) draw quad
|
||||||
probe (0, 0) rgba (10.0, 20.0, 30.0, 40.0)
|
probe (0, 0) rgba (10.0, 20.0, 30.0, 40.0)
|
||||||
|
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ float4 main(in float4 a : TEXCOORD0, in float3 b : TEXCOORD1) : sv_target
|
|||||||
}
|
}
|
||||||
|
|
||||||
[test]
|
[test]
|
||||||
todo(sm<4 | msl) draw quad
|
todo(msl) draw quad
|
||||||
probe (0, 0) rgba (10.0, 11.0, 20.0, 21.0)
|
probe (0, 0) rgba (10.0, 11.0, 20.0, 21.0)
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user