From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/shader_spirv.c | 58 ++++++++++++++++++++++++++++------ dlls/wined3d/stateblock.c | 3 ++ dlls/wined3d/wined3d_private.h | 7 ++++ 3 files changed, 59 insertions(+), 9 deletions(-)
diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c index 038c3067454..9a1fd1dd3fc 100644 --- a/dlls/wined3d/shader_spirv.c +++ b/dlls/wined3d/shader_spirv.c @@ -43,6 +43,8 @@ struct shader_spirv_resource_bindings
size_t binding_base[WINED3D_SHADER_TYPE_COUNT]; enum wined3d_shader_type so_stage; + + uint32_t ffp_extra_binding[2]; };
struct shader_spirv_priv @@ -104,8 +106,9 @@ struct wined3d_shader_spirv_compile_args { struct vkd3d_shader_varying_map_info varying_map; struct vkd3d_shader_spirv_target_info spirv_target; + struct vkd3d_shader_parameter_info parameter_info; enum vkd3d_shader_spirv_extension extensions[1]; - struct vkd3d_shader_parameter parameters[2]; + struct vkd3d_shader_parameter1 parameters[4]; unsigned int ps_alpha_swizzle[WINED3D_MAX_RENDER_TARGETS]; };
@@ -159,9 +162,9 @@ static void shader_spirv_compile_arguments_init(struct shader_spirv_compile_argu }
static void fill_ps_parameters(struct wined3d_shader_spirv_compile_args *vkd3d_args, - const struct shader_spirv_compile_arguments *compile_args) + const struct shader_spirv_compile_arguments *compile_args, uint32_t ffp_extra_binding) { - struct vkd3d_shader_parameter *parameters = vkd3d_args->parameters; + struct vkd3d_shader_parameter1 *parameters = vkd3d_args->parameters;
parameters[0].name = VKD3D_SHADER_PARAMETER_NAME_RASTERIZER_SAMPLE_COUNT; parameters[0].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT; @@ -173,24 +176,40 @@ static void fill_ps_parameters(struct wined3d_shader_spirv_compile_args *vkd3d_a parameters[1].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32; parameters[1].u.immediate_constant.u.u32 = compile_args->u.fs.args.flatshading;
- vkd3d_args->spirv_target.parameter_count = 2; - vkd3d_args->spirv_target.parameters = vkd3d_args->parameters; + parameters[2].name = VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_FUNC; + parameters[2].type = VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT; + parameters[2].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32; + parameters[2].u.immediate_constant.u.u32 = compile_args->u.fs.args.alpha_test_func + 1; + + parameters[3].name = VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF; + parameters[3].type = VKD3D_SHADER_PARAMETER_TYPE_BUFFER; + parameters[3].data_type = VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32; + parameters[3].u.buffer.set = 0; + parameters[3].u.buffer.binding = ffp_extra_binding; + parameters[3].u.buffer.offset = offsetof(struct wined3d_ffp_ps_constants, alpha_test_ref); + + vkd3d_args->parameter_info.parameter_count = 4; + vkd3d_args->parameter_info.parameters = vkd3d_args->parameters; }
static void shader_spirv_init_compile_args(const struct wined3d_vk_info *vk_info, struct wined3d_shader_spirv_compile_args *args, struct vkd3d_shader_interface_info *vkd3d_interface, enum vkd3d_shader_spirv_environment environment, enum wined3d_shader_type shader_type, enum vkd3d_shader_source_type source_type, - const struct shader_spirv_compile_arguments *compile_args) + const struct shader_spirv_compile_arguments *compile_args, + const struct shader_spirv_resource_bindings *bindings) { unsigned int i;
memset(args, 0, sizeof(*args)); args->spirv_target.type = VKD3D_SHADER_STRUCTURE_TYPE_SPIRV_TARGET_INFO; - args->spirv_target.next = vkd3d_interface; + args->spirv_target.next = &args->parameter_info; args->spirv_target.entry_point = "main"; args->spirv_target.environment = environment;
+ args->parameter_info.type = VKD3D_SHADER_STRUCTURE_TYPE_PARAMETER_INFO; + args->parameter_info.next = vkd3d_interface; + args->spirv_target.extensions = args->extensions;
if (vk_info->supported[WINED3D_VK_EXT_SHADER_STENCIL_EXPORT]) @@ -201,7 +220,7 @@ static void shader_spirv_init_compile_args(const struct wined3d_vk_info *vk_info { unsigned int rt_alpha_swizzle = compile_args->u.fs.args.rt_alpha_swizzle;
- fill_ps_parameters(args, compile_args); + fill_ps_parameters(args, compile_args, bindings->ffp_extra_binding[WINED3D_SHADER_TYPE_PIXEL]);
args->spirv_target.dual_source_blending = compile_args->u.fs.args.dual_source_blend;
@@ -275,7 +294,7 @@ static VkShaderModule shader_spirv_compile_shader(struct wined3d_context_vk *con
shader_spirv_init_shader_interface_vk(&iface, bindings, so_desc); shader_spirv_init_compile_args(vk_info, &compile_args, &iface.vkd3d_interface, - VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0, shader_type, source_type, args); + VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0, shader_type, source_type, args, bindings);
info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO; info.next = &compile_args.spirv_target; @@ -707,6 +726,27 @@ static bool shader_spirv_resource_bindings_init(struct shader_spirv_resource_bin return false; } } + + /* vkd3d-shader doesn't scan the uniform buffers we use for parameters. + * It can't really be reasonably modified to do so either, because + * parameters are specified in terms of the destination environment + * (SPIRV binding set and index). Add them manually here. + * + * Note that vkd3d-shader will ignore the extra binding specified in + * struct shader_spirv_resource_bindings, but we use it elsewhere. */ + + if (shader->source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE) + { + if (!shader_spirv_resource_bindings_add_binding(bindings, VKD3D_SHADER_DESCRIPTOR_TYPE_CBV, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, WINED3D_FFP_CONSTANTS_EXTRA_REGISTER, + shader_visibility, vk_stage, VKD3D_SHADER_BINDING_FLAG_BUFFER, &binding_idx)) + return false; + if (!wined3d_shader_resource_bindings_add_binding(wined3d_bindings, shader_type, + WINED3D_SHADER_DESCRIPTOR_TYPE_CBV, WINED3D_FFP_CONSTANTS_EXTRA_REGISTER, + WINED3D_SHADER_RESOURCE_BUFFER, WINED3D_DATA_FLOAT, binding_idx)) + return false; + bindings->ffp_extra_binding[shader_type] = binding_idx; + } }
return true; diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 77008088f85..a5c047be9dd 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -3991,6 +3991,9 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, } }
+ bind_push_constant_buffer(device, WINED3D_PUSH_CONSTANTS_PS_FFP, + WINED3D_SHADER_TYPE_PIXEL, WINED3D_FFP_CONSTANTS_EXTRA_REGISTER); + assert(list_empty(&stateblock->changed.changed_lights)); memset(&stateblock->changed, 0, sizeof(stateblock->changed)); list_init(&stateblock->changed.changed_lights); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 0ab36c2d94d..24ce6425a3f 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2818,8 +2818,15 @@ struct wined3d_ffp_ps_constants
/* States not used by the HLSL pipeline. */ float alpha_test_ref; + float padding[3]; /* to align to 16 bytes */ };
+/* Float/int/bool constants are bound to VKD3D_SHADER_D3DBC_*_CONSTANT_REGISTER + * which have the values 0/1/2 respectively. + * FFP uniform constants active even with shaders (e.g. alpha test ref) need to + * be additionally bound to a different slot. */ +#define WINED3D_FFP_CONSTANTS_EXTRA_REGISTER 3 + enum wined3d_push_constants { WINED3D_PUSH_CONSTANTS_VS_F,