This allows for the basic features necessary to compile sm1 shaders. This is the first step towards comprehensive Direct3D 1-9 support in the Vulkan backend.
Fixed-function d3d states that must be emulated with shaders in Vulkan (e.g. alpha test) are not yet implemented, nor is the fixed-function pipeline. Accordingly it is unlikely that any real applications run yet.
Tested with vkd3d's tests. Specifically, run `make crosstest` in a vkd3d tree, then:
wine tests/shader_runner.cross64.exe ../vkd3d/tests/hlsl/writemask-assignop-0.shader_test
-- v3: wined3d/spirv: Hook up sm1 interface matching. wined3d: Compile sm1 bytecode to spirv.
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 1 + dlls/wined3d/cs.c | 35 +++++++++++++++++++++++++--------- dlls/wined3d/wined3d_private.h | 1 + 3 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 3e6604c035e..0e6a7babfb1 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2322,6 +2322,7 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_ d3d_info->subpixel_viewport = true; d3d_info->fences = true; d3d_info->persistent_map = true; + d3d_info->gpu_push_constants = true;
/* Like GL, Vulkan doesn't explicitly specify a filling convention and only mandates that a * shared edge of two adjacent triangles generate a fragment for exactly one of the triangles. diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 37d160d8f25..fb114fb0b78 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2144,29 +2144,39 @@ static const struct push_constant_info size_t size; unsigned int max_count; DWORD mask; + enum wined3d_shader_type shader_type; + enum vkd3d_shader_d3dbc_constant_register shader_binding; } wined3d_cs_push_constant_info[] = { - [WINED3D_PUSH_CONSTANTS_VS_F] = {sizeof(struct wined3d_vec4), WINED3D_MAX_VS_CONSTS_F, WINED3D_SHADER_CONST_VS_F}, - [WINED3D_PUSH_CONSTANTS_PS_F] = {sizeof(struct wined3d_vec4), WINED3D_MAX_PS_CONSTS_F, WINED3D_SHADER_CONST_PS_F}, - [WINED3D_PUSH_CONSTANTS_VS_I] = {sizeof(struct wined3d_ivec4), WINED3D_MAX_CONSTS_I, WINED3D_SHADER_CONST_VS_I}, - [WINED3D_PUSH_CONSTANTS_PS_I] = {sizeof(struct wined3d_ivec4), WINED3D_MAX_CONSTS_I, WINED3D_SHADER_CONST_PS_I}, - [WINED3D_PUSH_CONSTANTS_VS_B] = {sizeof(BOOL), WINED3D_MAX_CONSTS_B, WINED3D_SHADER_CONST_VS_B}, - [WINED3D_PUSH_CONSTANTS_PS_B] = {sizeof(BOOL), WINED3D_MAX_CONSTS_B, WINED3D_SHADER_CONST_PS_B}, + [WINED3D_PUSH_CONSTANTS_VS_F] = {sizeof(struct wined3d_vec4), WINED3D_MAX_VS_CONSTS_F, WINED3D_SHADER_CONST_VS_F, WINED3D_SHADER_TYPE_VERTEX, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER}, + [WINED3D_PUSH_CONSTANTS_PS_F] = {sizeof(struct wined3d_vec4), WINED3D_MAX_PS_CONSTS_F, WINED3D_SHADER_CONST_PS_F, WINED3D_SHADER_TYPE_PIXEL, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER}, + [WINED3D_PUSH_CONSTANTS_VS_I] = {sizeof(struct wined3d_ivec4), WINED3D_MAX_CONSTS_I, WINED3D_SHADER_CONST_VS_I, WINED3D_SHADER_TYPE_VERTEX, VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER}, + [WINED3D_PUSH_CONSTANTS_PS_I] = {sizeof(struct wined3d_ivec4), WINED3D_MAX_CONSTS_I, WINED3D_SHADER_CONST_PS_I, WINED3D_SHADER_TYPE_PIXEL, VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER}, + [WINED3D_PUSH_CONSTANTS_VS_B] = {sizeof(BOOL), WINED3D_MAX_CONSTS_B, WINED3D_SHADER_CONST_VS_B, WINED3D_SHADER_TYPE_VERTEX, VKD3D_SHADER_D3DBC_BOOL_CONSTANT_REGISTER}, + [WINED3D_PUSH_CONSTANTS_PS_B] = {sizeof(BOOL), WINED3D_MAX_CONSTS_B, WINED3D_SHADER_CONST_PS_B, WINED3D_SHADER_TYPE_PIXEL, VKD3D_SHADER_D3DBC_BOOL_CONSTANT_REGISTER}, };
-static bool prepare_push_constant_buffer(struct wined3d_device *device, enum wined3d_push_constants type) +static bool prepare_push_constant_buffer(struct wined3d_device_context *context, enum wined3d_push_constants type) { const struct push_constant_info *info = &wined3d_cs_push_constant_info[type]; + struct wined3d_device *device = context->device; + bool gpu = device->adapter->d3d_info.gpu_push_constants; HRESULT hr;
- const struct wined3d_buffer_desc desc = + struct wined3d_buffer_desc desc = { .byte_width = info->max_count * info->size, .bind_flags = 0, .access = WINED3D_RESOURCE_ACCESS_CPU | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W, };
+ if (gpu) + { + desc.bind_flags = WINED3D_BIND_CONSTANT_BUFFER; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + } + if (!device->push_constants[type] && FAILED(hr = wined3d_buffer_create(device, &desc, NULL, NULL, &wined3d_null_parent_ops, &device->push_constants[type]))) { @@ -2174,6 +2184,13 @@ static bool prepare_push_constant_buffer(struct wined3d_device *device, enum win return false; }
+ if (gpu) + { + struct wined3d_constant_buffer_state state = {.buffer = device->push_constants[type], .size = desc.byte_width}; + + wined3d_device_context_emit_set_constant_buffers(context, info->shader_type, info->shader_binding, 1, &state); + } + return true; }
@@ -2219,7 +2236,7 @@ void wined3d_device_context_push_constants(struct wined3d_device_context *contex unsigned int byte_size = count * info->size; struct wined3d_box box;
- if (!prepare_push_constant_buffer(context->device, type)) + if (!prepare_push_constant_buffer(context, type)) return;
wined3d_box_set(&box, byte_offset, 0, byte_offset + byte_size, 1, 0, 1); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 238456e78d8..5a35ca88a7b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -236,6 +236,7 @@ struct wined3d_d3d_info uint32_t subpixel_viewport : 1; uint32_t fences : 1; uint32_t persistent_map : 1; + uint32_t gpu_push_constants : 1; enum wined3d_feature_level feature_level;
DWORD multisample_draw_location;
From: Fan Wenjie fanwj@mail.ustc.edu.cn
--- dlls/wined3d/shader.c | 15 +++++++-------- dlls/wined3d/shader_spirv.c | 33 +++++++++++++++++++++------------ dlls/wined3d/wined3d_private.h | 1 + 3 files changed, 29 insertions(+), 20 deletions(-)
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 428389a7177..1f0fe13402c 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -2395,7 +2395,6 @@ static void shader_trace(const void *code, size_t size, enum vkd3d_shader_source static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device *device, const struct wined3d_shader_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops) { - enum vkd3d_shader_source_type source_type; HRESULT hr;
TRACE("byte_code %p, byte_code_size %#lx.\n", desc->byte_code, (long)desc->byte_code_size); @@ -2424,8 +2423,8 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device const DWORD *ptr; void *fe_data;
- source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE; - if (!(shader->frontend = shader_select_frontend(source_type))) + shader->source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE; + if (!(shader->frontend = shader_select_frontend(shader->source_type))) { FIXME("Unable to find frontend for shader.\n"); hr = WINED3DERR_INVALIDCALL; @@ -2471,10 +2470,10 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device shader->byte_code_size = desc->byte_code_size;
max_version = shader_max_version_from_feature_level(device->cs->c.state->feature_level); - if (FAILED(hr = wined3d_shader_extract_from_dxbc(shader, max_version, &source_type))) + if (FAILED(hr = wined3d_shader_extract_from_dxbc(shader, max_version, &shader->source_type))) goto fail;
- if (!(shader->frontend = shader_select_frontend(source_type))) + if (!(shader->frontend = shader_select_frontend(shader->source_type))) { FIXME("Unable to find frontend for shader.\n"); hr = WINED3DERR_INVALIDCALL; @@ -2484,10 +2483,10 @@ static HRESULT shader_init(struct wined3d_shader *shader, struct wined3d_device
if (TRACE_ON(d3d_shader)) { - if (source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE) - shader_trace(shader->function, shader->functionLength, source_type); + if (shader->source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE) + shader_trace(shader->function, shader->functionLength, shader->source_type); else - shader_trace(shader->byte_code, shader->byte_code_size, source_type); + shader_trace(shader->byte_code, shader->byte_code_size, shader->source_type); }
diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c index b5b0e1f0462..f2e220beed2 100644 --- a/dlls/wined3d/shader_spirv.c +++ b/dlls/wined3d/shader_spirv.c @@ -228,9 +228,9 @@ static void shader_spirv_init_shader_interface_vk(struct wined3d_shader_spirv_sh }
static VkShaderModule shader_spirv_compile_shader(struct wined3d_context_vk *context_vk, - const struct wined3d_shader_desc *shader_desc, enum wined3d_shader_type shader_type, - const struct shader_spirv_compile_arguments *args, const struct shader_spirv_resource_bindings *bindings, - const struct wined3d_stream_output_desc *so_desc) + const struct wined3d_shader_desc *shader_desc, enum vkd3d_shader_source_type source_type, + enum wined3d_shader_type shader_type, const struct shader_spirv_compile_arguments *args, + const struct shader_spirv_resource_bindings *bindings, const struct wined3d_stream_output_desc *so_desc) { struct wined3d_shader_spirv_compile_args compile_args; struct wined3d_shader_spirv_shader_interface iface; @@ -252,7 +252,7 @@ static VkShaderModule shader_spirv_compile_shader(struct wined3d_context_vk *con info.next = &compile_args.spirv_target; info.source.code = shader_desc->byte_code; info.source.size = shader_desc->byte_code_size; - info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + info.source_type = source_type; info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY; info.options = spirv_compile_options; info.option_count = ARRAY_SIZE(spirv_compile_options); @@ -338,11 +338,19 @@ static struct shader_spirv_graphics_program_variant_vk *shader_spirv_find_graphi variant_vk->compile_args = args; variant_vk->binding_base = binding_base;
- shader_desc.byte_code = shader->byte_code; - shader_desc.byte_code_size = shader->byte_code_size; + if (shader->source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE) + { + shader_desc.byte_code = shader->function; + shader_desc.byte_code_size = shader->functionLength; + } + else + { + shader_desc.byte_code = shader->byte_code; + shader_desc.byte_code_size = shader->byte_code_size; + }
- if (!(variant_vk->vk_module = shader_spirv_compile_shader(context_vk, &shader_desc, shader_type, &args, - bindings, so_desc))) + if (!(variant_vk->vk_module = shader_spirv_compile_shader(context_vk, &shader_desc, + shader->source_type, shader_type, &args, bindings, so_desc))) return NULL; ++program_vk->variant_count;
@@ -370,8 +378,8 @@ static struct shader_spirv_compute_program_vk *shader_spirv_find_compute_program shader_desc.byte_code = shader->byte_code; shader_desc.byte_code_size = shader->byte_code_size;
- if (!(program->vk_module = shader_spirv_compile_shader(context_vk, &shader_desc, WINED3D_SHADER_TYPE_COMPUTE, - NULL, bindings, NULL))) + if (!(program->vk_module = shader_spirv_compile_shader(context_vk, &shader_desc, + shader->source_type, WINED3D_SHADER_TYPE_COMPUTE, NULL, bindings, NULL))) return NULL;
if (!(layout = wined3d_context_vk_get_pipeline_layout(context_vk, @@ -692,7 +700,7 @@ static void shader_spirv_scan_shader(struct wined3d_shader *shader, info.next = descriptor_info; info.source.code = shader->byte_code; info.source.size = shader->byte_code_size; - info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + info.source_type = shader->source_type; info.target_type = VKD3D_SHADER_TARGET_SPIRV_BINARY; info.options = spirv_compile_options; info.option_count = ARRAY_SIZE(spirv_compile_options); @@ -1049,7 +1057,8 @@ static uint64_t shader_spirv_compile(struct wined3d_context *context, const stru enum wined3d_shader_type shader_type) { struct shader_spirv_resource_bindings bindings = {0}; - return (uint64_t)shader_spirv_compile_shader(wined3d_context_vk(context), shader_desc, shader_type, NULL, &bindings, NULL); + return (uint64_t)shader_spirv_compile_shader(wined3d_context_vk(context), shader_desc, + VKD3D_SHADER_SOURCE_DXBC_TPF, shader_type, NULL, &bindings, NULL); }
static const struct wined3d_shader_backend_ops spirv_shader_backend_vk = diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 5a35ca88a7b..ff08a7f837f 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4251,6 +4251,7 @@ struct wined3d_shader void *byte_code; unsigned int byte_code_size; BOOL load_local_constsF; + enum vkd3d_shader_source_type source_type; const struct wined3d_shader_frontend *frontend; void *frontend_data; void *backend_data;
From: Zebediah Figura zfigura@codeweavers.com
--- configure.ac | 2 +- dlls/wined3d/shader_spirv.c | 59 +++++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac index cba55126869..941574bac26 100644 --- a/configure.ac +++ b/configure.ac @@ -1161,7 +1161,7 @@ then if test "$ac_cv_mingw_header_vkd3d_h" = "yes" -a "$ac_cv_mingw_header_vkd3d_shader_h" = "yes" then WINE_CHECK_MINGW_LIB(vkd3d,vkd3d_set_log_callback,[:],[:],[$VKD3D_PE_LIBS]) - WINE_CHECK_MINGW_LIB(vkd3d-shader,vkd3d_shader_serialize_dxbc,[:],[:],[$VKD3D_PE_LIBS]) + WINE_CHECK_MINGW_LIB(vkd3d-shader,vkd3d_shader_build_varying_map,[:],[:],[$VKD3D_PE_LIBS]) if test "$ac_cv_mingw_lib_vkd3d" = "no" -o "$ac_cv_mingw_lib_vkd3d_shader" = "no" then VKD3D_PE_CFLAGS="" diff --git a/dlls/wined3d/shader_spirv.c b/dlls/wined3d/shader_spirv.c index f2e220beed2..e1c50a1179c 100644 --- a/dlls/wined3d/shader_spirv.c +++ b/dlls/wined3d/shader_spirv.c @@ -53,10 +53,17 @@ struct shader_spirv_priv struct shader_spirv_resource_bindings bindings; };
+#define MAX_SM1_INTER_STAGE_VARYINGS 12 + struct shader_spirv_compile_arguments { union { + struct + { + struct vkd3d_shader_varying_map varying_map[MAX_SM1_INTER_STAGE_VARYINGS]; + unsigned int varying_count; + } vs; struct { uint32_t alpha_swizzle; @@ -81,6 +88,7 @@ struct shader_spirv_graphics_program_vk SIZE_T variants_size, variant_count;
struct vkd3d_shader_scan_descriptor_info descriptor_info; + struct vkd3d_shader_scan_signature_info signature_info; };
struct shader_spirv_compute_program_vk @@ -95,6 +103,7 @@ struct shader_spirv_compute_program_vk
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 sample_count; unsigned int ps_alpha_swizzle[WINED3D_MAX_RENDER_TARGETS]; @@ -155,6 +164,24 @@ static void shader_spirv_compile_arguments_init(struct shader_spirv_compile_argu args->u.fs.dual_source_blending = state->blend_state && state->blend_state->dual_source; break;
+ case WINED3D_SHADER_TYPE_VERTEX: + { + struct wined3d_shader *ps = state->shader[WINED3D_SHADER_TYPE_PIXEL]; + + if (ps) + { + struct shader_spirv_graphics_program_vk *vs_program = shader->backend_data; + struct shader_spirv_graphics_program_vk *ps_program = ps->backend_data; + + if (ps_program->signature_info.input.element_count > ARRAY_SIZE(args->u.vs.varying_map)) + ERR("Unexpected inter-stage varying count %u.\n", ps_program->signature_info.input.element_count); + if (shader->reg_maps.shader_version.major < 4) + vkd3d_shader_build_varying_map(&vs_program->signature_info.output, + &ps_program->signature_info.input, &args->u.vs.varying_count, args->u.vs.varying_map); + } + break; + } + default: break; } @@ -162,7 +189,8 @@ static void shader_spirv_compile_arguments_init(struct shader_spirv_compile_argu
static void shader_spirv_init_compile_args(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, const struct shader_spirv_compile_arguments *compile_args) + enum wined3d_shader_type shader_type, enum vkd3d_shader_source_type source_type, + const struct shader_spirv_compile_arguments *compile_args) { unsigned int i;
@@ -199,6 +227,18 @@ static void shader_spirv_init_compile_args(struct wined3d_shader_spirv_compile_a args->spirv_target.output_swizzles = args->ps_alpha_swizzle; args->spirv_target.output_swizzle_count = ARRAY_SIZE(args->ps_alpha_swizzle); } + else if (shader_type == WINED3D_SHADER_TYPE_VERTEX) + { + if (source_type == VKD3D_SHADER_SOURCE_D3D_BYTECODE) + { + args->spirv_target.next = &args->varying_map; + + args->varying_map.type = VKD3D_SHADER_STRUCTURE_TYPE_VARYING_MAP_INFO; + args->varying_map.next = vkd3d_interface; + args->varying_map.varying_map = compile_args->u.vs.varying_map; + args->varying_map.varying_count = compile_args->u.vs.varying_count; + } + } }
static void shader_spirv_init_shader_interface_vk(struct wined3d_shader_spirv_shader_interface *iface, @@ -246,7 +286,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(&compile_args, &iface.vkd3d_interface, - VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0, shader_type, args); + VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0, shader_type, source_type, args);
info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO; info.next = &compile_args.spirv_target; @@ -687,7 +727,8 @@ static bool shader_spirv_resource_bindings_init(struct shader_spirv_resource_bin }
static void shader_spirv_scan_shader(struct wined3d_shader *shader, - struct vkd3d_shader_scan_descriptor_info *descriptor_info) + struct vkd3d_shader_scan_descriptor_info *descriptor_info, + struct vkd3d_shader_scan_signature_info *signature_info) { struct vkd3d_shader_compile_info info; char *messages; @@ -696,6 +737,13 @@ static void shader_spirv_scan_shader(struct wined3d_shader *shader, memset(descriptor_info, 0, sizeof(*descriptor_info)); descriptor_info->type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_DESCRIPTOR_INFO;
+ if (signature_info) + { + memset(signature_info, 0, sizeof(*signature_info)); + signature_info->type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_SIGNATURE_INFO; + descriptor_info->next = signature_info; + } + info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO; info.next = descriptor_info; info.source.code = shader->byte_code; @@ -736,7 +784,7 @@ static void shader_spirv_precompile_compute(struct wined3d_shader *shader) shader->backend_data = program_vk; }
- shader_spirv_scan_shader(shader, &program_vk->descriptor_info); + shader_spirv_scan_shader(shader, &program_vk->descriptor_info, NULL); }
static void shader_spirv_precompile(void *shader_priv, struct wined3d_shader *shader) @@ -758,7 +806,7 @@ static void shader_spirv_precompile(void *shader_priv, struct wined3d_shader *sh shader->backend_data = program_vk; }
- shader_spirv_scan_shader(shader, &program_vk->descriptor_info); + shader_spirv_scan_shader(shader, &program_vk->descriptor_info, &program_vk->signature_info); }
static void shader_spirv_select(void *shader_priv, struct wined3d_context *context, @@ -967,6 +1015,7 @@ static void shader_spirv_destroy(struct wined3d_shader *shader) } heap_free(program_vk->variants); vkd3d_shader_free_scan_descriptor_info(&program_vk->descriptor_info); + vkd3d_shader_free_scan_signature_info(&program_vk->signature_info);
shader->backend_data = NULL; heap_free(program_vk);
This merge request was approved by Zebediah Figura.
Removed TAG_DXBC (which I had forgotten was not used elsewhere). Also fixed handling of Aon9 (thanks Henri for pointing that out).