diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 4a14846861..ba1ed8808a 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -462,7 +462,11 @@ enum vkd3d_shader_quirk /* Works around cases where app is relying on coherency between threads in a workgroup, * but forgets to use Device memory barriers properly. */ - VKD3D_SHADER_QUIRK_FORCE_DEVICE_MEMORY_BARRIER_THREAD_GROUP_COHERENCY = (1 << 21) + VKD3D_SHADER_QUIRK_FORCE_DEVICE_MEMORY_BARRIER_THREAD_GROUP_COHERENCY = (1 << 21), + + /* Extremely specific workaround for cubemap importance sampling pass. + * The lowest res mips may contain garbage. */ + VKD3D_SHADER_QUIRK_ASSUME_BROKEN_SUB_8x8_CUBE_MIPS = (1 << 22) }; struct vkd3d_shader_quirk_hash diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index c14ff4f7e3..df6c45fe0e 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -1116,6 +1116,20 @@ int vkd3d_shader_compile_dxil(const struct vkd3d_shader_code *dxbc, } } + if (quirks & VKD3D_SHADER_QUIRK_ASSUME_BROKEN_SUB_8x8_CUBE_MIPS) + { + const dxil_spv_option_shader_quirk helper = + { { DXIL_SPV_OPTION_SHADER_QUIRK }, + DXIL_SPV_SHADER_QUIRK_ASSUME_BROKEN_SUB_8x8_CUBE_MIPS }; + + if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS) + { + ERR("dxil-spirv does not support SHADER_QUIRK.\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; @@ -1618,6 +1632,20 @@ int vkd3d_shader_compile_dxil_export(const struct vkd3d_shader_code *dxil, } } + if (quirks & VKD3D_SHADER_QUIRK_ASSUME_BROKEN_SUB_8x8_CUBE_MIPS) + { + const dxil_spv_option_shader_quirk helper = + { { DXIL_SPV_OPTION_SHADER_QUIRK }, + DXIL_SPV_SHADER_QUIRK_ASSUME_BROKEN_SUB_8x8_CUBE_MIPS }; + + if (dxil_spv_converter_add_option(converter, &helper.base) != DXIL_SPV_SUCCESS) + { + ERR("dxil-spirv does not support SHADER_QUIRK.\n"); + ret = VKD3D_ERROR_NOT_IMPLEMENTED; + goto end; + } + } + if (compiler_args) { for (i = 0; i < compiler_args->target_extension_count; i++) diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 167f126a92..3ca4eed4b8 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -739,6 +739,17 @@ static const struct vkd3d_shader_quirk_info veilguard_quirks = { NULL, 0, VKD3D_SHADER_QUIRK_FORCE_DEVICE_MEMORY_BARRIER_THREAD_GROUP_COHERENCY, }; +static const struct vkd3d_shader_quirk_hash tfd_hashes[] = { + /* ReflectionCaptureFilteredImportanceSamplingCS is somewhat broken as it assumes + * that the lowest res mips are valid, but they are never written to by ReflectionCaptureGenerateMipmapCS. + * It stops at 8x8 (the workgroup size). The workaround just clamps the explicit LOD to whatever mips is 8x8. */ + { 0x74b8eaf23e3d166c, VKD3D_SHADER_QUIRK_ASSUME_BROKEN_SUB_8x8_CUBE_MIPS }, +}; + +static const struct vkd3d_shader_quirk_info tfd_quirks = { + tfd_hashes, ARRAY_SIZE(tfd_hashes), 0, +}; + static const struct vkd3d_shader_quirk_meta application_shader_quirks[] = { /* F1 2020 (1080110) */ { VKD3D_STRING_COMPARE_EXACT, "F1_2020_dx12.exe", &f1_2019_2020_quirks }, @@ -769,6 +780,8 @@ static const struct vkd3d_shader_quirk_meta application_shader_quirks[] = { { VKD3D_STRING_COMPARE_EXACT, "HuntGame.exe", &hunt_quirks }, /* Dragon Age: The Veilguard (1845910) */ { VKD3D_STRING_COMPARE_EXACT, "Dragon Age The Veilguard.exe", &veilguard_quirks }, + /* The First Descendant (2074920) */ + { VKD3D_STRING_COMPARE_EXACT, "M1-Win64-Shipping.exe", &tfd_quirks }, /* Unreal Engine 4 */ { VKD3D_STRING_COMPARE_ENDS_WITH, "-Shipping.exe", &ue4_quirks }, /* MSVC fails to compile empty array. */