RequestSwap to force a swap from the GL thread.

This commit is contained in:
Ben Vanik 2015-02-21 11:18:22 -08:00
parent 9b21dd8874
commit 5227fe72b5
5 changed files with 60 additions and 34 deletions

View File

@ -55,6 +55,7 @@ CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system)
register_file_(graphics_system_->register_file()), register_file_(graphics_system_->register_file()),
trace_writer_(graphics_system->memory()->membase()), trace_writer_(graphics_system->memory()->membase()),
worker_running_(true), worker_running_(true),
swap_mode_(SwapMode::kNormal),
time_base_(0), time_base_(0),
counter_(0), counter_(0),
primary_buffer_ptr_(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 { class CommandProcessor::RingbufferReader {
public: public:
RingbufferReader(uint8_t* membase, uint32_t base_ptr, uint32_t ptr_mask, 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) { uint32_t count) {
SCOPE_profile_cpu_f("gpu"); SCOPE_profile_cpu_f("gpu");
auto& regs = *register_file_;
PLOGI("XE_SWAP"); PLOGI("XE_SWAP");
// Xenia-specific VdSwap hook. // Xenia-specific VdSwap hook.
@ -823,38 +861,8 @@ bool CommandProcessor::ExecutePacketType3_XE_SWAP(RingbufferReader* reader,
// Ensure we issue any pending draws. // Ensure we issue any pending draws.
draw_batcher_.Flush(DrawBatcher::FlushMode::kMakeCoherent); draw_batcher_.Flush(DrawBatcher::FlushMode::kMakeCoherent);
if (swap_handler_) { if (swap_mode_ == SwapMode::kNormal) {
SwapParameters swap_params; IssueSwap();
// 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();
} }
trace_writer_.WriteEvent(EventType::kSwap); trace_writer_.WriteEvent(EventType::kSwap);

View File

@ -43,6 +43,11 @@ struct SwapParameters {
GLenum attachment; GLenum attachment;
}; };
enum class SwapMode {
kNormal,
kIgnored,
};
class CommandProcessor { class CommandProcessor {
public: public:
CommandProcessor(GL4GraphicsSystem* graphics_system); CommandProcessor(GL4GraphicsSystem* graphics_system);
@ -59,6 +64,9 @@ class CommandProcessor {
void Shutdown(); void Shutdown();
void CallInThread(std::function<void()> fn); void CallInThread(std::function<void()> fn);
void set_swap_mode(SwapMode swap_mode) { swap_mode_ = swap_mode; }
void IssueSwap();
void BeginTracing(const std::wstring& root_path); void BeginTracing(const std::wstring& root_path);
void EndTracing(); void EndTracing();
@ -207,6 +215,8 @@ class CommandProcessor {
std::function<void()> pending_fn_; std::function<void()> pending_fn_;
HANDLE pending_fn_event_; HANDLE pending_fn_event_;
SwapMode swap_mode_;
uint64_t time_base_; uint64_t time_base_;
uint32_t counter_; uint32_t counter_;

View File

@ -122,6 +122,10 @@ void GL4GraphicsSystem::EnableReadPointerWriteBack(uint32_t ptr,
command_processor_->EnableReadPointerWriteBack(ptr, block_size); 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, const uint8_t* GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data,
size_t trace_size, size_t trace_size,
TracePlaybackMode playback_mode) { TracePlaybackMode playback_mode) {

View File

@ -36,6 +36,8 @@ class GL4GraphicsSystem : public GraphicsSystem {
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count) override; void InitializeRingBuffer(uint32_t ptr, uint32_t page_count) override;
void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size) 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, const uint8_t* PlayTrace(const uint8_t* trace_data, size_t trace_size,
TracePlaybackMode playback_mode) override; TracePlaybackMode playback_mode) override;

View File

@ -39,6 +39,8 @@ class GraphicsSystem {
virtual void EnableReadPointerWriteBack(uint32_t ptr, virtual void EnableReadPointerWriteBack(uint32_t ptr,
uint32_t block_size) = 0; uint32_t block_size) = 0;
virtual void RequestSwap() = 0;
void DispatchInterruptCallback(uint32_t source, uint32_t cpu); void DispatchInterruptCallback(uint32_t source, uint32_t cpu);
enum class TracePlaybackMode { enum class TracePlaybackMode {