mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-12 06:45:16 +00:00
Remove explicit usage transition from the API and validation
This removes the following for both Buffer and Texture: - The builder's SetInitialUsage - The object's FreezeUsage and TransitionUsage methods - The CommandBuffer Transition<Object>Usage methods All samples and tests are simplified as a result. This also obsoletes the UsageValidationTest which is removed. Some validation was dependent on "current usage" and hasn't been reintroduced for implicit transitions yet: - Buffers can be used while mapped - Swapchain textures can be used after they have been presented. Validation for these will involve collecting all the resources used by a command buffer and will be done in a follow-up patch.
This commit is contained in:
committed by
Corentin Wallez
parent
d2312e8138
commit
d8c068fb4f
@@ -25,10 +25,7 @@ namespace backend {
|
||||
// Buffer
|
||||
|
||||
BufferBase::BufferBase(BufferBuilder* builder)
|
||||
: mDevice(builder->mDevice),
|
||||
mSize(builder->mSize),
|
||||
mAllowedUsage(builder->mAllowedUsage),
|
||||
mCurrentUsage(builder->mCurrentUsage) {
|
||||
: mDevice(builder->mDevice), mSize(builder->mSize), mAllowedUsage(builder->mAllowedUsage) {
|
||||
}
|
||||
|
||||
BufferBase::~BufferBase() {
|
||||
@@ -54,10 +51,6 @@ namespace backend {
|
||||
return mAllowedUsage;
|
||||
}
|
||||
|
||||
nxt::BufferUsageBit BufferBase::GetUsage() const {
|
||||
return mCurrentUsage;
|
||||
}
|
||||
|
||||
void BufferBase::CallMapReadCallback(uint32_t serial,
|
||||
nxtBufferMapAsyncStatus status,
|
||||
const void* pointer) {
|
||||
@@ -90,7 +83,7 @@ namespace backend {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(mCurrentUsage & nxt::BufferUsageBit::TransferDst)) {
|
||||
if (!(mAllowedUsage & nxt::BufferUsageBit::TransferDst)) {
|
||||
mDevice->HandleError("Buffer needs the transfer dst usage bit");
|
||||
return;
|
||||
}
|
||||
@@ -155,59 +148,33 @@ namespace backend {
|
||||
mMapUserdata = 0;
|
||||
}
|
||||
|
||||
bool BufferBase::IsFrozen() const {
|
||||
return mIsFrozen;
|
||||
}
|
||||
|
||||
bool BufferBase::HasFrozenUsage(nxt::BufferUsageBit usage) const {
|
||||
return mIsFrozen && (usage & mAllowedUsage);
|
||||
}
|
||||
|
||||
bool BufferBase::IsUsagePossible(nxt::BufferUsageBit allowedUsage, nxt::BufferUsageBit usage) {
|
||||
bool allowed = (usage & allowedUsage) == usage;
|
||||
bool readOnly = (usage & kReadOnlyBufferUsages) == usage;
|
||||
bool singleUse = nxt::HasZeroOrOneBits(usage);
|
||||
return allowed && (readOnly || singleUse);
|
||||
}
|
||||
|
||||
bool BufferBase::IsTransitionPossible(nxt::BufferUsageBit usage) const {
|
||||
if (mIsFrozen || mIsMapped) {
|
||||
bool BufferBase::ValidateMapBase(uint32_t start,
|
||||
uint32_t size,
|
||||
nxt::BufferUsageBit requiredUsage) {
|
||||
// TODO(cwallez@chromium.org): check for overflows.
|
||||
if (start + size > GetSize()) {
|
||||
mDevice->HandleError("Buffer map read out of range");
|
||||
return false;
|
||||
}
|
||||
return IsUsagePossible(mAllowedUsage, usage);
|
||||
}
|
||||
|
||||
void BufferBase::UpdateUsageInternal(nxt::BufferUsageBit usage) {
|
||||
ASSERT(IsTransitionPossible(usage));
|
||||
mCurrentUsage = usage;
|
||||
}
|
||||
|
||||
void BufferBase::TransitionUsage(nxt::BufferUsageBit usage) {
|
||||
if (!IsTransitionPossible(usage)) {
|
||||
mDevice->HandleError("Buffer frozen or usage not allowed");
|
||||
return;
|
||||
if (mIsMapped) {
|
||||
mDevice->HandleError("Buffer already mapped");
|
||||
return false;
|
||||
}
|
||||
TransitionUsageImpl(mCurrentUsage, usage);
|
||||
mCurrentUsage = usage;
|
||||
}
|
||||
|
||||
void BufferBase::FreezeUsage(nxt::BufferUsageBit usage) {
|
||||
if (!IsTransitionPossible(usage)) {
|
||||
mDevice->HandleError("Buffer frozen or usage not allowed");
|
||||
return;
|
||||
if (!(mAllowedUsage & requiredUsage)) {
|
||||
mDevice->HandleError("Buffer needs the correct map usage bit");
|
||||
return false;
|
||||
}
|
||||
mAllowedUsage = usage;
|
||||
TransitionUsageImpl(mCurrentUsage, usage);
|
||||
mCurrentUsage = usage;
|
||||
mIsFrozen = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// BufferBuilder
|
||||
|
||||
enum BufferSetProperties {
|
||||
BUFFER_PROPERTY_ALLOWED_USAGE = 0x1,
|
||||
BUFFER_PROPERTY_INITIAL_USAGE = 0x2,
|
||||
BUFFER_PROPERTY_SIZE = 0x4,
|
||||
BUFFER_PROPERTY_SIZE = 0x2,
|
||||
};
|
||||
|
||||
BufferBuilder::BufferBuilder(DeviceBase* device) : Builder(device) {
|
||||
@@ -236,11 +203,6 @@ namespace backend {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!BufferBase::IsUsagePossible(mAllowedUsage, mCurrentUsage)) {
|
||||
HandleError("Initial buffer usage is not allowed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mDevice->CreateBuffer(this);
|
||||
}
|
||||
|
||||
@@ -254,16 +216,6 @@ namespace backend {
|
||||
mPropertiesSet |= BUFFER_PROPERTY_ALLOWED_USAGE;
|
||||
}
|
||||
|
||||
void BufferBuilder::SetInitialUsage(nxt::BufferUsageBit usage) {
|
||||
if ((mPropertiesSet & BUFFER_PROPERTY_INITIAL_USAGE) != 0) {
|
||||
HandleError("Buffer initialUsage property set multiple times");
|
||||
return;
|
||||
}
|
||||
|
||||
mCurrentUsage = usage;
|
||||
mPropertiesSet |= BUFFER_PROPERTY_INITIAL_USAGE;
|
||||
}
|
||||
|
||||
void BufferBuilder::SetSize(uint32_t size) {
|
||||
if ((mPropertiesSet & BUFFER_PROPERTY_SIZE) != 0) {
|
||||
HandleError("Buffer size property set multiple times");
|
||||
@@ -274,27 +226,6 @@ namespace backend {
|
||||
mPropertiesSet |= BUFFER_PROPERTY_SIZE;
|
||||
}
|
||||
|
||||
bool BufferBase::ValidateMapBase(uint32_t start,
|
||||
uint32_t size,
|
||||
nxt::BufferUsageBit requiredUsage) {
|
||||
if (start + size > GetSize()) {
|
||||
mDevice->HandleError("Buffer map read out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mIsMapped) {
|
||||
mDevice->HandleError("Buffer already mapped");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(mCurrentUsage & requiredUsage)) {
|
||||
mDevice->HandleError("Buffer needs the correct map usage bit");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// BufferViewBase
|
||||
|
||||
BufferViewBase::BufferViewBase(BufferViewBuilder* builder)
|
||||
|
||||
@@ -38,12 +38,6 @@ namespace backend {
|
||||
|
||||
uint32_t GetSize() const;
|
||||
nxt::BufferUsageBit GetAllowedUsage() const;
|
||||
nxt::BufferUsageBit GetUsage() const;
|
||||
static bool IsUsagePossible(nxt::BufferUsageBit allowedUsage, nxt::BufferUsageBit usage);
|
||||
bool IsTransitionPossible(nxt::BufferUsageBit usage) const;
|
||||
bool IsFrozen() const;
|
||||
bool HasFrozenUsage(nxt::BufferUsageBit usage) const;
|
||||
void UpdateUsageInternal(nxt::BufferUsageBit usage);
|
||||
|
||||
DeviceBase* GetDevice() const;
|
||||
|
||||
@@ -59,8 +53,6 @@ namespace backend {
|
||||
nxtBufferMapWriteCallback callback,
|
||||
nxtCallbackUserdata userdata);
|
||||
void Unmap();
|
||||
void TransitionUsage(nxt::BufferUsageBit usage);
|
||||
void FreezeUsage(nxt::BufferUsageBit usage);
|
||||
|
||||
protected:
|
||||
void CallMapReadCallback(uint32_t serial,
|
||||
@@ -73,22 +65,18 @@ namespace backend {
|
||||
virtual void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t size) = 0;
|
||||
virtual void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t size) = 0;
|
||||
virtual void UnmapImpl() = 0;
|
||||
virtual void TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
|
||||
nxt::BufferUsageBit targetUsage) = 0;
|
||||
|
||||
bool ValidateMapBase(uint32_t start, uint32_t size, nxt::BufferUsageBit requiredUsage);
|
||||
|
||||
DeviceBase* mDevice;
|
||||
uint32_t mSize;
|
||||
nxt::BufferUsageBit mAllowedUsage = nxt::BufferUsageBit::None;
|
||||
nxt::BufferUsageBit mCurrentUsage = nxt::BufferUsageBit::None;
|
||||
|
||||
nxtBufferMapReadCallback mMapReadCallback = nullptr;
|
||||
nxtBufferMapWriteCallback mMapWriteCallback = nullptr;
|
||||
nxtCallbackUserdata mMapUserdata = 0;
|
||||
uint32_t mMapSerial = 0;
|
||||
|
||||
bool mIsFrozen = false;
|
||||
bool mIsMapped = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -122,6 +122,30 @@ namespace backend {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValidateCanUseAs(CommandBufferBuilder* builder,
|
||||
BufferBase* buffer,
|
||||
nxt::BufferUsageBit usage) {
|
||||
ASSERT(HasZeroOrOneBits(usage));
|
||||
if (!(buffer->GetAllowedUsage() & usage)) {
|
||||
builder->HandleError("buffer doesn't have the required usage.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValidateCanUseAs(CommandBufferBuilder* builder,
|
||||
TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) {
|
||||
ASSERT(HasZeroOrOneBits(usage));
|
||||
if (!(texture->GetAllowedUsage() & usage)) {
|
||||
builder->HandleError("texture doesn't have the required usage.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class PassType {
|
||||
Render,
|
||||
Compute,
|
||||
@@ -263,25 +287,7 @@ namespace backend {
|
||||
// CommandBuffer
|
||||
|
||||
CommandBufferBase::CommandBufferBase(CommandBufferBuilder* builder)
|
||||
: mDevice(builder->mDevice),
|
||||
mBuffersTransitioned(std::move(builder->mState->mBuffersTransitioned)),
|
||||
mTexturesTransitioned(std::move(builder->mState->mTexturesTransitioned)) {
|
||||
}
|
||||
|
||||
bool CommandBufferBase::ValidateResourceUsagesImmediate() {
|
||||
for (auto buffer : mBuffersTransitioned) {
|
||||
if (buffer->IsFrozen()) {
|
||||
mDevice->HandleError("Command buffer: cannot transition buffer with frozen usage");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto texture : mTexturesTransitioned) {
|
||||
if (texture->IsFrozen()) {
|
||||
mDevice->HandleError("Command buffer: cannot transition texture with frozen usage");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
: mDevice(builder->mDevice) {
|
||||
}
|
||||
|
||||
DeviceBase* CommandBufferBase::GetDevice() {
|
||||
@@ -352,10 +358,10 @@ namespace backend {
|
||||
CopyBufferToBufferCmd* copy = mIterator.NextCommand<CopyBufferToBufferCmd>();
|
||||
if (!ValidateCopySizeFitsInBuffer(this, copy->source, copy->size) ||
|
||||
!ValidateCopySizeFitsInBuffer(this, copy->destination, copy->size) ||
|
||||
!mState->ValidateCanUseBufferAs(copy->source.buffer.Get(),
|
||||
nxt::BufferUsageBit::TransferSrc) ||
|
||||
!mState->ValidateCanUseBufferAs(copy->destination.buffer.Get(),
|
||||
nxt::BufferUsageBit::TransferDst)) {
|
||||
!ValidateCanUseAs(this, copy->source.buffer.Get(),
|
||||
nxt::BufferUsageBit::TransferSrc) ||
|
||||
!ValidateCanUseAs(this, copy->destination.buffer.Get(),
|
||||
nxt::BufferUsageBit::TransferDst)) {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
@@ -371,10 +377,10 @@ namespace backend {
|
||||
!ValidateCopySizeFitsInBuffer(this, copy->source, bufferCopySize) ||
|
||||
!ValidateTexelBufferOffset(this, copy->destination.texture.Get(),
|
||||
copy->source) ||
|
||||
!mState->ValidateCanUseBufferAs(copy->source.buffer.Get(),
|
||||
nxt::BufferUsageBit::TransferSrc) ||
|
||||
!mState->ValidateCanUseTextureAs(copy->destination.texture.Get(),
|
||||
nxt::TextureUsageBit::TransferDst)) {
|
||||
!ValidateCanUseAs(this, copy->source.buffer.Get(),
|
||||
nxt::BufferUsageBit::TransferSrc) ||
|
||||
!ValidateCanUseAs(this, copy->destination.texture.Get(),
|
||||
nxt::TextureUsageBit::TransferDst)) {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
@@ -390,31 +396,14 @@ namespace backend {
|
||||
!ValidateCopySizeFitsInBuffer(this, copy->destination, bufferCopySize) ||
|
||||
!ValidateTexelBufferOffset(this, copy->source.texture.Get(),
|
||||
copy->destination) ||
|
||||
!mState->ValidateCanUseTextureAs(copy->source.texture.Get(),
|
||||
nxt::TextureUsageBit::TransferSrc) ||
|
||||
!mState->ValidateCanUseBufferAs(copy->destination.buffer.Get(),
|
||||
nxt::BufferUsageBit::TransferDst)) {
|
||||
!ValidateCanUseAs(this, copy->source.texture.Get(),
|
||||
nxt::TextureUsageBit::TransferSrc) ||
|
||||
!ValidateCanUseAs(this, copy->destination.buffer.Get(),
|
||||
nxt::BufferUsageBit::TransferDst)) {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Command::TransitionBufferUsage: {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
mIterator.NextCommand<TransitionBufferUsageCmd>();
|
||||
if (!mState->TransitionBufferUsage(cmd->buffer.Get(), cmd->usage)) {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Command::TransitionTextureUsage: {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
mIterator.NextCommand<TransitionTextureUsageCmd>();
|
||||
if (!mState->TransitionTextureUsage(cmd->texture.Get(), cmd->usage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
default:
|
||||
HandleError("Command disallowed outside of a pass");
|
||||
return false;
|
||||
@@ -474,9 +463,7 @@ namespace backend {
|
||||
SetBindGroupCmd* cmd = mIterator.NextCommand<SetBindGroupCmd>();
|
||||
|
||||
TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker);
|
||||
if (!mState->SetBindGroup(cmd->index, cmd->group.Get())) {
|
||||
return false;
|
||||
}
|
||||
mState->SetBindGroup(cmd->index, cmd->group.Get());
|
||||
} break;
|
||||
|
||||
default:
|
||||
@@ -490,10 +477,6 @@ namespace backend {
|
||||
}
|
||||
|
||||
bool CommandBufferBuilder::ValidateRenderPass(RenderPassDescriptorBase* renderPass) {
|
||||
if (!mState->BeginRenderPass(renderPass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PassResourceUsageTracker usageTracker;
|
||||
|
||||
// Track usage of the render pass attachments
|
||||
@@ -581,16 +564,14 @@ namespace backend {
|
||||
SetBindGroupCmd* cmd = mIterator.NextCommand<SetBindGroupCmd>();
|
||||
|
||||
TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker);
|
||||
if (!mState->SetBindGroup(cmd->index, cmd->group.Get())) {
|
||||
return false;
|
||||
}
|
||||
mState->SetBindGroup(cmd->index, cmd->group.Get());
|
||||
} break;
|
||||
|
||||
case Command::SetIndexBuffer: {
|
||||
SetIndexBufferCmd* cmd = mIterator.NextCommand<SetIndexBufferCmd>();
|
||||
|
||||
usageTracker.BufferUsedAs(cmd->buffer.Get(), nxt::BufferUsageBit::Index);
|
||||
if (!mState->SetIndexBuffer(cmd->buffer.Get())) {
|
||||
if (!mState->SetIndexBuffer()) {
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
@@ -602,7 +583,7 @@ namespace backend {
|
||||
|
||||
for (uint32_t i = 0; i < cmd->count; ++i) {
|
||||
usageTracker.BufferUsedAs(buffers[i].Get(), nxt::BufferUsageBit::Vertex);
|
||||
mState->SetVertexBuffer(cmd->startSlot + i, buffers[i].Get());
|
||||
mState->SetVertexBuffer(cmd->startSlot + i);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -848,22 +829,4 @@ namespace backend {
|
||||
memcpy(cmdOffsets, offsets, count * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::TransitionBufferUsage(BufferBase* buffer,
|
||||
nxt::BufferUsageBit usage) {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
mAllocator.Allocate<TransitionBufferUsageCmd>(Command::TransitionBufferUsage);
|
||||
new (cmd) TransitionBufferUsageCmd;
|
||||
cmd->buffer = buffer;
|
||||
cmd->usage = usage;
|
||||
}
|
||||
|
||||
void CommandBufferBuilder::TransitionTextureUsage(TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
mAllocator.Allocate<TransitionTextureUsageCmd>(Command::TransitionTextureUsage);
|
||||
new (cmd) TransitionTextureUsageCmd;
|
||||
cmd->texture = texture;
|
||||
cmd->usage = usage;
|
||||
}
|
||||
|
||||
} // namespace backend
|
||||
|
||||
@@ -42,14 +42,11 @@ namespace backend {
|
||||
class CommandBufferBase : public RefCounted {
|
||||
public:
|
||||
CommandBufferBase(CommandBufferBuilder* builder);
|
||||
bool ValidateResourceUsagesImmediate();
|
||||
|
||||
DeviceBase* GetDevice();
|
||||
|
||||
private:
|
||||
DeviceBase* mDevice;
|
||||
std::set<BufferBase*> mBuffersTransitioned;
|
||||
std::set<TextureBase*> mTexturesTransitioned;
|
||||
};
|
||||
|
||||
class CommandBufferBuilder : public Builder<CommandBufferBase> {
|
||||
@@ -130,7 +127,6 @@ namespace backend {
|
||||
uint32_t const* offsets);
|
||||
|
||||
void TransitionBufferUsage(BufferBase* buffer, nxt::BufferUsageBit usage);
|
||||
void TransitionTextureUsage(TextureBase* texture, nxt::TextureUsageBit usage);
|
||||
|
||||
private:
|
||||
friend class CommandBufferBase;
|
||||
|
||||
@@ -33,24 +33,6 @@ namespace backend {
|
||||
: mBuilder(mBuilder) {
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::ValidateCanUseBufferAs(BufferBase* buffer,
|
||||
nxt::BufferUsageBit usage) const {
|
||||
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
||||
mBuilder->HandleError("Buffer is not in the necessary usage");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::ValidateCanUseTextureAs(TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) const {
|
||||
if (!TextureHasGuaranteedUsageBit(texture, usage)) {
|
||||
mBuilder->HandleError("Texture is not in the necessary usage");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::ValidateCanDispatch() {
|
||||
constexpr ValidationAspects requiredAspects =
|
||||
1 << VALIDATION_ASPECT_PIPELINE | 1 << VALIDATION_ASPECT_BIND_GROUPS;
|
||||
@@ -99,32 +81,7 @@ namespace backend {
|
||||
return RevalidateCanDraw();
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::BeginRenderPass(RenderPassDescriptorBase* info) {
|
||||
for (uint32_t i : IterateBitSet(info->GetColorAttachmentMask())) {
|
||||
TextureBase* texture = info->GetColorAttachment(i).view->GetTexture();
|
||||
if (!EnsureTextureUsage(texture, nxt::TextureUsageBit::OutputAttachment)) {
|
||||
mBuilder->HandleError("Unable to ensure texture has OutputAttachment usage");
|
||||
return false;
|
||||
}
|
||||
mTexturesAttached.insert(texture);
|
||||
}
|
||||
|
||||
if (info->HasDepthStencilAttachment()) {
|
||||
TextureBase* texture = info->GetDepthStencilAttachment().view->GetTexture();
|
||||
if (!EnsureTextureUsage(texture, nxt::TextureUsageBit::OutputAttachment)) {
|
||||
mBuilder->HandleError("Unable to ensure texture has OutputAttachment usage");
|
||||
return false;
|
||||
}
|
||||
mTexturesAttached.insert(texture);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CommandBufferStateTracker::EndPass() {
|
||||
// Everything in mTexturesAttached should be for the current render pass.
|
||||
mTexturesAttached.clear();
|
||||
|
||||
mInputsSet.reset();
|
||||
mAspects = 0;
|
||||
mBindgroups.fill(nullptr);
|
||||
@@ -141,141 +98,31 @@ namespace backend {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::SetBindGroup(uint32_t index, BindGroupBase* bindgroup) {
|
||||
if (!ValidateBindGroupUsages(bindgroup)) {
|
||||
return false;
|
||||
}
|
||||
void CommandBufferStateTracker::SetBindGroup(uint32_t index, BindGroupBase* bindgroup) {
|
||||
mBindgroupsSet.set(index);
|
||||
mBindgroups[index] = bindgroup;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::SetIndexBuffer(BufferBase* buffer) {
|
||||
bool CommandBufferStateTracker::SetIndexBuffer() {
|
||||
if (!HavePipeline()) {
|
||||
mBuilder->HandleError("Can't set the index buffer without a pipeline");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto usage = nxt::BufferUsageBit::Index;
|
||||
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
||||
mBuilder->HandleError("Buffer needs the index usage bit to be guaranteed");
|
||||
return false;
|
||||
}
|
||||
|
||||
mAspects.set(VALIDATION_ASPECT_INDEX_BUFFER);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::SetVertexBuffer(uint32_t index, BufferBase* buffer) {
|
||||
bool CommandBufferStateTracker::SetVertexBuffer(uint32_t index) {
|
||||
if (!HavePipeline()) {
|
||||
mBuilder->HandleError("Can't set vertex buffers without a pipeline");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto usage = nxt::BufferUsageBit::Vertex;
|
||||
if (!BufferHasGuaranteedUsageBit(buffer, usage)) {
|
||||
mBuilder->HandleError("Buffer needs vertex usage bit to be guaranteed");
|
||||
return false;
|
||||
}
|
||||
|
||||
mInputsSet.set(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::TransitionBufferUsage(BufferBase* buffer,
|
||||
nxt::BufferUsageBit usage) {
|
||||
if (!buffer->IsTransitionPossible(usage)) {
|
||||
if (buffer->IsFrozen()) {
|
||||
mBuilder->HandleError("Buffer transition not possible (usage is frozen)");
|
||||
} else if (!BufferBase::IsUsagePossible(buffer->GetAllowedUsage(), usage)) {
|
||||
mBuilder->HandleError("Buffer transition not possible (usage not allowed)");
|
||||
} else {
|
||||
mBuilder->HandleError("Buffer transition not possible");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
mMostRecentBufferUsages[buffer] = usage;
|
||||
mBuffersTransitioned.insert(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::TransitionTextureUsage(TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) {
|
||||
if (!IsExplicitTextureTransitionPossible(texture, usage)) {
|
||||
if (texture->IsFrozen()) {
|
||||
mBuilder->HandleError("Texture transition not possible (usage is frozen)");
|
||||
} else if (!TextureBase::IsUsagePossible(texture->GetAllowedUsage(), usage)) {
|
||||
mBuilder->HandleError("Texture transition not possible (usage not allowed)");
|
||||
} else if (mTexturesAttached.find(texture) != mTexturesAttached.end()) {
|
||||
mBuilder->HandleError(
|
||||
"Texture transition not possible (texture is in use as a framebuffer "
|
||||
"attachment)");
|
||||
} else {
|
||||
mBuilder->HandleError("Texture transition not possible");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
mMostRecentTextureUsages[texture] = usage;
|
||||
mTexturesTransitioned.insert(texture);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::EnsureTextureUsage(TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) {
|
||||
if (texture->HasFrozenUsage(usage)) {
|
||||
return true;
|
||||
}
|
||||
if (!IsInternalTextureTransitionPossible(texture, usage)) {
|
||||
return false;
|
||||
}
|
||||
mMostRecentTextureUsages[texture] = usage;
|
||||
mTexturesTransitioned.insert(texture);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::BufferHasGuaranteedUsageBit(BufferBase* buffer,
|
||||
nxt::BufferUsageBit usage) const {
|
||||
ASSERT(usage != nxt::BufferUsageBit::None && nxt::HasZeroOrOneBits(usage));
|
||||
if (buffer->HasFrozenUsage(usage)) {
|
||||
return true;
|
||||
}
|
||||
auto it = mMostRecentBufferUsages.find(buffer);
|
||||
return it != mMostRecentBufferUsages.end() && (it->second & usage);
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::TextureHasGuaranteedUsageBit(TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) const {
|
||||
ASSERT(usage != nxt::TextureUsageBit::None && nxt::HasZeroOrOneBits(usage));
|
||||
if (texture->HasFrozenUsage(usage)) {
|
||||
return true;
|
||||
}
|
||||
auto it = mMostRecentTextureUsages.find(texture);
|
||||
return it != mMostRecentTextureUsages.end() && (it->second & usage);
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::IsInternalTextureTransitionPossible(
|
||||
TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) const {
|
||||
ASSERT(usage != nxt::TextureUsageBit::None && nxt::HasZeroOrOneBits(usage));
|
||||
if (mTexturesAttached.find(texture) != mTexturesAttached.end()) {
|
||||
return false;
|
||||
}
|
||||
return texture->IsTransitionPossible(usage);
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::IsExplicitTextureTransitionPossible(
|
||||
TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) const {
|
||||
const nxt::TextureUsageBit attachmentUsages = nxt::TextureUsageBit::OutputAttachment;
|
||||
if (usage & attachmentUsages) {
|
||||
return false;
|
||||
}
|
||||
return IsInternalTextureTransitionPossible(texture, usage);
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::RecomputeHaveAspectBindGroups() {
|
||||
if (mAspects[VALIDATION_ASPECT_BIND_GROUPS]) {
|
||||
return true;
|
||||
@@ -314,53 +161,6 @@ namespace backend {
|
||||
return mAspects[VALIDATION_ASPECT_PIPELINE];
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::ValidateBindGroupUsages(BindGroupBase* group) const {
|
||||
const auto& layoutInfo = group->GetLayout()->GetBindingInfo();
|
||||
for (size_t i = 0; i < kMaxBindingsPerGroup; ++i) {
|
||||
if (!layoutInfo.mask[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nxt::BindingType type = layoutInfo.types[i];
|
||||
switch (type) {
|
||||
case nxt::BindingType::UniformBuffer:
|
||||
case nxt::BindingType::StorageBuffer: {
|
||||
nxt::BufferUsageBit requiredUsage = nxt::BufferUsageBit::None;
|
||||
switch (type) {
|
||||
case nxt::BindingType::UniformBuffer:
|
||||
requiredUsage = nxt::BufferUsageBit::Uniform;
|
||||
break;
|
||||
|
||||
case nxt::BindingType::StorageBuffer:
|
||||
requiredUsage = nxt::BufferUsageBit::Storage;
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
auto buffer = group->GetBindingAsBufferView(i)->GetBuffer();
|
||||
if (!BufferHasGuaranteedUsageBit(buffer, requiredUsage)) {
|
||||
mBuilder->HandleError("Can't guarantee buffer usage needed by bind group");
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
case nxt::BindingType::SampledTexture: {
|
||||
auto requiredUsage = nxt::TextureUsageBit::Sampled;
|
||||
|
||||
auto texture = group->GetBindingAsTextureView(i)->GetTexture();
|
||||
if (!TextureHasGuaranteedUsageBit(texture, requiredUsage)) {
|
||||
mBuilder->HandleError("Can't guarantee texture usage needed by bind group");
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
case nxt::BindingType::Sampler:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CommandBufferStateTracker::RevalidateCanDraw() {
|
||||
if (!mAspects[VALIDATION_ASPECT_PIPELINE]) {
|
||||
mBuilder->HandleError("No active render pipeline");
|
||||
|
||||
@@ -31,29 +31,17 @@ namespace backend {
|
||||
|
||||
// Non-state-modifying validation functions
|
||||
bool ValidateCanCopy() const;
|
||||
bool ValidateCanUseBufferAs(BufferBase* buffer, nxt::BufferUsageBit usage) const;
|
||||
bool ValidateCanUseTextureAs(TextureBase* texture, nxt::TextureUsageBit usage) const;
|
||||
bool ValidateCanDispatch();
|
||||
bool ValidateCanDrawArrays();
|
||||
bool ValidateCanDrawElements();
|
||||
|
||||
// State-modifying methods
|
||||
void EndPass();
|
||||
bool BeginRenderPass(RenderPassDescriptorBase* info);
|
||||
bool SetComputePipeline(ComputePipelineBase* pipeline);
|
||||
bool SetRenderPipeline(RenderPipelineBase* pipeline);
|
||||
bool SetBindGroup(uint32_t index, BindGroupBase* bindgroup);
|
||||
bool SetIndexBuffer(BufferBase* buffer);
|
||||
bool SetVertexBuffer(uint32_t index, BufferBase* buffer);
|
||||
bool TransitionBufferUsage(BufferBase* buffer, nxt::BufferUsageBit usage);
|
||||
bool TransitionTextureUsage(TextureBase* texture, nxt::TextureUsageBit usage);
|
||||
bool EnsureTextureUsage(TextureBase* texture, nxt::TextureUsageBit usage);
|
||||
|
||||
// These collections are copied to the CommandBuffer at build time. These pointers will
|
||||
// remain valid since they are referenced by the bind groups which are referenced by this
|
||||
// command buffer.
|
||||
std::set<BufferBase*> mBuffersTransitioned;
|
||||
std::set<TextureBase*> mTexturesTransitioned;
|
||||
void SetBindGroup(uint32_t index, BindGroupBase* bindgroup);
|
||||
bool SetIndexBuffer();
|
||||
bool SetVertexBuffer(uint32_t index);
|
||||
|
||||
private:
|
||||
enum ValidationAspect {
|
||||
@@ -66,20 +54,11 @@ namespace backend {
|
||||
};
|
||||
using ValidationAspects = std::bitset<VALIDATION_ASPECT_COUNT>;
|
||||
|
||||
// Usage helper functions
|
||||
bool BufferHasGuaranteedUsageBit(BufferBase* buffer, nxt::BufferUsageBit usage) const;
|
||||
bool TextureHasGuaranteedUsageBit(TextureBase* texture, nxt::TextureUsageBit usage) const;
|
||||
bool IsInternalTextureTransitionPossible(TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) const;
|
||||
bool IsExplicitTextureTransitionPossible(TextureBase* texture,
|
||||
nxt::TextureUsageBit usage) const;
|
||||
|
||||
// Queries for lazily evaluated aspects
|
||||
bool RecomputeHaveAspectBindGroups();
|
||||
bool RecomputeHaveAspectVertexBuffers();
|
||||
|
||||
bool HavePipeline() const;
|
||||
bool ValidateBindGroupUsages(BindGroupBase* group) const;
|
||||
bool RevalidateCanDraw();
|
||||
|
||||
void SetPipelineCommon(PipelineBase* pipeline);
|
||||
@@ -93,10 +72,6 @@ namespace backend {
|
||||
std::bitset<kMaxVertexInputs> mInputsSet;
|
||||
PipelineBase* mLastPipeline = nullptr;
|
||||
RenderPipelineBase* mLastRenderPipeline = nullptr;
|
||||
|
||||
std::map<BufferBase*, nxt::BufferUsageBit> mMostRecentBufferUsages;
|
||||
std::map<TextureBase*, nxt::TextureUsageBit> mMostRecentTextureUsages;
|
||||
std::set<TextureBase*> mTexturesAttached;
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
|
||||
@@ -111,16 +111,6 @@ namespace backend {
|
||||
commands->NextData<uint32_t>(cmd->count);
|
||||
cmd->~SetVertexBuffersCmd();
|
||||
} break;
|
||||
case Command::TransitionBufferUsage: {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
commands->NextCommand<TransitionBufferUsageCmd>();
|
||||
cmd->~TransitionBufferUsageCmd();
|
||||
} break;
|
||||
case Command::TransitionTextureUsage: {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
commands->NextCommand<TransitionTextureUsageCmd>();
|
||||
cmd->~TransitionTextureUsageCmd();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
commands->DataWasDestroyed();
|
||||
@@ -206,14 +196,6 @@ namespace backend {
|
||||
commands->NextData<Ref<BufferBase>>(cmd->count);
|
||||
commands->NextData<uint32_t>(cmd->count);
|
||||
} break;
|
||||
|
||||
case Command::TransitionBufferUsage:
|
||||
commands->NextCommand<TransitionBufferUsageCmd>();
|
||||
break;
|
||||
|
||||
case Command::TransitionTextureUsage:
|
||||
commands->NextCommand<TransitionTextureUsageCmd>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,6 @@ namespace backend {
|
||||
SetBindGroup,
|
||||
SetIndexBuffer,
|
||||
SetVertexBuffers,
|
||||
TransitionBufferUsage,
|
||||
TransitionTextureUsage,
|
||||
};
|
||||
|
||||
struct BeginComputePassCmd {};
|
||||
@@ -151,18 +149,6 @@ namespace backend {
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
struct TransitionBufferUsageCmd {
|
||||
Ref<BufferBase> buffer;
|
||||
nxt::BufferUsageBit usage;
|
||||
};
|
||||
|
||||
struct TransitionTextureUsageCmd {
|
||||
Ref<TextureBase> texture;
|
||||
uint32_t startLevel;
|
||||
uint32_t levelCount;
|
||||
nxt::TextureUsageBit usage;
|
||||
};
|
||||
|
||||
// This needs to be called before the CommandIterator is freed so that the Ref<> present in
|
||||
// the commands have a chance to run their destructor and remove internal references.
|
||||
class CommandIterator;
|
||||
|
||||
@@ -28,8 +28,9 @@ namespace backend {
|
||||
return mDevice;
|
||||
}
|
||||
|
||||
bool QueueBase::ValidateSubmitCommand(CommandBufferBase* command) {
|
||||
return command->ValidateResourceUsagesImmediate();
|
||||
bool QueueBase::ValidateSubmitCommand(CommandBufferBase*) {
|
||||
// TODO(cwallez@chromium.org): Validate resources referenced by command buffers can be used
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace backend
|
||||
|
||||
@@ -77,10 +77,6 @@ namespace backend {
|
||||
mDevice->HandleError("Tried to present something other than the last NextTexture");
|
||||
return;
|
||||
}
|
||||
if (texture->GetUsage() != nxt::TextureUsageBit::Present) {
|
||||
mDevice->HandleError("Texture has not been transitioned to the Present usage");
|
||||
return;
|
||||
}
|
||||
|
||||
OnBeforePresent(texture);
|
||||
|
||||
|
||||
@@ -75,8 +75,7 @@ namespace backend {
|
||||
mHeight(builder->mHeight),
|
||||
mDepth(builder->mDepth),
|
||||
mNumMipLevels(builder->mNumMipLevels),
|
||||
mAllowedUsage(builder->mAllowedUsage),
|
||||
mCurrentUsage(builder->mCurrentUsage) {
|
||||
mAllowedUsage(builder->mAllowedUsage) {
|
||||
}
|
||||
|
||||
DeviceBase* TextureBase::GetDevice() const {
|
||||
@@ -104,64 +103,11 @@ namespace backend {
|
||||
nxt::TextureUsageBit TextureBase::GetAllowedUsage() const {
|
||||
return mAllowedUsage;
|
||||
}
|
||||
nxt::TextureUsageBit TextureBase::GetUsage() const {
|
||||
return mCurrentUsage;
|
||||
}
|
||||
|
||||
TextureViewBuilder* TextureBase::CreateTextureViewBuilder() {
|
||||
return new TextureViewBuilder(mDevice, this);
|
||||
}
|
||||
|
||||
bool TextureBase::IsFrozen() const {
|
||||
return mIsFrozen;
|
||||
}
|
||||
|
||||
bool TextureBase::HasFrozenUsage(nxt::TextureUsageBit usage) const {
|
||||
return mIsFrozen && (usage & mAllowedUsage);
|
||||
}
|
||||
|
||||
bool TextureBase::IsUsagePossible(nxt::TextureUsageBit allowedUsage,
|
||||
nxt::TextureUsageBit usage) {
|
||||
bool allowed = (usage & allowedUsage) == usage;
|
||||
bool singleUse = nxt::HasZeroOrOneBits(usage);
|
||||
return allowed && singleUse;
|
||||
}
|
||||
|
||||
bool TextureBase::IsTransitionPossible(nxt::TextureUsageBit usage) const {
|
||||
if (mIsFrozen) {
|
||||
return false;
|
||||
}
|
||||
if (mCurrentUsage == nxt::TextureUsageBit::Present) {
|
||||
return false;
|
||||
}
|
||||
return IsUsagePossible(mAllowedUsage, usage);
|
||||
}
|
||||
|
||||
void TextureBase::UpdateUsageInternal(nxt::TextureUsageBit usage) {
|
||||
ASSERT(IsTransitionPossible(usage));
|
||||
mCurrentUsage = usage;
|
||||
}
|
||||
|
||||
void TextureBase::TransitionUsage(nxt::TextureUsageBit usage) {
|
||||
if (!IsTransitionPossible(usage)) {
|
||||
mDevice->HandleError("Texture frozen or usage not allowed");
|
||||
return;
|
||||
}
|
||||
TransitionUsageImpl(mCurrentUsage, usage);
|
||||
UpdateUsageInternal(usage);
|
||||
}
|
||||
|
||||
void TextureBase::FreezeUsage(nxt::TextureUsageBit usage) {
|
||||
if (!IsTransitionPossible(usage)) {
|
||||
mDevice->HandleError("Texture frozen or usage not allowed");
|
||||
return;
|
||||
}
|
||||
mAllowedUsage = usage;
|
||||
TransitionUsageImpl(mCurrentUsage, usage);
|
||||
UpdateUsageInternal(usage);
|
||||
mIsFrozen = true;
|
||||
}
|
||||
|
||||
// TextureBuilder
|
||||
|
||||
enum TextureSetProperties {
|
||||
@@ -170,7 +116,6 @@ namespace backend {
|
||||
TEXTURE_PROPERTY_FORMAT = 0x4,
|
||||
TEXTURE_PROPERTY_MIP_LEVELS = 0x8,
|
||||
TEXTURE_PROPERTY_ALLOWED_USAGE = 0x10,
|
||||
TEXTURE_PROPERTY_INITIAL_USAGE = 0x20,
|
||||
};
|
||||
|
||||
TextureBuilder::TextureBuilder(DeviceBase* device) : Builder(device) {
|
||||
@@ -185,11 +130,6 @@ namespace backend {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!TextureBase::IsUsagePossible(mAllowedUsage, mCurrentUsage)) {
|
||||
HandleError("Initial texture usage is not allowed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO(cwallez@chromium.org): check stuff based on the dimension
|
||||
|
||||
return mDevice->CreateTexture(this);
|
||||
@@ -252,16 +192,6 @@ namespace backend {
|
||||
mAllowedUsage = usage;
|
||||
}
|
||||
|
||||
void TextureBuilder::SetInitialUsage(nxt::TextureUsageBit usage) {
|
||||
if ((mPropertiesSet & TEXTURE_PROPERTY_INITIAL_USAGE) != 0) {
|
||||
HandleError("Texture initial usage property set multiple times");
|
||||
return;
|
||||
}
|
||||
|
||||
mPropertiesSet |= TEXTURE_PROPERTY_INITIAL_USAGE;
|
||||
mCurrentUsage = usage;
|
||||
}
|
||||
|
||||
// TextureViewBase
|
||||
|
||||
TextureViewBase::TextureViewBase(TextureViewBuilder* builder) : mTexture(builder->mTexture) {
|
||||
|
||||
@@ -47,22 +47,10 @@ namespace backend {
|
||||
uint32_t GetDepth() const;
|
||||
uint32_t GetNumMipLevels() const;
|
||||
nxt::TextureUsageBit GetAllowedUsage() const;
|
||||
nxt::TextureUsageBit GetUsage() const;
|
||||
bool IsFrozen() const;
|
||||
bool HasFrozenUsage(nxt::TextureUsageBit usage) const;
|
||||
static bool IsUsagePossible(nxt::TextureUsageBit allowedUsage, nxt::TextureUsageBit usage);
|
||||
bool IsTransitionPossible(nxt::TextureUsageBit usage) const;
|
||||
void UpdateUsageInternal(nxt::TextureUsageBit usage);
|
||||
|
||||
DeviceBase* GetDevice() const;
|
||||
|
||||
// NXT API
|
||||
TextureViewBuilder* CreateTextureViewBuilder();
|
||||
void TransitionUsage(nxt::TextureUsageBit usage);
|
||||
void FreezeUsage(nxt::TextureUsageBit usage);
|
||||
|
||||
virtual void TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
|
||||
nxt::TextureUsageBit targetUsage) = 0;
|
||||
|
||||
private:
|
||||
DeviceBase* mDevice;
|
||||
@@ -72,8 +60,6 @@ namespace backend {
|
||||
uint32_t mWidth, mHeight, mDepth;
|
||||
uint32_t mNumMipLevels;
|
||||
nxt::TextureUsageBit mAllowedUsage = nxt::TextureUsageBit::None;
|
||||
nxt::TextureUsageBit mCurrentUsage = nxt::TextureUsageBit::None;
|
||||
bool mIsFrozen = false;
|
||||
};
|
||||
|
||||
class TextureBuilder : public Builder<TextureBase> {
|
||||
@@ -100,7 +86,6 @@ namespace backend {
|
||||
nxt::TextureFormat mFormat;
|
||||
uint32_t mNumMipLevels;
|
||||
nxt::TextureUsageBit mAllowedUsage = nxt::TextureUsageBit::None;
|
||||
nxt::TextureUsageBit mCurrentUsage = nxt::TextureUsageBit::None;
|
||||
};
|
||||
|
||||
class TextureViewBase : public RefCounted {
|
||||
|
||||
@@ -198,9 +198,6 @@ namespace backend { namespace d3d12 {
|
||||
ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource);
|
||||
}
|
||||
|
||||
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit, nxt::BufferUsageBit) {
|
||||
}
|
||||
|
||||
BufferView::BufferView(BufferViewBuilder* builder) : BufferViewBase(builder) {
|
||||
mCbvDesc.BufferLocation = ToBackend(GetBuffer())->GetVA() + GetOffset();
|
||||
mCbvDesc.SizeInBytes = GetD3D12Size();
|
||||
|
||||
@@ -43,8 +43,6 @@ namespace backend { namespace d3d12 {
|
||||
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void UnmapImpl() override;
|
||||
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
|
||||
nxt::BufferUsageBit targetUsage) override;
|
||||
|
||||
ComPtr<ID3D12Resource> mResource;
|
||||
bool mFixedResourceState = false;
|
||||
|
||||
@@ -408,18 +408,6 @@ namespace backend { namespace d3d12 {
|
||||
}
|
||||
} break;
|
||||
|
||||
case Command::TransitionBufferUsage: {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionBufferUsageCmd>();
|
||||
cmd->buffer->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
case Command::TransitionTextureUsage: {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionTextureUsageCmd>();
|
||||
cmd->texture->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
default: { UNREACHABLE(); } break;
|
||||
}
|
||||
}
|
||||
@@ -464,6 +452,7 @@ namespace backend { namespace d3d12 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommandBuffer::RecordRenderPass(ComPtr<ID3D12GraphicsCommandList> commandList,
|
||||
BindGroupStateTracker* bindingTracker,
|
||||
RenderPassDescriptor* renderPass) {
|
||||
@@ -471,13 +460,6 @@ namespace backend { namespace d3d12 {
|
||||
{
|
||||
for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) {
|
||||
auto& attachmentInfo = renderPass->GetColorAttachment(i);
|
||||
Texture* texture = ToBackend(attachmentInfo.view->GetTexture());
|
||||
|
||||
// It's already validated that this texture is either frozen to the correct
|
||||
// usage, or not frozen.
|
||||
if (!texture->IsFrozen()) {
|
||||
texture->UpdateUsageInternal(nxt::TextureUsageBit::OutputAttachment);
|
||||
}
|
||||
|
||||
// Load op - color
|
||||
if (attachmentInfo.loadOp == nxt::LoadOp::Clear) {
|
||||
@@ -491,12 +473,6 @@ namespace backend { namespace d3d12 {
|
||||
auto& attachmentInfo = renderPass->GetDepthStencilAttachment();
|
||||
Texture* texture = ToBackend(attachmentInfo.view->GetTexture());
|
||||
|
||||
// It's already validated that this texture is either frozen to the correct
|
||||
// usage, or not frozen.
|
||||
if (!texture->IsFrozen()) {
|
||||
texture->UpdateUsageInternal(nxt::TextureUsageBit::OutputAttachment);
|
||||
}
|
||||
|
||||
// Load op - depth/stencil
|
||||
bool doDepthClear = TextureFormatHasDepth(texture->GetFormat()) &&
|
||||
(attachmentInfo.depthLoadOp == nxt::LoadOp::Clear);
|
||||
|
||||
@@ -122,9 +122,8 @@ namespace backend { namespace d3d12 {
|
||||
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
resourceDescriptor.Flags = D3D12ResourceFlags(GetAllowedUsage(), GetFormat());
|
||||
|
||||
mResource =
|
||||
mDevice->GetResourceAllocator()->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor,
|
||||
D3D12TextureUsage(GetUsage(), GetFormat()));
|
||||
mResource = mDevice->GetResourceAllocator()->Allocate(
|
||||
D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor, D3D12_RESOURCE_STATE_COMMON);
|
||||
mResourcePtr = mResource.Get();
|
||||
}
|
||||
|
||||
@@ -174,9 +173,6 @@ namespace backend { namespace d3d12 {
|
||||
mLastUsage = usage;
|
||||
}
|
||||
|
||||
void Texture::TransitionUsageImpl(nxt::TextureUsageBit, nxt::TextureUsageBit) {
|
||||
}
|
||||
|
||||
TextureView::TextureView(TextureViewBuilder* builder) : TextureViewBase(builder) {
|
||||
mSrvDesc.Format = D3D12TextureFormat(GetTexture()->GetFormat());
|
||||
mSrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
|
||||
@@ -38,9 +38,6 @@ namespace backend { namespace d3d12 {
|
||||
nxt::TextureUsageBit usage);
|
||||
|
||||
private:
|
||||
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
|
||||
nxt::TextureUsageBit targetUsage) override;
|
||||
|
||||
Device* mDevice;
|
||||
ComPtr<ID3D12Resource> mResource = {};
|
||||
ID3D12Resource* mResourcePtr = nullptr;
|
||||
|
||||
@@ -38,8 +38,6 @@ namespace backend { namespace metal {
|
||||
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void UnmapImpl() override;
|
||||
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
|
||||
nxt::BufferUsageBit targetUsage) override;
|
||||
|
||||
id<MTLBuffer> mMtlBuffer = nil;
|
||||
};
|
||||
|
||||
@@ -68,9 +68,6 @@ namespace backend { namespace metal {
|
||||
// Nothing to do, Metal StorageModeShared buffers are always mapped.
|
||||
}
|
||||
|
||||
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit, nxt::BufferUsageBit) {
|
||||
}
|
||||
|
||||
BufferView::BufferView(BufferViewBuilder* builder) : BufferViewBase(builder) {
|
||||
}
|
||||
|
||||
|
||||
@@ -304,20 +304,6 @@ namespace backend { namespace metal {
|
||||
destinationBytesPerImage:copy->rowPitch * src.height];
|
||||
} break;
|
||||
|
||||
case Command::TransitionBufferUsage: {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionBufferUsageCmd>();
|
||||
|
||||
cmd->buffer->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
case Command::TransitionTextureUsage: {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionTextureUsageCmd>();
|
||||
|
||||
cmd->texture->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
default: { UNREACHABLE(); } break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,6 @@ namespace backend { namespace metal {
|
||||
|
||||
id<MTLTexture> GetMTLTexture();
|
||||
|
||||
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
|
||||
nxt::TextureUsageBit targetUsage) override;
|
||||
|
||||
private:
|
||||
id<MTLTexture> mMtlTexture = nil;
|
||||
};
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace backend { namespace metal {
|
||||
auto desc = [MTLTextureDescriptor new];
|
||||
[desc autorelease];
|
||||
desc.textureType = MetalTextureType(GetDimension());
|
||||
desc.usage = MetalTextureUsage(GetUsage());
|
||||
desc.usage = MetalTextureUsage(GetAllowedUsage());
|
||||
desc.pixelFormat = MetalPixelFormat(GetFormat());
|
||||
desc.width = GetWidth();
|
||||
desc.height = GetHeight();
|
||||
@@ -96,9 +96,6 @@ namespace backend { namespace metal {
|
||||
return mMtlTexture;
|
||||
}
|
||||
|
||||
void Texture::TransitionUsageImpl(nxt::TextureUsageBit, nxt::TextureUsageBit) {
|
||||
}
|
||||
|
||||
TextureView::TextureView(TextureViewBuilder* builder) : TextureViewBase(builder) {
|
||||
}
|
||||
|
||||
|
||||
@@ -171,9 +171,6 @@ namespace backend { namespace null {
|
||||
void Buffer::UnmapImpl() {
|
||||
}
|
||||
|
||||
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit, nxt::BufferUsageBit) {
|
||||
}
|
||||
|
||||
// CommandBuffer
|
||||
|
||||
CommandBuffer::CommandBuffer(CommandBufferBuilder* builder)
|
||||
@@ -184,27 +181,6 @@ namespace backend { namespace null {
|
||||
FreeCommands(&mCommands);
|
||||
}
|
||||
|
||||
void CommandBuffer::Execute() {
|
||||
Command type;
|
||||
while (mCommands.NextCommandId(&type)) {
|
||||
switch (type) {
|
||||
case Command::TransitionBufferUsage: {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionBufferUsageCmd>();
|
||||
cmd->buffer->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
case Command::TransitionTextureUsage: {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionTextureUsageCmd>();
|
||||
cmd->texture->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
default:
|
||||
SkipCommand(&mCommands, type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Queue
|
||||
|
||||
Queue::Queue(Device* device) : QueueBase(device) {
|
||||
@@ -213,31 +189,16 @@ namespace backend { namespace null {
|
||||
Queue::~Queue() {
|
||||
}
|
||||
|
||||
void Queue::Submit(uint32_t numCommands, CommandBuffer* const* commands) {
|
||||
void Queue::Submit(uint32_t, CommandBuffer* const*) {
|
||||
auto operations = ToBackend(GetDevice())->AcquirePendingOperations();
|
||||
|
||||
for (auto& operation : operations) {
|
||||
operation->Execute();
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < numCommands; ++i) {
|
||||
commands[i]->Execute();
|
||||
}
|
||||
|
||||
operations.clear();
|
||||
}
|
||||
|
||||
// Texture
|
||||
|
||||
Texture::Texture(TextureBuilder* builder) : TextureBase(builder) {
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
}
|
||||
|
||||
void Texture::TransitionUsageImpl(nxt::TextureUsageBit, nxt::TextureUsageBit) {
|
||||
}
|
||||
|
||||
// SwapChain
|
||||
|
||||
SwapChain::SwapChain(SwapChainBuilder* builder) : SwapChainBase(builder) {
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace backend { namespace null {
|
||||
using Sampler = SamplerBase;
|
||||
using ShaderModule = ShaderModuleBase;
|
||||
class SwapChain;
|
||||
class Texture;
|
||||
using Texture = TextureBase;
|
||||
using TextureView = TextureViewBase;
|
||||
|
||||
struct NullBackendTraits {
|
||||
@@ -140,8 +140,6 @@ namespace backend { namespace null {
|
||||
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void UnmapImpl() override;
|
||||
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
|
||||
nxt::BufferUsageBit targetUsage) override;
|
||||
|
||||
void MapAsyncImplCommon(uint32_t serial, uint32_t start, uint32_t count, bool isWrite);
|
||||
|
||||
@@ -153,8 +151,6 @@ namespace backend { namespace null {
|
||||
CommandBuffer(CommandBufferBuilder* builder);
|
||||
~CommandBuffer();
|
||||
|
||||
void Execute();
|
||||
|
||||
private:
|
||||
CommandIterator mCommands;
|
||||
};
|
||||
@@ -168,15 +164,6 @@ namespace backend { namespace null {
|
||||
void Submit(uint32_t numCommands, CommandBuffer* const* commands);
|
||||
};
|
||||
|
||||
class Texture : public TextureBase {
|
||||
public:
|
||||
Texture(TextureBuilder* builder);
|
||||
~Texture();
|
||||
|
||||
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
|
||||
nxt::TextureUsageBit targetUsage) override;
|
||||
};
|
||||
|
||||
class SwapChain : public SwapChainBase {
|
||||
public:
|
||||
SwapChain(SwapChainBuilder* builder);
|
||||
|
||||
@@ -54,9 +54,6 @@ namespace backend { namespace opengl {
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit, nxt::BufferUsageBit) {
|
||||
}
|
||||
|
||||
// BufferView
|
||||
|
||||
BufferView::BufferView(BufferViewBuilder* builder) : BufferViewBase(builder) {
|
||||
|
||||
@@ -34,8 +34,6 @@ namespace backend { namespace opengl {
|
||||
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void UnmapImpl() override;
|
||||
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
|
||||
nxt::BufferUsageBit targetUsage) override;
|
||||
|
||||
GLuint mBuffer = 0;
|
||||
};
|
||||
|
||||
@@ -374,20 +374,6 @@ namespace backend { namespace opengl {
|
||||
glDeleteFramebuffers(1, &readFBO);
|
||||
} break;
|
||||
|
||||
case Command::TransitionBufferUsage: {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionBufferUsageCmd>();
|
||||
|
||||
cmd->buffer->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
case Command::TransitionTextureUsage: {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionTextureUsageCmd>();
|
||||
|
||||
cmd->texture->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
default: { UNREACHABLE(); } break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,9 +111,6 @@ namespace backend { namespace opengl {
|
||||
return GetGLFormatInfo(GetFormat());
|
||||
}
|
||||
|
||||
void Texture::TransitionUsageImpl(nxt::TextureUsageBit, nxt::TextureUsageBit) {
|
||||
}
|
||||
|
||||
// TextureView
|
||||
|
||||
TextureView::TextureView(TextureViewBuilder* builder) : TextureViewBase(builder) {
|
||||
|
||||
@@ -37,9 +37,6 @@ namespace backend { namespace opengl {
|
||||
GLenum GetGLTarget() const;
|
||||
TextureFormatInfo GetGLFormat() const;
|
||||
|
||||
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
|
||||
nxt::TextureUsageBit targetUsage) override;
|
||||
|
||||
private:
|
||||
GLuint mHandle;
|
||||
GLenum mTarget;
|
||||
|
||||
@@ -238,9 +238,6 @@ namespace backend { namespace vulkan {
|
||||
// No need to do anything, we keep CPU-visible memory mapped at all time.
|
||||
}
|
||||
|
||||
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit, nxt::BufferUsageBit) {
|
||||
}
|
||||
|
||||
// MapRequestTracker
|
||||
|
||||
MapRequestTracker::MapRequestTracker(Device* device) : mDevice(device) {
|
||||
|
||||
@@ -45,8 +45,6 @@ namespace backend { namespace vulkan {
|
||||
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void UnmapImpl() override;
|
||||
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
|
||||
nxt::BufferUsageBit targetUsage) override;
|
||||
|
||||
VkBuffer mHandle = VK_NULL_HANDLE;
|
||||
DeviceMemoryAllocation mMemoryAllocation;
|
||||
|
||||
@@ -222,22 +222,6 @@ namespace backend { namespace vulkan {
|
||||
nextPassNumber++;
|
||||
} break;
|
||||
|
||||
case Command::TransitionBufferUsage: {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionBufferUsageCmd>();
|
||||
|
||||
Buffer* buffer = ToBackend(cmd->buffer.Get());
|
||||
buffer->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
case Command::TransitionTextureUsage: {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionTextureUsageCmd>();
|
||||
|
||||
Texture* texture = ToBackend(cmd->texture.Get());
|
||||
texture->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
default: { UNREACHABLE(); } break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,9 +343,6 @@ namespace backend { namespace vulkan {
|
||||
mLastUsage = usage;
|
||||
}
|
||||
|
||||
void Texture::TransitionUsageImpl(nxt::TextureUsageBit, nxt::TextureUsageBit) {
|
||||
}
|
||||
|
||||
TextureView::TextureView(TextureViewBuilder* builder) : TextureViewBase(builder) {
|
||||
Device* device = ToBackend(builder->GetDevice());
|
||||
|
||||
|
||||
@@ -40,9 +40,6 @@ namespace backend { namespace vulkan {
|
||||
void TransitionUsageNow(VkCommandBuffer commands, nxt::TextureUsageBit usage);
|
||||
|
||||
private:
|
||||
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
|
||||
nxt::TextureUsageBit targetUsage) override;
|
||||
|
||||
VkImage mHandle = VK_NULL_HANDLE;
|
||||
DeviceMemoryAllocation mMemoryAllocation;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user