llvmpipe: fix occlusion queries with early depth test

for genuine early depth tests, the samplecount must be updated after depth
test but before samplemask is applied

for inferred-early or regular depth tests, the samplemask can be applied
before the depth test

Fixes: d9276ae965 ("llvmpipe: handle gl_SampleMask writing.")

fixes:
dEQP-VK.fragment_operations.early_fragment.sample_count_early_fragment_tests_depth_samples_4

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15319>
(cherry picked from commit 42e78ba125)
This commit is contained in:
Mike Blumenkrantz 2022-03-09 11:48:51 -05:00 committed by Eric Engestrom
parent 518d3be130
commit 6af52034b2
2 changed files with 25 additions and 5 deletions

View file

@ -355,7 +355,7 @@
"description": "llvmpipe: fix occlusion queries with early depth test",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "d9276ae965aadf967ee8f2ca85dab1dd31881919"
},

View file

@ -304,6 +304,7 @@ generate_quad_mask(struct gallivm_state *gallivm,
#define LATE_DEPTH_TEST 0x2
#define EARLY_DEPTH_WRITE 0x4
#define LATE_DEPTH_WRITE 0x8
#define EARLY_DEPTH_TEST_INFERRED 0x10 //only with EARLY_DEPTH_TEST
static int
find_output_by_semantic( const struct tgsi_shader_info *info,
@ -647,10 +648,10 @@ generate_fs_loop(struct gallivm_state *gallivm,
key->stencil[1].writemask)))
depth_mode = LATE_DEPTH_TEST | LATE_DEPTH_WRITE;
else
depth_mode = EARLY_DEPTH_TEST | LATE_DEPTH_WRITE;
depth_mode = EARLY_DEPTH_TEST | LATE_DEPTH_WRITE | EARLY_DEPTH_TEST_INFERRED;
}
else
depth_mode = EARLY_DEPTH_TEST | EARLY_DEPTH_WRITE;
depth_mode = EARLY_DEPTH_TEST | EARLY_DEPTH_WRITE | EARLY_DEPTH_TEST_INFERRED;
}
else {
depth_mode = LATE_DEPTH_TEST | LATE_DEPTH_WRITE;
@ -1141,8 +1142,10 @@ generate_fs_loop(struct gallivm_state *gallivm,
if (key->min_samples == 1)
s_mask = LLVMBuildAnd(builder, s_mask, lp_build_mask_value(&mask), "");
/* if the shader writes sample mask use that */
if (shader->info.base.writes_samplemask) {
/* if the shader writes sample mask use that,
* but only if this isn't genuine early-depth to avoid breaking occlusion query */
if (shader->info.base.writes_samplemask &&
(!(depth_mode & EARLY_DEPTH_TEST) || (depth_mode & (EARLY_DEPTH_TEST_INFERRED)))) {
LLVMValueRef out_smask_idx = LLVMBuildShl(builder, lp_build_const_int32(gallivm, 1), sample_loop_state.counter, "");
out_smask_idx = lp_build_broadcast(gallivm, int_vec_type, out_smask_idx);
LLVMValueRef output_smask = LLVMBuildLoad(builder, out_sample_mask_storage, "");
@ -1258,6 +1261,23 @@ generate_fs_loop(struct gallivm_state *gallivm,
key->multisample ? s_mask : lp_build_mask_value(&mask), counter);
}
/* if this is genuine early-depth in the shader, write samplemask now
* after occlusion count has been updated
*/
if (key->multisample && shader->info.base.writes_samplemask &&
(depth_mode & (EARLY_DEPTH_TEST_INFERRED | EARLY_DEPTH_TEST)) == EARLY_DEPTH_TEST) {
/* if the shader writes sample mask use that */
LLVMValueRef out_smask_idx = LLVMBuildShl(builder, lp_build_const_int32(gallivm, 1), sample_loop_state.counter, "");
out_smask_idx = lp_build_broadcast(gallivm, int_vec_type, out_smask_idx);
LLVMValueRef output_smask = LLVMBuildLoad(builder, out_sample_mask_storage, "");
LLVMValueRef smask_bit = LLVMBuildAnd(builder, output_smask, out_smask_idx, "");
LLVMValueRef cmp = LLVMBuildICmp(builder, LLVMIntNE, smask_bit, lp_build_const_int_vec(gallivm, int_type, 0), "");
smask_bit = LLVMBuildSExt(builder, cmp, int_vec_type, "");
s_mask = LLVMBuildAnd(builder, s_mask, smask_bit, "");
}
if (key->multisample) {
/* store the sample mask for this loop */
LLVMBuildStore(builder, s_mask, s_mask_ptr);