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:
parent
574b951188
commit
c1583a558c
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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_
|
|
@ -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();
|
|
||||||
|
for (VkSemaphore semaphore : mRecordingContext.signalSemaphores) {
|
||||||
|
mDeleter->DeleteWhenUnused(semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::AddWaitSemaphore(VkSemaphore semaphore) {
|
mRecordingContext = CommandRecordingContext();
|
||||||
mWaitSemaphores.push_back(semaphore);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue