vkd3d-shader: Add interface for shader workarounds.

Don't really have much of a choice for the short term. :\

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-06-16 16:52:00 +02:00
parent 4c101a4e81
commit a08e493a3a
2 changed files with 49 additions and 0 deletions

View File

@ -284,6 +284,32 @@ enum vkd3d_shader_target_extension
VKD3D_SHADER_TARGET_EXTENSION_READ_STORAGE_IMAGE_WITHOUT_FORMAT
};
enum vkd3d_shader_quirk
{
/* If sample or sample_b is used in control flow, force LOD 0.0 (which game should expect anyway).
* Works around specific, questionable shaders which rely on this to give sensible results,
* since LOD can become garbage on certain implementations, and even on native drivers
* the result is implementation defined.
* Outside of making this edge case well-defined in Vulkan or hacking driver compilers,
* this is the pragmatic solution.
* Hoisting gradients is not possible in all cases,
* and would not be worth it until it's a widespread problem. */
VKD3D_SHADER_QUIRK_FORCE_EXPLICIT_LOD_IN_CONTROL_FLOW = (1 << 0)
};
struct vkd3d_shader_quirk_hash
{
vkd3d_shader_hash_t shader_hash;
uint32_t quirks;
};
struct vkd3d_shader_quirk_info
{
const struct vkd3d_shader_quirk_hash *hashes;
unsigned int num_hashes;
uint32_t default_quirks;
};
struct vkd3d_shader_compile_arguments
{
enum vkd3d_shader_target target;
@ -299,6 +325,7 @@ struct vkd3d_shader_compile_arguments
unsigned int output_swizzle_count;
uint64_t config_flags;
const struct vkd3d_shader_quirk_info *quirks;
};
enum vkd3d_tessellator_output_primitive

View File

@ -2241,6 +2241,7 @@ struct vkd3d_dxbc_compiler
struct vkd3d_spirv_builder spirv_builder;
uint32_t options;
uint32_t quirks;
struct rb_tree symbol_table;
uint32_t temp_id;
@ -2350,6 +2351,21 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
compiler->shader_version = *shader_version;
compiler->descriptor_qa_shader_hash = shader_hash;
if (compile_args && compile_args->quirks)
{
for (i = 0; i < compile_args->quirks->num_hashes; i++)
{
if (compile_args->quirks->hashes[i].shader_hash == shader_hash)
{
compiler->quirks = compile_args->quirks->hashes[i].quirks;
break;
}
}
if (i == compile_args->quirks->num_hashes)
compiler->quirks = compile_args->quirks->default_quirks;
}
max_element_count = max(output_signature->element_count, patch_constant_signature->element_count);
if (!(compiler->output_info = vkd3d_calloc(max_element_count, sizeof(*compiler->output_info))))
{
@ -9023,6 +9039,12 @@ 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)
{