diff options
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 23e70cd8a..ef12d9300 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -156,16 +156,15 @@ void Maxwell3D::ProcessQueryGet() { | |||
| 156 | // TODO(Subv): Support the other query units. | 156 | // TODO(Subv): Support the other query units. |
| 157 | ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop, | 157 | ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop, |
| 158 | "Units other than CROP are unimplemented"); | 158 | "Units other than CROP are unimplemented"); |
| 159 | ASSERT_MSG(regs.query.query_get.short_query, | ||
| 160 | "Writing the entire query result structure is unimplemented"); | ||
| 161 | 159 | ||
| 162 | u32 value = Memory::Read32(*address); | 160 | u32 value = Memory::Read32(*address); |
| 163 | u32 result = 0; | 161 | u64 result = 0; |
| 164 | 162 | ||
| 165 | // TODO(Subv): Support the other query variables | 163 | // TODO(Subv): Support the other query variables |
| 166 | switch (regs.query.query_get.select) { | 164 | switch (regs.query.query_get.select) { |
| 167 | case Regs::QuerySelect::Zero: | 165 | case Regs::QuerySelect::Zero: |
| 168 | result = 0; | 166 | // This seems to actually write the query sequence to the query address. |
| 167 | result = regs.query.query_sequence; | ||
| 169 | break; | 168 | break; |
| 170 | default: | 169 | default: |
| 171 | UNIMPLEMENTED_MSG("Unimplemented query select type {}", | 170 | UNIMPLEMENTED_MSG("Unimplemented query select type {}", |
| @@ -174,15 +173,31 @@ void Maxwell3D::ProcessQueryGet() { | |||
| 174 | 173 | ||
| 175 | // TODO(Subv): Research and implement how query sync conditions work. | 174 | // TODO(Subv): Research and implement how query sync conditions work. |
| 176 | 175 | ||
| 176 | struct LongQueryResult { | ||
| 177 | u64_le value; | ||
| 178 | u64_le timestamp; | ||
| 179 | }; | ||
| 180 | static_assert(sizeof(LongQueryResult) == 16, "LongQueryResult has wrong size"); | ||
| 181 | |||
| 177 | switch (regs.query.query_get.mode) { | 182 | switch (regs.query.query_get.mode) { |
| 178 | case Regs::QueryMode::Write: | 183 | case Regs::QueryMode::Write: |
| 179 | case Regs::QueryMode::Write2: { | 184 | case Regs::QueryMode::Write2: { |
| 180 | // Write the current query sequence to the sequence address. | ||
| 181 | u32 sequence = regs.query.query_sequence; | 185 | u32 sequence = regs.query.query_sequence; |
| 182 | Memory::Write32(*address, sequence); | 186 | if (regs.query.query_get.short_query) { |
| 183 | 187 | // Write the current query sequence to the sequence address. | |
| 184 | // TODO(Subv): Write the proper query response structure to the address when not using short | 188 | // TODO(Subv): Find out what happens if you use a long query type but mark it as a short |
| 185 | // mode. | 189 | // query. |
| 190 | Memory::Write32(*address, sequence); | ||
| 191 | } else { | ||
| 192 | // Write the 128-bit result structure in long mode. Note: We emulate an infinitely fast | ||
| 193 | // GPU, this command may actually take a while to complete in real hardware due to GPU | ||
| 194 | // wait queues. | ||
| 195 | LongQueryResult query_result{}; | ||
| 196 | query_result.value = result; | ||
| 197 | // TODO(Subv): Generate a real GPU timestamp and write it here instead of 0 | ||
| 198 | query_result.timestamp = 0; | ||
| 199 | Memory::WriteBlock(*address, &query_result, sizeof(query_result)); | ||
| 200 | } | ||
| 186 | break; | 201 | break; |
| 187 | } | 202 | } |
| 188 | default: | 203 | default: |