Lifetime fixes, cleanups

This commit is contained in:
Henrik Rydgård 2022-09-07 16:11:15 +02:00
parent befcfb470c
commit 77819c6f80
6 changed files with 60 additions and 46 deletions

View File

@ -136,6 +136,7 @@ public:
}
}
// Note! Does NOT delete any pointed-to data (in case you stored pointers in the map).
void Clear() {
memset(state.data(), (int)BucketState::FREE, state.size());
count_ = 0;

View File

@ -96,9 +96,14 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan, VkRenderPass compatibleR
ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
success = false;
} else {
// Success!
if (!tag.empty()) {
vulkan->SetDebugName(vkpipeline, VK_OBJECT_TYPE_PIPELINE, tag.c_str());
}
pipeline[rpType]->Post(vkpipeline);
}
// Having the desc stick around can be useful for debugging.
#ifndef _DEBUG
delete desc;
@ -107,6 +112,29 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan, VkRenderPass compatibleR
return success;
}
void VKRGraphicsPipeline::QueueForDeletion(VulkanContext *vulkan) {
for (int i = 0; i < RP_TYPE_COUNT; i++) {
if (!pipeline[i])
continue;
VkPipeline pipeline = this->pipeline[i]->BlockUntilReady();
vulkan->Delete().QueueDeletePipeline(pipeline);
vulkan->Delete().QueueCallback([](void *p) {
VKRGraphicsPipeline *pipeline = (VKRGraphicsPipeline *)p;
delete pipeline;
}, this);
}
}
u32 VKRGraphicsPipeline::GetVariantsBitmask() const {
u32 bitmask = 0;
for (int i = 0; i < RP_TYPE_COUNT; i++) {
if (pipeline[i]) {
bitmask |= 1 << i;
}
}
return bitmask;
}
bool VKRComputePipeline::Create(VulkanContext *vulkan) {
if (!desc) {
// Already failed to create this one.
@ -693,11 +721,12 @@ VkCommandBuffer VulkanRenderManager::GetInitCmd() {
return frameData_[curFrame].initCmd;
}
VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc, uint32_t variantBitmask) {
VKRGraphicsPipeline *VulkanRenderManager::CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc, uint32_t variantBitmask, const char *tag) {
VKRGraphicsPipeline *pipeline = new VKRGraphicsPipeline();
_dbg_assert_(desc->vertexShader);
_dbg_assert_(desc->fragmentShader);
pipeline->desc = desc;
pipeline->tag = tag;
if (curRenderStep_) {
// The common case
pipelinesToCheck_.push_back(pipeline);

View File

@ -155,31 +155,20 @@ struct VKRComputePipelineDesc {
VkComputePipelineCreateInfo pipe{ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO };
};
// Wrapped pipeline.
// Wrapped pipeline. Doesn't own desc.
struct VKRGraphicsPipeline {
VKRGraphicsPipeline() {
for (int i = 0; i < RP_TYPE_COUNT; i++) {
pipeline[i] = nullptr;
}
}
~VKRGraphicsPipeline() {
delete desc;
}
u32 GetVariantsBitmask() const {
u32 bitmask = 0;
for (int i = 0; i < RP_TYPE_COUNT; i++) {
if (pipeline[i]) {
bitmask |= 1 << i;
}
}
return bitmask;
}
VKRGraphicsPipelineDesc *desc = nullptr;
Promise<VkPipeline> *pipeline[RP_TYPE_COUNT];
~VKRGraphicsPipeline() {}
bool Create(VulkanContext *vulkan, VkRenderPass compatibleRenderPass, RenderPassType rpType);
// This deletes the whole VKRGraphicsPipeline, you must remove your last pointer to it when doing this.
void QueueForDeletion(VulkanContext *vulkan);
u32 GetVariantsBitmask() const;
VKRGraphicsPipelineDesc *desc = nullptr;
Promise<VkPipeline> *pipeline[RP_TYPE_COUNT]{};
std::string tag;
};
struct VKRComputePipeline {
@ -260,7 +249,7 @@ public:
// We delay creating pipelines until the end of the current render pass, so we can create the right type immediately.
// Unless a variantBitmask is passed in, in which case we can just go ahead.
// WARNING: desc must stick around during the lifetime of the pipeline! It's not enough to build it on the stack and drop it.
VKRGraphicsPipeline *CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc, uint32_t variantBitmask);
VKRGraphicsPipeline *CreateGraphicsPipeline(VKRGraphicsPipelineDesc *desc, uint32_t variantBitmask, const char *tag);
VKRComputePipeline *CreateComputePipeline(VKRComputePipelineDesc *desc);
void NudgeCompilerThread() {

View File

@ -249,12 +249,14 @@ public:
class VKPipeline : public Pipeline {
public:
VKPipeline(VulkanRenderManager *rm, size_t size, PipelineFlags _flags) : rm_(rm), flags(_flags) {
VKPipeline(VulkanContext *vulkan, size_t size, PipelineFlags _flags) : vulkan_(vulkan), flags(_flags) {
uboSize_ = (int)size;
ubo_ = new uint8_t[uboSize_];
}
~VKPipeline() {
// TODO: Right now we just leak the pipeline! This is not good.
if (pipeline) {
pipeline->QueueForDeletion(vulkan_);
}
delete[] ubo_;
}
@ -282,7 +284,7 @@ public:
bool usesStencil = false;
private:
VulkanRenderManager *rm_;
VulkanContext *vulkan_;
uint8_t *ubo_;
int uboSize_;
};
@ -1040,7 +1042,7 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
pipelineFlags |= PIPELINE_FLAG_USES_DEPTH_STENCIL;
}
VKPipeline *pipeline = new VKPipeline(&renderManager_, desc.uniformDesc ? desc.uniformDesc->uniformBufferSize : 16 * sizeof(float), (PipelineFlags)pipelineFlags);
VKPipeline *pipeline = new VKPipeline(vulkan_, desc.uniformDesc ? desc.uniformDesc->uniformBufferSize : 16 * sizeof(float), (PipelineFlags)pipelineFlags);
VKRGraphicsPipelineDesc &gDesc = pipeline->vkrDesc;
@ -1110,7 +1112,7 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
VkPipelineRasterizationStateCreateInfo rs{ VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
raster->ToVulkan(&gDesc.rs);
pipeline->pipeline = renderManager_.CreateGraphicsPipeline(&gDesc, 1 << RP_TYPE_BACKBUFFER);
pipeline->pipeline = renderManager_.CreateGraphicsPipeline(&gDesc, 1 << RP_TYPE_BACKBUFFER, "thin3d");
if (desc.uniformDesc) {
pipeline->dynamicUniformSize = (int)desc.uniformDesc->uniformBufferSize;

View File

@ -35,21 +35,12 @@ PipelineManagerVulkan::~PipelineManagerVulkan() {
void PipelineManagerVulkan::Clear() {
pipelines_.Iterate([&](const VulkanPipelineKey &key, VulkanPipeline *value) {
for (int i = 0; i < RP_TYPE_COUNT; i++) {
if (value->pipeline) {
if (value->pipeline->pipeline[i]) {
VkPipeline pipeline = value->pipeline->pipeline[i]->BlockUntilReady();
vulkan_->Delete().QueueDeletePipeline(pipeline);
vulkan_->Delete().QueueCallback([](void *p) {
VKRGraphicsPipeline *pipeline = (VKRGraphicsPipeline *)p;
delete pipeline;
}, value->pipeline);
}
} else {
// Something went wrong.
ERROR_LOG(G3D, "Null pipeline found in PipelineManagerVulkan::Clear - didn't wait for asyncs?");
}
if (!value->pipeline) {
// Something went wrong.
ERROR_LOG(G3D, "Null pipeline found in PipelineManagerVulkan::Clear - didn't wait for asyncs?");
delete value;
}
value->pipeline->QueueForDeletion(vulkan_);
delete value;
});
@ -181,7 +172,8 @@ static std::string CutFromMain(std::string str) {
static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, VkPipelineCache pipelineCache,
VkPipelineLayout layout, const VulkanPipelineRasterStateKey &key,
const DecVtxFormat *decFmt, VulkanVertexShader *vs, VulkanFragmentShader *fs, bool useHwTransform, u32 variantBitmask) {
VKRGraphicsPipelineDesc *desc = new VKRGraphicsPipelineDesc();
VulkanPipeline *vulkanPipeline = new VulkanPipeline();
VKRGraphicsPipelineDesc *desc = &vulkanPipeline->desc;
desc->pipelineCache = pipelineCache;
PROFILE_THIS_SCOPE("pipelinebuild");
@ -304,9 +296,8 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager,
desc->pipelineLayout = layout;
VKRGraphicsPipeline *pipeline = renderManager->CreateGraphicsPipeline(desc, variantBitmask);
VKRGraphicsPipeline *pipeline = renderManager->CreateGraphicsPipeline(desc, variantBitmask, "game");
VulkanPipeline *vulkanPipeline = new VulkanPipeline();
vulkanPipeline->pipeline = pipeline;
vulkanPipeline->flags = 0;
if (useBlendConstant)

View File

@ -28,6 +28,7 @@
#include "GPU/Vulkan/VulkanUtil.h"
#include "GPU/Vulkan/StateMappingVulkan.h"
#include "GPU/Vulkan/VulkanQueueRunner.h"
#include "GPU/Vulkan/VulkanRenderManager.h"
struct VKRGraphicsPipeline;
class VulkanRenderManager;
@ -53,6 +54,7 @@ struct VulkanPipelineKey {
// Simply wraps a Vulkan pipeline, providing some metadata.
struct VulkanPipeline {
VKRGraphicsPipeline *pipeline;
VKRGraphicsPipelineDesc desc;
int flags; // PipelineFlags enum above.
bool UsesBlendConstant() const { return (flags & PIPELINE_FLAG_USES_BLEND_CONSTANT) != 0; }