mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
vkd3d-shader: Write zeroes for uninitialized outputs in vsir_program_remap_output_signature().
This commit is contained in:
parent
e781abc3fb
commit
7e4ab9c7c0
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
@ -290,6 +290,15 @@ static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigne
|
|||||||
dst->reg.idx[0].offset = idx;
|
dst->reg.idx[0].offset = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dst_param_init_output(struct vkd3d_shader_dst_param *dst,
|
||||||
|
enum vkd3d_data_type data_type, uint32_t idx, uint32_t write_mask)
|
||||||
|
{
|
||||||
|
vsir_dst_param_init(dst, VKD3DSPR_OUTPUT, data_type, 1);
|
||||||
|
dst->reg.idx[0].offset = idx;
|
||||||
|
dst->reg.dimension = VSIR_DIMENSION_VEC4;
|
||||||
|
dst->write_mask = write_mask;
|
||||||
|
}
|
||||||
|
|
||||||
void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location,
|
void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location,
|
||||||
enum vkd3d_shader_opcode opcode)
|
enum vkd3d_shader_opcode opcode)
|
||||||
{
|
{
|
||||||
@ -984,8 +993,12 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program
|
|||||||
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);
|
bool allows_subset_masks = target_allows_subset_masks(compile_info);
|
||||||
struct shader_signature *signature = &program->output_signature;
|
struct shader_signature *signature = &program->output_signature;
|
||||||
|
unsigned int orig_element_count = signature->element_count;
|
||||||
const struct vkd3d_shader_varying_map_info *varying_map;
|
const struct vkd3d_shader_varying_map_info *varying_map;
|
||||||
|
struct signature_element *new_elements, *e;
|
||||||
|
unsigned int uninit_varying_count = 0;
|
||||||
unsigned int subset_varying_count = 0;
|
unsigned int subset_varying_count = 0;
|
||||||
|
unsigned int new_register_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)))
|
||||||
@ -994,8 +1007,8 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program
|
|||||||
for (i = 0; i < signature->element_count; ++i)
|
for (i = 0; i < signature->element_count; ++i)
|
||||||
{
|
{
|
||||||
const struct vkd3d_shader_varying_map *map = find_varying_map(varying_map, i);
|
const struct vkd3d_shader_varying_map *map = find_varying_map(varying_map, i);
|
||||||
struct signature_element *e = &signature->elements[i];
|
|
||||||
|
|
||||||
|
e = &signature->elements[i];
|
||||||
if (map)
|
if (map)
|
||||||
{
|
{
|
||||||
unsigned int input_mask = map->input_mask;
|
unsigned int input_mask = map->input_mask;
|
||||||
@ -1024,17 +1037,87 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program
|
|||||||
{
|
{
|
||||||
e->target_location = SIGNATURE_TARGET_LOCATION_UNUSED;
|
e->target_location = SIGNATURE_TARGET_LOCATION_UNUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_register_count = max(new_register_count, e->register_index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle uninitialized varyings by writing them before every ret.
|
||||||
|
*
|
||||||
|
* As far as sm1-sm3 is concerned, drivers disagree on what uninitialized
|
||||||
|
* varyings contain.
|
||||||
|
*
|
||||||
|
* - Diffuse (COLOR0) reliably contains (1, 1, 1, 1) in SM1/2.
|
||||||
|
* In SM3 it may contain (0, 0, 0, 0), (0, 0, 0, 1), or (1, 1, 1, 1).
|
||||||
|
*
|
||||||
|
* - Specular (COLOR1) contains (0, 0, 0, 0) or (0, 0, 0, 1).
|
||||||
|
* WARP writes (1, 1, 1, 1).
|
||||||
|
*
|
||||||
|
* - Anything else contains (0, 0, 0, 0) or (0, 0, 0, 1).
|
||||||
|
*
|
||||||
|
* We don't have enough knowledge to identify diffuse here. Instead we deal
|
||||||
|
* with that in vsir_program_ensure_diffuse(), by always writing diffuse if
|
||||||
|
* the shader doesn't.
|
||||||
|
*/
|
||||||
|
|
||||||
for (i = 0; i < varying_map->varying_count; ++i)
|
for (i = 0; i < varying_map->varying_count; ++i)
|
||||||
{
|
{
|
||||||
if (varying_map->varying_map[i].output_signature_index >= signature->element_count)
|
if (varying_map->varying_map[i].output_signature_index >= signature->element_count)
|
||||||
|
++uninit_varying_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(new_elements = vkd3d_realloc(signature->elements,
|
||||||
|
(signature->element_count + uninit_varying_count) * sizeof(*signature->elements))))
|
||||||
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
||||||
|
signature->elements = new_elements;
|
||||||
|
|
||||||
|
for (i = 0; i < varying_map->varying_count; ++i)
|
||||||
|
{
|
||||||
|
const struct vkd3d_shader_varying_map *map = &varying_map->varying_map[i];
|
||||||
|
|
||||||
|
if (map->output_signature_index < orig_element_count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TRACE("Synthesizing zero value for uninitialized output %u (mask %u).\n",
|
||||||
|
map->input_register_index, map->input_mask);
|
||||||
|
e = &signature->elements[signature->element_count++];
|
||||||
|
memset(e, 0, sizeof(*e));
|
||||||
|
e->sysval_semantic = VKD3D_SHADER_SV_NONE;
|
||||||
|
e->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
|
||||||
|
e->register_count = 1;
|
||||||
|
e->mask = map->input_mask;
|
||||||
|
e->used_mask = map->input_mask;
|
||||||
|
e->register_index = new_register_count++;
|
||||||
|
e->target_location = map->input_register_index;
|
||||||
|
e->interpolation_mode = VKD3DSIM_LINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write each uninitialized varying before each ret. */
|
||||||
|
for (i = 0; i < program->instructions.count; ++i)
|
||||||
|
{
|
||||||
|
struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
|
||||||
|
struct vkd3d_shader_location loc;
|
||||||
|
|
||||||
|
if (ins->opcode != VKD3DSIH_RET)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
loc = ins->location;
|
||||||
|
if (!shader_instruction_array_insert_at(&program->instructions, i, uninit_varying_count))
|
||||||
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
ins = &program->instructions.elements[i];
|
||||||
|
|
||||||
|
for (unsigned int j = signature->element_count - uninit_varying_count; j < signature->element_count; ++j)
|
||||||
{
|
{
|
||||||
vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
|
e = &signature->elements[j];
|
||||||
"Aborting due to not yet implemented feature: "
|
|
||||||
"The next stage consumes varyings not written by this stage.");
|
vsir_instruction_init_with_params(program, ins, &loc, VKD3DSIH_MOV, 1, 1);
|
||||||
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, e->register_index, e->mask);
|
||||||
|
vsir_src_param_init(&ins->src[0], VKD3DSPR_IMMCONST, VKD3D_DATA_FLOAT, 0);
|
||||||
|
ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
|
||||||
|
++ins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i += uninit_varying_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Vulkan (without KHR_maintenance4) disallows any mismatching masks,
|
/* Vulkan (without KHR_maintenance4) disallows any mismatching masks,
|
||||||
|
@ -13,7 +13,7 @@ float4 main(float4 v : texcoord0) : sv_target
|
|||||||
|
|
||||||
[test]
|
[test]
|
||||||
clear rtv 0 1 0 0 1
|
clear rtv 0 1 0 0 1
|
||||||
todo draw quad
|
draw quad
|
||||||
probe (0, 0) rgba (0, 0, 0, 1)
|
probe (0, 0) rgba (0, 0, 0, 1)
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ float4 main(float2 v : texcoord3, float3 w : texcoord1) : sv_target
|
|||||||
|
|
||||||
[test]
|
[test]
|
||||||
clear rtv 0 1 0 0 1
|
clear rtv 0 1 0 0 1
|
||||||
todo draw quad
|
draw quad
|
||||||
probe (0, 0) rgba (0, 0, 0, 0)
|
probe (0, 0) rgba (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user