From 1ed7f3e0281de29fd99f7d4802fcc5a1906930f8 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Mon, 7 Sep 2015 19:22:44 -0300 Subject: [PATCH] GSP: Implement command 0x05, used for flushing caches May fix additional texture caching issues. (Though mostly in homebrew, I haven't seen any commercial software use this to flush anything but command lists.) --- src/citra_qt/debugger/graphics.cpp | 4 ++-- src/core/hle/service/gsp_gpu.cpp | 28 +++++++++++++++++++--------- src/core/hle/service/gsp_gpu.h | 19 +++++++++++++++---- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/citra_qt/debugger/graphics.cpp b/src/citra_qt/debugger/graphics.cpp index 8008f914c..eccd619ba 100644 --- a/src/citra_qt/debugger/graphics.cpp +++ b/src/citra_qt/debugger/graphics.cpp @@ -30,11 +30,11 @@ QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) con { std::map command_names = { { GSP_GPU::CommandId::REQUEST_DMA, "REQUEST_DMA" }, - { GSP_GPU::CommandId::SET_COMMAND_LIST_FIRST, "SET_COMMAND_LIST_FIRST" }, + { GSP_GPU::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST" }, { GSP_GPU::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL" }, { GSP_GPU::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER" }, { GSP_GPU::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY" }, - { GSP_GPU::CommandId::SET_COMMAND_LIST_LAST, "SET_COMMAND_LIST_LAST" } + { GSP_GPU::CommandId::CACHE_FLUSH, "CACHE_FLUSH" }, }; const u32* command_data = reinterpret_cast(&command); QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9").arg(command_names[command.id]) diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index c3d0d28a5..481da0c9f 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -377,12 +377,16 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { command.dma_request.size); break; - // ctrulib homebrew sends all relevant command list data with this command, - // hence we do all "interesting" stuff here and do nothing in SET_COMMAND_LIST_FIRST. - // TODO: This will need some rework in the future. - case CommandId::SET_COMMAND_LIST_LAST: + // TODO: This will need some rework in the future. (why?) + case CommandId::SUBMIT_GPU_CMDLIST: { - auto& params = command.set_command_list_last; + auto& params = command.submit_gpu_cmdlist; + + if (params.do_flush) { + // This flag flushes the command list (params.address, params.size) from the cache. + // Command lists are not processed by the hardware renderer, so we don't need to + // actually flush them in Citra. + } WriteGPURegister(static_cast(GPU_REG_INDEX(command_processor_config.address)), Memory::VirtualToPhysicalAddress(params.address) >> 3); @@ -391,6 +395,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though WriteGPURegister(static_cast(GPU_REG_INDEX(command_processor_config.trigger)), 1); + // TODO(yuriks): Figure out the meaning of the `flags` field. + break; } @@ -434,7 +440,6 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { break; } - // TODO: Check if texture copies are implemented correctly.. case CommandId::SET_TEXTURE_COPY: { auto& params = command.texture_copy; @@ -456,10 +461,15 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { break; } - // TODO: Figure out what exactly SET_COMMAND_LIST_FIRST and SET_COMMAND_LIST_LAST - // are supposed to do. - case CommandId::SET_COMMAND_LIST_FIRST: + case CommandId::CACHE_FLUSH: { + for (auto& region : command.cache_flush.regions) { + if (region.size == 0) + break; + + VideoCore::g_renderer->hw_rasterizer->NotifyFlush( + Memory::VirtualToPhysicalAddress(region.address), region.size); + } break; } diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h index 8bcb30ad1..0e2f7a21e 100644 --- a/src/core/hle/service/gsp_gpu.h +++ b/src/core/hle/service/gsp_gpu.h @@ -31,7 +31,8 @@ enum class InterruptId : u8 { /// GSP command ID enum class CommandId : u32 { REQUEST_DMA = 0x00, - SET_COMMAND_LIST_LAST = 0x01, + /// Submits a commandlist for execution by the GPU. + SUBMIT_GPU_CMDLIST = 0x01, // Fills a given memory range with a particular value SET_MEMORY_FILL = 0x02, @@ -42,8 +43,8 @@ enum class CommandId : u32 { // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path SET_TEXTURE_COPY = 0x04, - - SET_COMMAND_LIST_FIRST = 0x05, + /// Flushes up to 3 cache regions in a single command. + CACHE_FLUSH = 0x05, }; /// GSP thread interrupt relay queue @@ -106,7 +107,10 @@ struct Command { struct { u32 address; u32 size; - } set_command_list_last; + u32 flags; + u32 unused[3]; + u32 do_flush; + } submit_gpu_cmdlist; struct { u32 start1; @@ -138,6 +142,13 @@ struct Command { u32 flags; } texture_copy; + struct { + struct { + u32 address; + u32 size; + } regions[3]; + } cache_flush; + u8 raw_data[0x1C]; }; };