CommandBufferResourceUsage: track render and compute separately.

This change is a preparation for making the compute pass track the
synchronization scope usages per dispatch instead of for the whole pass.

 - Split the tracking of render and compute passes usages.
 - Rename PassTextureUsage to TextureSubresourceUsage since is it not
   per-pass
 - Add SyncScopeResourceUsage as a subclass of PassResourceUsage to
   start modifying some of the code to work with synchronization scopes
   (even if syncscope == pass at the moment).

There are no functional changes.

Bug: dawn:632
Change-Id: Ieeb6d70a44dc1c726f26989eebcd87e63e732785
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/49883
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Corentin Wallez 2021-05-05 15:41:13 +00:00 committed by Commit Bot service account
parent c63ac30826
commit 2dd2d67dbc
23 changed files with 141 additions and 113 deletions

View File

@ -133,8 +133,7 @@ namespace dawn_native {
mUsage(descriptor->usage), mUsage(descriptor->usage),
mState(BufferState::Unmapped) { mState(BufferState::Unmapped) {
// Add readonly storage usage if the buffer has a storage usage. The validation rules in // Add readonly storage usage if the buffer has a storage usage. The validation rules in
// ValidatePassResourceUsage will make sure we don't use both at the same // ValidateSyncScopeResourceUsage will make sure we don't use both at the same time.
// time.
if (mUsage & wgpu::BufferUsage::Storage) { if (mUsage & wgpu::BufferUsage::Storage) {
mUsage |= kReadOnlyStorageBuffer; mUsage |= kReadOnlyStorageBuffer;
} }

View File

@ -470,9 +470,9 @@ namespace dawn_native {
} }
CommandBufferResourceUsage CommandEncoder::AcquireResourceUsages() { CommandBufferResourceUsage CommandEncoder::AcquireResourceUsages() {
return CommandBufferResourceUsage{mEncodingContext.AcquirePassUsages(), return CommandBufferResourceUsage{
std::move(mTopLevelBuffers), std::move(mTopLevelTextures), mEncodingContext.AcquireRenderPassUsages(), mEncodingContext.AcquireComputePassUsages(),
std::move(mUsedQuerySets)}; std::move(mTopLevelBuffers), std::move(mTopLevelTextures), std::move(mUsedQuerySets)};
} }
CommandIterator CommandEncoder::AcquireCommands() { CommandIterator CommandEncoder::AcquireCommands() {
@ -936,21 +936,21 @@ namespace dawn_native {
DAWN_TRY(device->ValidateIsAlive()); DAWN_TRY(device->ValidateIsAlive());
if (device->IsValidationEnabled()) { if (device->IsValidationEnabled()) {
DAWN_TRY( DAWN_TRY(ValidateFinish());
ValidateFinish(mEncodingContext.GetIterator(), mEncodingContext.GetPassUsages()));
} }
return device->CreateCommandBuffer(this, descriptor); return device->CreateCommandBuffer(this, descriptor);
} }
// Implementation of the command buffer validation that can be precomputed before submit // Implementation of the command buffer validation that can be precomputed before submit
MaybeError CommandEncoder::ValidateFinish(CommandIterator* commands, MaybeError CommandEncoder::ValidateFinish() const {
const PerPassUsages& perPassUsages) const {
TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "CommandEncoder::ValidateFinish"); TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "CommandEncoder::ValidateFinish");
DAWN_TRY(GetDevice()->ValidateObject(this)); DAWN_TRY(GetDevice()->ValidateObject(this));
for (const PassResourceUsage& passUsage : perPassUsages) { for (const PassResourceUsage& passUsage : mEncodingContext.GetRenderPassUsages()) {
DAWN_TRY(ValidatePassResourceUsage(passUsage)); DAWN_TRY(ValidateSyncScopeResourceUsage(passUsage));
} }
// TODO(dawn:632): The synchronization scopes of compute passes should be validated here
// once they are tracked per-dispatch.
if (mDebugGroupStackSize != 0) { if (mDebugGroupStackSize != 0) {
return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop."); return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop.");

View File

@ -73,8 +73,7 @@ namespace dawn_native {
ResultOrError<Ref<CommandBufferBase>> FinishInternal( ResultOrError<Ref<CommandBufferBase>> FinishInternal(
const CommandBufferDescriptor* descriptor); const CommandBufferDescriptor* descriptor);
MaybeError ValidateFinish(CommandIterator* commands, MaybeError ValidateFinish() const;
const PerPassUsages& perPassUsages) const;
EncodingContext mEncodingContext; EncodingContext mEncodingContext;
std::set<BufferBase*> mTopLevelBuffers; std::set<BufferBase*> mTopLevelBuffers;

View File

@ -28,20 +28,10 @@
namespace dawn_native { namespace dawn_native {
// Performs the per-pass usage validation checks // Performs validation of the "synchronization scope" rules of WebGPU.
// This will eventually need to differentiate between render and compute passes. MaybeError ValidateSyncScopeResourceUsage(const SyncScopeResourceUsage& scope) {
// It will be valid to use a buffer both as uniform and storage in the same compute pass.
// TODO(yunchao.he@intel.com): add read/write usage tracking for compute
MaybeError ValidatePassResourceUsage(const PassResourceUsage& pass) {
// TODO(cwallez@chromium.org): Remove this special casing once the PassResourceUsage is a
// SyncScopeResourceUsage.
if (pass.passType != PassType::Render) {
return {};
}
// Buffers can only be used as single-write or multiple read. // Buffers can only be used as single-write or multiple read.
for (size_t i = 0; i < pass.buffers.size(); ++i) { for (wgpu::BufferUsage usage : scope.bufferUsages) {
wgpu::BufferUsage usage = pass.bufferUsages[i];
bool readOnly = IsSubset(usage, kReadOnlyBufferUsages); bool readOnly = IsSubset(usage, kReadOnlyBufferUsages);
bool singleUse = wgpu::HasZeroOrOneBits(usage); bool singleUse = wgpu::HasZeroOrOneBits(usage);
@ -53,7 +43,7 @@ namespace dawn_native {
// Check that every single subresource is used as either a single-write usage or a // Check that every single subresource is used as either a single-write usage or a
// combination of readonly usages. // combination of readonly usages.
for (const PassTextureUsage& textureUsage : pass.textureUsages) { for (const TextureSubresourceUsage& textureUsage : scope.textureUsages) {
MaybeError error = {}; MaybeError error = {};
textureUsage.Iterate([&](const SubresourceRange&, const wgpu::TextureUsage& usage) { textureUsage.Iterate([&](const SubresourceRange&, const wgpu::TextureUsage& usage) {
bool readOnly = IsSubset(usage, kReadOnlyTextureUsages); bool readOnly = IsSubset(usage, kReadOnlyTextureUsages);

View File

@ -24,10 +24,10 @@
namespace dawn_native { namespace dawn_native {
class QuerySetBase; class QuerySetBase;
struct PassResourceUsage; struct SyncScopeResourceUsage;
struct TexelBlockInfo; struct TexelBlockInfo;
MaybeError ValidatePassResourceUsage(const PassResourceUsage& usage); MaybeError ValidateSyncScopeResourceUsage(const SyncScopeResourceUsage& usage);
MaybeError ValidateTimestampQuery(QuerySetBase* querySet, uint32_t queryIndex); MaybeError ValidateTimestampQuery(QuerySetBase* querySet, uint32_t queryIndex);

View File

@ -55,7 +55,8 @@ namespace dawn_native {
return {}; return {};
})) { })) {
mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage()); mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage(),
PassType::Compute);
} }
} }

View File

@ -76,25 +76,43 @@ namespace dawn_native {
mCurrentEncoder = passEncoder; mCurrentEncoder = passEncoder;
} }
void EncodingContext::ExitPass(const ObjectBase* passEncoder, PassResourceUsage passUsage) { void EncodingContext::ExitPass(const ObjectBase* passEncoder,
PassResourceUsage passUsage,
PassType type) {
// Assert we're not at the top level. // Assert we're not at the top level.
ASSERT(mCurrentEncoder != mTopLevelEncoder); ASSERT(mCurrentEncoder != mTopLevelEncoder);
// Assert the pass encoder is current. // Assert the pass encoder is current.
ASSERT(mCurrentEncoder == passEncoder); ASSERT(mCurrentEncoder == passEncoder);
mCurrentEncoder = mTopLevelEncoder; mCurrentEncoder = mTopLevelEncoder;
mPassUsages.push_back(std::move(passUsage));
if (type == PassType::Render) {
mRenderPassUsages.push_back(std::move(passUsage));
} else {
mComputePassUsages.push_back(std::move(passUsage));
}
} }
const PerPassUsages& EncodingContext::GetPassUsages() const { const RenderPassUsages& EncodingContext::GetRenderPassUsages() const {
ASSERT(!mWerePassUsagesAcquired); ASSERT(!mWereRenderPassUsagesAcquired);
return mPassUsages; return mRenderPassUsages;
} }
PerPassUsages EncodingContext::AcquirePassUsages() { RenderPassUsages EncodingContext::AcquireRenderPassUsages() {
ASSERT(!mWerePassUsagesAcquired); ASSERT(!mWereRenderPassUsagesAcquired);
mWerePassUsagesAcquired = true; mWereRenderPassUsagesAcquired = true;
return std::move(mPassUsages); return std::move(mRenderPassUsages);
}
const ComputePassUsages& EncodingContext::GetComputePassUsages() const {
ASSERT(!mWereComputePassUsagesAcquired);
return mComputePassUsages;
}
ComputePassUsages EncodingContext::AcquireComputePassUsages() {
ASSERT(!mWereComputePassUsagesAcquired);
mWereComputePassUsagesAcquired = true;
return std::move(mComputePassUsages);
} }
MaybeError EncodingContext::Finish() { MaybeError EncodingContext::Finish() {

View File

@ -79,11 +79,13 @@ namespace dawn_native {
// Functions to set current encoder state // Functions to set current encoder state
void EnterPass(const ObjectBase* passEncoder); void EnterPass(const ObjectBase* passEncoder);
void ExitPass(const ObjectBase* passEncoder, PassResourceUsage passUsages); void ExitPass(const ObjectBase* passEncoder, PassResourceUsage passUsages, PassType type);
MaybeError Finish(); MaybeError Finish();
const PerPassUsages& GetPassUsages() const; const RenderPassUsages& GetRenderPassUsages() const;
PerPassUsages AcquirePassUsages(); const ComputePassUsages& GetComputePassUsages() const;
RenderPassUsages AcquireRenderPassUsages();
ComputePassUsages AcquireComputePassUsages();
private: private:
bool IsFinished() const; bool IsFinished() const;
@ -101,8 +103,10 @@ namespace dawn_native {
// CommandEncoder::Begin/EndPass. // CommandEncoder::Begin/EndPass.
const ObjectBase* mCurrentEncoder; const ObjectBase* mCurrentEncoder;
PerPassUsages mPassUsages; RenderPassUsages mRenderPassUsages;
bool mWerePassUsagesAcquired = false; bool mWereRenderPassUsagesAcquired = false;
ComputePassUsages mComputePassUsages;
bool mWereComputePassUsagesAcquired = false;
CommandAllocator mAllocator; CommandAllocator mAllocator;
CommandIterator mIterator; CommandIterator mIterator;

View File

@ -30,27 +30,31 @@ namespace dawn_native {
enum class PassType { Render, Compute }; enum class PassType { Render, Compute };
// The texture usage inside passes must be tracked per-subresource. // The texture usage inside passes must be tracked per-subresource.
using PassTextureUsage = SubresourceStorage<wgpu::TextureUsage>; using TextureSubresourceUsage = SubresourceStorage<wgpu::TextureUsage>;
// Which resources are used by pass and how they are used. The command buffer validation // Which resources are used by a synchronization scope and how they are used. The command
// pre-computes this information so that backends with explicit barriers don't have to // buffer validation pre-computes this information so that backends with explicit barriers
// re-compute it. // don't have to re-compute it.
struct PassResourceUsage { struct SyncScopeResourceUsage {
PassType passType;
std::vector<BufferBase*> buffers; std::vector<BufferBase*> buffers;
std::vector<wgpu::BufferUsage> bufferUsages; std::vector<wgpu::BufferUsage> bufferUsages;
std::vector<TextureBase*> textures; std::vector<TextureBase*> textures;
std::vector<PassTextureUsage> textureUsages; std::vector<TextureSubresourceUsage> textureUsages;
};
// Additional data tracked per-pass.
struct PassResourceUsage : public SyncScopeResourceUsage {
std::vector<QuerySetBase*> querySets; std::vector<QuerySetBase*> querySets;
std::vector<std::vector<bool>> queryAvailabilities; std::vector<std::vector<bool>> queryAvailabilities;
}; };
using PerPassUsages = std::vector<PassResourceUsage>; using RenderPassUsages = std::vector<PassResourceUsage>;
using ComputePassUsages = std::vector<PassResourceUsage>;
struct CommandBufferResourceUsage { struct CommandBufferResourceUsage {
PerPassUsages perPass; RenderPassUsages renderPasses;
ComputePassUsages computePasses;
std::set<BufferBase*> topLevelBuffers; std::set<BufferBase*> topLevelBuffers;
std::set<TextureBase*> topLevelTextures; std::set<TextureBase*> topLevelTextures;
std::set<QuerySetBase*> usedQuerySets; std::set<QuerySetBase*> usedQuerySets;

View File

@ -37,13 +37,13 @@ namespace dawn_native {
TextureBase* texture = view->GetTexture(); TextureBase* texture = view->GetTexture();
const SubresourceRange& range = view->GetSubresourceRange(); const SubresourceRange& range = view->GetSubresourceRange();
// Get or create a new PassTextureUsage for that texture (initially filled with // Get or create a new TextureSubresourceUsage for that texture (initially filled with
// wgpu::TextureUsage::None) // wgpu::TextureUsage::None)
auto it = mTextureUsages.emplace( auto it = mTextureUsages.emplace(
std::piecewise_construct, std::forward_as_tuple(texture), std::piecewise_construct, std::forward_as_tuple(texture),
std::forward_as_tuple(texture->GetFormat().aspects, texture->GetArrayLayers(), std::forward_as_tuple(texture->GetFormat().aspects, texture->GetArrayLayers(),
texture->GetNumMipLevels(), wgpu::TextureUsage::None)); texture->GetNumMipLevels(), wgpu::TextureUsage::None));
PassTextureUsage& textureUsage = it.first->second; TextureSubresourceUsage& textureUsage = it.first->second;
textureUsage.Update(range, textureUsage.Update(range,
[usage](const SubresourceRange&, wgpu::TextureUsage* storedUsage) { [usage](const SubresourceRange&, wgpu::TextureUsage* storedUsage) {
@ -52,14 +52,14 @@ namespace dawn_native {
} }
void PassResourceUsageTracker::AddTextureUsage(TextureBase* texture, void PassResourceUsageTracker::AddTextureUsage(TextureBase* texture,
const PassTextureUsage& textureUsage) { const TextureSubresourceUsage& textureUsage) {
// Get or create a new PassTextureUsage for that texture (initially filled with // Get or create a new TextureSubresourceUsage for that texture (initially filled with
// wgpu::TextureUsage::None) // wgpu::TextureUsage::None)
auto it = mTextureUsages.emplace( auto it = mTextureUsages.emplace(
std::piecewise_construct, std::forward_as_tuple(texture), std::piecewise_construct, std::forward_as_tuple(texture),
std::forward_as_tuple(texture->GetFormat().aspects, texture->GetArrayLayers(), std::forward_as_tuple(texture->GetFormat().aspects, texture->GetArrayLayers(),
texture->GetNumMipLevels(), wgpu::TextureUsage::None)); texture->GetNumMipLevels(), wgpu::TextureUsage::None));
PassTextureUsage* passTextureUsage = &it.first->second; TextureSubresourceUsage* passTextureUsage = &it.first->second;
passTextureUsage->Merge( passTextureUsage->Merge(
textureUsage, [](const SubresourceRange&, wgpu::TextureUsage* storedUsage, textureUsage, [](const SubresourceRange&, wgpu::TextureUsage* storedUsage,
@ -86,7 +86,6 @@ namespace dawn_native {
// Returns the per-pass usage for use by backends for APIs with explicit barriers. // Returns the per-pass usage for use by backends for APIs with explicit barriers.
PassResourceUsage PassResourceUsageTracker::AcquireResourceUsage() { PassResourceUsage PassResourceUsageTracker::AcquireResourceUsage() {
PassResourceUsage result; PassResourceUsage result;
result.passType = mPassType;
result.buffers.reserve(mBufferUsages.size()); result.buffers.reserve(mBufferUsages.size());
result.bufferUsages.reserve(mBufferUsages.size()); result.bufferUsages.reserve(mBufferUsages.size());
result.textures.reserve(mTextureUsages.size()); result.textures.reserve(mTextureUsages.size());

View File

@ -38,7 +38,7 @@ namespace dawn_native {
PassResourceUsageTracker(PassType passType); PassResourceUsageTracker(PassType passType);
void BufferUsedAs(BufferBase* buffer, wgpu::BufferUsage usage); void BufferUsedAs(BufferBase* buffer, wgpu::BufferUsage usage);
void TextureViewUsedAs(TextureViewBase* texture, wgpu::TextureUsage usage); void TextureViewUsedAs(TextureViewBase* texture, wgpu::TextureUsage usage);
void AddTextureUsage(TextureBase* texture, const PassTextureUsage& textureUsage); void AddTextureUsage(TextureBase* texture, const TextureSubresourceUsage& textureUsage);
void TrackQueryAvailability(QuerySetBase* querySet, uint32_t queryIndex); void TrackQueryAvailability(QuerySetBase* querySet, uint32_t queryIndex);
const QueryAvailabilityMap& GetQueryAvailabilityMap() const; const QueryAvailabilityMap& GetQueryAvailabilityMap() const;
@ -48,7 +48,7 @@ namespace dawn_native {
private: private:
PassType mPassType; PassType mPassType;
std::map<BufferBase*, wgpu::BufferUsage> mBufferUsages; std::map<BufferBase*, wgpu::BufferUsage> mBufferUsages;
std::map<TextureBase*, PassTextureUsage> mTextureUsages; std::map<TextureBase*, TextureSubresourceUsage> mTextureUsages;
// Dedicated to track the availability of the queries used on render pass. The same query // Dedicated to track the availability of the queries used on render pass. The same query
// cannot be written twice in same render pass, so each render pass also need to have its // cannot be written twice in same render pass, so each render pass also need to have its
// own query availability map for validation. // own query availability map for validation.

View File

@ -37,6 +37,18 @@ namespace dawn_native {
namespace { namespace {
MaybeError ValidateSyncScopeUsedInSubmit(const SyncScopeResourceUsage& scope) {
for (const BufferBase* buffer : scope.buffers) {
DAWN_TRY(buffer->ValidateCanUseOnQueueNow());
}
for (const TextureBase* texture : scope.textures) {
DAWN_TRY(texture->ValidateCanUseInSubmitNow());
}
return {};
}
void CopyTextureData(uint8_t* dstPointer, void CopyTextureData(uint8_t* dstPointer,
const uint8_t* srcPointer, const uint8_t* srcPointer,
uint32_t depth, uint32_t depth,
@ -410,13 +422,11 @@ namespace dawn_native {
const CommandBufferResourceUsage& usages = commands[i]->GetResourceUsages(); const CommandBufferResourceUsage& usages = commands[i]->GetResourceUsages();
for (const PassResourceUsage& passUsages : usages.perPass) { for (const SyncScopeResourceUsage& scope : usages.renderPasses) {
for (const BufferBase* buffer : passUsages.buffers) { DAWN_TRY(ValidateSyncScopeUsedInSubmit(scope));
DAWN_TRY(buffer->ValidateCanUseOnQueueNow());
}
for (const TextureBase* texture : passUsages.textures) {
DAWN_TRY(texture->ValidateCanUseInSubmitNow());
} }
for (const SyncScopeResourceUsage& scope : usages.computePasses) {
DAWN_TRY(ValidateSyncScopeUsedInSubmit(scope));
} }
for (const BufferBase* buffer : usages.topLevelBuffers) { for (const BufferBase* buffer : usages.topLevelBuffers) {

View File

@ -137,7 +137,7 @@ namespace dawn_native {
const PassResourceUsage& usages) const { const PassResourceUsage& usages) const {
TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "RenderBundleEncoder::ValidateFinish"); TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "RenderBundleEncoder::ValidateFinish");
DAWN_TRY(GetDevice()->ValidateObject(this)); DAWN_TRY(GetDevice()->ValidateObject(this));
DAWN_TRY(ValidatePassResourceUsage(usages)); DAWN_TRY(ValidateSyncScopeResourceUsage(usages));
return {}; return {};
} }

View File

@ -101,7 +101,8 @@ namespace dawn_native {
allocator->Allocate<EndRenderPassCmd>(Command::EndRenderPass); allocator->Allocate<EndRenderPassCmd>(Command::EndRenderPass);
return {}; return {};
})) { })) {
mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage()); mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage(),
PassType::Render);
} }
} }

View File

@ -441,7 +441,7 @@ namespace dawn_native {
mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false); mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);
// Add readonly storage usage if the texture has a storage usage. The validation rules in // Add readonly storage usage if the texture has a storage usage. The validation rules in
// ValidatePassResourceUsage will make sure we don't use both at the same time. // ValidateSyncScopeResourceUsage will make sure we don't use both at the same time.
if (mUsage & wgpu::TextureUsage::Storage) { if (mUsage & wgpu::TextureUsage::Storage) {
mUsage |= kReadOnlyStorageTexture; mUsage |= kReadOnlyStorageTexture;
} }

View File

@ -682,8 +682,8 @@ namespace dawn_native { namespace d3d12 {
} }
}; };
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass; size_t nextComputePassNumber = 0;
uint32_t nextPassNumber = 0; size_t nextRenderPassNumber = 0;
Command type; Command type;
while (mCommands.NextCommandId(&type)) { while (mCommands.NextCommandId(&type)) {
@ -691,12 +691,12 @@ namespace dawn_native { namespace d3d12 {
case Command::BeginComputePass: { case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>(); mCommands.NextCommand<BeginComputePassCmd>();
PrepareResourcesForComputePass(commandContext, PrepareResourcesForComputePass(
passResourceUsages[nextPassNumber]); commandContext, GetResourceUsages().computePasses[nextComputePassNumber]);
bindingTracker.SetInComputePass(true); bindingTracker.SetInComputePass(true);
DAWN_TRY(RecordComputePass(commandContext, &bindingTracker)); DAWN_TRY(RecordComputePass(commandContext, &bindingTracker));
nextPassNumber++; nextComputePassNumber++;
break; break;
} }
@ -705,14 +705,14 @@ namespace dawn_native { namespace d3d12 {
mCommands.NextCommand<BeginRenderPassCmd>(); mCommands.NextCommand<BeginRenderPassCmd>();
const bool passHasUAV = PrepareResourcesForRenderPass( const bool passHasUAV = PrepareResourcesForRenderPass(
commandContext, passResourceUsages[nextPassNumber]); commandContext, GetResourceUsages().renderPasses[nextRenderPassNumber]);
bindingTracker.SetInComputePass(false); bindingTracker.SetInComputePass(false);
LazyClearRenderPassAttachments(beginRenderPassCmd); LazyClearRenderPassAttachments(beginRenderPassCmd);
DAWN_TRY(RecordRenderPass(commandContext, &bindingTracker, beginRenderPassCmd, DAWN_TRY(RecordRenderPass(commandContext, &bindingTracker, beginRenderPassCmd,
passHasUAV)); passHasUAV));
nextPassNumber++; nextRenderPassNumber++;
break; break;
} }

View File

@ -776,7 +776,7 @@ namespace dawn_native { namespace d3d12 {
void Texture::TrackUsageAndGetResourceBarrierForPass( void Texture::TrackUsageAndGetResourceBarrierForPass(
CommandRecordingContext* commandContext, CommandRecordingContext* commandContext,
std::vector<D3D12_RESOURCE_BARRIER>* barriers, std::vector<D3D12_RESOURCE_BARRIER>* barriers,
const PassTextureUsage& textureUsages) { const TextureSubresourceUsage& textureUsages) {
if (mResourceAllocation.GetInfo().mMethod != AllocationMethod::kExternal) { if (mResourceAllocation.GetInfo().mMethod != AllocationMethod::kExternal) {
// Track the underlying heap to ensure residency. // Track the underlying heap to ensure residency.
Heap* heap = ToBackend(mResourceAllocation.GetResourceHeap()); Heap* heap = ToBackend(mResourceAllocation.GetResourceHeap());

View File

@ -64,7 +64,7 @@ namespace dawn_native { namespace d3d12 {
void TrackUsageAndGetResourceBarrierForPass(CommandRecordingContext* commandContext, void TrackUsageAndGetResourceBarrierForPass(CommandRecordingContext* commandContext,
std::vector<D3D12_RESOURCE_BARRIER>* barrier, std::vector<D3D12_RESOURCE_BARRIER>* barrier,
const PassTextureUsage& textureUsages); const TextureSubresourceUsage& textureUsages);
void TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext, void TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
std::vector<D3D12_RESOURCE_BARRIER>* barrier, std::vector<D3D12_RESOURCE_BARRIER>* barrier,
wgpu::TextureUsage usage, wgpu::TextureUsage usage,

View File

@ -551,25 +551,25 @@ namespace dawn_native { namespace metal {
} }
MaybeError CommandBuffer::FillCommands(CommandRecordingContext* commandContext) { MaybeError CommandBuffer::FillCommands(CommandRecordingContext* commandContext) {
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass; size_t nextComputePassNumber = 0;
size_t nextPassNumber = 0; size_t nextRenderPassNumber = 0;
auto LazyClearForPass = [](const PassResourceUsage& usages, auto LazyClearForPass = [](const SyncScopeResourceUsage& scope,
CommandRecordingContext* commandContext) { CommandRecordingContext* commandContext) {
for (size_t i = 0; i < usages.textures.size(); ++i) { for (size_t i = 0; i < scope.textures.size(); ++i) {
Texture* texture = ToBackend(usages.textures[i]); Texture* texture = ToBackend(scope.textures[i]);
// Clear subresources that are not render attachments. Render attachments will be // Clear subresources that are not render attachments. Render attachments will be
// cleared in RecordBeginRenderPass by setting the loadop to clear when the texture // cleared in RecordBeginRenderPass by setting the loadop to clear when the texture
// subresource has not been initialized before the render pass. // subresource has not been initialized before the render pass.
usages.textureUsages[i].Iterate( scope.textureUsages[i].Iterate(
[&](const SubresourceRange& range, wgpu::TextureUsage usage) { [&](const SubresourceRange& range, wgpu::TextureUsage usage) {
if (usage & ~wgpu::TextureUsage::RenderAttachment) { if (usage & ~wgpu::TextureUsage::RenderAttachment) {
texture->EnsureSubresourceContentInitialized(range); texture->EnsureSubresourceContentInitialized(range);
} }
}); });
} }
for (BufferBase* bufferBase : usages.buffers) { for (BufferBase* bufferBase : scope.buffers) {
ToBackend(bufferBase)->EnsureDataInitialized(commandContext); ToBackend(bufferBase)->EnsureDataInitialized(commandContext);
} }
}; };
@ -580,19 +580,21 @@ namespace dawn_native { namespace metal {
case Command::BeginComputePass: { case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>(); mCommands.NextCommand<BeginComputePassCmd>();
LazyClearForPass(passResourceUsages[nextPassNumber], commandContext); LazyClearForPass(GetResourceUsages().computePasses[nextComputePassNumber],
commandContext);
commandContext->EndBlit(); commandContext->EndBlit();
DAWN_TRY(EncodeComputePass(commandContext)); DAWN_TRY(EncodeComputePass(commandContext));
nextPassNumber++; nextComputePassNumber++;
break; break;
} }
case Command::BeginRenderPass: { case Command::BeginRenderPass: {
BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>(); BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
LazyClearForPass(passResourceUsages[nextPassNumber], commandContext); LazyClearForPass(GetResourceUsages().renderPasses[nextRenderPassNumber],
commandContext);
commandContext->EndBlit(); commandContext->EndBlit();
LazyClearRenderPassAttachments(cmd); LazyClearRenderPassAttachments(cmd);
@ -600,7 +602,7 @@ namespace dawn_native { namespace metal {
DAWN_TRY(EncodeRenderPass(commandContext, descriptor.Get(), cmd->width, DAWN_TRY(EncodeRenderPass(commandContext, descriptor.Get(), cmd->width,
cmd->height)); cmd->height));
nextPassNumber++; nextRenderPassNumber++;
break; break;
} }

View File

@ -536,14 +536,14 @@ namespace dawn_native { namespace opengl {
MaybeError CommandBuffer::Execute() { MaybeError CommandBuffer::Execute() {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl; const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
auto TransitionForPass = [](const PassResourceUsage& usages) { auto LazyClearForPass = [](const SyncScopeResourceUsage& scope) {
for (size_t i = 0; i < usages.textures.size(); i++) { for (size_t i = 0; i < scope.textures.size(); i++) {
Texture* texture = ToBackend(usages.textures[i]); Texture* texture = ToBackend(scope.textures[i]);
// Clear subresources that are not render attachments. Render attachments will be // Clear subresources that are not render attachments. Render attachments will be
// cleared in RecordBeginRenderPass by setting the loadop to clear when the texture // cleared in RecordBeginRenderPass by setting the loadop to clear when the texture
// subresource has not been initialized before the render pass. // subresource has not been initialized before the render pass.
usages.textureUsages[i].Iterate( scope.textureUsages[i].Iterate(
[&](const SubresourceRange& range, wgpu::TextureUsage usage) { [&](const SubresourceRange& range, wgpu::TextureUsage usage) {
if (usage & ~wgpu::TextureUsage::RenderAttachment) { if (usage & ~wgpu::TextureUsage::RenderAttachment) {
texture->EnsureSubresourceContentInitialized(range); texture->EnsureSubresourceContentInitialized(range);
@ -551,34 +551,33 @@ namespace dawn_native { namespace opengl {
}); });
} }
for (BufferBase* bufferBase : usages.buffers) { for (BufferBase* bufferBase : scope.buffers) {
ToBackend(bufferBase)->EnsureDataInitialized(); ToBackend(bufferBase)->EnsureDataInitialized();
} }
}; };
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass; size_t nextComputePassNumber = 0;
uint32_t nextPassNumber = 0; size_t nextRenderPassNumber = 0;
Command type; Command type;
while (mCommands.NextCommandId(&type)) { while (mCommands.NextCommandId(&type)) {
switch (type) { switch (type) {
case Command::BeginComputePass: { case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>(); mCommands.NextCommand<BeginComputePassCmd>();
TransitionForPass(passResourceUsages[nextPassNumber]); LazyClearForPass(GetResourceUsages().computePasses[nextComputePassNumber]);
DAWN_TRY(ExecuteComputePass()); DAWN_TRY(ExecuteComputePass());
nextPassNumber++; nextComputePassNumber++;
break; break;
} }
case Command::BeginRenderPass: { case Command::BeginRenderPass: {
auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>(); auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
TransitionForPass(passResourceUsages[nextPassNumber]); LazyClearForPass(GetResourceUsages().renderPasses[nextRenderPassNumber]);
LazyClearRenderPassAttachments(cmd); LazyClearRenderPassAttachments(cmd);
DAWN_TRY(ExecuteRenderPass(cmd)); DAWN_TRY(ExecuteRenderPass(cmd));
nextPassNumber++; nextRenderPassNumber++;
break; break;
} }

View File

@ -596,8 +596,8 @@ namespace dawn_native { namespace vulkan {
} }
}; };
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass; size_t nextComputePassNumber = 0;
size_t nextPassNumber = 0; size_t nextRenderPassNumber = 0;
Command type; Command type;
while (mCommands.NextCommandId(&type)) { while (mCommands.NextCommandId(&type)) {
@ -774,24 +774,26 @@ namespace dawn_native { namespace vulkan {
case Command::BeginRenderPass: { case Command::BeginRenderPass: {
BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>(); BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
PrepareResourcesForRenderPass(device, recordingContext, PrepareResourcesForRenderPass(
passResourceUsages[nextPassNumber]); device, recordingContext,
GetResourceUsages().renderPasses[nextRenderPassNumber]);
LazyClearRenderPassAttachments(cmd); LazyClearRenderPassAttachments(cmd);
DAWN_TRY(RecordRenderPass(recordingContext, cmd)); DAWN_TRY(RecordRenderPass(recordingContext, cmd));
nextPassNumber++; nextRenderPassNumber++;
break; break;
} }
case Command::BeginComputePass: { case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>(); mCommands.NextCommand<BeginComputePassCmd>();
PrepareResourcesForComputePass(device, recordingContext, PrepareResourcesForComputePass(
passResourceUsages[nextPassNumber]); device, recordingContext,
GetResourceUsages().computePasses[nextComputePassNumber]);
DAWN_TRY(RecordComputePass(recordingContext)); DAWN_TRY(RecordComputePass(recordingContext));
nextPassNumber++; nextComputePassNumber++;
break; break;
} }

View File

@ -863,7 +863,7 @@ namespace dawn_native { namespace vulkan {
} }
void Texture::TransitionUsageForPass(CommandRecordingContext* recordingContext, void Texture::TransitionUsageForPass(CommandRecordingContext* recordingContext,
const PassTextureUsage& textureUsages, const TextureSubresourceUsage& textureUsages,
std::vector<VkImageMemoryBarrier>* imageBarriers, std::vector<VkImageMemoryBarrier>* imageBarriers,
VkPipelineStageFlags* srcStages, VkPipelineStageFlags* srcStages,
VkPipelineStageFlags* dstStages) { VkPipelineStageFlags* dstStages) {

View File

@ -78,7 +78,7 @@ namespace dawn_native { namespace vulkan {
VkPipelineStageFlags* srcStages, VkPipelineStageFlags* srcStages,
VkPipelineStageFlags* dstStages); VkPipelineStageFlags* dstStages);
void TransitionUsageForPass(CommandRecordingContext* recordingContext, void TransitionUsageForPass(CommandRecordingContext* recordingContext,
const PassTextureUsage& textureUsages, const TextureSubresourceUsage& textureUsages,
std::vector<VkImageMemoryBarrier>* imageBarriers, std::vector<VkImageMemoryBarrier>* imageBarriers,
VkPipelineStageFlags* srcStages, VkPipelineStageFlags* srcStages,
VkPipelineStageFlags* dstStages); VkPipelineStageFlags* dstStages);