1
0
Fork 0
forked from suyu/suyu

GPU: Partial implementation of long GPU queries.

Long queries write a 128-bit result value to memory, which consists of a 64 bit query value and a 64 bit timestamp.

In this implementation, only select=Zero of the Crop unit is implemented, this writes the query sequence as a 64 bit value, and a 0u64 value for the timestamp, since we emulate an infinitely fast GPU.

This specific type was hwtested, but more rigorous tests should be performed in the future for the other types.
This commit is contained in:
Subv 2018-06-03 19:17:31 -05:00
parent bbbe34429e
commit d57333406d

View file

@ -156,16 +156,15 @@ void Maxwell3D::ProcessQueryGet() {
// TODO(Subv): Support the other query units. // TODO(Subv): Support the other query units.
ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop, ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop,
"Units other than CROP are unimplemented"); "Units other than CROP are unimplemented");
ASSERT_MSG(regs.query.query_get.short_query,
"Writing the entire query result structure is unimplemented");
u32 value = Memory::Read32(*address); u32 value = Memory::Read32(*address);
u32 result = 0; u64 result = 0;
// TODO(Subv): Support the other query variables // TODO(Subv): Support the other query variables
switch (regs.query.query_get.select) { switch (regs.query.query_get.select) {
case Regs::QuerySelect::Zero: case Regs::QuerySelect::Zero:
result = 0; // This seems to actually write the query sequence to the query address.
result = regs.query.query_sequence;
break; break;
default: default:
UNIMPLEMENTED_MSG("Unimplemented query select type {}", UNIMPLEMENTED_MSG("Unimplemented query select type {}",
@ -174,15 +173,31 @@ void Maxwell3D::ProcessQueryGet() {
// TODO(Subv): Research and implement how query sync conditions work. // TODO(Subv): Research and implement how query sync conditions work.
struct LongQueryResult {
u64_le value;
u64_le timestamp;
};
static_assert(sizeof(LongQueryResult) == 16, "LongQueryResult has wrong size");
switch (regs.query.query_get.mode) { switch (regs.query.query_get.mode) {
case Regs::QueryMode::Write: case Regs::QueryMode::Write:
case Regs::QueryMode::Write2: { case Regs::QueryMode::Write2: {
// Write the current query sequence to the sequence address.
u32 sequence = regs.query.query_sequence; u32 sequence = regs.query.query_sequence;
Memory::Write32(*address, sequence); if (regs.query.query_get.short_query) {
// Write the current query sequence to the sequence address.
// TODO(Subv): Write the proper query response structure to the address when not using short // TODO(Subv): Find out what happens if you use a long query type but mark it as a short
// mode. // query.
Memory::Write32(*address, sequence);
} else {
// Write the 128-bit result structure in long mode. Note: We emulate an infinitely fast
// GPU, this command may actually take a while to complete in real hardware due to GPU
// wait queues.
LongQueryResult query_result{};
query_result.value = result;
// TODO(Subv): Generate a real GPU timestamp and write it here instead of 0
query_result.timestamp = 0;
Memory::WriteBlock(*address, &query_result, sizeof(query_result));
}
break; break;
} }
default: default: