diff options
Diffstat (limited to 'src/gpu/vk')
-rw-r--r-- | src/gpu/vk/GrVkCommandBuffer.cpp | 96 | ||||
-rw-r--r-- | src/gpu/vk/GrVkCommandBuffer.h | 4 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 24 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.h | 15 | ||||
-rw-r--r-- | src/gpu/vk/GrVkSemaphore.cpp | 14 | ||||
-rw-r--r-- | src/gpu/vk/GrVkSemaphore.h | 42 |
6 files changed, 139 insertions, 56 deletions
diff --git a/src/gpu/vk/GrVkCommandBuffer.cpp b/src/gpu/vk/GrVkCommandBuffer.cpp index 8a17a4f033..27642dfe63 100644 --- a/src/gpu/vk/GrVkCommandBuffer.cpp +++ b/src/gpu/vk/GrVkCommandBuffer.cpp @@ -445,12 +445,36 @@ void GrVkPrimaryCommandBuffer::executeCommands(const GrVkGpu* gpu, this->invalidateState(); } +static void submit_to_queue(const GrVkInterface* interface, + VkQueue queue, + VkFence fence, + uint32_t waitCount, + const VkSemaphore* waitSemaphores, + const VkPipelineStageFlags* waitStages, + uint32_t commandBufferCount, + const VkCommandBuffer* commandBuffers, + uint32_t signalCount, + const VkSemaphore* signalSemaphores) { + VkSubmitInfo submitInfo; + memset(&submitInfo, 0, sizeof(VkSubmitInfo)); + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.pNext = nullptr; + submitInfo.waitSemaphoreCount = waitCount; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = commandBufferCount; + submitInfo.pCommandBuffers = commandBuffers; + submitInfo.signalSemaphoreCount = signalCount; + submitInfo.pSignalSemaphores = signalSemaphores; + GR_VK_CALL_ERRCHECK(interface, QueueSubmit(queue, 1, &submitInfo, fence)); +} + void GrVkPrimaryCommandBuffer::submitToQueue( const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync, - SkTArray<const GrVkSemaphore::Resource*>& signalSemaphores, - SkTArray<const GrVkSemaphore::Resource*>& waitSemaphores) { + SkTArray<GrVkSemaphore::Resource*>& signalSemaphores, + SkTArray<GrVkSemaphore::Resource*>& waitSemaphores) { SkASSERT(!fIsActive); VkResult err; @@ -466,33 +490,51 @@ void GrVkPrimaryCommandBuffer::submitToQueue( } int signalCount = signalSemaphores.count(); - SkTArray<VkSemaphore> vkSignalSem(signalCount); - for (int i = 0; i < signalCount; ++i) { - this->addResource(signalSemaphores[i]); - vkSignalSem.push_back(signalSemaphores[i]->semaphore()); - } - int waitCount = waitSemaphores.count(); - SkTArray<VkSemaphore> vkWaitSems(waitCount); - SkTArray<VkPipelineStageFlags> vkWaitStages(waitCount); - for (int i = 0; i < waitCount; ++i) { - this->addResource(waitSemaphores[i]); - vkWaitSems.push_back(waitSemaphores[i]->semaphore()); - vkWaitStages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); - } - VkSubmitInfo submitInfo; - memset(&submitInfo, 0, sizeof(VkSubmitInfo)); - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pNext = nullptr; - submitInfo.waitSemaphoreCount = waitCount; - submitInfo.pWaitSemaphores = vkWaitSems.begin(); - submitInfo.pWaitDstStageMask = vkWaitStages.begin(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &fCmdBuffer; - submitInfo.signalSemaphoreCount = vkSignalSem.count(); - submitInfo.pSignalSemaphores = vkSignalSem.begin(); - GR_VK_CALL_ERRCHECK(gpu->vkInterface(), QueueSubmit(queue, 1, &submitInfo, fSubmitFence)); + if (0 == signalCount && 0 == waitCount) { + // This command buffer has no dependent semaphores so we can simply just submit it to the + // queue with no worries. + submit_to_queue(gpu->vkInterface(), queue, fSubmitFence, 0, nullptr, nullptr, + 1, &fCmdBuffer, 0, nullptr); + } else { + GrVkSemaphore::Resource::AcquireMutex(); + + SkTArray<VkSemaphore> vkSignalSems(signalCount); + for (int i = 0; i < signalCount; ++i) { + if (signalSemaphores[i]->shouldSignal()) { + this->addResource(signalSemaphores[i]); + vkSignalSems.push_back(signalSemaphores[i]->semaphore()); + } + } + + SkTArray<VkSemaphore> vkWaitSems(waitCount); + SkTArray<VkPipelineStageFlags> vkWaitStages(waitCount); + for (int i = 0; i < waitCount; ++i) { + if (waitSemaphores[i]->shouldWait()) { + this->addResource(waitSemaphores[i]); + vkWaitSems.push_back(waitSemaphores[i]->semaphore()); + vkWaitStages.push_back(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + } + } + submit_to_queue(gpu->vkInterface(), queue, fSubmitFence, + vkWaitSems.count(), vkWaitSems.begin(), vkWaitStages.begin(), + 1, &fCmdBuffer, + vkSignalSems.count(), vkSignalSems.begin()); + // Since shouldSignal/Wait do not require a mutex to be held, we must make sure that we mark + // the semaphores after we've submitted. Thus in the worst case another submit grabs the + // mutex and then realizes it doesn't need to submit the semaphore. We will never end up + // where a semaphore doesn't think it needs to be submitted (cause of querying + // shouldSignal/Wait), but it should need to. + for (int i = 0; i < signalCount; ++i) { + signalSemaphores[i]->markAsSignaled(); + } + for (int i = 0; i < waitCount; ++i) { + waitSemaphores[i]->markAsWaited(); + } + + GrVkSemaphore::Resource::ReleaseMutex(); + } if (GrVkGpu::kForce_SyncQueue == sync) { err = GR_VK_CALL(gpu->vkInterface(), diff --git a/src/gpu/vk/GrVkCommandBuffer.h b/src/gpu/vk/GrVkCommandBuffer.h index 7d16242e6b..362d457773 100644 --- a/src/gpu/vk/GrVkCommandBuffer.h +++ b/src/gpu/vk/GrVkCommandBuffer.h @@ -269,8 +269,8 @@ public: const VkImageResolve* regions); void submitToQueue(const GrVkGpu* gpu, VkQueue queue, GrVkGpu::SyncQueue sync, - SkTArray<const GrVkSemaphore::Resource*>& signalSemaphores, - SkTArray<const GrVkSemaphore::Resource*>& waitSemaphores); + SkTArray<GrVkSemaphore::Resource*>& signalSemaphores, + SkTArray<GrVkSemaphore::Resource*>& waitSemaphores); bool finished(const GrVkGpu* gpu) const; #ifdef SK_TRACE_VK_RESOURCES diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index e1be99e872..f7e3d47dd9 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -2162,16 +2162,17 @@ sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrVkGpu::makeSemaphore(bool isOwned) { return GrVkSemaphore::Make(this, isOwned); } -sk_sp<GrSemaphore> GrVkGpu::onWrapBackendSemaphore(const GrBackendSemaphore& semaphore, - GrWrapOwnership ownership) { - return GrVkSemaphore::MakeWrapped(this, semaphore.vkSemaphore(), ownership); +sk_sp<GrSemaphore> GrVkGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore, + GrResourceProvider::SemaphoreWrapType wrapType, + GrWrapOwnership ownership) { + return GrVkSemaphore::MakeWrapped(this, semaphore.vkSemaphore(), wrapType, ownership); } -void GrVkGpu::onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) { +void GrVkGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) { GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get()); - if (vkSem) { - const GrVkSemaphore::Resource* resource = vkSem->getResource(); + GrVkSemaphore::Resource* resource = vkSem->getResource(); + if (resource->shouldSignal()) { resource->ref(); fSemaphoresToSignal.push_back(resource); } @@ -2181,13 +2182,14 @@ void GrVkGpu::onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) { } } -void GrVkGpu::onWaitSemaphore(sk_sp<GrSemaphore> semaphore) { +void GrVkGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) { GrVkSemaphore* vkSem = static_cast<GrVkSemaphore*>(semaphore.get()); - SkASSERT(vkSem); - const GrVkSemaphore::Resource* resource = vkSem->getResource(); - resource->ref(); - fSemaphoresToWaitOn.push_back(resource); + GrVkSemaphore::Resource* resource = vkSem->getResource(); + if (resource->shouldWait()) { + resource->ref(); + fSemaphoresToWaitOn.push_back(resource); + } } sk_sp<GrSemaphore> GrVkGpu::prepareTextureForCrossContextUsage(GrTexture* texture) { diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index e3055945bc..8cc98d9da1 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -135,6 +135,12 @@ public: void deleteFence(GrFence) const override; sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override; + sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore, + GrResourceProvider::SemaphoreWrapType wrapType, + GrWrapOwnership ownership) override; + void insertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override; + void waitSemaphore(sk_sp<GrSemaphore> semaphore) override; + sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override; void generateMipmap(GrVkTexture* tex, GrSurfaceOrigin texOrigin); @@ -204,11 +210,6 @@ private: void onFinishFlush(bool insertedSemaphores) override; - void onInsertSemaphore(sk_sp<GrSemaphore> semaphore, bool flush) override; - void onWaitSemaphore(sk_sp<GrSemaphore> semaphore) override; - sk_sp<GrSemaphore> onWrapBackendSemaphore(const GrBackendSemaphore& semaphore, - GrWrapOwnership ownership) override; - // Ends and submits the current command buffer to the queue and then creates a new command // buffer and begins it. If sync is set to kForce_SyncQueue, the function will wait for all // work in the queue to finish before returning. If this GrVkGpu object has any semaphores in @@ -265,8 +266,8 @@ private: GrVkPrimaryCommandBuffer* fCurrentCmdBuffer; - SkSTArray<1, const GrVkSemaphore::Resource*> fSemaphoresToWaitOn; - SkSTArray<1, const GrVkSemaphore::Resource*> fSemaphoresToSignal; + SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToWaitOn; + SkSTArray<1, GrVkSemaphore::Resource*> fSemaphoresToSignal; VkPhysicalDeviceMemoryProperties fPhysDevMemProps; diff --git a/src/gpu/vk/GrVkSemaphore.cpp b/src/gpu/vk/GrVkSemaphore.cpp index 38946f4566..4a23c43eea 100644 --- a/src/gpu/vk/GrVkSemaphore.cpp +++ b/src/gpu/vk/GrVkSemaphore.cpp @@ -16,6 +16,8 @@ #undef CreateSemaphore #endif +SkMutex GrVkSemaphore::Resource::gMutex; + sk_sp<GrVkSemaphore> GrVkSemaphore::Make(const GrVkGpu* gpu, bool isOwned) { VkSemaphoreCreateInfo createInfo; memset(&createInfo, 0, sizeof(VkSemaphoreCreateInfo)); @@ -26,22 +28,26 @@ sk_sp<GrVkSemaphore> GrVkSemaphore::Make(const GrVkGpu* gpu, bool isOwned) { GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateSemaphore(gpu->device(), &createInfo, nullptr, &semaphore)); - return sk_sp<GrVkSemaphore>(new GrVkSemaphore(gpu, semaphore, isOwned)); + return sk_sp<GrVkSemaphore>(new GrVkSemaphore(gpu, semaphore, false, false, isOwned)); } sk_sp<GrVkSemaphore> GrVkSemaphore::MakeWrapped(const GrVkGpu* gpu, VkSemaphore semaphore, + WrapType wrapType, GrWrapOwnership ownership) { if (VK_NULL_HANDLE == semaphore) { return nullptr; } - return sk_sp<GrVkSemaphore>(new GrVkSemaphore(gpu, semaphore, + bool prohibitSignal = WrapType::kWillWait == wrapType; + bool prohibitWait = WrapType::kWillSignal == wrapType; + return sk_sp<GrVkSemaphore>(new GrVkSemaphore(gpu, semaphore, prohibitSignal, prohibitWait, kBorrow_GrWrapOwnership != ownership)); } -GrVkSemaphore::GrVkSemaphore(const GrVkGpu* gpu, VkSemaphore semaphore, bool isOwned) +GrVkSemaphore::GrVkSemaphore(const GrVkGpu* gpu, VkSemaphore semaphore, bool prohibitSignal, + bool prohibitWait, bool isOwned) : INHERITED(gpu) { - fResource = new Resource(semaphore, isOwned); + fResource = new Resource(semaphore, prohibitSignal, prohibitWait, isOwned); } GrVkSemaphore::~GrVkSemaphore() { diff --git a/src/gpu/vk/GrVkSemaphore.h b/src/gpu/vk/GrVkSemaphore.h index b99eb944f7..36d1e6ee5d 100644 --- a/src/gpu/vk/GrVkSemaphore.h +++ b/src/gpu/vk/GrVkSemaphore.h @@ -9,6 +9,8 @@ #define GrVkSemaphore_DEFINED #include "GrSemaphore.h" + +#include "GrResourceProvider.h" #include "GrVkResource.h" #include "vk/GrVkTypes.h" @@ -20,21 +22,47 @@ class GrVkSemaphore : public GrSemaphore { public: static sk_sp<GrVkSemaphore> Make(const GrVkGpu* gpu, bool isOwned); + using WrapType = GrResourceProvider::SemaphoreWrapType; + static sk_sp<GrVkSemaphore> MakeWrapped(const GrVkGpu* gpu, VkSemaphore semaphore, + WrapType wrapType, GrWrapOwnership); ~GrVkSemaphore() override; class Resource : public GrVkResource { public: - Resource(VkSemaphore semaphore, bool isOwned) - : INHERITED(), fSemaphore(semaphore), fIsOwned(isOwned) {} + Resource(VkSemaphore semaphore, bool prohibitSignal, bool prohibitWait, bool isOwned) + : INHERITED() + , fSemaphore(semaphore) + , fHasBeenSubmittedToQueueForSignal(prohibitSignal) + , fHasBeenSubmittedToQueueForWait(prohibitWait) + , fIsOwned(isOwned) {} ~Resource() override {} VkSemaphore semaphore() const { return fSemaphore; } + static void AcquireMutex() { gMutex.acquire(); } + static void ReleaseMutex() { gMutex.release(); } + + bool shouldSignal() const { + return !fHasBeenSubmittedToQueueForSignal; + } + bool shouldWait() const { + return !fHasBeenSubmittedToQueueForWait; + } + + void markAsSignaled() { + gMutex.assertHeld(); + fHasBeenSubmittedToQueueForSignal = true; + } + void markAsWaited() { + gMutex.assertHeld(); + fHasBeenSubmittedToQueueForWait = true; + } + #ifdef SK_TRACE_VK_RESOURCES void dumpInfo() const override { SkDebugf("GrVkSemaphore: %d (%d refs)\n", fSemaphore, this->getRefCnt()); @@ -43,20 +71,24 @@ public: private: void freeGPUData(const GrVkGpu* gpu) const override; + static SkMutex gMutex; VkSemaphore fSemaphore; + bool fHasBeenSubmittedToQueueForSignal; + bool fHasBeenSubmittedToQueueForWait; bool fIsOwned; typedef GrVkResource INHERITED; }; - const Resource* getResource() const { return fResource; } + Resource* getResource() { return fResource; } private: - GrVkSemaphore(const GrVkGpu* gpu, VkSemaphore semaphore, bool isOwned); + GrVkSemaphore(const GrVkGpu* gpu, VkSemaphore semaphore, bool prohibitSignal, bool prohibitWait, + bool isOwned); void setBackendSemaphore(GrBackendSemaphore*) const override; - const Resource* fResource; + Resource* fResource; typedef GrSemaphore INHERITED; }; |