mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader/ir: Allow controlling the fog source through a parameter.
This commit is contained in:
committed by
Henri Verbeet
parent
fc98cb482f
commit
1fbbc82f3a
Notes:
Henri Verbeet
2024-12-02 17:19:05 +01:00
Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1265
@@ -968,6 +968,8 @@ static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const
|
||||
|
||||
if (dst_param->reg.type == VKD3DSPR_RASTOUT && dst_param->reg.idx[0].offset == VSIR_RASTOUT_POINT_SIZE)
|
||||
sm1->p.program->has_point_size = true;
|
||||
if (dst_param->reg.type == VKD3DSPR_RASTOUT && dst_param->reg.idx[0].offset == VSIR_RASTOUT_FOG)
|
||||
sm1->p.program->has_fog = true;
|
||||
}
|
||||
|
||||
static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1,
|
||||
|
@@ -6907,6 +6907,177 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p
|
||||
return VKD3D_OK;
|
||||
}
|
||||
|
||||
static enum vkd3d_result vsir_program_add_fog_output(struct vsir_program *program,
|
||||
struct vsir_transformation_context *ctx)
|
||||
{
|
||||
struct shader_signature *signature = &program->output_signature;
|
||||
const struct vkd3d_shader_parameter1 *source_parameter;
|
||||
uint32_t register_idx = 0;
|
||||
|
||||
if (!is_pre_rasterization_shader(program->shader_version.type))
|
||||
return VKD3D_OK;
|
||||
|
||||
if (!(source_parameter = vsir_program_get_parameter(program, VKD3D_SHADER_PARAMETER_NAME_FOG_SOURCE)))
|
||||
return VKD3D_OK;
|
||||
|
||||
if (source_parameter->type == VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT)
|
||||
{
|
||||
enum vkd3d_shader_fog_source source = source_parameter->u.immediate_constant.u.u32;
|
||||
|
||||
if (source == VKD3D_SHADER_FOG_SOURCE_FOG)
|
||||
return VKD3D_OK;
|
||||
|
||||
if (source == VKD3D_SHADER_FOG_SOURCE_FOG_OR_SPECULAR_W
|
||||
&& !vsir_signature_find_element_by_name(signature, "COLOR", 1))
|
||||
return VKD3D_OK;
|
||||
}
|
||||
|
||||
if (vsir_signature_find_element_by_name(signature, "FOG", 0))
|
||||
return VKD3D_OK;
|
||||
|
||||
for (unsigned int i = 0; i < signature->element_count; ++i)
|
||||
register_idx = max(register_idx, signature->elements[i].register_index + 1);
|
||||
|
||||
if (!add_signature_element(signature, "FOG", 0, VKD3DSP_WRITEMASK_0, register_idx, VKD3DSIM_LINEAR))
|
||||
return VKD3D_ERROR_OUT_OF_MEMORY;
|
||||
return VKD3D_OK;
|
||||
}
|
||||
|
||||
static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *program,
|
||||
const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_fog_source source, uint32_t temp,
|
||||
uint32_t fog_signature_idx, uint32_t source_signature_idx, size_t *ret_pos)
|
||||
{
|
||||
const struct signature_element *e = &program->output_signature.elements[source_signature_idx];
|
||||
struct vkd3d_shader_instruction_array *instructions = &program->instructions;
|
||||
size_t pos = ret - instructions->elements;
|
||||
struct vkd3d_shader_instruction *ins;
|
||||
|
||||
if (!shader_instruction_array_insert_at(&program->instructions, pos, 2))
|
||||
return VKD3D_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
ins = &program->instructions.elements[pos];
|
||||
|
||||
/* Write the fog output. */
|
||||
vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_MOV, 1, 1);
|
||||
dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, fog_signature_idx, 0x1);
|
||||
src_param_init_temp_float4(&ins->src[0], temp);
|
||||
if (source == VKD3D_SHADER_FOG_SOURCE_Z)
|
||||
ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z);
|
||||
else /* Position or specular W. */
|
||||
ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W);
|
||||
++ins;
|
||||
|
||||
/* Write the position or specular output. */
|
||||
vsir_instruction_init_with_params(program, ins, &ret->location, VKD3DSIH_MOV, 1, 1);
|
||||
dst_param_init_output(&ins->dst[0], vkd3d_data_type_from_component_type(e->component_type),
|
||||
source_signature_idx, e->mask);
|
||||
src_param_init_temp_float4(&ins->src[0], temp);
|
||||
++ins;
|
||||
|
||||
*ret_pos = pos + 2;
|
||||
return VKD3D_OK;
|
||||
}
|
||||
|
||||
static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *program,
|
||||
struct vsir_transformation_context *ctx)
|
||||
{
|
||||
struct vkd3d_shader_message_context *message_context = ctx->message_context;
|
||||
const struct vkd3d_shader_parameter1 *source_parameter = NULL;
|
||||
uint32_t fog_signature_idx, source_signature_idx, temp;
|
||||
static const struct vkd3d_shader_location no_loc;
|
||||
enum vkd3d_shader_fog_source source;
|
||||
const struct signature_element *e;
|
||||
|
||||
if (!is_pre_rasterization_shader(program->shader_version.type))
|
||||
return VKD3D_OK;
|
||||
|
||||
if (!(source_parameter = vsir_program_get_parameter(program, VKD3D_SHADER_PARAMETER_NAME_FOG_SOURCE)))
|
||||
return VKD3D_OK;
|
||||
|
||||
if (source_parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT)
|
||||
{
|
||||
vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED,
|
||||
"Unsupported fog source parameter type %#x.", source_parameter->type);
|
||||
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if (source_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32)
|
||||
{
|
||||
vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE,
|
||||
"Invalid fog source parameter data type %#x.", source_parameter->data_type);
|
||||
return VKD3D_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
source = source_parameter->u.immediate_constant.u.u32;
|
||||
|
||||
TRACE("Fog source %#x.\n", source);
|
||||
|
||||
if (source == VKD3D_SHADER_FOG_SOURCE_FOG)
|
||||
return VKD3D_OK;
|
||||
|
||||
if (source == VKD3D_SHADER_FOG_SOURCE_FOG_OR_SPECULAR_W)
|
||||
{
|
||||
if (program->has_fog || !(e = vsir_signature_find_element_by_name(&program->output_signature, "COLOR", 1)))
|
||||
return VKD3D_OK;
|
||||
source_signature_idx = e - program->output_signature.elements;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!vsir_signature_find_sysval(&program->output_signature,
|
||||
VKD3D_SHADER_SV_POSITION, 0, &source_signature_idx))
|
||||
{
|
||||
vkd3d_shader_error(ctx->message_context, &no_loc,
|
||||
VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC, "Shader does not write position.");
|
||||
return VKD3D_ERROR_INVALID_SHADER;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(e = vsir_signature_find_element_by_name(&program->output_signature, "FOG", 0)))
|
||||
{
|
||||
ERR("Fog output not found.\n");
|
||||
return VKD3D_ERROR_INVALID_SHADER;
|
||||
}
|
||||
fog_signature_idx = e - program->output_signature.elements;
|
||||
|
||||
temp = program->temp_count++;
|
||||
|
||||
/* Insert a fog write before each ret, and convert either specular or
|
||||
* position output to a temp. */
|
||||
for (size_t i = 0; i < program->instructions.count; ++i)
|
||||
{
|
||||
struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
|
||||
|
||||
if (vsir_instruction_is_dcl(ins))
|
||||
continue;
|
||||
|
||||
if (ins->opcode == VKD3DSIH_RET)
|
||||
{
|
||||
size_t new_pos;
|
||||
int ret;
|
||||
|
||||
if ((ret = insert_vertex_fog_before_ret(program, ins, source, temp,
|
||||
fog_signature_idx, source_signature_idx, &new_pos)) < 0)
|
||||
return ret;
|
||||
i = new_pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < ins->dst_count; ++j)
|
||||
{
|
||||
struct vkd3d_shader_dst_param *dst = &ins->dst[j];
|
||||
|
||||
/* Note we run after I/O normalization. */
|
||||
if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == source_signature_idx)
|
||||
{
|
||||
dst->reg.type = VKD3DSPR_TEMP;
|
||||
dst->reg.idx[0].offset = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
program->has_fog = true;
|
||||
|
||||
return VKD3D_OK;
|
||||
}
|
||||
|
||||
struct validation_context
|
||||
{
|
||||
struct vkd3d_shader_message_context *message_context;
|
||||
@@ -8994,6 +9165,9 @@ enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uin
|
||||
/* For vsir_program_insert_fragment_fog(). */
|
||||
vsir_transform(&ctx, vsir_program_add_fog_input);
|
||||
|
||||
/* For vsir_program_insert_vertex_fog(). */
|
||||
vsir_transform(&ctx, vsir_program_add_fog_output);
|
||||
|
||||
return ctx.result;
|
||||
}
|
||||
|
||||
@@ -9049,6 +9223,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t
|
||||
vsir_transform(&ctx, vsir_program_insert_point_size_clamp);
|
||||
vsir_transform(&ctx, vsir_program_insert_point_coord);
|
||||
vsir_transform(&ctx, vsir_program_insert_fragment_fog);
|
||||
vsir_transform(&ctx, vsir_program_insert_vertex_fog);
|
||||
|
||||
if (TRACE_ON())
|
||||
vsir_program_trace(program);
|
||||
|
@@ -1428,6 +1428,7 @@ struct vsir_program
|
||||
bool use_vocp;
|
||||
bool has_point_size;
|
||||
bool has_point_coord;
|
||||
bool has_fog;
|
||||
uint8_t diffuse_written_mask;
|
||||
enum vsir_control_flow_type cf_type;
|
||||
enum vsir_normalisation_level normalisation_level;
|
||||
|
Reference in New Issue
Block a user