vkd3d-shader: Opt-in to early fragment tests with descriptor QA.

Since we introduce side effects, avoid full late-Z for everything, which
is slow, and not necessarily correct either.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-05-19 17:02:38 +02:00
parent 077740f15c
commit a3fb2f1cd6
3 changed files with 55 additions and 0 deletions

View File

@ -587,6 +587,11 @@ struct vkd3d_shader_scan_info
{
struct hash_map register_map;
bool use_vocp;
bool early_fragment_tests;
bool has_side_effects;
bool needs_late_zs;
bool discards;
};
enum vkd3d_component_type

View File

@ -5626,6 +5626,14 @@ static void vkd3d_dxbc_compiler_emit_initial_declarations(struct vkd3d_dxbc_comp
case VKD3D_SHADER_TYPE_PIXEL:
vkd3d_spirv_set_execution_model(builder, SpvExecutionModelFragment);
vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeOriginUpperLeft, NULL, 0);
/* We introduce side effects into fragment shaders when we enable descriptor QA,
* so try to force EarlyFragmentTests if it's safe to do so. */
if ((compiler->shader_interface.flags & VKD3D_SHADER_INTERFACE_DESCRIPTOR_QA_BUFFER) &&
!compiler->scan_info->early_fragment_tests && !compiler->scan_info->has_side_effects &&
!compiler->scan_info->discards && !compiler->scan_info->needs_late_zs)
{
vkd3d_dxbc_compiler_emit_execution_mode(compiler, SpvExecutionModeEarlyFragmentTests, NULL, 0);
}
break;
case VKD3D_SHADER_TYPE_COMPUTE:
vkd3d_spirv_set_execution_model(builder, SpvExecutionModelGLCompute);

View File

@ -426,6 +426,16 @@ static bool vkd3d_shader_instruction_is_uav_read(const struct vkd3d_shader_instr
|| ((handler_idx == VKD3DSIH_LD_STRUCTURED || handler_idx == VKD3DSIH_LD_STRUCTURED_FEEDBACK) && instruction->src[2].reg.type == VKD3DSPR_UAV);
}
static bool vkd3d_shader_instruction_is_uav_write(const struct vkd3d_shader_instruction *instruction)
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx;
return (VKD3DSIH_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_ATOMIC_XOR)
|| (VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR)
|| handler_idx == VKD3DSIH_STORE_UAV_TYPED
|| handler_idx == VKD3DSIH_STORE_RAW
|| handler_idx == VKD3DSIH_STORE_STRUCTURED;
}
static bool vkd3d_shader_instruction_is_uav_atomic(const struct vkd3d_shader_instruction *instruction)
{
enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx;
@ -458,6 +468,7 @@ static bool vkd3d_shader_instruction_is_uav_counter(const struct vkd3d_shader_in
static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_info *scan_info,
const struct vkd3d_shader_register *reg)
{
scan_info->has_side_effects = true;
vkd3d_shader_scan_set_register_flags(scan_info, VKD3DSPR_UAV,
reg->idx[0].offset, VKD3D_SHADER_UAV_FLAG_ATOMIC_COUNTER);
}
@ -471,6 +482,24 @@ static void vkd3d_shader_scan_input_declaration(struct vkd3d_shader_scan_info *s
scan_info->use_vocp = true;
}
static void vkd3d_shader_scan_output_declaration(struct vkd3d_shader_scan_info *scan_info,
const struct vkd3d_shader_instruction *instruction)
{
switch (instruction->declaration.dst.reg.type)
{
case VKD3DSPR_DEPTHOUT:
case VKD3DSPR_DEPTHOUTLE:
case VKD3DSPR_DEPTHOUTGE:
case VKD3DSPR_STENCILREFOUT:
case VKD3DSPR_SAMPLEMASK:
scan_info->needs_late_zs = true;
break;
default:
break;
}
}
static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_info,
const struct vkd3d_shader_instruction *instruction)
{
@ -482,6 +511,16 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_in
case VKD3DSIH_DCL_INPUT:
vkd3d_shader_scan_input_declaration(scan_info, instruction);
break;
case VKD3DSIH_DCL_OUTPUT:
vkd3d_shader_scan_output_declaration(scan_info, instruction);
break;
case VKD3DSIH_DISCARD:
scan_info->discards = true;
break;
case VKD3DSIH_DCL_GLOBAL_FLAGS:
if (instruction->flags & VKD3DSGF_FORCE_EARLY_DEPTH_STENCIL)
scan_info->early_fragment_tests = true;
break;
default:
break;
}
@ -510,6 +549,9 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_in
}
}
if (vkd3d_shader_instruction_is_uav_write(instruction))
scan_info->has_side_effects = true;
if (vkd3d_shader_instruction_is_uav_counter(instruction))
vkd3d_shader_scan_record_uav_counter(scan_info, &instruction->src[0].reg);
}