diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 48218ff2..72aeb1d5 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -307,6 +307,10 @@ enum vkd3d_shader_quirk /* After every write to group shared memory, force a memory barrier. * This works around buggy games which forget to use barrier(). */ VKD3D_SHADER_QUIRK_FORCE_TGSM_BARRIERS = (1 << 1), + + /* For Position builtins in Output storage class, emit Invariant decoration. + * Normally, games have to emit Precise math for position, but if they forget ... */ + VKD3D_SHADER_QUIRK_INVARIANT_POSITION = (1 << 2), }; struct vkd3d_shader_quirk_hash diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 56c79fc8..2068a449 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -490,6 +490,7 @@ int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc, unsigned int i, max_size; vkd3d_shader_hash_t hash; int ret = VKD3D_OK; + uint32_t quirks; void *code; dxil_spv_set_thread_log_callback(vkd3d_dxil_log_callback, NULL); @@ -502,6 +503,7 @@ int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc, spirv->meta.replaced = true; return ret; } + quirks = vkd3d_shader_compile_arguments_select_quirks(compiler_args, hash); dxil_spv_begin_thread_allocator_context(); @@ -760,6 +762,18 @@ int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc, } } + if (quirks & VKD3D_SHADER_QUIRK_INVARIANT_POSITION) + { + const dxil_spv_option_invariant_position helper = + { { DXIL_SPV_OPTION_INVARIANT_POSITION }, DXIL_SPV_TRUE }; + if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS) + { + ERR("dxil-spirv does not support INVARIANT_POSITION.\n"); + ret = VKD3D_ERROR_NOT_IMPLEMENTED; + goto end; + } + } + remap_userdata.shader_interface_info = shader_interface_info; remap_userdata.shader_interface_local_info = NULL; remap_userdata.num_root_descriptors = num_root_descriptors; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index dc74e724..cbb0aa67 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -3845,8 +3845,14 @@ static void vkd3d_dxbc_compiler_emit_store_dst_scalar(struct vkd3d_dxbc_compiler vkd3d_dxbc_compiler_emit_store_dst_components(compiler, dst, component_type, component_ids); } +static bool vkd3d_dxbc_compiler_has_quirk(struct vkd3d_dxbc_compiler *compiler, + enum vkd3d_shader_quirk quirk) +{ + return !!(compiler->quirks & quirk); +} + static void vkd3d_dxbc_compiler_decorate_builtin(struct vkd3d_dxbc_compiler *compiler, - uint32_t target_id, SpvBuiltIn builtin) + uint32_t target_id, SpvBuiltIn builtin, SpvStorageClass storage_class) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -3883,6 +3889,13 @@ static void vkd3d_dxbc_compiler_decorate_builtin(struct vkd3d_dxbc_compiler *com case SpvBuiltInCullDistance: vkd3d_spirv_enable_capability(builder, SpvCapabilityCullDistance); break; + case SpvBuiltInPosition: + if (storage_class == SpvStorageClassOutput && + vkd3d_dxbc_compiler_has_quirk(compiler, VKD3D_SHADER_QUIRK_INVARIANT_POSITION)) + { + vkd3d_spirv_build_op_decorate(builder, target_id, SpvDecorationInvariant, NULL, 0); + } + break; default: break; } @@ -3961,7 +3974,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_draw_parameter_fixup(struct vkd3d_dxbc_ base_var_id = vkd3d_dxbc_compiler_emit_variable(compiler, &builder->global_stream, SpvStorageClassInput, VKD3D_TYPE_INT, 1); vkd3d_spirv_add_iface_variable(builder, base_var_id); - vkd3d_dxbc_compiler_decorate_builtin(compiler, base_var_id, base); + vkd3d_dxbc_compiler_decorate_builtin(compiler, base_var_id, base, SpvStorageClassInput); type_id = vkd3d_spirv_get_type_id(builder, VKD3D_TYPE_INT, 1); base_id = vkd3d_spirv_build_op_load(builder, @@ -4364,7 +4377,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_builtin_variable(struct vkd3d_dxbc_comp &builder->global_stream, storage_class, builtin->component_type, builtin->component_count, array_size); vkd3d_spirv_add_iface_variable(builder, id); - vkd3d_dxbc_compiler_decorate_builtin(compiler, id, builtin->spirv_builtin); + vkd3d_dxbc_compiler_decorate_builtin(compiler, id, builtin->spirv_builtin, storage_class); if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && storage_class == SpvStorageClassInput && builtin->component_type != VKD3D_TYPE_FLOAT && builtin->component_type != VKD3D_TYPE_BOOL) @@ -9065,12 +9078,6 @@ static void vkd3d_dxbc_compiler_emit_lod(struct vkd3d_dxbc_compiler *compiler, dst, val_id, image.sampled_type, resource->swizzle); } -static bool vkd3d_dxbc_compiler_has_quirk(struct vkd3d_dxbc_compiler *compiler, - enum vkd3d_shader_quirk quirk) -{ - return !!(compiler->quirks & quirk); -} - static void vkd3d_dxbc_compiler_emit_sample(struct vkd3d_dxbc_compiler *compiler, const struct vkd3d_shader_instruction *instruction) {