|
|
@@ -100,7 +100,7 @@ namespace BansheeEngine
|
|
|
VulkanCmdBuffer::VulkanCmdBuffer(VulkanDevice& device, UINT32 id, VkCommandPool pool, UINT32 queueFamily, bool secondary)
|
|
|
: mId(id), mQueueFamily(queueFamily), mState(State::Ready), mDevice(device), mPool(pool), mFenceCounter(0)
|
|
|
, mFramebuffer(VK_NULL_HANDLE), mRenderPass(VK_NULL_HANDLE), mPresentSemaphore(VK_NULL_HANDLE)
|
|
|
- , mRenderTargetWidth(0), mRenderTargetHeight(0)
|
|
|
+ , mRenderTargetWidth(0), mRenderTargetHeight(0), mGlobalQueueIdx(-1)
|
|
|
{
|
|
|
VkCommandBufferAllocateInfo cmdBufferAllocInfo;
|
|
|
cmdBufferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
|
@@ -250,167 +250,12 @@ namespace BansheeEngine
|
|
|
mState = State::Recording;
|
|
|
}
|
|
|
|
|
|
- void VulkanCmdBuffer::refreshFenceStatus()
|
|
|
- {
|
|
|
- VkResult result = vkGetFenceStatus(mDevice.getLogical(), mFence);
|
|
|
- assert(result == VK_SUCCESS || result == VK_NOT_READY);
|
|
|
-
|
|
|
- bool signaled = result == VK_SUCCESS;
|
|
|
-
|
|
|
- if (mState == State::Submitted)
|
|
|
- {
|
|
|
- if(signaled)
|
|
|
- {
|
|
|
- mState = State::Ready;
|
|
|
- vkResetCommandBuffer(mCmdBuffer, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); // Note: Maybe better not to release resources?
|
|
|
-
|
|
|
- result = vkResetFences(mDevice.getLogical(), 1, &mFence);
|
|
|
- assert(result == VK_SUCCESS);
|
|
|
-
|
|
|
- mFenceCounter++;
|
|
|
-
|
|
|
- for (auto& entry : mResources)
|
|
|
- {
|
|
|
- ResourceUseHandle& useHandle = entry.second;
|
|
|
- assert(useHandle.used);
|
|
|
-
|
|
|
- entry.first->notifyDone();
|
|
|
- }
|
|
|
-
|
|
|
- for (auto& entry : mImages)
|
|
|
- {
|
|
|
- ResourceUseHandle& useHandle = entry.second.useHandle;
|
|
|
- assert(useHandle.used);
|
|
|
-
|
|
|
- entry.first->notifyDone();
|
|
|
- }
|
|
|
-
|
|
|
- for (auto& entry : mBuffers)
|
|
|
- {
|
|
|
- ResourceUseHandle& useHandle = entry.second.useHandle;
|
|
|
- assert(useHandle.used);
|
|
|
-
|
|
|
- entry.first->notifyDone();
|
|
|
- }
|
|
|
-
|
|
|
- mResources.clear();
|
|
|
- mImages.clear();
|
|
|
- mBuffers.clear();
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- assert(!signaled); // We reset the fence along with mState so this shouldn't be possible
|
|
|
- }
|
|
|
-
|
|
|
- void VulkanCmdBuffer::setRenderTarget(const SPtr<RenderTargetCore>& rt)
|
|
|
- {
|
|
|
- assert(mState != State::RecordingRenderPass && mState != State::Submitted);
|
|
|
-
|
|
|
- if(rt == nullptr)
|
|
|
- {
|
|
|
- mFramebuffer = VK_NULL_HANDLE;
|
|
|
- mRenderPass = VK_NULL_HANDLE;
|
|
|
- mPresentSemaphore = VK_NULL_HANDLE;
|
|
|
- mRenderTargetWidth = 0;
|
|
|
- mRenderTargetHeight = 0;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- rt->getCustomAttribute("FB", &mFramebuffer);
|
|
|
- rt->getCustomAttribute("RP", &mRenderPass);
|
|
|
-
|
|
|
- if (rt->getProperties().isWindow())
|
|
|
- rt->getCustomAttribute("PS", &mPresentSemaphore);
|
|
|
- else
|
|
|
- mPresentSemaphore = VK_NULL_HANDLE;
|
|
|
-
|
|
|
- mRenderTargetWidth = rt->getProperties().getWidth();
|
|
|
- mRenderTargetHeight = rt->getProperties().getHeight();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // TODO
|
|
|
- }
|
|
|
-
|
|
|
- void VulkanCmdBuffer::registerResource(VulkanResource* res, VulkanUseFlags flags)
|
|
|
- {
|
|
|
- auto insertResult = mResources.insert(std::make_pair(res, ResourceUseHandle()));
|
|
|
- if(insertResult.second) // New element
|
|
|
- {
|
|
|
- ResourceUseHandle& useHandle = insertResult.first->second;
|
|
|
- useHandle.used = false;
|
|
|
- useHandle.flags = flags;
|
|
|
-
|
|
|
- res->notifyBound();
|
|
|
- }
|
|
|
- else // Existing element
|
|
|
- {
|
|
|
- ResourceUseHandle& useHandle = insertResult.first->second;
|
|
|
-
|
|
|
- assert(!useHandle.used);
|
|
|
- useHandle.flags |= flags;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void VulkanCmdBuffer::registerResource(VulkanImage* res, VkAccessFlags accessFlags, VkImageLayout layout,
|
|
|
- const VkImageSubresourceRange& range, VulkanUseFlags flags)
|
|
|
- {
|
|
|
- auto insertResult = mImages.insert(std::make_pair(res, ImageInfo()));
|
|
|
- if (insertResult.second) // New element
|
|
|
- {
|
|
|
- ImageInfo& imageInfo = insertResult.first->second;
|
|
|
- imageInfo.accessFlags = accessFlags;
|
|
|
- imageInfo.layout = layout;
|
|
|
- imageInfo.range = range;
|
|
|
-
|
|
|
- imageInfo.useHandle.used = false;
|
|
|
- imageInfo.useHandle.flags = flags;
|
|
|
-
|
|
|
- res->notifyBound();
|
|
|
- }
|
|
|
- else // Existing element
|
|
|
- {
|
|
|
- ImageInfo& imageInfo = insertResult.first->second;
|
|
|
-
|
|
|
- assert(!imageInfo.useHandle.used);
|
|
|
- imageInfo.useHandle.flags |= flags;
|
|
|
-
|
|
|
- assert(imageInfo.layout == layout && "Cannot bind the same image with two different layouts on the same command buffer.");
|
|
|
- imageInfo.accessFlags |= accessFlags;
|
|
|
- imageInfo.range = range;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void VulkanCmdBuffer::registerResource(VulkanBuffer* res, VkAccessFlags accessFlags, VulkanUseFlags flags)
|
|
|
- {
|
|
|
- auto insertResult = mBuffers.insert(std::make_pair(res, BufferInfo()));
|
|
|
- if (insertResult.second) // New element
|
|
|
- {
|
|
|
- BufferInfo& bufferInfo = insertResult.first->second;
|
|
|
- bufferInfo.accessFlags = accessFlags;
|
|
|
-
|
|
|
- bufferInfo.useHandle.used = false;
|
|
|
- bufferInfo.useHandle.flags = flags;
|
|
|
-
|
|
|
- res->notifyBound();
|
|
|
- }
|
|
|
- else // Existing element
|
|
|
- {
|
|
|
- BufferInfo& bufferInfo = insertResult.first->second;
|
|
|
-
|
|
|
- assert(!bufferInfo.useHandle.used);
|
|
|
- bufferInfo.useHandle.flags |= flags;
|
|
|
- bufferInfo.accessFlags |= accessFlags;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
void VulkanCmdBuffer::submit(VulkanQueue* queue, UINT32 queueIdx, UINT32 syncMask)
|
|
|
{
|
|
|
assert(isReadyForSubmit());
|
|
|
|
|
|
// Issue pipeline barriers for queue transitions (need to happen on original queue first, then on new queue)
|
|
|
- for(auto& entry : mBuffers)
|
|
|
+ for (auto& entry : mBuffers)
|
|
|
{
|
|
|
VulkanBuffer* resource = static_cast<VulkanBuffer*>(entry.first);
|
|
|
|
|
|
@@ -436,7 +281,7 @@ namespace BansheeEngine
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- for(auto& entry : mImages)
|
|
|
+ for (auto& entry : mImages)
|
|
|
{
|
|
|
VulkanImage* resource = static_cast<VulkanImage*>(entry.first);
|
|
|
|
|
|
@@ -501,11 +346,11 @@ namespace BansheeEngine
|
|
|
continue;
|
|
|
|
|
|
UINT32 numQueues = device.getNumQueues(otherQueueType);
|
|
|
- for(UINT32 j = 0; j < numQueues; j++)
|
|
|
+ for (UINT32 j = 0; j < numQueues; j++)
|
|
|
{
|
|
|
// Try to find a queue not currently executing
|
|
|
VulkanQueue* curQueue = device.getQueue(otherQueueType, j);
|
|
|
- if(!curQueue->isExecuting())
|
|
|
+ if (!curQueue->isExecuting())
|
|
|
{
|
|
|
otherQueue = curQueue;
|
|
|
otherQueueIdx = j;
|
|
|
@@ -513,7 +358,7 @@ namespace BansheeEngine
|
|
|
}
|
|
|
|
|
|
// Can't find empty one, use the first one then
|
|
|
- if(otherQueue == nullptr)
|
|
|
+ if (otherQueue == nullptr)
|
|
|
{
|
|
|
otherQueue = device.getQueue(otherQueueType, 0);
|
|
|
otherQueueIdx = 0;
|
|
|
@@ -576,13 +421,14 @@ namespace BansheeEngine
|
|
|
|
|
|
queue->submit(this, mSemaphoresTemp, numSemaphores);
|
|
|
|
|
|
+ mGlobalQueueIdx = CommandSyncMask::getGlobalQueueIdx(queue->getType(), queueIdx);
|
|
|
for (auto& entry : mResources)
|
|
|
{
|
|
|
ResourceUseHandle& useHandle = entry.second;
|
|
|
assert(!useHandle.used);
|
|
|
|
|
|
useHandle.used = true;
|
|
|
- entry.first->notifyUsed(this, useHandle.flags);
|
|
|
+ entry.first->notifyUsed(mGlobalQueueIdx, mQueueFamily, useHandle.flags);
|
|
|
}
|
|
|
|
|
|
for (auto& entry : mImages)
|
|
|
@@ -591,7 +437,7 @@ namespace BansheeEngine
|
|
|
assert(!useHandle.used);
|
|
|
|
|
|
useHandle.used = true;
|
|
|
- entry.first->notifyUsed(this, useHandle.flags);
|
|
|
+ entry.first->notifyUsed(mGlobalQueueIdx, mQueueFamily, useHandle.flags);
|
|
|
}
|
|
|
|
|
|
for (auto& entry : mBuffers)
|
|
|
@@ -600,7 +446,7 @@ namespace BansheeEngine
|
|
|
assert(!useHandle.used);
|
|
|
|
|
|
useHandle.used = true;
|
|
|
- entry.first->notifyUsed(this, useHandle.flags);
|
|
|
+ entry.first->notifyUsed(mGlobalQueueIdx, mQueueFamily, useHandle.flags);
|
|
|
}
|
|
|
|
|
|
cbm.refreshStates(deviceIdx);
|
|
|
@@ -620,6 +466,161 @@ namespace BansheeEngine
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ void VulkanCmdBuffer::refreshFenceStatus()
|
|
|
+ {
|
|
|
+ VkResult result = vkGetFenceStatus(mDevice.getLogical(), mFence);
|
|
|
+ assert(result == VK_SUCCESS || result == VK_NOT_READY);
|
|
|
+
|
|
|
+ bool signaled = result == VK_SUCCESS;
|
|
|
+
|
|
|
+ if (mState == State::Submitted)
|
|
|
+ {
|
|
|
+ if(signaled)
|
|
|
+ {
|
|
|
+ mState = State::Ready;
|
|
|
+ vkResetCommandBuffer(mCmdBuffer, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); // Note: Maybe better not to release resources?
|
|
|
+
|
|
|
+ result = vkResetFences(mDevice.getLogical(), 1, &mFence);
|
|
|
+ assert(result == VK_SUCCESS);
|
|
|
+
|
|
|
+ mFenceCounter++;
|
|
|
+
|
|
|
+ for (auto& entry : mResources)
|
|
|
+ {
|
|
|
+ ResourceUseHandle& useHandle = entry.second;
|
|
|
+ assert(useHandle.used);
|
|
|
+
|
|
|
+ entry.first->notifyDone(mGlobalQueueIdx, useHandle.flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (auto& entry : mImages)
|
|
|
+ {
|
|
|
+ ResourceUseHandle& useHandle = entry.second.useHandle;
|
|
|
+ assert(useHandle.used);
|
|
|
+
|
|
|
+ entry.first->notifyDone(mGlobalQueueIdx, useHandle.flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (auto& entry : mBuffers)
|
|
|
+ {
|
|
|
+ ResourceUseHandle& useHandle = entry.second.useHandle;
|
|
|
+ assert(useHandle.used);
|
|
|
+
|
|
|
+ entry.first->notifyDone(mGlobalQueueIdx, useHandle.flags);
|
|
|
+ }
|
|
|
+
|
|
|
+ mResources.clear();
|
|
|
+ mImages.clear();
|
|
|
+ mBuffers.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ assert(!signaled); // We reset the fence along with mState so this shouldn't be possible
|
|
|
+ }
|
|
|
+
|
|
|
+ void VulkanCmdBuffer::setRenderTarget(const SPtr<RenderTargetCore>& rt)
|
|
|
+ {
|
|
|
+ assert(mState != State::RecordingRenderPass && mState != State::Submitted);
|
|
|
+
|
|
|
+ if(rt == nullptr)
|
|
|
+ {
|
|
|
+ mFramebuffer = VK_NULL_HANDLE;
|
|
|
+ mRenderPass = VK_NULL_HANDLE;
|
|
|
+ mPresentSemaphore = VK_NULL_HANDLE;
|
|
|
+ mRenderTargetWidth = 0;
|
|
|
+ mRenderTargetHeight = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rt->getCustomAttribute("FB", &mFramebuffer);
|
|
|
+ rt->getCustomAttribute("RP", &mRenderPass);
|
|
|
+
|
|
|
+ if (rt->getProperties().isWindow())
|
|
|
+ rt->getCustomAttribute("PS", &mPresentSemaphore);
|
|
|
+ else
|
|
|
+ mPresentSemaphore = VK_NULL_HANDLE;
|
|
|
+
|
|
|
+ mRenderTargetWidth = rt->getProperties().getWidth();
|
|
|
+ mRenderTargetHeight = rt->getProperties().getHeight();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // TODO
|
|
|
+ }
|
|
|
+
|
|
|
+ void VulkanCmdBuffer::registerResource(VulkanResource* res, VulkanUseFlags flags)
|
|
|
+ {
|
|
|
+ auto insertResult = mResources.insert(std::make_pair(res, ResourceUseHandle()));
|
|
|
+ if(insertResult.second) // New element
|
|
|
+ {
|
|
|
+ ResourceUseHandle& useHandle = insertResult.first->second;
|
|
|
+ useHandle.used = false;
|
|
|
+ useHandle.flags = flags;
|
|
|
+
|
|
|
+ res->notifyBound();
|
|
|
+ }
|
|
|
+ else // Existing element
|
|
|
+ {
|
|
|
+ ResourceUseHandle& useHandle = insertResult.first->second;
|
|
|
+
|
|
|
+ assert(!useHandle.used);
|
|
|
+ useHandle.flags |= flags;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void VulkanCmdBuffer::registerResource(VulkanImage* res, VkAccessFlags accessFlags, VkImageLayout layout,
|
|
|
+ const VkImageSubresourceRange& range, VulkanUseFlags flags)
|
|
|
+ {
|
|
|
+ auto insertResult = mImages.insert(std::make_pair(res, ImageInfo()));
|
|
|
+ if (insertResult.second) // New element
|
|
|
+ {
|
|
|
+ ImageInfo& imageInfo = insertResult.first->second;
|
|
|
+ imageInfo.accessFlags = accessFlags;
|
|
|
+ imageInfo.layout = layout;
|
|
|
+ imageInfo.range = range;
|
|
|
+
|
|
|
+ imageInfo.useHandle.used = false;
|
|
|
+ imageInfo.useHandle.flags = flags;
|
|
|
+
|
|
|
+ res->notifyBound();
|
|
|
+ }
|
|
|
+ else // Existing element
|
|
|
+ {
|
|
|
+ ImageInfo& imageInfo = insertResult.first->second;
|
|
|
+
|
|
|
+ assert(!imageInfo.useHandle.used);
|
|
|
+ imageInfo.useHandle.flags |= flags;
|
|
|
+
|
|
|
+ assert(imageInfo.layout == layout && "Cannot bind the same image with two different layouts on the same command buffer.");
|
|
|
+ imageInfo.accessFlags |= accessFlags;
|
|
|
+ imageInfo.range = range;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void VulkanCmdBuffer::registerResource(VulkanBuffer* res, VkAccessFlags accessFlags, VulkanUseFlags flags)
|
|
|
+ {
|
|
|
+ auto insertResult = mBuffers.insert(std::make_pair(res, BufferInfo()));
|
|
|
+ if (insertResult.second) // New element
|
|
|
+ {
|
|
|
+ BufferInfo& bufferInfo = insertResult.first->second;
|
|
|
+ bufferInfo.accessFlags = accessFlags;
|
|
|
+
|
|
|
+ bufferInfo.useHandle.used = false;
|
|
|
+ bufferInfo.useHandle.flags = flags;
|
|
|
+
|
|
|
+ res->notifyBound();
|
|
|
+ }
|
|
|
+ else // Existing element
|
|
|
+ {
|
|
|
+ BufferInfo& bufferInfo = insertResult.first->second;
|
|
|
+
|
|
|
+ assert(!bufferInfo.useHandle.used);
|
|
|
+ bufferInfo.useHandle.flags |= flags;
|
|
|
+ bufferInfo.accessFlags |= accessFlags;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
VulkanCommandBuffer::VulkanCommandBuffer(VulkanDevice& device, GpuQueueType type, UINT32 deviceIdx,
|
|
|
UINT32 queueIdx, bool secondary)
|
|
|
: CommandBuffer(type, deviceIdx, queueIdx, secondary), mBuffer(nullptr)
|