diff --git a/include/private/vkd3d_shader.h b/include/private/vkd3d_shader.h index ed2fc890..1f8fa397 100644 --- a/include/private/vkd3d_shader.h +++ b/include/private/vkd3d_shader.h @@ -125,9 +125,16 @@ struct vkd3d_shader_interface unsigned int uav_counter_count; }; +struct vkd3d_shader_compile_arguments +{ + unsigned int *output_swizzles; + unsigned int output_swizzle_count; +}; + int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_code *spirv, uint32_t compiler_options, - const struct vkd3d_shader_interface *shader_interface); + const struct vkd3d_shader_interface *shader_interface, + const struct vkd3d_shader_compile_arguments *compile_args); void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code); enum vkd3d_filter @@ -390,6 +397,20 @@ struct vkd3d_shader_signature_element *vkd3d_shader_find_signature_element( unsigned int semantic_index, unsigned int stream_index); void vkd3d_shader_free_shader_signature(struct vkd3d_shader_signature *signature); +/* swizzle bits fields: wwzzyyxx */ +#define VKD3D_SWIZZLE_X (0u) +#define VKD3D_SWIZZLE_Y (1u) +#define VKD3D_SWIZZLE_Z (2u) +#define VKD3D_SWIZZLE_W (3u) +#define VKD3D_SWIZZLE_MASK (0x3u) +#define VKD3D_SWIZZLE_SHIFT(idx) (2u * (idx)) +#define VKD3D_SWIZZLE(x, y, z, w) (((x & VKD3D_SWIZZLE_MASK) << VKD3D_SWIZZLE_SHIFT(0)) \ + | ((y & VKD3D_SWIZZLE_MASK) << VKD3D_SWIZZLE_SHIFT(1)) \ + | ((z & VKD3D_SWIZZLE_MASK) << VKD3D_SWIZZLE_SHIFT(2)) \ + | ((w & VKD3D_SWIZZLE_MASK) << VKD3D_SWIZZLE_SHIFT(3))) +#define VKD3D_NO_SWIZZLE \ + VKD3D_SWIZZLE(VKD3D_SWIZZLE_X, VKD3D_SWIZZLE_Y, VKD3D_SWIZZLE_Z, VKD3D_SWIZZLE_W) + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 53ddd445..4b2b46c3 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -1839,6 +1839,7 @@ struct vkd3d_dxbc_compiler struct vkd3d_shader_interface shader_interface; struct vkd3d_push_constant_buffer_binding *push_constants; + const struct vkd3d_shader_compile_arguments *compile_args; bool after_declarations_section; const struct vkd3d_shader_signature *input_signature; @@ -1860,6 +1861,7 @@ struct vkd3d_dxbc_compiler struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_desc *shader_desc, uint32_t compiler_options, const struct vkd3d_shader_interface *shader_interface, + const struct vkd3d_shader_compile_arguments *compile_args, const struct vkd3d_shader_scan_info *scan_info) { const struct vkd3d_shader_signature *output_signature = &shader_desc->output_signature; @@ -1926,6 +1928,7 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader compiler->push_constants[i].pc = shader_interface->push_constant_buffers[i]; } } + compiler->compile_args = compile_args; compiler->scan_info = scan_info; @@ -3013,6 +3016,18 @@ static unsigned int vkd3d_dxbc_compiler_get_output_variable_index( return register_idx; } +static unsigned int get_shader_output_swizzle(struct vkd3d_dxbc_compiler *compiler, + unsigned int register_idx) +{ + const struct vkd3d_shader_compile_arguments *compile_args; + + if (!(compile_args = compiler->compile_args)) + return VKD3D_NO_SWIZZLE; + if (register_idx >= compile_args->output_swizzle_count) + return VKD3D_NO_SWIZZLE; + return compile_args->output_swizzles[register_idx]; +} + static uint32_t vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_dst_param *dst, enum vkd3d_shader_input_sysval_semantic sysval) { @@ -3069,7 +3084,10 @@ static uint32_t vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *comp compiler->output_info[signature_idx].component_type = component_type; } - if ((use_private_variable = component_type != VKD3D_TYPE_FLOAT || component_count != VKD3D_VEC4_SIZE)) + use_private_variable = component_type != VKD3D_TYPE_FLOAT || component_count != VKD3D_VEC4_SIZE + || (signature_element + && get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_NO_SWIZZLE); + if (use_private_variable) storage_class = SpvStorageClassPrivate; vkd3d_symbol_make_register(®_symbol, reg); @@ -5900,7 +5918,7 @@ static void vkd3d_dxbc_compiler_emit_output_setup_function(struct vkd3d_dxbc_com uint32_t param_type_id[MAX_REG_OUTPUT + 1], param_id[MAX_REG_OUTPUT + 1] = {}; const struct vkd3d_shader_signature *signature = compiler->output_signature; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; - DWORD write_mask, variable_idx; + DWORD write_mask, swizzle, variable_idx; unsigned int i, count; function_id = compiler->output_setup_function_id; @@ -5945,8 +5963,9 @@ static void vkd3d_dxbc_compiler_emit_output_setup_function(struct vkd3d_dxbc_com continue; write_mask = signature->elements[i].mask & 0xff; + swizzle = get_shader_output_swizzle(compiler, signature->elements[i].register_index); val_id = vkd3d_dxbc_compiler_emit_swizzle(compiler, - param_id[variable_idx], VKD3D_TYPE_FLOAT, VKD3D_NO_SWIZZLE, write_mask); + param_id[variable_idx], VKD3D_TYPE_FLOAT, swizzle, write_mask); if (compiler->output_info[i].component_type != VKD3D_TYPE_FLOAT) { diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 9db8b569..1de56ac9 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -58,7 +58,8 @@ static void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser) int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_code *spirv, uint32_t compiler_options, - const struct vkd3d_shader_interface *shader_interface) + const struct vkd3d_shader_interface *shader_interface, + const struct vkd3d_shader_compile_arguments *compile_args) { struct vkd3d_shader_instruction instruction; struct vkd3d_dxbc_compiler *spirv_compiler; @@ -66,8 +67,8 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, struct vkd3d_shader_parser parser; int ret; - TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x, shader_interface %p.\n", - dxbc->code, dxbc->size, spirv, compiler_options, shader_interface); + TRACE("dxbc {%p, %zu}, spirv %p, compiler_options %#x, shader_interface %p, compile_args %p.\n", + dxbc->code, dxbc->size, spirv, compiler_options, shader_interface, compile_args); if ((ret = vkd3d_shader_scan_dxbc(dxbc, &scan_info)) < 0) return ret; @@ -76,7 +77,7 @@ int vkd3d_shader_compile_dxbc(const struct vkd3d_shader_code *dxbc, return ret; if (!(spirv_compiler = vkd3d_dxbc_compiler_create(&parser.shader_version, - &parser.shader_desc, compiler_options, shader_interface, &scan_info))) + &parser.shader_desc, compiler_options, shader_interface, compile_args, &scan_info))) { ERR("Failed to create DXBC compiler.\n"); vkd3d_shader_parser_destroy(&parser); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 45af2db4..4aeeb50e 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -780,6 +780,7 @@ struct vkd3d_dxbc_compiler; struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_desc *shader_desc, uint32_t compiler_options, const struct vkd3d_shader_interface *shader_interface, + const struct vkd3d_shader_compile_arguments *compile_args, const struct vkd3d_shader_scan_info *scan_info) DECLSPEC_HIDDEN; void vkd3d_dxbc_compiler_handle_instruction(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_instruction *instruction) DECLSPEC_HIDDEN; @@ -850,18 +851,6 @@ static inline unsigned int vkd3d_write_mask_component_count(DWORD write_mask) return count; } -/* swizzle bits fields: wwzzyyxx */ -#define VKD3D_SWIZZLE_X (0u) -#define VKD3D_SWIZZLE_Y (1u) -#define VKD3D_SWIZZLE_Z (2u) -#define VKD3D_SWIZZLE_W (3u) -#define VKD3D_SWIZZLE_MASK (0x3u) -#define VKD3D_SWIZZLE_SHIFT(idx) (2u * (idx)) -#define VKD3D_NO_SWIZZLE ((VKD3D_SWIZZLE_X << VKD3D_SWIZZLE_SHIFT(0)) \ - | (VKD3D_SWIZZLE_Y << VKD3D_SWIZZLE_SHIFT(1)) \ - | (VKD3D_SWIZZLE_Z << VKD3D_SWIZZLE_SHIFT(2)) \ - | (VKD3D_SWIZZLE_W << VKD3D_SWIZZLE_SHIFT(3))) - static inline unsigned int vkd3d_swizzle_get_component(DWORD swizzle, unsigned int idx) { diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 4841b0de..826d68f6 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1284,7 +1284,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, shader_desc.flags = 0; dump_shader_stage(stage, code->pShaderBytecode, code->BytecodeLength); - if ((ret = vkd3d_shader_compile_dxbc(&dxbc, &spirv, 0, shader_interface)) < 0) + if ((ret = vkd3d_shader_compile_dxbc(&dxbc, &spirv, 0, shader_interface, NULL)) < 0) { WARN("Failed to compile shader, vkd3d result %d.\n", ret); return hresult_from_vkd3d_result(ret); diff --git a/programs/vkd3d-compiler/main.c b/programs/vkd3d-compiler/main.c index 2e656688..83ccd3d6 100644 --- a/programs/vkd3d-compiler/main.c +++ b/programs/vkd3d-compiler/main.c @@ -163,7 +163,7 @@ int main(int argc, char **argv) return 1; } - hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, options.compiler_options, NULL); + hr = vkd3d_shader_compile_dxbc(&dxbc, &spirv, options.compiler_options, NULL, NULL); vkd3d_shader_free_shader_code(&dxbc); if (FAILED(hr)) {