Added reference counting for PipelineLayout objects
Bug: b/155664177
Change-Id: I9322be202434908dfd652980f50e1024cf2efa2d
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/45368
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Tested-by: Trevor Black <vantablack@google.com>
Presubmit-Ready: Trevor Black <vantablack@google.com>
diff --git a/src/Vulkan/VkDestroy.hpp b/src/Vulkan/VkDestroy.hpp
index 3e0589c..4b057a1 100644
--- a/src/Vulkan/VkDestroy.hpp
+++ b/src/Vulkan/VkDestroy.hpp
@@ -65,4 +65,22 @@
}
}
+template<typename VkT>
+inline void release(VkT vkObject, const VkAllocationCallbacks *pAllocator)
+{
+ auto object = Cast(vkObject);
+ if(object)
+ {
+ using T = typename std::remove_pointer<decltype(object)>::type;
+ if(object->release(pAllocator))
+ {
+ object->~T();
+ // object may not point to the same pointer as vkObject, for dispatchable objects,
+ // for example, so make sure to deallocate based on the vkObject pointer, which
+ // should always point to the beginning of the allocated memory
+ vk::deallocate(vkObject, pAllocator);
+ }
+ }
+}
+
} // namespace vk
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 0de27b2..e0af236 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -14,6 +14,7 @@
#include "VkPipeline.hpp"
+#include "VkDestroy.hpp"
#include "VkDevice.hpp"
#include "VkPipelineCache.hpp"
#include "VkPipelineLayout.hpp"
@@ -137,11 +138,19 @@
namespace vk {
-Pipeline::Pipeline(PipelineLayout const *layout, const Device *device)
+Pipeline::Pipeline(PipelineLayout *layout, const Device *device)
: layout(layout)
, device(device)
, robustBufferAccess(device->getEnabledFeatures().robustBufferAccess)
{
+ layout->incRefCount();
+}
+
+void Pipeline::destroy(const VkAllocationCallbacks *pAllocator)
+{
+ destroyPipeline(pAllocator);
+
+ vk::release(static_cast<VkPipelineLayout>(*layout), pAllocator);
}
GraphicsPipeline::GraphicsPipeline(const VkGraphicsPipelineCreateInfo *pCreateInfo, void *mem, const Device *device)
diff --git a/src/Vulkan/VkPipeline.hpp b/src/Vulkan/VkPipeline.hpp
index 0f2611d..ca2ecf2 100644
--- a/src/Vulkan/VkPipeline.hpp
+++ b/src/Vulkan/VkPipeline.hpp
@@ -42,7 +42,7 @@
class Pipeline
{
public:
- Pipeline(PipelineLayout const *layout, const Device *device);
+ Pipeline(PipelineLayout *layout, const Device *device);
virtual ~Pipeline() = default;
operator VkPipeline()
@@ -55,23 +55,20 @@
return vk::VkTtoT<Pipeline, VkPipeline>(object);
}
- void destroy(const VkAllocationCallbacks *pAllocator)
- {
- destroyPipeline(pAllocator);
- }
+ void destroy(const VkAllocationCallbacks *pAllocator);
virtual void destroyPipeline(const VkAllocationCallbacks *pAllocator) = 0;
#ifndef NDEBUG
virtual VkPipelineBindPoint bindPoint() const = 0;
#endif
- PipelineLayout const *getLayout() const
+ PipelineLayout *getLayout() const
{
return layout;
}
protected:
- PipelineLayout const *layout = nullptr;
+ PipelineLayout *layout = nullptr;
Device const *const device;
const bool robustBufferAccess = true;
diff --git a/src/Vulkan/VkPipelineLayout.cpp b/src/Vulkan/VkPipelineLayout.cpp
index f01ed90..96a84a7 100644
--- a/src/Vulkan/VkPipelineLayout.cpp
+++ b/src/Vulkan/VkPipelineLayout.cpp
@@ -55,6 +55,8 @@
size_t pushConstantRangesSize = pCreateInfo->pushConstantRangeCount * sizeof(VkPushConstantRange);
pushConstantRanges = reinterpret_cast<VkPushConstantRange *>(bindingStorage);
memcpy(pushConstantRanges, pCreateInfo->pPushConstantRanges, pushConstantRangesSize);
+
+ incRefCount();
}
void PipelineLayout::destroy(const VkAllocationCallbacks *pAllocator)
@@ -62,6 +64,16 @@
vk::deallocate(descriptorSets[0].bindings, pAllocator); // pushConstantRanges are in the same allocation
}
+bool PipelineLayout::release(const VkAllocationCallbacks *pAllocator)
+{
+ if(decRefCount() == 0)
+ {
+ vk::deallocate(descriptorSets[0].bindings, pAllocator); // pushConstantRanges are in the same allocation
+ return true;
+ }
+ return false;
+}
+
size_t PipelineLayout::ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo)
{
uint32_t bindingsCount = 0;
@@ -107,4 +119,14 @@
return DescriptorSetLayout::IsDescriptorDynamic(getDescriptorType(setNumber, bindingNumber));
}
+uint32_t PipelineLayout::incRefCount()
+{
+ return ++refCount;
+}
+
+uint32_t PipelineLayout::decRefCount()
+{
+ return --refCount;
+}
+
} // namespace vk
diff --git a/src/Vulkan/VkPipelineLayout.hpp b/src/Vulkan/VkPipelineLayout.hpp
index 1ce716c..6f68dc8 100644
--- a/src/Vulkan/VkPipelineLayout.hpp
+++ b/src/Vulkan/VkPipelineLayout.hpp
@@ -25,6 +25,7 @@
public:
PipelineLayout(const VkPipelineLayoutCreateInfo *pCreateInfo, void *mem);
void destroy(const VkAllocationCallbacks *pAllocator);
+ bool release(const VkAllocationCallbacks *pAllocator);
static size_t ComputeRequiredAllocationSize(const VkPipelineLayoutCreateInfo *pCreateInfo);
@@ -41,6 +42,9 @@
const uint32_t identifier;
+ uint32_t incRefCount();
+ uint32_t decRefCount();
+
private:
struct Binding
{
@@ -60,6 +64,8 @@
const uint32_t descriptorSetCount = 0;
const uint32_t pushConstantRangeCount = 0;
VkPushConstantRange *pushConstantRanges = nullptr;
+
+ std::atomic<uint32_t> refCount{ 0 };
};
static inline PipelineLayout *Cast(VkPipelineLayout object)
diff --git a/src/Vulkan/libVulkan.cpp b/src/Vulkan/libVulkan.cpp
index 33facca..4b4247d 100644
--- a/src/Vulkan/libVulkan.cpp
+++ b/src/Vulkan/libVulkan.cpp
@@ -1909,7 +1909,7 @@
TRACE("(VkDevice device = %p, VkPipelineLayout pipelineLayout = %p, const VkAllocationCallbacks* pAllocator = %p)",
device, static_cast<void *>(pipelineLayout), pAllocator);
- vk::destroy(pipelineLayout, pAllocator);
+ vk::release(pipelineLayout, pAllocator);
}
VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSampler *pSampler)