Maxwell3D: Correct query reporting.
This commit is contained in:
		
				
					committed by
					
						 FernandoS27
						FernandoS27
					
				
			
			
				
	
			
			
			
						parent
						
							84ea9c2b42
						
					
				
				
					commit
					0cb3bcfbb7
				
			| @@ -519,61 +519,66 @@ void Maxwell3D::ProcessFirmwareCall4() { | ||||
|     regs.reg_array[0xd00] = 1; | ||||
| } | ||||
|  | ||||
| void Maxwell3D::ProcessQueryGet() { | ||||
|     const GPUVAddr sequence_address{regs.query.QueryAddress()}; | ||||
|     // Since the sequence address is given as a GPU VAddr, we have to convert it to an application | ||||
|     // VAddr before writing. | ||||
|  | ||||
|     // TODO(Subv): Support the other query units. | ||||
|     ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop, | ||||
|                "Units other than CROP are unimplemented"); | ||||
|  | ||||
|     u64 result = 0; | ||||
|  | ||||
|     // TODO(Subv): Support the other query variables | ||||
|     switch (regs.query.query_get.select) { | ||||
|     case Regs::QuerySelect::Zero: | ||||
|         // This seems to actually write the query sequence to the query address. | ||||
|         result = regs.query.query_sequence; | ||||
|         break; | ||||
|     default: | ||||
|         result = 1; | ||||
|         UNIMPLEMENTED_MSG("Unimplemented query select type {}", | ||||
|                           static_cast<u32>(regs.query.query_get.select.Value())); | ||||
|     } | ||||
|  | ||||
|     // TODO(Subv): Research and implement how query sync conditions work. | ||||
|  | ||||
| void Maxwell3D::StampQueryResult(u64 payload, bool long_query) { | ||||
|     struct LongQueryResult { | ||||
|         u64_le value; | ||||
|         u64_le timestamp; | ||||
|     }; | ||||
|     static_assert(sizeof(LongQueryResult) == 16, "LongQueryResult has wrong size"); | ||||
|     const GPUVAddr sequence_address{regs.query.QueryAddress()}; | ||||
|     if (long_query) { | ||||
|         // 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 = payload; | ||||
|         // TODO(Subv): Generate a real GPU timestamp and write it here instead of CoreTiming | ||||
|         query_result.timestamp = system.CoreTiming().GetTicks(); | ||||
|         memory_manager.WriteBlock(sequence_address, &query_result, sizeof(query_result)); | ||||
|     } else { | ||||
|         memory_manager.Write<u32>(sequence_address, static_cast<u32>(payload)); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     switch (regs.query.query_get.mode) { | ||||
|     case Regs::QueryMode::Write: | ||||
|     case Regs::QueryMode::Write2: { | ||||
|         u32 sequence = regs.query.query_sequence; | ||||
|         if (regs.query.query_get.short_query) { | ||||
|             // Write the current query sequence to the sequence address. | ||||
|             // TODO(Subv): Find out what happens if you use a long query type but mark it as a short | ||||
|             // query. | ||||
|             memory_manager.Write<u32>(sequence_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 CoreTiming | ||||
|             query_result.timestamp = system.CoreTiming().GetTicks(); | ||||
|             memory_manager.WriteBlock(sequence_address, &query_result, sizeof(query_result)); | ||||
|         } | ||||
| void Maxwell3D::ProcessQueryGet() { | ||||
|     // TODO(Subv): Support the other query units. | ||||
|     ASSERT_MSG(regs.query.query_get.unit == Regs::QueryUnit::Crop, | ||||
|                "Units other than CROP are unimplemented"); | ||||
|  | ||||
|     switch (regs.query.query_get.operation) { | ||||
|     case Regs::QueryOperation::Release: { | ||||
|         u64 result = regs.query.query_sequence; | ||||
|         StampQueryResult(result, regs.query.query_get.short_query == 0); | ||||
|         break; | ||||
|     } | ||||
|     case Regs::QueryOperation::Acquire: { | ||||
|         // Todo(Blinkhawk): Under this operation, the GPU waits for the CPU | ||||
|         // to write a value that matches the current payload. | ||||
|         UNIMPLEMENTED_MSG("Unimplemented query operation ACQUIRE"); | ||||
|         break; | ||||
|     } | ||||
|     case Regs::QueryOperation::Counter: { | ||||
|         u64 result{}; | ||||
|         switch (regs.query.query_get.select) { | ||||
|         case Regs::QuerySelect::Zero: | ||||
|             result = 0; | ||||
|             break; | ||||
|         default: | ||||
|             result = 1; | ||||
|             UNIMPLEMENTED_MSG("Unimplemented query select type {}", | ||||
|                               static_cast<u32>(regs.query.query_get.select.Value())); | ||||
|         } | ||||
|         StampQueryResult(result, regs.query.query_get.short_query == 0); | ||||
|         break; | ||||
|     } | ||||
|     case Regs::QueryOperation::Trap: { | ||||
|         UNIMPLEMENTED_MSG("Unimplemented query operation TRAP"); | ||||
|         break; | ||||
|     } | ||||
|     default: { | ||||
|         UNIMPLEMENTED_MSG("Unknown query operation"); | ||||
|         break; | ||||
|     } | ||||
|     default: | ||||
|         UNIMPLEMENTED_MSG("Query mode {} not implemented", | ||||
|                           static_cast<u32>(regs.query.query_get.mode.Value())); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -71,12 +71,11 @@ public: | ||||
|         static constexpr std::size_t MaxConstBuffers = 18; | ||||
|         static constexpr std::size_t MaxConstBufferSize = 0x10000; | ||||
|  | ||||
|         enum class QueryMode : u32 { | ||||
|             Write = 0, | ||||
|             Sync = 1, | ||||
|             // TODO(Subv): It is currently unknown what the difference between method 2 and method 0 | ||||
|             // is. | ||||
|             Write2 = 2, | ||||
|         enum class QueryOperation : u32 { | ||||
|             Release = 0, | ||||
|             Acquire = 1, | ||||
|             Counter = 2, | ||||
|             Trap = 3, | ||||
|         }; | ||||
|  | ||||
|         enum class QueryUnit : u32 { | ||||
| @@ -1077,7 +1076,7 @@ public: | ||||
|                     u32 query_sequence; | ||||
|                     union { | ||||
|                         u32 raw; | ||||
|                         BitField<0, 2, QueryMode> mode; | ||||
|                         BitField<0, 2, QueryOperation> operation; | ||||
|                         BitField<4, 1, u32> fence; | ||||
|                         BitField<12, 4, QueryUnit> unit; | ||||
|                         BitField<16, 1, QuerySyncCondition> sync_cond; | ||||
| @@ -1409,6 +1408,9 @@ private: | ||||
|     /// Handles a write to the QUERY_GET register. | ||||
|     void ProcessQueryGet(); | ||||
|  | ||||
|     // Writes the query result accordingly | ||||
|     void StampQueryResult(u64 payload, bool long_query); | ||||
|  | ||||
|     // Handles Conditional Rendering | ||||
|     void ProcessQueryCondition(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user