diff --git a/src/xenia/gpu/gl4/command_processor.cc b/src/xenia/gpu/gl4/command_processor.cc index 47b9e83e6..39204fd58 100644 --- a/src/xenia/gpu/gl4/command_processor.cc +++ b/src/xenia/gpu/gl4/command_processor.cc @@ -55,6 +55,7 @@ CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system) register_file_(graphics_system_->register_file()), trace_writer_(graphics_system->memory()->membase()), worker_running_(true), + swap_mode_(SwapMode::kNormal), time_base_(0), counter_(0), primary_buffer_ptr_(0), @@ -480,6 +481,45 @@ void CommandProcessor::ReturnFromWait() { } } +void CommandProcessor::IssueSwap() { + if (!swap_handler_) { + return; + } + + auto& regs = *register_file_; + SwapParameters swap_params; + + // Lookup the framebuffer in the recently-resolved list. + // TODO(benvanik): make this much more sophisticated. + // TODO(benvanik): handle not found cases. + // TODO(benvanik): handle dirty cases (resolved to sysmem, touched). + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // HACK: just use whatever our current framebuffer is. + if (active_framebuffer_) { + swap_params.framebuffer = active_framebuffer_->framebuffer; + // TODO(benvanik): pick the right one? + swap_params.attachment = GL_COLOR_ATTACHMENT0; + } else { + swap_params.framebuffer = 0; + } + + // Guess frontbuffer dimensions. + // Command buffer seems to set these right before the XE_SWAP. + uint32_t window_scissor_tl = regs[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL].u32; + uint32_t window_scissor_br = regs[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR].u32; + swap_params.x = window_scissor_tl & 0x7FFF; + swap_params.y = (window_scissor_tl >> 16) & 0x7FFF; + swap_params.width = window_scissor_br & 0x7FFF - swap_params.x; + swap_params.height = (window_scissor_br >> 16) & 0x7FFF - swap_params.y; + + PrepareForWait(); + swap_handler_(swap_params); + ReturnFromWait(); + + // Remove any dead textures, etc. + texture_cache_.Scavenge(); +} + class CommandProcessor::RingbufferReader { public: RingbufferReader(uint8_t* membase, uint32_t base_ptr, uint32_t ptr_mask, @@ -809,8 +849,6 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingbufferReader* reader, uint32_t count) { SCOPE_profile_cpu_f("gpu"); - auto& regs = *register_file_; - PLOGI("XE_SWAP"); // Xenia-specific VdSwap hook. @@ -823,38 +861,8 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingbufferReader* reader, // Ensure we issue any pending draws. draw_batcher_.Flush(DrawBatcher::FlushMode::kMakeCoherent); - if (swap_handler_) { - SwapParameters swap_params; - - // Lookup the framebuffer in the recently-resolved list. - // TODO(benvanik): make this much more sophisticated. - // TODO(benvanik): handle not found cases. - // TODO(benvanik): handle dirty cases (resolved to sysmem, touched). - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // HACK: just use whatever our current framebuffer is. - if (active_framebuffer_) { - swap_params.framebuffer = active_framebuffer_->framebuffer; - // TODO(benvanik): pick the right one? - swap_params.attachment = GL_COLOR_ATTACHMENT0; - } else { - swap_params.framebuffer = 0; - } - - // Guess frontbuffer dimensions. - // Command buffer seems to set these right before the XE_SWAP. - uint32_t window_scissor_tl = regs[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_TL].u32; - uint32_t window_scissor_br = regs[XE_GPU_REG_PA_SC_WINDOW_SCISSOR_BR].u32; - swap_params.x = window_scissor_tl & 0x7FFF; - swap_params.y = (window_scissor_tl >> 16) & 0x7FFF; - swap_params.width = window_scissor_br & 0x7FFF - swap_params.x; - swap_params.height = (window_scissor_br >> 16) & 0x7FFF - swap_params.y; - - PrepareForWait(); - swap_handler_(swap_params); - ReturnFromWait(); - - // Remove any dead textures, etc. - texture_cache_.Scavenge(); + if (swap_mode_ == SwapMode::kNormal) { + IssueSwap(); } trace_writer_.WriteEvent(EventType::kSwap); diff --git a/src/xenia/gpu/gl4/command_processor.h b/src/xenia/gpu/gl4/command_processor.h index 3d47971be..18735371e 100644 --- a/src/xenia/gpu/gl4/command_processor.h +++ b/src/xenia/gpu/gl4/command_processor.h @@ -43,6 +43,11 @@ struct SwapParameters { GLenum attachment; }; +enum class SwapMode { + kNormal, + kIgnored, +}; + class CommandProcessor { public: CommandProcessor(GL4GraphicsSystem* graphics_system); @@ -59,6 +64,9 @@ class CommandProcessor { void Shutdown(); void CallInThread(std::function fn); + void set_swap_mode(SwapMode swap_mode) { swap_mode_ = swap_mode; } + void IssueSwap(); + void BeginTracing(const std::wstring& root_path); void EndTracing(); @@ -207,6 +215,8 @@ class CommandProcessor { std::function pending_fn_; HANDLE pending_fn_event_; + SwapMode swap_mode_; + uint64_t time_base_; uint32_t counter_; diff --git a/src/xenia/gpu/gl4/gl4_graphics_system.cc b/src/xenia/gpu/gl4/gl4_graphics_system.cc index f5913d1fe..8884b7070 100644 --- a/src/xenia/gpu/gl4/gl4_graphics_system.cc +++ b/src/xenia/gpu/gl4/gl4_graphics_system.cc @@ -122,6 +122,10 @@ void GL4GraphicsSystem::EnableReadPointerWriteBack(uint32_t ptr, command_processor_->EnableReadPointerWriteBack(ptr, block_size); } +void GL4GraphicsSystem::RequestSwap() { + command_processor_->CallInThread([&]() { command_processor_->IssueSwap(); }); +} + const uint8_t* GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode) { diff --git a/src/xenia/gpu/gl4/gl4_graphics_system.h b/src/xenia/gpu/gl4/gl4_graphics_system.h index 77b144da0..d969bb660 100644 --- a/src/xenia/gpu/gl4/gl4_graphics_system.h +++ b/src/xenia/gpu/gl4/gl4_graphics_system.h @@ -36,6 +36,8 @@ class GL4GraphicsSystem : public GraphicsSystem { void InitializeRingBuffer(uint32_t ptr, uint32_t page_count) override; void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size) override; + void RequestSwap() override; + const uint8_t* PlayTrace(const uint8_t* trace_data, size_t trace_size, TracePlaybackMode playback_mode) override; diff --git a/src/xenia/gpu/graphics_system.h b/src/xenia/gpu/graphics_system.h index d5b588a70..50be9f7c0 100644 --- a/src/xenia/gpu/graphics_system.h +++ b/src/xenia/gpu/graphics_system.h @@ -39,6 +39,8 @@ class GraphicsSystem { virtual void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size) = 0; + virtual void RequestSwap() = 0; + void DispatchInterruptCallback(uint32_t source, uint32_t cpu); enum class TracePlaybackMode {