diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index e45f7b4a9b..58c8c9374a 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -34,7 +34,7 @@ GPU::GPU(VideoCore::RasterizerInterface& rasterizer) { maxwell_compute = std::make_unique(); maxwell_dma = std::make_unique(rasterizer, *memory_manager); kepler_memory = std::make_unique(rasterizer, *memory_manager); - pullerState.semaphore_off_val = true; + regs.semaphore_off_val = true; } GPU::~GPU() = default; @@ -285,25 +285,25 @@ void GPU::ProcessSemaphoreTriggerMethod() { // CoreTiming const auto acquire_timestamp = CoreTiming::GetTicks(); if (op == GpuSemaphoreOperation::WriteLong) { - Memory::Write32(pullerState.semaphore.SmaphoreAddress(), sequence); - Memory::Write32(pullerState.semaphore.SmaphoreAddress() + 0x4, 0); - Memory::Write64(pullerState.semaphore.SmaphoreAddress() + 0x8, acquire_timestamp); + Memory::Write32(regs.smaphore_address.SmaphoreAddress(), sequence); + Memory::Write32(regs.smaphore_address.SmaphoreAddress() + 0x4, 0); + Memory::Write64(regs.smaphore_address.SmaphoreAddress() + 0x8, acquire_timestamp); } else { - const u32 word = Memory::Read32(pullerState.semaphore.SmaphoreAddress()); - if ((op == GpuSemaphoreOperation::AcquireEqual && word == pullerState.semaphore_sequence) || + const u32 word = Memory::Read32(regs.smaphore_address.SmaphoreAddress()); + if ((op == GpuSemaphoreOperation::AcquireEqual && word == regs.semaphore_sequence) || (op == GpuSemaphoreOperation::AcquireGequal && - static_cast(word - pullerState.semaphore_sequence) > 0) || - (op == GpuSemaphoreOperation::AcquireMask && (word & pullerState.semaphore_sequence))) { + static_cast(word - regs.semaphore_sequence) > 0) || + (op == GpuSemaphoreOperation::AcquireMask && (word & regs.semaphore_sequence))) { // Nothing to do in this case } else { - pullerState.acquire_source = true; - pullerState.acquire_value = pullerState.semaphore_sequence; + regs.acquire_source = true; + regs.acquire_value = regs.semaphore_sequence; if (op == GpuSemaphoreOperation::AcquireEqual) { - pullerState.acquire_active = true; - pullerState.acquire_mode = false; + regs.acquire_active = true; + regs.acquire_mode = false; } else if (op == GpuSemaphoreOperation::AcquireGequal) { - pullerState.acquire_active = true; - pullerState.acquire_mode = true; + regs.acquire_active = true; + regs.acquire_mode = true; } else if (op == GpuSemaphoreOperation::AcquireMask) { // TODO(kemathe) The acquire mask operation waits for a value that, ANDed with // semaphore_sequence, gives a non-0 result @@ -316,27 +316,27 @@ void GPU::ProcessSemaphoreTriggerMethod() { } void GPU::ProcessSemaphoreRelease() { - if (!pullerState.semaphore_off_val) { + if (!regs.semaphore_off_val) { LOG_ERROR(HW_GPU, "Semaphore can't be released since it is not currently been acquired"); return; } - Memory::Write32(pullerState.semaphore.SmaphoreAddress(), + Memory::Write32(regs.smaphore_address.SmaphoreAddress(), regs.reg_array[static_cast(BufferMethods::SemaphoreRelease)]); } void GPU::ProcessSemaphoreAcquire() { - if (!pullerState.semaphore_off_val) { + if (!regs.semaphore_off_val) { LOG_ERROR(HW_GPU, "Semaphore has already be acquired"); return; } - const u32 word = Memory::Read32(pullerState.semaphore.SmaphoreAddress()); + const u32 word = Memory::Read32(regs.smaphore_address.SmaphoreAddress()); const auto value = regs.reg_array[static_cast(BufferMethods::SemaphoreAcquire)]; if (word != value) { - pullerState.acquire_active = true; - pullerState.acquire_value = value; + regs.acquire_active = true; + regs.acquire_value = value; // TODO(kemathe73) figure out how to do the acquire_timeout - pullerState.acquire_mode = false; - pullerState.acquire_source = false; + regs.acquire_mode = false; + regs.acquire_source = false; } } void GPU::ProcessSetSemaphoreAddressHigh() { @@ -346,7 +346,7 @@ void GPU::ProcessSetSemaphoreAddressHigh() { LOG_ERROR(HW_GPU, "SemaphoreAddressHigh too large"); return; } - pullerState.semaphore.smaphore_address_high = addrHigh; + regs.smaphore_address.smaphore_address_high = addrHigh; } void GPU::ProcessSetSemaphoreAddressLow() { const auto addrLow = regs.reg_array[static_cast(BufferMethods::SemaphoreAddressLow)]; @@ -355,21 +355,17 @@ void GPU::ProcessSetSemaphoreAddressLow() { LOG_ERROR(HW_GPU, "SemaphoreAddressLow unaligned"); return; } - pullerState.semaphore.smaphore_address_low = addrLow; + regs.smaphore_address.smaphore_address_low = addrLow; } void GPU::SetReferenceCount() { // TODO(kmather73) Wait for all previously submitted commands complete before setting. - pullerState.reference_count = regs.reg_array[static_cast(BufferMethods::RefCnt)]; + regs.reference_count = regs.reg_array[static_cast(BufferMethods::RefCnt)]; } void GPU::ProcessSetSemaphoreSequence() { - pullerState.semaphore_sequence = + regs.semaphore_sequence = regs.reg_array[static_cast(BufferMethods::SemaphoreSequence)]; } -const u32 GPU::ReferenceCount() const { - return pullerState.reference_count; -} - } // namespace Tegra diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 863351111d..bd8fe3b18d 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -156,8 +156,36 @@ public: /// Returns a const reference to the GPU DMA pusher. const Tegra::DmaPusher& DmaPusher() const; - // The puser and the puller share the reference counter, the pusher only had read access - const u32 ReferenceCount() const; + struct Regs { + static constexpr size_t NUM_REGS = 0x140; + + union { + struct { + u32 acquire_mode; + u32 acquire_source; + // The puser and the puller share the reference counter, the pusher only has read + // access + u32 reference_count; + u32 acquire_active; + u32 acquire_timeout; + u32 acquire_value; + u32 semaphore_off_val; + u32 semaphore_sequence; + + struct { + u32 smaphore_address_high; + u32 smaphore_address_low; + + GPUVAddr SmaphoreAddress() const { + return static_cast( + (static_cast(smaphore_address_high) << 32) | + smaphore_address_low); + } + } smaphore_address; + }; + std::array reg_array; + }; + } regs{}; private: std::unique_ptr dma_pusher; @@ -177,34 +205,6 @@ private: /// Inline memory engine std::unique_ptr kepler_memory; - struct Regs { - static constexpr size_t NUM_REGS = 0x40; - - union { - std::array reg_array; - }; - } regs{}; - - struct { - u32 reference_count; - bool acquire_active; - u32 acquire_timeout; - u32 acquire_value; - bool semaphore_off_val; - struct { - u8 smaphore_address_high; - u32 smaphore_address_low; - - GPUVAddr SmaphoreAddress() const { - return static_cast((static_cast(smaphore_address_high) << 32) | - smaphore_address_low); - } - } semaphore; - u32 semaphore_sequence; - bool acquire_mode; - bool acquire_source; - } pullerState{}; - void ProcessBindMethod(const MethodCall& method_call); void ProcessSemaphoreTriggerMethod(); void ProcessSemaphoreRelease(); @@ -222,4 +222,19 @@ private: bool ExecuteMethodOnEngine(const MethodCall& method_call); }; +#define ASSERT_REG_POSITION(field_name, position) \ + static_assert(offsetof(GPU::Regs, field_name) == position * 4, \ + "Field " #field_name " has invalid position") + +ASSERT_REG_POSITION(acquire_mode, 0x0); +ASSERT_REG_POSITION(acquire_source, 0x1); +ASSERT_REG_POSITION(reference_count, 0x2); +ASSERT_REG_POSITION(acquire_active, 0x3); +ASSERT_REG_POSITION(acquire_timeout, 0x4); +ASSERT_REG_POSITION(acquire_value, 0x5); +ASSERT_REG_POSITION(semaphore_off_val, 0x6); +ASSERT_REG_POSITION(semaphore_sequence, 0x7); +ASSERT_REG_POSITION(smaphore_address, 0x8); +#undef ASSERT_REG_POSITION + } // namespace Tegra