|
|
@@ -5,42 +5,93 @@
|
|
|
|
|
|
namespace BansheeEngine
|
|
|
{
|
|
|
- VulkanResource::VulkanResource(VulkanResourceManager* owner)
|
|
|
- :mOwner(owner)
|
|
|
+ VulkanResource::VulkanResource(VulkanResourceManager* owner, bool concurrency)
|
|
|
+ : mOwner(owner), mState(concurrency ? State::Shared : State::Normal), mNumHandles(0)
|
|
|
+ , mHandleCapacity(INITIAL_HANDLE_CAPACITY)
|
|
|
{
|
|
|
-
|
|
|
+ UINT32 bytesCapacity = sizeof(UseHandle) * mHandleCapacity;
|
|
|
+ mHandles = (UseHandle*)mAlloc.alloc(sizeof(UseHandle) * INITIAL_HANDLE_CAPACITY);
|
|
|
+ memset(mHandles, 0, bytesCapacity);
|
|
|
}
|
|
|
|
|
|
VulkanResource::~VulkanResource()
|
|
|
{
|
|
|
- assert(mIsDestroyed && "Vulkan resource getting destructed without destroy() called first.");
|
|
|
+ assert(mState == State::Destroyed && "Vulkan resource getting destructed without destroy() called first.");
|
|
|
+
|
|
|
+ mAlloc.free(mHandles);
|
|
|
+ mAlloc.clear();
|
|
|
}
|
|
|
|
|
|
- void VulkanResource::notifyUsed(VulkanCmdBuffer& buffer, VulkanUseFlags flags)
|
|
|
+ void VulkanResource::notifyUsed(VulkanCmdBuffer* buffer, VulkanUseFlags flags)
|
|
|
{
|
|
|
- assert(!isUsed() && !mIsDestroyed);
|
|
|
+ assert(mState != State::Destroyed);
|
|
|
+
|
|
|
+ if(isUsed() && mState == State::Normal) // Used without support for concurrency
|
|
|
+ {
|
|
|
+ assert(mQueueFamily == buffer->getQueueFamily() &&
|
|
|
+ "Vulkan resource without concurrency support can only be used by one queue family at once.");
|
|
|
+ }
|
|
|
+
|
|
|
+ mNumHandles++;
|
|
|
+
|
|
|
+ if(mNumHandles > mHandleCapacity)
|
|
|
+ {
|
|
|
+ UINT32 bytesCapacity = sizeof(UseHandle) * mHandleCapacity;
|
|
|
+ void* tempData = bs_stack_alloc(bytesCapacity);
|
|
|
+ memcpy(tempData, mHandles, bytesCapacity);
|
|
|
+
|
|
|
+ mAlloc.free(mHandles);
|
|
|
+ mHandles = (UseHandle*)mAlloc.alloc(bytesCapacity * 2);
|
|
|
+ memcpy(mHandles, tempData, bytesCapacity);
|
|
|
+
|
|
|
+ bs_stack_free(tempData);
|
|
|
|
|
|
- // Note: I could allow resource usage on multiple command buffers at once by keeping a list of separate usage
|
|
|
- // flags and ID's, per buffer.
|
|
|
+ memset(mHandles + mHandleCapacity, 0, bytesCapacity);
|
|
|
+ mHandleCapacity *= 2;
|
|
|
+ }
|
|
|
|
|
|
- mCmdBufferId = buffer.getId();
|
|
|
- mFlags |= flags;
|
|
|
+ for(UINT32 i = 0; i < mHandleCapacity; i++)
|
|
|
+ {
|
|
|
+ if (mHandles[i].buffer == nullptr)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ mHandles[i].buffer = buffer;
|
|
|
+ mHandles[i].flags |= flags;
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ mQueueFamily = buffer->getQueueFamily();
|
|
|
}
|
|
|
|
|
|
- void VulkanResource::notifyDone()
|
|
|
+ void VulkanResource::notifyDone(VulkanCmdBuffer* buffer)
|
|
|
{
|
|
|
- mCmdBufferId = -1;
|
|
|
- mFlags = VulkanUseFlag::None;
|
|
|
+ bool foundBuffer = false;
|
|
|
+ for(UINT32 i = 0; i < mNumHandles; i++)
|
|
|
+ {
|
|
|
+ if(mHandles[i].buffer == buffer)
|
|
|
+ {
|
|
|
+ mHandles[i].buffer = nullptr;
|
|
|
+ mHandles[i].flags = VulkanUseFlag::None;
|
|
|
+
|
|
|
+ foundBuffer = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ assert(foundBuffer);
|
|
|
+
|
|
|
+ mNumHandles--;
|
|
|
|
|
|
- if (mIsDestroyed) // Queued for destruction
|
|
|
+ if (!isUsed() && mState == State::Destroyed) // Queued for destruction
|
|
|
mOwner->destroy(this);
|
|
|
}
|
|
|
|
|
|
void VulkanResource::destroy()
|
|
|
{
|
|
|
- assert(!mIsDestroyed && "Vulkan resource destroy() called more than once.");
|
|
|
+ assert(mState != State::Destroyed && "Vulkan resource destroy() called more than once.");
|
|
|
|
|
|
- mIsDestroyed = true;
|
|
|
+ mState = State::Destroyed;
|
|
|
|
|
|
// If not used, destroy right away, otherwise check when it is reported as finished on the device
|
|
|
if (!isUsed())
|