mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Vulkan: Keep state on Clear cmds when used later.
This also removes duplicate state - for example our UI has some duplicate Scissor commands.
This commit is contained in:
parent
73d6446d72
commit
954f93046f
3 changed files with 82 additions and 1 deletions
|
@ -611,6 +611,10 @@ void VulkanQueueRunner::LogRenderPass(const VKRStep &pass) {
|
|||
ILOG("RenderPass Begin(%x)", fb);
|
||||
for (auto &cmd : pass.commands) {
|
||||
switch (cmd.cmd) {
|
||||
case VKRRenderCommand::REMOVED:
|
||||
ILOG(" REMOVED");
|
||||
break;
|
||||
|
||||
case VKRRenderCommand::BIND_PIPELINE:
|
||||
ILOG(" BindPipeline(%x)", (int)(intptr_t)cmd.pipeline.pipeline);
|
||||
break;
|
||||
|
@ -733,6 +737,9 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
|
|||
|
||||
for (const auto &c : commands) {
|
||||
switch (c.cmd) {
|
||||
case VKRRenderCommand::REMOVED:
|
||||
break;
|
||||
|
||||
case VKRRenderCommand::BIND_PIPELINE:
|
||||
if (c.pipeline.pipeline != lastPipeline) {
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, c.pipeline.pipeline);
|
||||
|
|
|
@ -16,6 +16,7 @@ enum {
|
|||
};
|
||||
|
||||
enum class VKRRenderCommand : uint8_t {
|
||||
REMOVED,
|
||||
BIND_PIPELINE,
|
||||
STENCIL,
|
||||
BLEND,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
#include "Common/Log.h"
|
||||
|
@ -612,6 +613,70 @@ bool VulkanRenderManager::InitDepthStencilBuffer(VkCommandBuffer cmd) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void RemoveDrawCommands(std::vector<VkRenderData> *cmds) {
|
||||
// Here we remove any DRAW type commands when we hit a CLEAR.
|
||||
cmds->erase(std::remove_if(cmds->begin(), cmds->end(), [](const VkRenderData &data) {
|
||||
return data.cmd == VKRRenderCommand::DRAW || data.cmd == VKRRenderCommand::DRAW_INDEXED;
|
||||
}), cmds->end());
|
||||
}
|
||||
|
||||
static void CleanupRenderCommands(std::vector<VkRenderData> *cmds) {
|
||||
size_t lastCommand[256];
|
||||
memset(lastCommand, -1, sizeof(lastCommand));
|
||||
|
||||
// Find any duplicate state commands (likely from RemoveDrawCommands.)
|
||||
for (size_t i = 0; i < cmds->size(); ++i) {
|
||||
auto &c = cmds->at(i);
|
||||
auto &lastOfCmd = lastCommand[(uint8_t)c.cmd];
|
||||
|
||||
switch (c.cmd) {
|
||||
case VKRRenderCommand::REMOVED:
|
||||
// Ignore, in case some other code starts using this.
|
||||
continue;
|
||||
|
||||
case VKRRenderCommand::BIND_PIPELINE:
|
||||
case VKRRenderCommand::VIEWPORT:
|
||||
case VKRRenderCommand::SCISSOR:
|
||||
case VKRRenderCommand::BLEND:
|
||||
case VKRRenderCommand::STENCIL:
|
||||
if (lastOfCmd != -1) {
|
||||
cmds->at(lastOfCmd).cmd = VKRRenderCommand::REMOVED;
|
||||
}
|
||||
break;
|
||||
|
||||
case VKRRenderCommand::PUSH_CONSTANTS:
|
||||
// TODO: For now, we have to keep this one (it has an offset.) Still update lastCommand.
|
||||
break;
|
||||
|
||||
case VKRRenderCommand::CLEAR:
|
||||
// Ignore, doesn't participate in state.
|
||||
continue;
|
||||
|
||||
case VKRRenderCommand::DRAW_INDEXED:
|
||||
case VKRRenderCommand::DRAW:
|
||||
default:
|
||||
// Boundary - must keep state before this.
|
||||
memset(lastCommand, -1, sizeof(lastCommand));
|
||||
continue;
|
||||
}
|
||||
|
||||
lastOfCmd = i;
|
||||
}
|
||||
|
||||
// At this point, anything in lastCommand can be cleaned up too.
|
||||
// Note that it's safe to remove the last unused PUSH_CONSTANTS here.
|
||||
for (size_t i = 0; i < ARRAY_SIZE(lastCommand); ++i) {
|
||||
auto &lastOfCmd = lastCommand[i];
|
||||
if (lastOfCmd != -1) {
|
||||
cmds->at(lastOfCmd).cmd = VKRRenderCommand::REMOVED;
|
||||
}
|
||||
}
|
||||
|
||||
cmds->erase(std::remove_if(cmds->begin(), cmds->end(), [](const VkRenderData &data) {
|
||||
return data.cmd == VKRRenderCommand::REMOVED;
|
||||
}), cmds->end());
|
||||
}
|
||||
|
||||
void VulkanRenderManager::Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask) {
|
||||
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == VKRStepType::RENDER);
|
||||
if (!clearMask)
|
||||
|
@ -628,7 +693,7 @@ void VulkanRenderManager::Clear(uint32_t clearColor, float clearZ, int clearSten
|
|||
|
||||
// In case there were commands already.
|
||||
curRenderStep_->render.numDraws = 0;
|
||||
curRenderStep_->commands.clear();
|
||||
RemoveDrawCommands(&curRenderStep_->commands);
|
||||
} else {
|
||||
VkRenderData data{ VKRRenderCommand::CLEAR };
|
||||
data.clear.clearColor = clearColor;
|
||||
|
@ -738,6 +803,14 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in
|
|||
|
||||
void VulkanRenderManager::Finish() {
|
||||
curRenderStep_ = nullptr;
|
||||
|
||||
// Let's do just a bit of cleanup on render commands now.
|
||||
for (auto &step : steps_) {
|
||||
if (step->stepType == VKRStepType::RENDER) {
|
||||
CleanupRenderCommands(&step->commands);
|
||||
}
|
||||
}
|
||||
|
||||
int curFrame = vulkan_->GetCurFrame();
|
||||
FrameData &frameData = frameData_[curFrame];
|
||||
if (!useThread_) {
|
||||
|
|
Loading…
Add table
Reference in a new issue