Vulkan: Semi-gross hack that massively improves the perf of MGS2:Acid.

This commit is contained in:
Henrik Rydgård committed 2018-04-13 17:32:56 +02:00
1 parent 81276c8862
commit 413a204138
8 files changed
+111 -5

No files matched your search

+67 -1
View File
@@ -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++) {