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:
parent
c63ac30826
commit
2dd2d67dbc
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
})) {
|
})) {
|
||||||
mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage());
|
mEncodingContext->ExitPass(this, mUsageTracker.AcquireResourceUsage(),
|
||||||
|
PassType::Compute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue