Create CommandRecordingContext

Adds a structure that contains wait / signal semaphores and the current command buffer. Will allow us to have a list of pending semaphores after recording, either to consume or do something smarter with in the future.

Bug: chromium:976495
Change-Id: Ib61455039bd97ac8b0ff701af2b694cc8794226d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9600
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Idan Raiter 2019-08-02 05:16:42 +00:00 committed by Commit Bot service account
parent 574b951188
commit c1583a558c
12 changed files with 141 additions and 72 deletions

View File

@ -163,7 +163,8 @@ namespace dawn_native { namespace vulkan {
return mHandle; return mHandle;
} }
void Buffer::TransitionUsageNow(VkCommandBuffer commands, dawn::BufferUsageBit usage) { void Buffer::TransitionUsageNow(CommandRecordingContext* recordingContext,
dawn::BufferUsageBit usage) {
bool lastIncludesTarget = (mLastUsage & usage) == usage; bool lastIncludesTarget = (mLastUsage & usage) == usage;
bool lastReadOnly = (mLastUsage & kReadOnlyBufferUsages) == mLastUsage; bool lastReadOnly = (mLastUsage & kReadOnlyBufferUsages) == mLastUsage;
@ -193,8 +194,8 @@ namespace dawn_native { namespace vulkan {
barrier.size = GetSize(); barrier.size = GetSize();
ToBackend(GetDevice()) ToBackend(GetDevice())
->fn.CmdPipelineBarrier(commands, srcStages, dstStages, 0, 0, nullptr, 1, &barrier, 0, ->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
nullptr); nullptr, 1, &barrier, 0, nullptr);
mLastUsage = usage; mLastUsage = usage;
} }
@ -212,8 +213,8 @@ namespace dawn_native { namespace vulkan {
MaybeError Buffer::MapReadAsyncImpl(uint32_t serial) { MaybeError Buffer::MapReadAsyncImpl(uint32_t serial) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
VkCommandBuffer commands = device->GetPendingCommandBuffer(); CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
TransitionUsageNow(commands, dawn::BufferUsageBit::MapRead); TransitionUsageNow(recordingContext, dawn::BufferUsageBit::MapRead);
uint8_t* memory = mMemoryAllocation.GetMappedPointer(); uint8_t* memory = mMemoryAllocation.GetMappedPointer();
ASSERT(memory != nullptr); ASSERT(memory != nullptr);
@ -226,8 +227,8 @@ namespace dawn_native { namespace vulkan {
MaybeError Buffer::MapWriteAsyncImpl(uint32_t serial) { MaybeError Buffer::MapWriteAsyncImpl(uint32_t serial) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
VkCommandBuffer commands = device->GetPendingCommandBuffer(); CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
TransitionUsageNow(commands, dawn::BufferUsageBit::MapWrite); TransitionUsageNow(recordingContext, dawn::BufferUsageBit::MapWrite);
uint8_t* memory = mMemoryAllocation.GetMappedPointer(); uint8_t* memory = mMemoryAllocation.GetMappedPointer();
ASSERT(memory != nullptr); ASSERT(memory != nullptr);

View File

@ -23,6 +23,7 @@
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
struct CommandRecordingContext;
class Device; class Device;
class Buffer : public BufferBase { class Buffer : public BufferBase {
@ -38,7 +39,8 @@ namespace dawn_native { namespace vulkan {
// Transitions the buffer to be used as `usage`, recording any necessary barrier in // Transitions the buffer to be used as `usage`, recording any necessary barrier in
// `commands`. // `commands`.
// TODO(cwallez@chromium.org): coalesce barriers and do them early when possible. // TODO(cwallez@chromium.org): coalesce barriers and do them early when possible.
void TransitionUsageNow(VkCommandBuffer commands, dawn::BufferUsageBit usage); void TransitionUsageNow(CommandRecordingContext* recordingContext,
dawn::BufferUsageBit usage);
private: private:
// Dawn API // Dawn API

View File

@ -18,6 +18,7 @@
#include "dawn_native/Commands.h" #include "dawn_native/Commands.h"
#include "dawn_native/vulkan/BindGroupVk.h" #include "dawn_native/vulkan/BindGroupVk.h"
#include "dawn_native/vulkan/BufferVk.h" #include "dawn_native/vulkan/BufferVk.h"
#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/ComputePipelineVk.h" #include "dawn_native/vulkan/ComputePipelineVk.h"
#include "dawn_native/vulkan/DeviceVk.h" #include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h" #include "dawn_native/vulkan/FencedDeleter.h"
@ -189,9 +190,11 @@ namespace dawn_native { namespace vulkan {
std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups> mDynamicOffsets; std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups> mDynamicOffsets;
}; };
void RecordBeginRenderPass(VkCommandBuffer commands, void RecordBeginRenderPass(CommandRecordingContext* recordingContext,
Device* device, Device* device,
BeginRenderPassCmd* renderPass) { BeginRenderPassCmd* renderPass) {
VkCommandBuffer commands = recordingContext->commandBuffer;
// Query a VkRenderPass from the cache // Query a VkRenderPass from the cache
VkRenderPass renderPassVK = VK_NULL_HANDLE; VkRenderPass renderPassVK = VK_NULL_HANDLE;
{ {
@ -232,7 +235,7 @@ namespace dawn_native { namespace vulkan {
attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) { attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) {
ToBackend(attachmentInfo.view->GetTexture()) ToBackend(attachmentInfo.view->GetTexture())
->EnsureSubresourceContentInitialized( ->EnsureSubresourceContentInitialized(
commands, attachmentInfo.view->GetBaseMipLevel(), recordingContext, attachmentInfo.view->GetBaseMipLevel(),
attachmentInfo.view->GetLevelCount(), attachmentInfo.view->GetLevelCount(),
attachmentInfo.view->GetBaseArrayLayer(), attachmentInfo.view->GetBaseArrayLayer(),
attachmentInfo.view->GetLayerCount()); attachmentInfo.view->GetLayerCount());
@ -339,14 +342,16 @@ namespace dawn_native { namespace vulkan {
FreeCommands(&mCommands); FreeCommands(&mCommands);
} }
void CommandBuffer::RecordCommands(VkCommandBuffer commands) { void CommandBuffer::RecordCommands(CommandRecordingContext* recordingContext) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
VkCommandBuffer commands = recordingContext->commandBuffer;
// Records the necessary barriers for the resource usage pre-computed by the frontend // Records the necessary barriers for the resource usage pre-computed by the frontend
auto TransitionForPass = [](VkCommandBuffer commands, const PassResourceUsage& usages) { auto TransitionForPass = [](CommandRecordingContext* recordingContext,
const PassResourceUsage& usages) {
for (size_t i = 0; i < usages.buffers.size(); ++i) { for (size_t i = 0; i < usages.buffers.size(); ++i) {
Buffer* buffer = ToBackend(usages.buffers[i]); Buffer* buffer = ToBackend(usages.buffers[i]);
buffer->TransitionUsageNow(commands, usages.bufferUsages[i]); buffer->TransitionUsageNow(recordingContext, usages.bufferUsages[i]);
} }
for (size_t i = 0; i < usages.textures.size(); ++i) { for (size_t i = 0; i < usages.textures.size(); ++i) {
Texture* texture = ToBackend(usages.textures[i]); Texture* texture = ToBackend(usages.textures[i]);
@ -354,8 +359,8 @@ namespace dawn_native { namespace vulkan {
// TODO(natlee@microsoft.com): Update clearing here when subresource tracking is // TODO(natlee@microsoft.com): Update clearing here when subresource tracking is
// implemented // implemented
texture->EnsureSubresourceContentInitialized( texture->EnsureSubresourceContentInitialized(
commands, 0, texture->GetNumMipLevels(), 0, texture->GetArrayLayers()); recordingContext, 0, texture->GetNumMipLevels(), 0, texture->GetArrayLayers());
texture->TransitionUsageNow(commands, usages.textureUsages[i]); texture->TransitionUsageNow(recordingContext, usages.textureUsages[i]);
} }
}; };
@ -370,8 +375,8 @@ namespace dawn_native { namespace vulkan {
Buffer* srcBuffer = ToBackend(copy->source.Get()); Buffer* srcBuffer = ToBackend(copy->source.Get());
Buffer* dstBuffer = ToBackend(copy->destination.Get()); Buffer* dstBuffer = ToBackend(copy->destination.Get());
srcBuffer->TransitionUsageNow(commands, dawn::BufferUsageBit::CopySrc); srcBuffer->TransitionUsageNow(recordingContext, dawn::BufferUsageBit::CopySrc);
dstBuffer->TransitionUsageNow(commands, dawn::BufferUsageBit::CopyDst); dstBuffer->TransitionUsageNow(recordingContext, dawn::BufferUsageBit::CopyDst);
VkBufferCopy region; VkBufferCopy region;
region.srcOffset = copy->sourceOffset; region.srcOffset = copy->sourceOffset;
@ -399,13 +404,14 @@ namespace dawn_native { namespace vulkan {
subresource.mipLevel, 1, subresource.baseArrayLayer, 1); subresource.mipLevel, 1, subresource.baseArrayLayer, 1);
} else { } else {
ToBackend(dst.texture) ToBackend(dst.texture)
->EnsureSubresourceContentInitialized(commands, subresource.mipLevel, 1, ->EnsureSubresourceContentInitialized(recordingContext,
subresource.mipLevel, 1,
subresource.baseArrayLayer, 1); subresource.baseArrayLayer, 1);
} }
ToBackend(src.buffer) ToBackend(src.buffer)
->TransitionUsageNow(commands, dawn::BufferUsageBit::CopySrc); ->TransitionUsageNow(recordingContext, dawn::BufferUsageBit::CopySrc);
ToBackend(dst.texture) ToBackend(dst.texture)
->TransitionUsageNow(commands, dawn::TextureUsageBit::CopyDst); ->TransitionUsageNow(recordingContext, dawn::TextureUsageBit::CopyDst);
VkBuffer srcBuffer = ToBackend(src.buffer)->GetHandle(); VkBuffer srcBuffer = ToBackend(src.buffer)->GetHandle();
VkImage dstImage = ToBackend(dst.texture)->GetHandle(); VkImage dstImage = ToBackend(dst.texture)->GetHandle();
@ -426,13 +432,14 @@ namespace dawn_native { namespace vulkan {
VkImageSubresourceLayers subresource = region.imageSubresource; VkImageSubresourceLayers subresource = region.imageSubresource;
ToBackend(src.texture) ToBackend(src.texture)
->EnsureSubresourceContentInitialized(commands, subresource.mipLevel, 1, ->EnsureSubresourceContentInitialized(recordingContext,
subresource.mipLevel, 1,
subresource.baseArrayLayer, 1); subresource.baseArrayLayer, 1);
ToBackend(src.texture) ToBackend(src.texture)
->TransitionUsageNow(commands, dawn::TextureUsageBit::CopySrc); ->TransitionUsageNow(recordingContext, dawn::TextureUsageBit::CopySrc);
ToBackend(dst.buffer) ToBackend(dst.buffer)
->TransitionUsageNow(commands, dawn::BufferUsageBit::CopyDst); ->TransitionUsageNow(recordingContext, dawn::BufferUsageBit::CopyDst);
VkImage srcImage = ToBackend(src.texture)->GetHandle(); VkImage srcImage = ToBackend(src.texture)->GetHandle();
VkBuffer dstBuffer = ToBackend(dst.buffer)->GetHandle(); VkBuffer dstBuffer = ToBackend(dst.buffer)->GetHandle();
@ -452,7 +459,8 @@ namespace dawn_native { namespace vulkan {
VkImageSubresourceLayers srcSubresource = region.srcSubresource; VkImageSubresourceLayers srcSubresource = region.srcSubresource;
ToBackend(src.texture) ToBackend(src.texture)
->EnsureSubresourceContentInitialized(commands, srcSubresource.mipLevel, 1, ->EnsureSubresourceContentInitialized(recordingContext,
srcSubresource.mipLevel, 1,
srcSubresource.baseArrayLayer, 1); srcSubresource.baseArrayLayer, 1);
if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize,
dstSubresource.mipLevel)) { dstSubresource.mipLevel)) {
@ -461,14 +469,14 @@ namespace dawn_native { namespace vulkan {
dstSubresource.mipLevel, 1, dstSubresource.baseArrayLayer, 1); dstSubresource.mipLevel, 1, dstSubresource.baseArrayLayer, 1);
} else { } else {
ToBackend(dst.texture) ToBackend(dst.texture)
->EnsureSubresourceContentInitialized(commands, dstSubresource.mipLevel, ->EnsureSubresourceContentInitialized(recordingContext,
1, dstSubresource.baseArrayLayer, dstSubresource.mipLevel, 1,
1); dstSubresource.baseArrayLayer, 1);
} }
ToBackend(src.texture) ToBackend(src.texture)
->TransitionUsageNow(commands, dawn::TextureUsageBit::CopySrc); ->TransitionUsageNow(recordingContext, dawn::TextureUsageBit::CopySrc);
ToBackend(dst.texture) ToBackend(dst.texture)
->TransitionUsageNow(commands, dawn::TextureUsageBit::CopyDst); ->TransitionUsageNow(recordingContext, dawn::TextureUsageBit::CopyDst);
VkImage srcImage = ToBackend(src.texture)->GetHandle(); VkImage srcImage = ToBackend(src.texture)->GetHandle();
VkImage dstImage = ToBackend(dst.texture)->GetHandle(); VkImage dstImage = ToBackend(dst.texture)->GetHandle();
@ -481,8 +489,8 @@ namespace dawn_native { namespace vulkan {
case Command::BeginRenderPass: { case Command::BeginRenderPass: {
BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>(); BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
TransitionForPass(commands, passResourceUsages[nextPassNumber]); TransitionForPass(recordingContext, passResourceUsages[nextPassNumber]);
RecordRenderPass(commands, cmd); RecordRenderPass(recordingContext, cmd);
nextPassNumber++; nextPassNumber++;
} break; } break;
@ -490,8 +498,8 @@ namespace dawn_native { namespace vulkan {
case Command::BeginComputePass: { case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>(); mCommands.NextCommand<BeginComputePassCmd>();
TransitionForPass(commands, passResourceUsages[nextPassNumber]); TransitionForPass(recordingContext, passResourceUsages[nextPassNumber]);
RecordComputePass(commands); RecordComputePass(recordingContext);
nextPassNumber++; nextPassNumber++;
} break; } break;
@ -501,8 +509,9 @@ namespace dawn_native { namespace vulkan {
} }
} }
void CommandBuffer::RecordComputePass(VkCommandBuffer commands) { void CommandBuffer::RecordComputePass(CommandRecordingContext* recordingContext) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
VkCommandBuffer commands = recordingContext->commandBuffer;
DescriptorSetTracker descriptorSets; DescriptorSetTracker descriptorSets;
@ -558,11 +567,12 @@ namespace dawn_native { namespace vulkan {
// EndComputePass should have been called // EndComputePass should have been called
UNREACHABLE(); UNREACHABLE();
} }
void CommandBuffer::RecordRenderPass(VkCommandBuffer commands, void CommandBuffer::RecordRenderPass(CommandRecordingContext* recordingContext,
BeginRenderPassCmd* renderPassCmd) { BeginRenderPassCmd* renderPassCmd) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
VkCommandBuffer commands = recordingContext->commandBuffer;
RecordBeginRenderPass(commands, device, renderPassCmd); RecordBeginRenderPass(recordingContext, device, renderPassCmd);
// Set the default value for the dynamic state // Set the default value for the dynamic state
{ {

View File

@ -26,6 +26,7 @@ namespace dawn_native {
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
struct CommandRecordingContext;
class Device; class Device;
class CommandBuffer : public CommandBufferBase { class CommandBuffer : public CommandBufferBase {
@ -33,11 +34,12 @@ namespace dawn_native { namespace vulkan {
CommandBuffer(CommandEncoderBase* encoder, const CommandBufferDescriptor* descriptor); CommandBuffer(CommandEncoderBase* encoder, const CommandBufferDescriptor* descriptor);
~CommandBuffer(); ~CommandBuffer();
void RecordCommands(VkCommandBuffer commands); void RecordCommands(CommandRecordingContext* recordingContext);
private: private:
void RecordComputePass(VkCommandBuffer commands); void RecordComputePass(CommandRecordingContext* recordingContext);
void RecordRenderPass(VkCommandBuffer commands, BeginRenderPassCmd* renderPass); void RecordRenderPass(CommandRecordingContext* recordingContext,
BeginRenderPassCmd* renderPass);
CommandIterator mCommands; CommandIterator mCommands;
}; };

View File

@ -0,0 +1,33 @@
// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DAWNNATIVE_VULKAN_COMMANDRECORDINGCONTEXT_H_
#define DAWNNATIVE_VULKAN_COMMANDRECORDINGCONTEXT_H_
#include "common/vulkan_platform.h"
#include <vector>
namespace dawn_native { namespace vulkan {
// Used to track operations that are handled after recording.
// Currently only tracks semaphores, but may be used to do barrier coalescing in the future.
struct CommandRecordingContext {
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
std::vector<VkSemaphore> waitSemaphores = {};
std::vector<VkSemaphore> signalSemaphores = {};
};
}} // namespace dawn_native::vulkan
#endif // DAWNNATIVE_VULKAN_COMMANDRECORDINGCONTEXT_H_

View File

@ -108,7 +108,8 @@ namespace dawn_native { namespace vulkan {
} }
mUnusedCommands.clear(); mUnusedCommands.clear();
ASSERT(mWaitSemaphores.empty()); ASSERT(mRecordingContext.waitSemaphores.empty());
ASSERT(mRecordingContext.signalSemaphores.empty());
for (VkFence fence : mUnusedFences) { for (VkFence fence : mUnusedFences) {
fn.DestroyFence(mVkDevice, fence, nullptr); fn.DestroyFence(mVkDevice, fence, nullptr);
@ -276,6 +277,14 @@ namespace dawn_native { namespace vulkan {
return mPendingCommands.commandBuffer; return mPendingCommands.commandBuffer;
} }
CommandRecordingContext* Device::GetPendingRecordingContext() {
if (mRecordingContext.commandBuffer == VK_NULL_HANDLE) {
mRecordingContext.commandBuffer = GetPendingCommandBuffer();
}
return &mRecordingContext;
}
void Device::SubmitPendingCommands() { void Device::SubmitPendingCommands() {
if (mPendingCommands.pool == VK_NULL_HANDLE) { if (mPendingCommands.pool == VK_NULL_HANDLE) {
return; return;
@ -285,19 +294,21 @@ namespace dawn_native { namespace vulkan {
ASSERT(false); ASSERT(false);
} }
std::vector<VkPipelineStageFlags> dstStageMasks(mWaitSemaphores.size(), std::vector<VkPipelineStageFlags> dstStageMasks(mRecordingContext.waitSemaphores.size(),
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
VkSubmitInfo submitInfo; VkSubmitInfo submitInfo;
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = nullptr; submitInfo.pNext = nullptr;
submitInfo.waitSemaphoreCount = static_cast<uint32_t>(mWaitSemaphores.size()); submitInfo.waitSemaphoreCount =
submitInfo.pWaitSemaphores = mWaitSemaphores.data(); static_cast<uint32_t>(mRecordingContext.waitSemaphores.size());
submitInfo.pWaitSemaphores = mRecordingContext.waitSemaphores.data();
submitInfo.pWaitDstStageMask = dstStageMasks.data(); submitInfo.pWaitDstStageMask = dstStageMasks.data();
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &mPendingCommands.commandBuffer; submitInfo.pCommandBuffers = &mPendingCommands.commandBuffer;
submitInfo.signalSemaphoreCount = 0; submitInfo.signalSemaphoreCount =
submitInfo.pSignalSemaphores = 0; static_cast<uint32_t>(mRecordingContext.signalSemaphores.size());
submitInfo.pSignalSemaphores = mRecordingContext.signalSemaphores.data();
VkFence fence = GetUnusedFence(); VkFence fence = GetUnusedFence();
if (fn.QueueSubmit(mQueue, 1, &submitInfo, fence) != VK_SUCCESS) { if (fn.QueueSubmit(mQueue, 1, &submitInfo, fence) != VK_SUCCESS) {
@ -309,14 +320,15 @@ namespace dawn_native { namespace vulkan {
mPendingCommands = CommandPoolAndBuffer(); mPendingCommands = CommandPoolAndBuffer();
mFencesInFlight.emplace(fence, mLastSubmittedSerial); mFencesInFlight.emplace(fence, mLastSubmittedSerial);
for (VkSemaphore semaphore : mWaitSemaphores) { for (VkSemaphore semaphore : mRecordingContext.waitSemaphores) {
mDeleter->DeleteWhenUnused(semaphore); mDeleter->DeleteWhenUnused(semaphore);
} }
mWaitSemaphores.clear();
}
void Device::AddWaitSemaphore(VkSemaphore semaphore) { for (VkSemaphore semaphore : mRecordingContext.signalSemaphores) {
mWaitSemaphores.push_back(semaphore); mDeleter->DeleteWhenUnused(semaphore);
}
mRecordingContext = CommandRecordingContext();
} }
ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalDevice) { ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalDevice) {
@ -529,7 +541,7 @@ namespace dawn_native { namespace vulkan {
// Insert pipeline barrier to ensure correct ordering with previous memory operations on the // Insert pipeline barrier to ensure correct ordering with previous memory operations on the
// buffer. // buffer.
ToBackend(destination) ToBackend(destination)
->TransitionUsageNow(GetPendingCommandBuffer(), dawn::BufferUsageBit::CopyDst); ->TransitionUsageNow(GetPendingRecordingContext(), dawn::BufferUsageBit::CopyDst);
VkBufferCopy copy; VkBufferCopy copy;
copy.srcOffset = sourceOffset; copy.srcOffset = sourceOffset;

View File

@ -20,6 +20,7 @@
#include "common/Serial.h" #include "common/Serial.h"
#include "common/SerialQueue.h" #include "common/SerialQueue.h"
#include "dawn_native/Device.h" #include "dawn_native/Device.h"
#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/Forward.h" #include "dawn_native/vulkan/Forward.h"
#include "dawn_native/vulkan/VulkanFunctions.h" #include "dawn_native/vulkan/VulkanFunctions.h"
#include "dawn_native/vulkan/VulkanInfo.h" #include "dawn_native/vulkan/VulkanInfo.h"
@ -59,9 +60,9 @@ namespace dawn_native { namespace vulkan {
RenderPassCache* GetRenderPassCache() const; RenderPassCache* GetRenderPassCache() const;
VkCommandBuffer GetPendingCommandBuffer(); VkCommandBuffer GetPendingCommandBuffer();
CommandRecordingContext* GetPendingRecordingContext();
Serial GetPendingCommandSerial() const override; Serial GetPendingCommandSerial() const override;
void SubmitPendingCommands(); void SubmitPendingCommands();
void AddWaitSemaphore(VkSemaphore semaphore);
// Dawn API // Dawn API
CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder, CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder,
@ -142,7 +143,8 @@ namespace dawn_native { namespace vulkan {
SerialQueue<CommandPoolAndBuffer> mCommandsInFlight; SerialQueue<CommandPoolAndBuffer> mCommandsInFlight;
std::vector<CommandPoolAndBuffer> mUnusedCommands; std::vector<CommandPoolAndBuffer> mUnusedCommands;
CommandPoolAndBuffer mPendingCommands; CommandPoolAndBuffer mPendingCommands;
std::vector<VkSemaphore> mWaitSemaphores;
CommandRecordingContext mRecordingContext;
}; };
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan

View File

@ -184,7 +184,7 @@ namespace dawn_native { namespace vulkan {
} }
nextTexture->texture.u64 = mSwapChainImages[mLastImageIndex].GetU64(); nextTexture->texture.u64 = mSwapChainImages[mLastImageIndex].GetU64();
mDevice->AddWaitSemaphore(semaphore); mDevice->GetPendingRecordingContext()->waitSemaphores.push_back(semaphore);
return DAWN_SWAP_CHAIN_NO_ERROR; return DAWN_SWAP_CHAIN_NO_ERROR;
} }

View File

@ -15,6 +15,7 @@
#include "dawn_native/vulkan/QueueVk.h" #include "dawn_native/vulkan/QueueVk.h"
#include "dawn_native/vulkan/CommandBufferVk.h" #include "dawn_native/vulkan/CommandBufferVk.h"
#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/DeviceVk.h" #include "dawn_native/vulkan/DeviceVk.h"
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
@ -30,9 +31,9 @@ namespace dawn_native { namespace vulkan {
device->Tick(); device->Tick();
VkCommandBuffer commandBuffer = device->GetPendingCommandBuffer(); CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
for (uint32_t i = 0; i < commandCount; ++i) { for (uint32_t i = 0; i < commandCount; ++i) {
ToBackend(commands[i])->RecordCommands(commandBuffer); ToBackend(commands[i])->RecordCommands(recordingContext);
} }
device->SubmitPendingCommands(); device->SubmitPendingCommands();

View File

@ -51,8 +51,8 @@ namespace dawn_native { namespace vulkan {
// Perform the necessary pipeline barriers for the texture to be used with the usage // Perform the necessary pipeline barriers for the texture to be used with the usage
// requested by the implementation. // requested by the implementation.
VkCommandBuffer commands = device->GetPendingCommandBuffer(); CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
ToBackend(texture)->TransitionUsageNow(commands, mTextureUsage); ToBackend(texture)->TransitionUsageNow(recordingContext, mTextureUsage);
device->SubmitPendingCommands(); device->SubmitPendingCommands();
} }

View File

@ -15,6 +15,7 @@
#include "dawn_native/vulkan/TextureVk.h" #include "dawn_native/vulkan/TextureVk.h"
#include "dawn_native/vulkan/AdapterVk.h" #include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/DeviceVk.h" #include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h" #include "dawn_native/vulkan/FencedDeleter.h"
@ -436,7 +437,7 @@ namespace dawn_native { namespace vulkan {
range.levelCount = GetNumMipLevels(); range.levelCount = GetNumMipLevels();
range.baseArrayLayer = 0; range.baseArrayLayer = 0;
range.layerCount = GetArrayLayers(); range.layerCount = GetArrayLayers();
TransitionUsageNow(ToBackend(GetDevice())->GetPendingCommandBuffer(), TransitionUsageNow(ToBackend(GetDevice())->GetPendingRecordingContext(),
dawn::TextureUsageBit::CopyDst); dawn::TextureUsageBit::CopyDst);
if (GetFormat().HasDepthOrStencil()) { if (GetFormat().HasDepthOrStencil()) {
@ -494,7 +495,8 @@ namespace dawn_native { namespace vulkan {
return VulkanAspectMask(GetFormat()); return VulkanAspectMask(GetFormat());
} }
void Texture::TransitionUsageNow(VkCommandBuffer commands, dawn::TextureUsageBit usage) { void Texture::TransitionUsageNow(CommandRecordingContext* recordingContext,
dawn::TextureUsageBit usage) {
// Avoid encoding barriers when it isn't needed. // Avoid encoding barriers when it isn't needed.
bool lastReadOnly = (mLastUsage & kReadOnlyTextureUsages) == mLastUsage; bool lastReadOnly = (mLastUsage & kReadOnlyTextureUsages) == mLastUsage;
if (lastReadOnly && mLastUsage == usage) { if (lastReadOnly && mLastUsage == usage) {
@ -525,13 +527,13 @@ namespace dawn_native { namespace vulkan {
barrier.subresourceRange.layerCount = GetArrayLayers(); barrier.subresourceRange.layerCount = GetArrayLayers();
ToBackend(GetDevice()) ToBackend(GetDevice())
->fn.CmdPipelineBarrier(commands, srcStages, dstStages, 0, 0, nullptr, 0, nullptr, 1, ->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
&barrier); nullptr, 0, nullptr, 1, &barrier);
mLastUsage = usage; mLastUsage = usage;
} }
void Texture::ClearTexture(VkCommandBuffer commands, void Texture::ClearTexture(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
@ -543,13 +545,13 @@ namespace dawn_native { namespace vulkan {
range.baseArrayLayer = baseArrayLayer; range.baseArrayLayer = baseArrayLayer;
range.layerCount = layerCount; range.layerCount = layerCount;
TransitionUsageNow(commands, dawn::TextureUsageBit::CopyDst); TransitionUsageNow(recordingContext, dawn::TextureUsageBit::CopyDst);
if (GetFormat().HasDepthOrStencil()) { if (GetFormat().HasDepthOrStencil()) {
VkClearDepthStencilValue clear_color[1]; VkClearDepthStencilValue clear_color[1];
clear_color[0].depth = 0.0f; clear_color[0].depth = 0.0f;
clear_color[0].stencil = 0u; clear_color[0].stencil = 0u;
ToBackend(GetDevice()) ToBackend(GetDevice())
->fn.CmdClearDepthStencilImage(commands, GetHandle(), ->fn.CmdClearDepthStencilImage(recordingContext->commandBuffer, GetHandle(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1,
&range); &range);
} else { } else {
@ -559,14 +561,15 @@ namespace dawn_native { namespace vulkan {
clear_color[0].float32[2] = 0.0f; clear_color[0].float32[2] = 0.0f;
clear_color[0].float32[3] = 0.0f; clear_color[0].float32[3] = 0.0f;
ToBackend(GetDevice()) ToBackend(GetDevice())
->fn.CmdClearColorImage(commands, GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(),
clear_color, 1, &range); VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1,
&range);
} }
SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, layerCount); SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, layerCount);
GetDevice()->IncrementLazyClearCountForTesting(); GetDevice()->IncrementLazyClearCountForTesting();
} }
void Texture::EnsureSubresourceContentInitialized(VkCommandBuffer commands, void Texture::EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
@ -584,7 +587,7 @@ namespace dawn_native { namespace vulkan {
// If subresource has not been initialized, clear it to black as it could contain dirty // If subresource has not been initialized, clear it to black as it could contain dirty
// bits from recycled memory // bits from recycled memory
ClearTexture(commands, baseMipLevel, levelCount, baseArrayLayer, layerCount); ClearTexture(recordingContext, baseMipLevel, levelCount, baseArrayLayer, layerCount);
} }
} }

View File

@ -22,6 +22,8 @@
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
struct CommandRecordingContext;
VkFormat VulkanImageFormat(dawn::TextureFormat format); VkFormat VulkanImageFormat(dawn::TextureFormat format);
VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, const Format& format); VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, const Format& format);
VkSampleCountFlagBits VulkanSampleCount(uint32_t sampleCount); VkSampleCountFlagBits VulkanSampleCount(uint32_t sampleCount);
@ -38,8 +40,9 @@ namespace dawn_native { namespace vulkan {
// Transitions the texture to be used as `usage`, recording any necessary barrier in // Transitions the texture to be used as `usage`, recording any necessary barrier in
// `commands`. // `commands`.
// TODO(cwallez@chromium.org): coalesce barriers and do them early when possible. // TODO(cwallez@chromium.org): coalesce barriers and do them early when possible.
void TransitionUsageNow(VkCommandBuffer commands, dawn::TextureUsageBit usage); void TransitionUsageNow(CommandRecordingContext* recordingContext,
void EnsureSubresourceContentInitialized(VkCommandBuffer commands, dawn::TextureUsageBit usage);
void EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
@ -47,7 +50,7 @@ namespace dawn_native { namespace vulkan {
private: private:
void DestroyImpl() override; void DestroyImpl() override;
void ClearTexture(VkCommandBuffer commands, void ClearTexture(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,