[GPU] Add workaround for occlusion queries.

This commit is contained in:
Joel Linn 2020-06-01 14:00:22 +02:00 committed by Rick Gibbed
parent aa73d652ba
commit 68dd818029
4 changed files with 42 additions and 4 deletions

View File

@ -1145,9 +1145,24 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_ZPD(RingBuffer* reader,
// Writeback initiator. // Writeback initiator.
WriteRegister(XE_GPU_REG_VGT_EVENT_INITIATOR, initiator & 0x3F); WriteRegister(XE_GPU_REG_VGT_EVENT_INITIATOR, initiator & 0x3F);
// TODO: Flag the backend CP to write out zpass counters to // Occlusion queries:
// REG_RB_SAMPLE_COUNT_ADDR (probably # pixels passed depth test). // This command is send on query begin and end.
// This applies to the last draw, I believe. // As a workaround report some fixed amount of passed samples.
auto fake_sample_count = cvars::query_occlusion_fake_sample_count;
if (fake_sample_count >= 0) {
auto* pSampleCounts =
memory_->TranslatePhysical<xe_gpu_depth_sample_counts*>(
register_file_->values[XE_GPU_REG_RB_SAMPLE_COUNT_ADDR].u32);
// 0xFFFFFEED is written to this two locations by D3D only on D3DISSUE_END
// and used to detect a finished query.
bool isEnd = pSampleCounts->ZPass_A == xe::byte_swap(0xFFFFFEED) &&
pSampleCounts->ZPass_B == xe::byte_swap(0xFFFFFEED);
std::memset(pSampleCounts, 0, sizeof(xe_gpu_depth_sample_counts));
if (isEnd) {
pSampleCounts->ZPass_A = fake_sample_count;
pSampleCounts->Total_A = fake_sample_count;
}
}
return true; return true;
} }

View File

@ -27,3 +27,10 @@ DEFINE_bool(
"may be used to bypass fetch constant type errors in certain games until " "may be used to bypass fetch constant type errors in certain games until "
"the real reason why they're invalid is found.", "the real reason why they're invalid is found.",
"GPU"); "GPU");
DEFINE_int32(query_occlusion_fake_sample_count, 1000,
"If set to -1 no sample counts are written, games may hang. Else, "
"the sample count of every tile will be incremented on every "
"EVENT_WRITE_ZPD by this number. Setting this to 0 means "
"everything is reported as occluded.",
"GPU");

View File

@ -20,4 +20,6 @@ DECLARE_bool(vsync);
DECLARE_bool(gpu_allow_invalid_fetch_constants); DECLARE_bool(gpu_allow_invalid_fetch_constants);
DECLARE_int32(query_occlusion_fake_sample_count);
#endif // XENIA_GPU_GPU_FLAGS_H_ #endif // XENIA_GPU_GPU_FLAGS_H_

View File

@ -2,7 +2,7 @@
****************************************************************************** ******************************************************************************
* Xenia : Xbox 360 Emulator Research Project * * Xenia : Xbox 360 Emulator Research Project *
****************************************************************************** ******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. * * Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. * * Released under the BSD license - see LICENSE in the root for more details. *
****************************************************************************** ******************************************************************************
*/ */
@ -849,6 +849,20 @@ XEPACKEDUNION(xe_gpu_memexport_stream_t, {
}); });
}); });
XEPACKEDSTRUCT(xe_gpu_depth_sample_counts, {
// This is little endian as it is swapped in D3D code.
// Corresponding A and B values are summed up by D3D.
// Occlusion there is calculated by substracting begin from end struct.
uint32_t Total_A;
uint32_t Total_B;
uint32_t ZFail_A;
uint32_t ZFail_B;
uint32_t ZPass_A;
uint32_t ZPass_B;
uint32_t StencilFail_A;
uint32_t StencilFail_B;
});
// Enum of event values used for VGT_EVENT_INITIATOR // Enum of event values used for VGT_EVENT_INITIATOR
enum Event { enum Event {
VS_DEALLOC = 0, VS_DEALLOC = 0,