From ae5cd6573f123994fff999de5e63c72fc090c9c9 Mon Sep 17 00:00:00 2001 From: Elizabeth Figura Date: Thu, 11 Jul 2024 17:25:16 -0500 Subject: [PATCH] vkd3d-shader: Allow controlling d3d color shade mode through vkd3d-shader parameters. --- include/vkd3d_shader.h | 24 ++++++++++++++++++++++++ libs/vkd3d-shader/ir.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 4acb6224..d4756810 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -553,6 +553,30 @@ enum vkd3d_shader_parameter_name * \since 1.13 */ VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, + /** + * Whether to use flat interpolation for fragment shader colour inputs. + * If the value is nonzero, inputs whose semantic usage is COLOR will use + * flat interpolation instead of linear. + * This parameter is ignored if the shader model is 4 or greater, since only + * shader model 3 and below do not specify the interpolation mode in the + * shader bytecode. + * + * This parameter can be used to implement fixed function shade mode, as + * present in Direct3D versions up to 9, if the target environment does not + * support shade mode as part of its own fixed-function API (as Vulkan and + * core OpenGL). + * + * The data type for this parameter must be + * VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32. + * + * The default value is zero, i.e. use linear interpolation. + * + * Only VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT is supported in this + * version of vkd3d-shader. + * + * \since 1.13 + */ + VKD3D_SHADER_PARAMETER_NAME_FLAT_INTERPOLATION, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), }; diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 6c98a32e..e0ac6322 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1723,7 +1723,33 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi } } -static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program *program) +static bool use_flat_interpolation(const struct vsir_program *program, + struct vkd3d_shader_message_context *message_context) +{ + static const struct vkd3d_shader_location no_loc; + const struct vkd3d_shader_parameter1 *parameter; + + if (!(parameter = vsir_program_get_parameter(program, VKD3D_SHADER_PARAMETER_NAME_FLAT_INTERPOLATION))) + return false; + + if (parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) + { + vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, + "Unsupported flat interpolation parameter type %#x.\n", parameter->type); + return false; + } + if (parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) + { + vkd3d_shader_error(message_context, &no_loc, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, + "Invalid flat interpolation parameter data type %#x.\n", parameter->data_type); + return false; + } + + return parameter->u.immediate_constant.u.u32; +} + +static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program *program, + struct vkd3d_shader_message_context *message_context) { struct io_normaliser normaliser = {program->instructions}; struct vkd3d_shader_instruction *ins; @@ -1786,6 +1812,18 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program return VKD3D_ERROR_OUT_OF_MEMORY; } + if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL + && program->shader_version.major < 4 && use_flat_interpolation(program, message_context)) + { + for (i = 0; i < program->input_signature.element_count; ++i) + { + struct signature_element *element = &program->input_signature.elements[i]; + + if (!ascii_strcasecmp(element->semantic_name, "COLOR")) + element->interpolation_mode = VKD3DSIM_CONSTANT; + } + } + normaliser.phase = VKD3DSIH_INVALID; for (i = 0; i < normaliser.instructions.count; ++i) shader_instruction_normalise_io_params(&normaliser.instructions.elements[i], &normaliser); @@ -6591,7 +6629,7 @@ enum vkd3d_result vsir_program_normalise(struct vsir_program *program, uint64_t return result; } - if ((result = vsir_program_normalise_io_registers(program)) < 0) + if ((result = vsir_program_normalise_io_registers(program, message_context)) < 0) return result; if ((result = instruction_array_normalise_flat_constants(program)) < 0)