mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-13 14:30:27 +02:00
Create framebuffer variants on demand
This commit is contained in:
1 parent
e828df9f25
commit
80ca822bf2
4 files changed
+69
-50
No files matched your search
@@ -615,13 +615,13 @@ std::string VulkanQueueRunner::StepToString(const VKRStep &step) const {
|
||||
break;
|
||||
}
|
||||
case VKRStepType::COPY:
|
||||
snprintf(buffer, sizeof(buffer), "COPY '%s' %s -> %s (%dx%d, %s)", step.tag, step.copy.src->tag.c_str(), step.copy.dst->tag.c_str(), step.copy.srcRect.extent.width, step.copy.srcRect.extent.height, AspectToString(step.copy.aspectMask));
|
||||
snprintf(buffer, sizeof(buffer), "COPY '%s' %s -> %s (%dx%d, %s)", step.tag, step.copy.src->Tag(), step.copy.dst->Tag(), step.copy.srcRect.extent.width, step.copy.srcRect.extent.height, AspectToString(step.copy.aspectMask));
|
||||
break;
|
||||
case VKRStepType::BLIT:
|
||||
snprintf(buffer, sizeof(buffer), "BLIT '%s' %s -> %s (%dx%d->%dx%d, %s)", step.tag, step.copy.src->tag.c_str(), step.copy.dst->tag.c_str(), step.blit.srcRect.extent.width, step.blit.srcRect.extent.height, step.blit.dstRect.extent.width, step.blit.dstRect.extent.height, AspectToString(step.blit.aspectMask));
|
||||
snprintf(buffer, sizeof(buffer), "BLIT '%s' %s -> %s (%dx%d->%dx%d, %s)", step.tag, step.copy.src->Tag(), step.copy.dst->Tag(), step.blit.srcRect.extent.width, step.blit.srcRect.extent.height, step.blit.dstRect.extent.width, step.blit.dstRect.extent.height, AspectToString(step.blit.aspectMask));
|
||||
break;
|
||||
case VKRStepType::READBACK:
|
||||
snprintf(buffer, sizeof(buffer), "READBACK '%s' %s (%dx%d, %s)", step.tag, step.readback.src->tag.c_str(), step.readback.srcRect.extent.width, step.readback.srcRect.extent.height, AspectToString(step.readback.aspectMask));
|
||||
snprintf(buffer, sizeof(buffer), "READBACK '%s' %s (%dx%d, %s)", step.tag, step.readback.src->Tag(), step.readback.srcRect.extent.width, step.readback.srcRect.extent.height, AspectToString(step.readback.aspectMask));
|
||||
break;
|
||||
case VKRStepType::READBACK_IMAGE:
|
||||
snprintf(buffer, sizeof(buffer), "READBACK_IMAGE '%s' (%dx%d)", step.tag, step.readback_image.srcRect.extent.width, step.readback_image.srcRect.extent.height);
|
||||
@@ -780,14 +780,14 @@ const char *ImageLayoutToString(VkImageLayout layout) {
|
||||
|
||||
void VulkanQueueRunner::LogRenderPass(const VKRStep &pass, bool verbose) {
|
||||
const auto &r = pass.render;
|
||||
const char *framebuf = r.framebuffer ? r.framebuffer->tag.c_str() : "backbuffer";
|
||||
const char *framebuf = r.framebuffer ? r.framebuffer->Tag() : "backbuffer";
|
||||
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.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));
|
||||
INFO_LOG(G3D, " PRETRANSITION: %s %s -> %s", pass.preTransitions[i].fb->Tag(), AspectToString(pass.preTransitions[i].aspect), ImageLayoutToString(pass.preTransitions[i].targetLayout));
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
@@ -1317,8 +1317,14 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
_dbg_assert_(step.render.finalColorLayout != VK_IMAGE_LAYOUT_UNDEFINED);
|
||||
_dbg_assert_(step.render.finalDepthStencilLayout != VK_IMAGE_LAYOUT_UNDEFINED);
|
||||
|
||||
RPKey key{
|
||||
step.render.colorLoad, step.render.depthLoad, step.render.stencilLoad,
|
||||
step.render.colorStore, step.render.depthStore, step.render.stencilStore,
|
||||
};
|
||||
renderPass = GetRenderPass(key);
|
||||
|
||||
VKRFramebuffer *fb = step.render.framebuffer;
|
||||
framebuf = fb->framebuf[step.render.renderPassType];
|
||||
framebuf = fb->Get(renderPass, step.render.renderPassType);
|
||||
w = fb->width;
|
||||
h = fb->height;
|
||||
|
||||
@@ -1340,12 +1346,6 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
|
||||
TransitionToOptimal(cmd, fb->color.image, fb->color.layout, fb->depth.image, fb->depth.layout, &recordBarrier_);
|
||||
|
||||
RPKey key{
|
||||
step.render.colorLoad, step.render.depthLoad, step.render.stencilLoad,
|
||||
step.render.colorStore, step.render.depthStore, step.render.stencilStore,
|
||||
};
|
||||
renderPass = GetRenderPass(key);
|
||||
|
||||
// The transition from the optimal format happens after EndRenderPass, now that we don't
|
||||
// do it as part of the renderpass itself anymore.
|
||||
|
||||
@@ -1359,18 +1359,18 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
numClearVals = 2;
|
||||
}
|
||||
} else {
|
||||
framebuf = backbuffer_;
|
||||
|
||||
// Raw, rotated backbuffer size.
|
||||
w = vulkan_->GetBackbufferWidth();
|
||||
h = vulkan_->GetBackbufferHeight();
|
||||
|
||||
RPKey key{
|
||||
VKRRenderPassLoadAction::CLEAR, VKRRenderPassLoadAction::CLEAR, VKRRenderPassLoadAction::CLEAR,
|
||||
VKRRenderPassStoreAction::STORE, VKRRenderPassStoreAction::DONT_CARE, VKRRenderPassStoreAction::DONT_CARE,
|
||||
};
|
||||
renderPass = GetRenderPass(key);
|
||||
|
||||
framebuf = backbuffer_;
|
||||
|
||||
// Raw, rotated backbuffer size.
|
||||
w = vulkan_->GetBackbufferWidth();
|
||||
h = vulkan_->GetBackbufferHeight();
|
||||
|
||||
Uint8x4ToFloat4(clearVal[0].color.float32, step.render.clearColor);
|
||||
numClearVals = 2; // We don't bother with a depth buffer here.
|
||||
clearVal[1].depthStencil.depth = 0.0f;
|
||||
|
||||
@@ -129,36 +129,43 @@ bool VKRComputePipeline::Create(VulkanContext *vulkan) {
|
||||
return success;
|
||||
}
|
||||
|
||||
VKRFramebuffer::VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VKRRenderPass *compatibleRenderPass, int _width, int _height, const char *tag) : vulkan_(vk) {
|
||||
VKRFramebuffer::VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VKRRenderPass *compatibleRenderPass, int _width, int _height, const char *tag) : vulkan_(vk), tag_(tag) {
|
||||
width = _width;
|
||||
height = _height;
|
||||
|
||||
CreateImage(vulkan_, initCmd, color, width, height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true, tag);
|
||||
CreateImage(vulkan_, initCmd, depth, width, height, vulkan_->GetDeviceInfo().preferredDepthStencilFormat, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false, tag);
|
||||
|
||||
for (int i = 0; i < RP_TYPE_COUNT; i++) {
|
||||
VkFramebufferCreateInfo fbci{ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
|
||||
VkImageView views[2]{};
|
||||
// We create the actual framebuffer objects on demand, because some combinations might not make sense.
|
||||
}
|
||||
|
||||
fbci.renderPass = compatibleRenderPass->pass[i];
|
||||
fbci.attachmentCount = 2;
|
||||
fbci.pAttachments = views;
|
||||
views[0] = color.imageView;
|
||||
views[1] = depth.imageView;
|
||||
fbci.width = width;
|
||||
fbci.height = height;
|
||||
fbci.layers = 1;
|
||||
|
||||
VkResult res = vkCreateFramebuffer(vulkan_->GetDevice(), &fbci, nullptr, &framebuf[i]);
|
||||
_assert_(res == VK_SUCCESS);
|
||||
|
||||
if (tag && vk->Extensions().EXT_debug_utils) {
|
||||
vk->SetDebugName(color.image, VK_OBJECT_TYPE_IMAGE, StringFromFormat("fb_color_%s", tag).c_str());
|
||||
vk->SetDebugName(depth.image, VK_OBJECT_TYPE_IMAGE, StringFromFormat("fb_depth_%s", tag).c_str());
|
||||
vk->SetDebugName(framebuf[i], VK_OBJECT_TYPE_FRAMEBUFFER, StringFromFormat("fb_%s", tag).c_str());
|
||||
this->tag = tag;
|
||||
}
|
||||
VkFramebuffer VKRFramebuffer::Get(VKRRenderPass *compatibleRenderPass, RenderPassType renderPassType) {
|
||||
if (framebuf[(int)renderPassType]) {
|
||||
return framebuf[(int)renderPassType];
|
||||
}
|
||||
|
||||
VkFramebufferCreateInfo fbci{ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO };
|
||||
VkImageView views[2]{};
|
||||
|
||||
fbci.renderPass = compatibleRenderPass->pass[(int)renderPassType];
|
||||
fbci.attachmentCount = 2;
|
||||
fbci.pAttachments = views;
|
||||
views[0] = color.imageView;
|
||||
views[1] = depth.imageView;
|
||||
fbci.width = width;
|
||||
fbci.height = height;
|
||||
fbci.layers = 1;
|
||||
|
||||
VkResult res = vkCreateFramebuffer(vulkan_->GetDevice(), &fbci, nullptr, &framebuf[(int)renderPassType]);
|
||||
_assert_(res == VK_SUCCESS);
|
||||
|
||||
if (!tag_.empty() && vulkan_->Extensions().EXT_debug_utils) {
|
||||
vulkan_->SetDebugName(color.image, VK_OBJECT_TYPE_IMAGE, StringFromFormat("fb_color_%s", tag_.c_str()).c_str());
|
||||
vulkan_->SetDebugName(depth.image, VK_OBJECT_TYPE_IMAGE, StringFromFormat("fb_depth_%s", tag_.c_str()).c_str());
|
||||
vulkan_->SetDebugName(framebuf[(int)renderPassType], VK_OBJECT_TYPE_FRAMEBUFFER, StringFromFormat("fb_%s", tag_.c_str()).c_str());
|
||||
}
|
||||
|
||||
return framebuf[(int)renderPassType];
|
||||
}
|
||||
|
||||
VKRFramebuffer::~VKRFramebuffer() {
|
||||
|
||||
@@ -46,14 +46,23 @@ public:
|
||||
VKRFramebuffer(VulkanContext *vk, VkCommandBuffer initCmd, VKRRenderPass *compatibleRenderPass, int _width, int _height, const char *tag);
|
||||
~VKRFramebuffer();
|
||||
|
||||
VkFramebuffer framebuf[RP_TYPE_COUNT]{};
|
||||
VKRImage color{};
|
||||
VKRImage depth{};
|
||||
VkFramebuffer Get(VKRRenderPass *compatibleRenderPass, RenderPassType rpType);
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
VKRImage color{};
|
||||
VKRImage depth{};
|
||||
|
||||
const char *Tag() const {
|
||||
return tag_.c_str();
|
||||
}
|
||||
|
||||
// TODO: Hide.
|
||||
VulkanContext *vulkan_;
|
||||
std::string tag;
|
||||
private:
|
||||
VkFramebuffer framebuf[RP_TYPE_COUNT]{};
|
||||
|
||||
std::string tag_;
|
||||
};
|
||||
|
||||
enum class VKRRunType {
|
||||
@@ -124,8 +133,8 @@ struct VKRGraphicsPipelineDesc {
|
||||
VkPipelineMultisampleStateCreateInfo ms{ VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
||||
|
||||
// Replaced the ShaderStageInfo with promises here so we can wait for compiles to finish.
|
||||
Promise<VkShaderModule> *vertexShader;
|
||||
Promise<VkShaderModule> *fragmentShader;
|
||||
Promise<VkShaderModule> *vertexShader = nullptr;
|
||||
Promise<VkShaderModule> *fragmentShader = nullptr;
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssembly{ VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
|
||||
VkVertexInputAttributeDescription attrs[8]{};
|
||||
@@ -133,11 +142,11 @@ struct VKRGraphicsPipelineDesc {
|
||||
VkPipelineVertexInputStateCreateInfo vis{ VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
||||
VkPipelineViewportStateCreateInfo views{ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO };
|
||||
|
||||
VkPipelineLayout pipelineLayout;
|
||||
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
||||
|
||||
// Does not include the render pass type, it's passed in separately since the
|
||||
// desc is persistent.
|
||||
RPKey rpKey;
|
||||
RPKey rpKey{};
|
||||
};
|
||||
|
||||
// All the data needed to create a compute pipeline.
|
||||
@@ -239,6 +248,7 @@ public:
|
||||
// Deferred creation, like in GL. Unlike GL though, the purpose is to allow background creation and avoiding
|
||||
// stalling the emulation thread as much as possible.
|
||||
// We delay creating pipelines until the end of the current render pass, so we can create the right type immediately.
|
||||
// WARNING: desc must stick around! It's not enough to build it on the stack.
|
||||
VKRGraphicsPipeline *CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc) {
|
||||
VKRGraphicsPipeline *pipeline = new VKRGraphicsPipeline();
|
||||
_dbg_assert_(desc->vertexShader);
|
||||
|
||||
@@ -273,6 +273,7 @@ public:
|
||||
}
|
||||
|
||||
VKRGraphicsPipeline *pipeline = nullptr;
|
||||
VKRGraphicsPipelineDesc vkrDesc;
|
||||
PipelineFlags flags;
|
||||
|
||||
int stride[4]{};
|
||||
@@ -1041,7 +1042,7 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
|
||||
|
||||
VKPipeline *pipeline = new VKPipeline(&renderManager_, desc.uniformDesc ? desc.uniformDesc->uniformBufferSize : 16 * sizeof(float), (PipelineFlags)pipelineFlags);
|
||||
|
||||
VKRGraphicsPipelineDesc gDesc{};
|
||||
VKRGraphicsPipelineDesc &gDesc = pipeline->vkrDesc;
|
||||
|
||||
std::vector<VkPipelineShaderStageCreateInfo> stages;
|
||||
stages.resize(desc.shaders.size());
|
||||
@@ -1079,6 +1080,7 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
|
||||
|
||||
gDesc.blend0 = blend->attachments[0];
|
||||
gDesc.cbs = blend->info;
|
||||
gDesc.cbs.pAttachments = &gDesc.blend0;
|
||||
|
||||
gDesc.dss = depth->info;
|
||||
|
||||
@@ -1090,7 +1092,7 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
|
||||
// We treat the three stencil states as a unit in other places, so let's do that here too.
|
||||
const VkDynamicState dynamics[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE, VK_DYNAMIC_STATE_STENCIL_WRITE_MASK };
|
||||
gDesc.ds.dynamicStateCount = depth->info.stencilTestEnable ? ARRAY_SIZE(dynamics) : 2;
|
||||
for (int i = 0; i < gDesc.ds.dynamicStateCount; i++) {
|
||||
for (size_t i = 0; i < gDesc.ds.dynamicStateCount; i++) {
|
||||
gDesc.dynamicStates[i] = dynamics[i];
|
||||
}
|
||||
gDesc.ds.pDynamicStates = gDesc.dynamicStates;
|
||||
|
||||
Reference in new issue
Block a user