Rename Vulkan attachment operation variables. Prep for supporting specifying store op.

This commit is contained in:
Henrik Rydgård 2022-06-11 13:22:40 +02:00
parent 4aee9623e6
commit acb84f0648
6 changed files with 66 additions and 65 deletions

1
.gitignore vendored
View file

@ -98,6 +98,7 @@ ppge_atlas.zim.png
local.properties
r.sh
Windows/compileData*
Windows/*.ipch
# For vim
*.swp

View file

@ -31,7 +31,7 @@ void VulkanQueueRunner::CreateDeviceObjects() {
INFO_LOG(G3D, "VulkanQueueRunner::CreateDeviceObjects");
InitBackbufferRenderPass();
framebufferRenderPass_ = GetRenderPass(VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR, VKRRenderPassAction::CLEAR);
framebufferRenderPass_ = GetRenderPass(VKRRenderPassLoadAction::CLEAR, VKRRenderPassLoadAction::CLEAR, VKRRenderPassLoadAction::CLEAR);
#if 0
// Just to check whether it makes sense to split some of these. drawidx is way bigger than the others...
@ -199,13 +199,13 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(const RPKey &key) {
attachments[0].format = VK_FORMAT_R8G8B8A8_UNORM;
attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
switch (key.colorLoadAction) {
case VKRRenderPassAction::CLEAR:
case VKRRenderPassLoadAction::CLEAR:
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
break;
case VKRRenderPassAction::KEEP:
case VKRRenderPassLoadAction::KEEP:
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
break;
case VKRRenderPassAction::DONT_CARE:
case VKRRenderPassLoadAction::DONT_CARE:
default:
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
break;
@ -220,24 +220,24 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(const RPKey &key) {
attachments[1].format = vulkan_->GetDeviceInfo().preferredDepthStencilFormat;
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
switch (key.depthLoadAction) {
case VKRRenderPassAction::CLEAR:
case VKRRenderPassLoadAction::CLEAR:
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
break;
case VKRRenderPassAction::KEEP:
case VKRRenderPassLoadAction::KEEP:
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
break;
case VKRRenderPassAction::DONT_CARE:
case VKRRenderPassLoadAction::DONT_CARE:
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
break;
}
switch (key.stencilLoadAction) {
case VKRRenderPassAction::CLEAR:
case VKRRenderPassLoadAction::CLEAR:
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
break;
case VKRRenderPassAction::KEEP:
case VKRRenderPassLoadAction::KEEP:
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
break;
case VKRRenderPassAction::DONT_CARE:
case VKRRenderPassLoadAction::DONT_CARE:
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
break;
}
@ -303,24 +303,24 @@ void VulkanQueueRunner::PreprocessSteps(std::vector<VKRStep *> &steps) {
if (steps.size() > 1 && steps[j]->stepType == VKRStepType::RENDER &&
steps[j]->render.numDraws == 0 &&
steps[j]->render.numReads == 0 &&
steps[j]->render.color == VKRRenderPassAction::CLEAR &&
steps[j]->render.stencil == VKRRenderPassAction::CLEAR &&
steps[j]->render.depth == VKRRenderPassAction::CLEAR) {
steps[j]->render.colorLoad == VKRRenderPassLoadAction::CLEAR &&
steps[j]->render.stencilLoad == VKRRenderPassLoadAction::CLEAR &&
steps[j]->render.depthLoad == VKRRenderPassLoadAction::CLEAR) {
// Drop the clear step, and merge it into the next step that touches the same framebuffer.
for (int i = j + 1; i < (int)steps.size(); i++) {
if (steps[i]->stepType == VKRStepType::RENDER &&
steps[i]->render.framebuffer == steps[j]->render.framebuffer) {
if (steps[i]->render.color != VKRRenderPassAction::CLEAR) {
steps[i]->render.color = VKRRenderPassAction::CLEAR;
if (steps[i]->render.colorLoad != VKRRenderPassLoadAction::CLEAR) {
steps[i]->render.colorLoad = VKRRenderPassLoadAction::CLEAR;
steps[i]->render.clearColor = steps[j]->render.clearColor;
}
if (steps[i]->render.depth != VKRRenderPassAction::CLEAR) {
steps[i]->render.depth = VKRRenderPassAction::CLEAR;
if (steps[i]->render.depthLoad != VKRRenderPassLoadAction::CLEAR) {
steps[i]->render.depthLoad = VKRRenderPassLoadAction::CLEAR;
steps[i]->render.clearDepth = steps[j]->render.clearDepth;
}
if (steps[i]->render.stencil != VKRRenderPassAction::CLEAR) {
steps[i]->render.stencil = VKRRenderPassAction::CLEAR;
if (steps[i]->render.stencilLoad != VKRRenderPassLoadAction::CLEAR) {
steps[i]->render.stencilLoad = VKRRenderPassLoadAction::CLEAR;
steps[i]->render.clearStencil = steps[j]->render.clearStencil;
}
MergeRenderAreaRectInto(&steps[i]->render.renderArea, steps[j]->render.renderArea);
@ -489,9 +489,9 @@ void VulkanQueueRunner::ApplyMGSHack(std::vector<VKRStep *> &steps) {
steps[i]->render.numDraws == 1 &&
steps[i + 1]->render.numDraws == 1 &&
steps[i + 2]->render.numDraws == 1 &&
steps[i]->render.color == VKRRenderPassAction::DONT_CARE &&
steps[i + 1]->render.color == VKRRenderPassAction::KEEP &&
steps[i + 2]->render.color == VKRRenderPassAction::DONT_CARE))
steps[i]->render.colorLoad == VKRRenderPassLoadAction::DONT_CARE &&
steps[i + 1]->render.colorLoad == VKRRenderPassLoadAction::KEEP &&
steps[i + 2]->render.colorLoad == VKRRenderPassLoadAction::DONT_CARE))
continue;
VKRFramebuffer *depalFramebuffer = steps[i]->render.framebuffer;
VKRFramebuffer *targetFramebuffer = steps[i + 1]->render.framebuffer;
@ -501,7 +501,7 @@ void VulkanQueueRunner::ApplyMGSHack(std::vector<VKRStep *> &steps) {
// This should be a depal draw.
if (steps[j]->render.numDraws != 1)
break;
if (steps[j]->render.color != VKRRenderPassAction::DONT_CARE)
if (steps[j]->render.colorLoad != VKRRenderPassLoadAction::DONT_CARE)
break;
if (steps[j]->render.framebuffer != depalFramebuffer)
break;
@ -510,7 +510,7 @@ void VulkanQueueRunner::ApplyMGSHack(std::vector<VKRStep *> &steps) {
// This should be a target draw.
if (steps[j]->render.numDraws != 1)
break;
if (steps[j]->render.color != VKRRenderPassAction::KEEP)
if (steps[j]->render.colorLoad != VKRRenderPassLoadAction::KEEP)
break;
if (steps[j]->render.framebuffer != targetFramebuffer)
break;
@ -706,7 +706,7 @@ void VulkanQueueRunner::ApplyRenderPassMerge(std::vector<VKRStep *> &steps) {
};
auto renderHasClear = [](const VKRStep *step) {
const auto &r = step->render;
return r.color == VKRRenderPassAction::CLEAR || r.depth == VKRRenderPassAction::CLEAR || r.stencil == VKRRenderPassAction::CLEAR;
return r.colorLoad == VKRRenderPassLoadAction::CLEAR || r.depthLoad == VKRRenderPassLoadAction::CLEAR || r.stencilLoad == VKRRenderPassLoadAction::CLEAR;
};
// Now, let's go through the steps. If we find one that is rendered to more than once,
@ -797,13 +797,13 @@ void VulkanQueueRunner::LogSteps(const std::vector<VKRStep *> &steps, bool verbo
INFO_LOG(G3D, "------------------- SUBMIT ------------------");
}
const char *RenderPassActionName(VKRRenderPassAction a) {
const char *RenderPassActionName(VKRRenderPassLoadAction a) {
switch (a) {
case VKRRenderPassAction::CLEAR:
case VKRRenderPassLoadAction::CLEAR:
return "CLEAR";
case VKRRenderPassAction::DONT_CARE:
case VKRRenderPassLoadAction::DONT_CARE:
return "DONT_CARE";
case VKRRenderPassAction::KEEP:
case VKRRenderPassLoadAction::KEEP:
return "KEEP";
}
return "?";
@ -829,7 +829,7 @@ void VulkanQueueRunner::LogRenderPass(const VKRStep &pass, bool verbose) {
int w = r.framebuffer ? r.framebuffer->width : vulkan_->GetBackbufferWidth();
int h = r.framebuffer ? r.framebuffer->height : vulkan_->GetBackbufferHeight();
INFO_LOG(G3D, "RENDER %s Begin(%s, draws: %d, %dx%d, %s, %s, %s)", pass.tag, framebuf, r.numDraws, w, h, RenderPassActionName(r.color), RenderPassActionName(r.depth), RenderPassActionName(r.stencil));
INFO_LOG(G3D, "RENDER %s Begin(%s, draws: %d, %dx%d, %s, %s, %s)", pass.tag, framebuf, r.numDraws, w, h, RenderPassActionName(r.colorLoad), RenderPassActionName(r.depthLoad), RenderPassActionName(r.stencilLoad));
// TODO: Log these in detail.
for (int i = 0; i < (int)pass.preTransitions.size(); i++) {
INFO_LOG(G3D, " PRETRANSITION: %s %s -> %s", pass.preTransitions[i].fb->tag.c_str(), AspectToString(pass.preTransitions[i].aspect), ImageLayoutToString(pass.preTransitions[i].targetLayout));
@ -1098,7 +1098,7 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
// Don't execute empty renderpasses that keep the contents.
if (step.commands.empty() && step.render.color == VKRRenderPassAction::KEEP && step.render.depth == VKRRenderPassAction::KEEP && step.render.stencil == VKRRenderPassAction::KEEP) {
if (step.commands.empty() && step.render.colorLoad == VKRRenderPassLoadAction::KEEP && step.render.depthLoad == VKRRenderPassLoadAction::KEEP && step.render.stencilLoad == VKRRenderPassLoadAction::KEEP) {
// Flush the pending barrier
recordBarrier_.Flush(cmd);
// Nothing to do.
@ -1372,7 +1372,7 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
// To avoid this, we transition to GENERAL and back in this case (ARM-approved workaround).
// See pull request #10723.
bool maliBugWorkaround = step.render.numDraws == 0 &&
step.render.color == VKRRenderPassAction::CLEAR &&
step.render.colorLoad == VKRRenderPassLoadAction::CLEAR &&
vulkan_->GetPhysicalDeviceProperties().properties.driverVersion == 0xaa9c4b29;
if (maliBugWorkaround) {
recordBarrier_.TransitionImage(step.render.framebuffer->color.image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
@ -1385,16 +1385,16 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
TransitionToOptimal(cmd, fb->color.image, fb->color.layout, fb->depth.image, fb->depth.layout, &recordBarrier_);
renderPass = GetRenderPass(step.render.color, step.render.depth, step.render.stencil);
renderPass = GetRenderPass(step.render.colorLoad, step.render.depthLoad, step.render.stencilLoad);
// The transition from the optimal format happens after EndRenderPass, now that we don't
// do it as part of the renderpass itself anymore.
if (step.render.color == VKRRenderPassAction::CLEAR) {
if (step.render.colorLoad == VKRRenderPassLoadAction::CLEAR) {
Uint8x4ToFloat4(clearVal[0].color.float32, step.render.clearColor);
numClearVals = 1;
}
if (step.render.depth == VKRRenderPassAction::CLEAR || step.render.stencil == VKRRenderPassAction::CLEAR) {
if (step.render.depthLoad == VKRRenderPassLoadAction::CLEAR || step.render.stencilLoad == VKRRenderPassLoadAction::CLEAR) {
clearVal[1].depthStencil.depth = step.render.clearDepth;
clearVal[1].depthStencil.stencil = step.render.clearStencil;
numClearVals = 2;

View file

@ -121,7 +121,7 @@ enum class VKRStepType : uint8_t {
READBACK_IMAGE,
};
enum class VKRRenderPassAction : uint8_t {
enum class VKRRenderPassLoadAction : uint8_t {
DONT_CARE,
CLEAR,
KEEP,
@ -153,9 +153,9 @@ struct VKRStep {
union {
struct {
VKRFramebuffer *framebuffer;
VKRRenderPassAction color;
VKRRenderPassAction depth;
VKRRenderPassAction stencil;
VKRRenderPassLoadAction colorLoad;
VKRRenderPassLoadAction depthLoad;
VKRRenderPassLoadAction stencilLoad;
uint32_t clearColor;
float clearDepth;
int clearStencil;
@ -222,21 +222,21 @@ public:
return framebufferRenderPass_;
}
inline int RPIndex(VKRRenderPassAction color, VKRRenderPassAction depth) {
inline int RPIndex(VKRRenderPassLoadAction color, VKRRenderPassLoadAction depth) {
return (int)depth * 3 + (int)color;
}
void CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels);
struct RPKey {
VKRRenderPassAction colorLoadAction;
VKRRenderPassAction depthLoadAction;
VKRRenderPassAction stencilLoadAction;
VKRRenderPassLoadAction colorLoadAction;
VKRRenderPassLoadAction depthLoadAction;
VKRRenderPassLoadAction stencilLoadAction;
};
// Only call this from the render thread! Also ok during initialization (LoadCache).
VkRenderPass GetRenderPass(
VKRRenderPassAction colorLoadAction, VKRRenderPassAction depthLoadAction, VKRRenderPassAction stencilLoadAction) {
VKRRenderPassLoadAction colorLoadAction, VKRRenderPassLoadAction depthLoadAction, VKRRenderPassLoadAction stencilLoadAction) {
RPKey key{ colorLoadAction, depthLoadAction, stencilLoadAction };
return GetRenderPass(key);
}

View file

@ -642,18 +642,18 @@ void VulkanRenderManager::EndCurRenderStep() {
}
}
void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, VKRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) {
void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassLoadAction color, VKRRenderPassLoadAction depth, VKRRenderPassLoadAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag) {
_dbg_assert_(insideFrame_);
// Eliminate dupes (bind of the framebuffer we already are rendering to), instantly convert to a clear if possible.
if (!steps_.empty() && steps_.back()->stepType == VKRStepType::RENDER && steps_.back()->render.framebuffer == fb) {
u32 clearMask = 0;
if (color == VKRRenderPassAction::CLEAR) {
if (color == VKRRenderPassLoadAction::CLEAR) {
clearMask |= VK_IMAGE_ASPECT_COLOR_BIT;
}
if (depth == VKRRenderPassAction::CLEAR) {
if (depth == VKRRenderPassLoadAction::CLEAR) {
clearMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
if (stencil == VKRRenderPassAction::CLEAR) {
if (stencil == VKRRenderPassLoadAction::CLEAR) {
clearMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
@ -689,7 +689,7 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
// More redundant bind elimination.
if (curRenderStep_) {
if (curRenderStep_->commands.empty()) {
if (curRenderStep_->render.color != VKRRenderPassAction::CLEAR && curRenderStep_->render.depth != VKRRenderPassAction::CLEAR && curRenderStep_->render.stencil != VKRRenderPassAction::CLEAR) {
if (curRenderStep_->render.colorLoad != VKRRenderPassLoadAction::CLEAR && curRenderStep_->render.depthLoad != VKRRenderPassLoadAction::CLEAR && curRenderStep_->render.stencilLoad != VKRRenderPassLoadAction::CLEAR) {
// Can trivially kill the last empty render step.
_dbg_assert_(steps_.back() == curRenderStep_);
delete steps_.back();
@ -706,14 +706,14 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
// TODO: Determine which versions and do this only where necessary.
u32 lateClearMask = 0;
if (depth != stencil && vulkan_->GetPhysicalDeviceProperties().properties.vendorID == VULKAN_VENDOR_ARM) {
if (stencil == VKRRenderPassAction::DONT_CARE) {
if (stencil == VKRRenderPassLoadAction::DONT_CARE) {
stencil = depth;
} else if (depth == VKRRenderPassAction::DONT_CARE) {
} else if (depth == VKRRenderPassLoadAction::DONT_CARE) {
depth = stencil;
} else if (stencil == VKRRenderPassAction::CLEAR) {
} else if (stencil == VKRRenderPassLoadAction::CLEAR) {
depth = stencil;
lateClearMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
} else if (depth == VKRRenderPassAction::CLEAR) {
} else if (depth == VKRRenderPassLoadAction::CLEAR) {
stencil = depth;
lateClearMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
}
@ -721,9 +721,9 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
VKRStep *step = new VKRStep{ VKRStepType::RENDER };
step->render.framebuffer = fb;
step->render.color = color;
step->render.depth = depth;
step->render.stencil = stencil;
step->render.colorLoad = color;
step->render.depthLoad = depth;
step->render.stencilLoad = stencil;
step->render.clearColor = clearColor;
step->render.clearDepth = clearDepth;
step->render.clearStencil = clearStencil;
@ -736,7 +736,7 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
if (fb) {
// If there's a KEEP, we naturally read from the framebuffer.
if (color == VKRRenderPassAction::KEEP || depth == VKRRenderPassAction::KEEP || stencil == VKRRenderPassAction::KEEP) {
if (color == VKRRenderPassLoadAction::KEEP || depth == VKRRenderPassLoadAction::KEEP || stencil == VKRRenderPassLoadAction::KEEP) {
step->dependencies.insert(fb);
}
}
@ -761,7 +761,7 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
}
}
if (color == VKRRenderPassAction::CLEAR || depth == VKRRenderPassAction::CLEAR || stencil == VKRRenderPassAction::CLEAR) {
if (color == VKRRenderPassLoadAction::CLEAR || depth == VKRRenderPassLoadAction::CLEAR || stencil == VKRRenderPassLoadAction::CLEAR) {
curRenderArea_.SetRect(0, 0, curWidth_, curHeight_);
}
@ -1021,9 +1021,9 @@ void VulkanRenderManager::Clear(uint32_t clearColor, float clearZ, int clearSten
curRenderStep_->render.clearColor = clearColor;
curRenderStep_->render.clearDepth = clearZ;
curRenderStep_->render.clearStencil = clearStencil;
curRenderStep_->render.color = (clearMask & VK_IMAGE_ASPECT_COLOR_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP;
curRenderStep_->render.depth = (clearMask & VK_IMAGE_ASPECT_DEPTH_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP;
curRenderStep_->render.stencil = (clearMask & VK_IMAGE_ASPECT_STENCIL_BIT) ? VKRRenderPassAction::CLEAR : VKRRenderPassAction::KEEP;
curRenderStep_->render.colorLoad = (clearMask & VK_IMAGE_ASPECT_COLOR_BIT) ? VKRRenderPassLoadAction::CLEAR : VKRRenderPassLoadAction::KEEP;
curRenderStep_->render.depthLoad = (clearMask & VK_IMAGE_ASPECT_DEPTH_BIT) ? VKRRenderPassLoadAction::CLEAR : VKRRenderPassLoadAction::KEEP;
curRenderStep_->render.stencilLoad = (clearMask & VK_IMAGE_ASPECT_STENCIL_BIT) ? VKRRenderPassLoadAction::CLEAR : VKRRenderPassLoadAction::KEEP;
// In case there were commands already.
curRenderStep_->render.numDraws = 0;

View file

@ -210,7 +210,7 @@ public:
//
// It can be useful to use GetCurrentStepId() to figure out when you need to send all this state again, if you're
// not keeping track of your calls to this function on your own.
void BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassAction color, VKRRenderPassAction depth, VKRRenderPassAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag);
void BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRRenderPassLoadAction color, VKRRenderPassLoadAction depth, VKRRenderPassLoadAction stencil, uint32_t clearColor, float clearDepth, uint8_t clearStencil, const char *tag);
// Returns an ImageView corresponding to a framebuffer. Is called BindFramebufferAsTexture to maintain a similar interface
// as the other backends, even though there's no actual binding happening here.

View file

@ -1530,9 +1530,9 @@ DataFormat VKContext::PreferredFramebufferReadbackFormat(Framebuffer *src) {
void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) {
VKFramebuffer *fb = (VKFramebuffer *)fbo;
VKRRenderPassAction color = (VKRRenderPassAction)rp.color;
VKRRenderPassAction depth = (VKRRenderPassAction)rp.depth;
VKRRenderPassAction stencil = (VKRRenderPassAction)rp.stencil;
VKRRenderPassLoadAction color = (VKRRenderPassLoadAction)rp.color;
VKRRenderPassLoadAction depth = (VKRRenderPassLoadAction)rp.depth;
VKRRenderPassLoadAction stencil = (VKRRenderPassLoadAction)rp.stencil;
renderManager_.BindFramebufferAsRenderTarget(fb ? fb->GetFB() : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil, tag);
curFramebuffer_ = fb;