mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-26 19:58:36 +01:00
Vulkan: Semi-gross hack that massively improves the perf of MGS2:Acid.
This commit is contained in:
1 parent
81276c8862
commit
413a204138
8 files changed
+111
-5
No files matched your search
@@ -347,7 +347,7 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(const RPKey &key) {
|
||||
return pass;
|
||||
}
|
||||
|
||||
void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector<VKRStep *> &steps) {
|
||||
void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector<VKRStep *> &steps) {
|
||||
// Optimizes renderpasses, then sequences them.
|
||||
// Planned optimizations:
|
||||
// * Create copies of render target that are rendered to multiple times and textured from in sequence, and push those render passes
|
||||
@@ -397,6 +397,12 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector<VKRStep
|
||||
}
|
||||
}
|
||||
|
||||
// Queue hacks.
|
||||
if (hacksEnabled_ & QUEUE_HACK_MGS2_ACID) {
|
||||
// Massive speedup.
|
||||
ApplyMGSHack(steps);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < steps.size(); i++) {
|
||||
const VKRStep &step = *steps[i];
|
||||
switch (step.stepType) {
|
||||
@@ -422,6 +428,66 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector<VKRStep
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanQueueRunner::ApplyMGSHack(std::vector<VKRStep *> &steps) {
|
||||
// We want to turn a sequence of copy,render(1),copy,render(1),copy,render(1) to copy,copy,copy,render(n).
|
||||
|
||||
for (int i = 0; i < (int)steps.size() - 3; i++) {
|
||||
int last = -1;
|
||||
if (!(steps[i]->stepType == VKRStepType::COPY &&
|
||||
steps[i + 1]->stepType == VKRStepType::RENDER &&
|
||||
steps[i + 2]->stepType == VKRStepType::COPY &&
|
||||
steps[i + 1]->render.numDraws == 1 &&
|
||||
steps[i]->copy.dst == steps[i + 2]->copy.dst))
|
||||
continue;
|
||||
// Looks promising! Let's start by finding the last one.
|
||||
for (int j = i; j < (int)steps.size(); j++) {
|
||||
switch (steps[j]->stepType) {
|
||||
case VKRStepType::RENDER:
|
||||
if (steps[j]->render.numDraws > 1)
|
||||
last = j - 1;
|
||||
break;
|
||||
case VKRStepType::COPY:
|
||||
if (steps[j]->copy.dst != steps[i]->copy.dst)
|
||||
last = j - 1;
|
||||
break;
|
||||
}
|
||||
if (last != -1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (last != -1) {
|
||||
// We've got a sequence from i to last that needs reordering.
|
||||
// First, let's sort it, keeping the same length.
|
||||
std::vector<VKRStep *> copies;
|
||||
std::vector<VKRStep *> renders;
|
||||
for (int n = i; n <= last; n++) {
|
||||
if (steps[n]->stepType == VKRStepType::COPY)
|
||||
copies.push_back(steps[n]);
|
||||
else if (steps[n]->stepType == VKRStepType::RENDER)
|
||||
renders.push_back(steps[n]);
|
||||
}
|
||||
// Write the copies back. TODO: Combine them too.
|
||||
for (int j = 0; j < (int)copies.size(); j++) {
|
||||
steps[i + j] = copies[j];
|
||||
}
|
||||
// Write the renders back (so they will be deleted properly).
|
||||
for (int j = 0; j < (int)renders.size(); j++) {
|
||||
steps[i + j + copies.size()] = renders[j];
|
||||
}
|
||||
assert(steps[i + j + copies.size()]->stepType == VKRStepType::RENDER);
|
||||
// Combine the renders.
|
||||
for (int j = 1; j < (int)renders.size(); j++) {
|
||||
for (int k = 0; k < renders[j]->commands.size(); k++) {
|
||||
steps[i + copies.size()]->commands.push_back(renders[j]->commands[k]);
|
||||
}
|
||||
steps[i + copies.size() + j]->stepType = VKRStepType::RENDER_SKIP;
|
||||
}
|
||||
// We're done.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanQueueRunner::LogSteps(const std::vector<VKRStep *> &steps) {
|
||||
ILOG("=======================================");
|
||||
for (size_t i = 0; i < steps.size(); i++) {
|
||||
|
||||
Reference in new issue
Block a user