D3D11: Refactor Buffer classes.
- GPUOnlyBuffer is renamed to GPUUsableBuffer. This will allow it
to be extended by a subclass in future which supports mapping
a draw buffer (with uniform, index, storage usages, etc).
- MapInternal now has additional MapMode parameter.
- Clear function used for Occlusion Query should be a special
function. It will be named PredicatedClear. To indicate that the
clearing will be affected by a predicate, unlike mapping based Clear
which won't be affected by it.
- GetD3D11ConstantBuffer() and EnsureConstantBufferIsUpdated() are
combined. They are currently always called together, there is no point
having two separate methods.
- Similarly for CreateD3D11UnorderedAccessView1() and MarkMutated().
Bug: 345471009
Change-Id: Ifa237e6bacb591a1ee8e9b9f76c2e5d809899efc
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/194800
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Quyen Le <lehoangquyen@chromium.org>
diff --git a/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp b/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
index 8629f34..ba2cfbd 100644
--- a/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
+++ b/src/dawn/native/d3d11/BindGroupTrackerD3D11.cpp
@@ -190,10 +190,9 @@
bindingInfo.visibility,
wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute));
ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
- DAWN_TRY_ASSIGN(d3d11UAV, ToGPUOnlyBuffer(binding.buffer)
- ->CreateD3D11UnorderedAccessView1(
- offset, binding.size));
- ToGPUOnlyBuffer(binding.buffer)->MarkMutated();
+ DAWN_TRY_ASSIGN(d3d11UAV, ToGPUUsableBuffer(binding.buffer)
+ ->UseAsUAV(mCommandContext, offset,
+ binding.size));
uavsInBindGroup.insert(uavsInBindGroup.begin(),
std::move(d3d11UAV));
break;
@@ -309,10 +308,9 @@
switch (layout.type) {
case wgpu::BufferBindingType::Uniform: {
- ToGPUOnlyBuffer(binding.buffer)
- ->EnsureConstantBufferIsUpdated(mCommandContext);
- ID3D11Buffer* d3d11Buffer =
- ToGPUOnlyBuffer(binding.buffer)->GetD3D11ConstantBuffer();
+ ID3D11Buffer* d3d11Buffer;
+ DAWN_TRY_ASSIGN(d3d11Buffer, ToGPUUsableBuffer(binding.buffer)
+ ->GetD3D11ConstantBuffer(mCommandContext));
// https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1
// Offset and size are measured in shader constants, which are 16 bytes
// (4*32-bit components). And the offsets and counts must be multiples
@@ -346,10 +344,9 @@
wgpu::ShaderStage::Fragment | wgpu::ShaderStage::Compute));
if (bindingVisibility & wgpu::ShaderStage::Compute) {
ComPtr<ID3D11UnorderedAccessView> d3d11UAV;
- DAWN_TRY_ASSIGN(d3d11UAV, ToGPUOnlyBuffer(binding.buffer)
- ->CreateD3D11UnorderedAccessView1(
- offset, binding.size));
- ToGPUOnlyBuffer(binding.buffer)->MarkMutated();
+ DAWN_TRY_ASSIGN(d3d11UAV,
+ ToGPUUsableBuffer(binding.buffer)
+ ->UseAsUAV(mCommandContext, offset, binding.size));
deviceContext->CSSetUnorderedAccessViews(
bindingSlot, 1, d3d11UAV.GetAddressOf(), nullptr);
}
@@ -358,8 +355,8 @@
case wgpu::BufferBindingType::ReadOnlyStorage: {
ComPtr<ID3D11ShaderResourceView> d3d11SRV;
DAWN_TRY_ASSIGN(d3d11SRV,
- ToGPUOnlyBuffer(binding.buffer)
- ->CreateD3D11ShaderResourceView(offset, binding.size));
+ ToGPUUsableBuffer(binding.buffer)
+ ->UseAsSRV(mCommandContext, offset, binding.size));
if (bindingVisibility & wgpu::ShaderStage::Vertex) {
deviceContext->VSSetShaderResources(bindingSlot, 1,
d3d11SRV.GetAddressOf());
diff --git a/src/dawn/native/d3d11/BufferD3D11.cpp b/src/dawn/native/d3d11/BufferD3D11.cpp
index 3401b6b..307e905 100644
--- a/src/dawn/native/d3d11/BufferD3D11.cpp
+++ b/src/dawn/native/d3d11/BufferD3D11.cpp
@@ -52,11 +52,13 @@
namespace {
-constexpr wgpu::BufferUsage kD3D11AllowedUniformBufferUsages =
+constexpr wgpu::BufferUsage kD3D11GPUOnlyUniformBufferUsages =
wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
constexpr wgpu::BufferUsage kCopyUsages = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
+constexpr wgpu::BufferUsage kStagingUsages = kMappableBufferUsages | kCopyUsages;
+
// Resource usage Default Dynamic Immutable Staging
// ------------------------------------------------------------
// GPU-read Yes Yes Yes Yes[1]
@@ -78,7 +80,7 @@
bool IsStaging(wgpu::BufferUsage usage) {
// Must have at least MapWrite or MapRead bit
- return IsMappable(usage) && IsSubset(usage, kMappableBufferUsages | kCopyUsages);
+ return IsMappable(usage) && IsSubset(usage, kStagingUsages);
}
UINT D3D11BufferBindFlags(wgpu::BufferUsage usage) {
@@ -94,6 +96,7 @@
bindFlags |= D3D11_BIND_CONSTANT_BUFFER;
}
if (usage & (wgpu::BufferUsage::Storage | kInternalStorageBuffer)) {
+ DAWN_ASSERT(!IsMappable(usage));
bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
}
if (usage & kReadOnlyStorageBuffer) {
@@ -113,7 +116,7 @@
UINT D3D11BufferMiscFlags(wgpu::BufferUsage usage) {
UINT miscFlags = 0;
- if (usage & (wgpu::BufferUsage::Storage | kInternalStorageBuffer)) {
+ if (usage & (wgpu::BufferUsage::Storage | kInternalStorageBuffer | kReadOnlyStorageBuffer)) {
miscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
}
if (usage & wgpu::BufferUsage::Indirect) {
@@ -144,9 +147,14 @@
// For CPU-to-GPU upload buffers(CopySrc|MapWrite), they can be emulated in the system memory, and
// then written into the dest GPU buffer via ID3D11DeviceContext::UpdateSubresource.
class UploadBuffer final : public Buffer {
- using Buffer::Buffer;
+ public:
+ UploadBuffer(DeviceBase* device, const UnpackedPtr<BufferDescriptor>& descriptor)
+ : Buffer(device,
+ descriptor,
+ /*internalMappableFlags=*/kMappableBufferUsages) {}
~UploadBuffer() override = default;
+ private:
MaybeError InitializeInternal() override {
mUploadData = std::unique_ptr<uint8_t[]>(AllocNoThrow<uint8_t>(GetAllocatedSize()));
if (mUploadData == nullptr) {
@@ -155,7 +163,8 @@
return {};
}
- MaybeError MapInternal(const ScopedCommandRecordingContext* commandContext) override {
+ MaybeError MapInternal(const ScopedCommandRecordingContext* commandContext,
+ wgpu::MapMode) override {
mMappedData = mUploadData.get();
return {};
}
@@ -205,8 +214,11 @@
// Buffer that supports mapping and copying.
class StagingBuffer final : public Buffer {
- using Buffer::Buffer;
+ public:
+ StagingBuffer(DeviceBase* device, const UnpackedPtr<BufferDescriptor>& descriptor)
+ : Buffer(device, descriptor, /*internalMappableFlags=*/kMappableBufferUsages) {}
+ private:
void DestroyImpl() override {
// TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
// - It may be called if the buffer is explicitly destroyed with APIDestroy.
@@ -251,7 +263,8 @@
return {};
}
- MaybeError MapInternal(const ScopedCommandRecordingContext* commandContext) override {
+ MaybeError MapInternal(const ScopedCommandRecordingContext* commandContext,
+ wgpu::MapMode) override {
DAWN_ASSERT(IsMappable(GetUsage()));
DAWN_ASSERT(!mMappedData);
@@ -317,7 +330,7 @@
}
ScopedMap scopedMap;
- DAWN_TRY_ASSIGN(scopedMap, ScopedMap::Create(commandContext, this));
+ DAWN_TRY_ASSIGN(scopedMap, ScopedMap::Create(commandContext, this, wgpu::MapMode::Write));
DAWN_ASSERT(scopedMap.GetMappedData());
memcpy(scopedMap.GetMappedData() + offset, data, size);
@@ -328,6 +341,65 @@
ComPtr<ID3D11Buffer> mD3d11Buffer;
};
+// Buffer that can only be written/read by GPU.
+class GPUOnlyBuffer final : public GPUUsableBuffer {
+ public:
+ GPUOnlyBuffer(DeviceBase* device, const UnpackedPtr<BufferDescriptor>& descriptor)
+ : GPUUsableBuffer(device, descriptor, /*internalMappableFlags=*/wgpu::BufferUsage::None) {}
+
+ ResultOrError<ID3D11Buffer*> GetD3D11ConstantBuffer(
+ const ScopedCommandRecordingContext* commandContext) override;
+ ResultOrError<ID3D11Buffer*> GetD3D11NonConstantBuffer(
+ const ScopedCommandRecordingContext* commandContext) override;
+
+ ResultOrError<ComPtr<ID3D11ShaderResourceView>> UseAsSRV(
+ const ScopedCommandRecordingContext* commandContext,
+ uint64_t offset,
+ uint64_t size) override;
+ ResultOrError<ComPtr<ID3D11UnorderedAccessView1>> UseAsUAV(
+ const ScopedCommandRecordingContext* commandContext,
+ uint64_t offset,
+ uint64_t size) override;
+
+ MaybeError PredicatedClear(const ScopedSwapStateCommandRecordingContext* commandContext,
+ ID3D11Predicate* predicate,
+ uint8_t clearValue,
+ uint64_t offset,
+ uint64_t size) override;
+
+ private:
+ // Dawn API
+ void DestroyImpl() override;
+ void SetLabelImpl() override;
+
+ MaybeError InitializeInternal() override;
+
+ MaybeError CopyToInternal(const ScopedCommandRecordingContext* commandContext,
+ uint64_t sourceOffset,
+ size_t size,
+ Buffer* destination,
+ uint64_t destinationOffset) override;
+ MaybeError CopyFromD3DInternal(const ScopedCommandRecordingContext* commandContext,
+ ID3D11Buffer* srcD3D11Buffer,
+ uint64_t sourceOffset,
+ size_t size,
+ uint64_t destinationOffset) override;
+
+ MaybeError WriteInternal(const ScopedCommandRecordingContext* commandContext,
+ uint64_t bufferOffset,
+ const void* data,
+ size_t size) override;
+
+ MaybeError ClearPaddingInternal(const ScopedCommandRecordingContext* commandContext) override;
+
+ // The buffer object for constant buffer usage.
+ ComPtr<ID3D11Buffer> mD3d11ConstantBuffer;
+ // The buffer object for non-constant buffer usages(e.g. storage buffer, vertex buffer, etc.)
+ ComPtr<ID3D11Buffer> mD3d11NonConstantBuffer;
+
+ bool mConstantBufferIsUpdated = true;
+};
+
// static
ResultOrError<Ref<Buffer>> Buffer::Create(Device* device,
const UnpackedPtr<BufferDescriptor>& descriptor,
@@ -349,6 +421,11 @@
return buffer;
}
+Buffer::Buffer(DeviceBase* device,
+ const UnpackedPtr<BufferDescriptor>& descriptor,
+ wgpu::BufferUsage internalMappableFlags)
+ : BufferBase(device, descriptor), mInternalMappableFlags(internalMappableFlags) {}
+
MaybeError Buffer::Initialize(bool mappedAtCreation,
const ScopedCommandRecordingContext* commandContext) {
// TODO(dawn:1705): handle mappedAtCreation for NonzeroClearResourcesOnCreationForTesting
@@ -373,14 +450,14 @@
SetLabelImpl();
if (!mappedAtCreation) {
- if (commandContext) {
- DAWN_TRY(ClearInitialResource(commandContext));
- } else {
- auto tmpCommandContext =
- ToBackend(GetDevice()->GetQueue())
- ->GetScopedPendingCommandContext(QueueBase::SubmitMode::Normal);
- DAWN_TRY(ClearInitialResource(&tmpCommandContext));
- }
+ if (commandContext) {
+ DAWN_TRY(ClearInitialResource(commandContext));
+ } else {
+ auto tmpCommandContext =
+ ToBackend(GetDevice()->GetQueue())
+ ->GetScopedPendingCommandContext(QueueBase::SubmitMode::Normal);
+ DAWN_TRY(ClearInitialResource(&tmpCommandContext));
+ }
}
return {};
@@ -401,18 +478,38 @@
Buffer::~Buffer() = default;
bool Buffer::IsCPUWritableAtCreation() const {
- return IsMappable(GetUsage());
+ return IsCPUWritable();
+}
+
+bool Buffer::IsCPUWritable() const {
+ return mInternalMappableFlags & wgpu::BufferUsage::MapWrite;
+}
+
+bool Buffer::IsCPUReadable() const {
+ return mInternalMappableFlags & wgpu::BufferUsage::MapRead;
}
MaybeError Buffer::MapAtCreationImpl() {
- DAWN_ASSERT(IsMappable(GetUsage()));
+ DAWN_ASSERT(IsCPUWritable());
auto commandContext = ToBackend(GetDevice()->GetQueue())
->GetScopedPendingCommandContext(QueueBase::SubmitMode::Normal);
- return MapInternal(&commandContext);
+ return MapInternal(&commandContext, wgpu::MapMode::Write);
+}
+
+MaybeError Buffer::MapInternal(const ScopedCommandRecordingContext* commandContext,
+ wgpu::MapMode mode) {
+ DAWN_UNREACHABLE();
+
+ return {};
+}
+
+void Buffer::UnmapInternal(const ScopedCommandRecordingContext* commandContext) {
+ DAWN_UNREACHABLE();
}
MaybeError Buffer::MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) {
- DAWN_ASSERT(IsMappable(GetUsage()));
+ DAWN_ASSERT((mode == wgpu::MapMode::Write && IsCPUWritable()) ||
+ (mode == wgpu::MapMode::Read && IsCPUReadable()));
mMapReadySerial = mLastUsageSerial;
const ExecutionSerial completedSerial = GetDevice()->GetQueue()->GetCompletedCommandSerial();
@@ -420,22 +517,23 @@
// commands. To avoid that, instead we ask Queue to do the map later when mLastUsageSerial has
// passed.
if (mMapReadySerial > completedSerial) {
- ToBackend(GetDevice()->GetQueue())->TrackPendingMapBuffer({this}, mMapReadySerial);
+ ToBackend(GetDevice()->GetQueue())->TrackPendingMapBuffer({this}, mode, mMapReadySerial);
} else {
auto commandContext = ToBackend(GetDevice()->GetQueue())
->GetScopedPendingCommandContext(QueueBase::SubmitMode::Normal);
- DAWN_TRY(FinalizeMap(&commandContext, completedSerial));
+ DAWN_TRY(FinalizeMap(&commandContext, completedSerial, mode));
}
return {};
}
MaybeError Buffer::FinalizeMap(ScopedCommandRecordingContext* commandContext,
- ExecutionSerial completedSerial) {
+ ExecutionSerial completedSerial,
+ wgpu::MapMode mode) {
// Needn't map the buffer if this is for a previous mapAsync that was cancelled.
if (completedSerial >= mMapReadySerial) {
// TODO(dawn:1705): make sure the map call is not blocked by the GPU operations.
- DAWN_TRY(MapInternal(commandContext));
+ DAWN_TRY(MapInternal(commandContext, mode));
DAWN_TRY(EnsureDataInitialized(commandContext));
}
@@ -525,6 +623,15 @@
return {};
}
+MaybeError Buffer::PredicatedClear(const ScopedSwapStateCommandRecordingContext* commandContext,
+ ID3D11Predicate* predicate,
+ uint8_t clearValue,
+ uint64_t offset,
+ uint64_t size) {
+ DAWN_UNREACHABLE();
+ return {};
+}
+
MaybeError Buffer::Clear(const ScopedCommandRecordingContext* commandContext,
uint8_t clearValue,
uint64_t offset,
@@ -538,7 +645,7 @@
// Map the buffer if it is possible, so EnsureDataInitializedAsDestination() and ClearInternal()
// can write the mapped memory directly.
ScopedMap scopedMap;
- DAWN_TRY_ASSIGN(scopedMap, ScopedMap::Create(commandContext, this));
+ DAWN_TRY_ASSIGN(scopedMap, ScopedMap::Create(commandContext, this, wgpu::MapMode::Write));
// For non-staging buffers, we can use UpdateSubresource to write the data.
DAWN_TRY(EnsureDataInitializedAsDestination(commandContext, offset, size));
@@ -584,7 +691,7 @@
// Map the buffer if it is possible, so EnsureDataInitializedAsDestination() and WriteInternal()
// can write the mapped memory directly.
ScopedMap scopedMap;
- DAWN_TRY_ASSIGN(scopedMap, ScopedMap::Create(commandContext, this));
+ DAWN_TRY_ASSIGN(scopedMap, ScopedMap::Create(commandContext, this, wgpu::MapMode::Write));
// For non-staging buffers, we can use UpdateSubresource to write the data.
DAWN_TRY(EnsureDataInitializedAsDestination(commandContext, offset, size));
@@ -609,8 +716,12 @@
ResultOrError<Buffer::ScopedMap> Buffer::ScopedMap::Create(
const ScopedCommandRecordingContext* commandContext,
- Buffer* buffer) {
- if (!IsMappable(buffer->GetUsage())) {
+ Buffer* buffer,
+ wgpu::MapMode mode) {
+ if (mode == wgpu::MapMode::Write && !buffer->IsCPUWritable()) {
+ return ScopedMap();
+ }
+ if (mode == wgpu::MapMode::Read && !buffer->IsCPUReadable()) {
return ScopedMap();
}
@@ -618,7 +729,7 @@
return ScopedMap(commandContext, buffer, /*needsUnmap=*/false);
}
- DAWN_TRY(buffer->MapInternal(commandContext));
+ DAWN_TRY(buffer->MapInternal(commandContext, mode));
return ScopedMap(commandContext, buffer, /*needsUnmap=*/true);
}
@@ -661,6 +772,153 @@
return mBuffer ? mBuffer->mMappedData.get() : nullptr;
}
+// GPUUsableBuffer
+ID3D11Buffer* GPUUsableBuffer::GetD3D11ConstantBufferForTesting() {
+ ID3D11Buffer* buffer;
+ if (GetDevice()->ConsumedError(GetD3D11ConstantBuffer(nullptr), &buffer)) {
+ return nullptr;
+ }
+
+ return buffer;
+}
+
+ID3D11Buffer* GPUUsableBuffer::GetD3D11NonConstantBufferForTesting() {
+ ID3D11Buffer* buffer;
+ if (GetDevice()->ConsumedError(GetD3D11NonConstantBuffer(nullptr), &buffer)) {
+ return nullptr;
+ }
+
+ return buffer;
+}
+
+ResultOrError<ComPtr<ID3D11ShaderResourceView>>
+GPUUsableBuffer::CreateD3D11ShaderResourceViewFromD3DBuffer(ID3D11Buffer* d3d11Buffer,
+ uint64_t offset,
+ uint64_t size) {
+ DAWN_ASSERT(IsAligned(offset, 4u));
+ DAWN_ASSERT(IsAligned(size, 4u));
+ UINT firstElement = static_cast<UINT>(offset / 4);
+ UINT numElements = static_cast<UINT>(size / 4);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+ desc.Format = DXGI_FORMAT_R32_TYPELESS;
+ desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
+ desc.BufferEx.FirstElement = firstElement;
+ desc.BufferEx.NumElements = numElements;
+ desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
+ ComPtr<ID3D11ShaderResourceView> srv;
+ DAWN_TRY(CheckHRESULT(ToBackend(GetDevice())
+ ->GetD3D11Device()
+ ->CreateShaderResourceView(d3d11Buffer, &desc, &srv),
+ "ShaderResourceView creation"));
+
+ return srv;
+}
+
+ResultOrError<ComPtr<ID3D11UnorderedAccessView1>>
+GPUUsableBuffer::CreateD3D11UnorderedAccessViewFromD3DBuffer(ID3D11Buffer* d3d11Buffer,
+ uint64_t offset,
+ uint64_t size) {
+ DAWN_ASSERT(IsAligned(offset, 4u));
+ DAWN_ASSERT(IsAligned(size, 4u));
+
+ UINT firstElement = static_cast<UINT>(offset / 4);
+ UINT numElements = static_cast<UINT>(size / 4);
+
+ D3D11_UNORDERED_ACCESS_VIEW_DESC1 desc;
+ desc.Format = DXGI_FORMAT_R32_TYPELESS;
+ desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+ desc.Buffer.FirstElement = firstElement;
+ desc.Buffer.NumElements = numElements;
+ desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
+
+ ComPtr<ID3D11UnorderedAccessView1> uav;
+ DAWN_TRY(CheckHRESULT(ToBackend(GetDevice())
+ ->GetD3D11Device5()
+ ->CreateUnorderedAccessView1(d3d11Buffer, &desc, &uav),
+ "UnorderedAccessView creation"));
+
+ return uav;
+}
+
+MaybeError GPUUsableBuffer::UpdateD3D11ConstantBuffer(
+ const ScopedCommandRecordingContext* commandContext,
+ ID3D11Buffer* d3d11Buffer,
+ bool firstTimeUpdate,
+ uint64_t offset,
+ const void* data,
+ size_t size) {
+ DAWN_ASSERT(size > 0);
+
+ // For a full size write, UpdateSubresource1(D3D11_COPY_DISCARD) can be used to update
+ // constant buffer.
+ // WriteInternal() can be called with GetAllocatedSize(). We treat it as a full buffer write as
+ // well.
+ bool fullSizeUpdate = size >= GetSize() && offset == 0;
+ if (fullSizeUpdate || firstTimeUpdate) {
+ // Offset and size must be aligned with 16 for using UpdateSubresource1() on constant
+ // buffer.
+ size_t alignedOffset;
+ if (offset < kConstantBufferUpdateAlignment - 1) {
+ alignedOffset = 0;
+ } else {
+ // For offset we align to value <= offset.
+ alignedOffset = Align(offset - (kConstantBufferUpdateAlignment - 1),
+ kConstantBufferUpdateAlignment);
+ }
+ size_t alignedEnd = Align(offset + size, kConstantBufferUpdateAlignment);
+ size_t alignedSize = alignedEnd - alignedOffset;
+
+ DAWN_ASSERT((alignedSize % kConstantBufferUpdateAlignment) == 0);
+ DAWN_ASSERT(alignedSize <= GetAllocatedSize());
+ DAWN_ASSERT(offset >= alignedOffset);
+
+ // Extra bytes on the left of offset we could write to. This is only valid if
+ // firstTimeUpdate = true.
+ size_t leftExtraBytes = offset - alignedOffset;
+ DAWN_ASSERT(leftExtraBytes == 0 || firstTimeUpdate);
+
+ // The layout of the buffer is like this:
+ // |..........................| leftExtraBytes | data | ............... |
+ // |<----------------- offset ---------------->|<-- size -->|
+ // |<----- alignedOffset ---->|<--------- alignedSize --------->|
+ std::unique_ptr<uint8_t[]> alignedBuffer;
+ if (size != alignedSize) {
+ alignedBuffer.reset(new uint8_t[alignedSize]);
+ std::memcpy(alignedBuffer.get() + leftExtraBytes, data, size);
+ data = alignedBuffer.get();
+ }
+
+ D3D11_BOX dstBox;
+ dstBox.left = static_cast<UINT>(alignedOffset);
+ dstBox.top = 0;
+ dstBox.front = 0;
+ dstBox.right = static_cast<UINT>(alignedOffset + alignedSize);
+ dstBox.bottom = 1;
+ dstBox.back = 1;
+ // For full buffer write, D3D11_COPY_DISCARD is used to avoid GPU CPU synchronization.
+ commandContext->UpdateSubresource1(d3d11Buffer, /*DstSubresource=*/0, &dstBox, data,
+ /*SrcRowPitch=*/0,
+ /*SrcDepthPitch=*/0,
+ /*CopyFlags=*/D3D11_COPY_DISCARD);
+ return {};
+ }
+
+ // If copy offset and size are not 16 bytes aligned, we have to create a staging buffer for
+ // transfer the data to constant buffer.
+ Ref<BufferBase> stagingBuffer;
+ DAWN_TRY_ASSIGN(stagingBuffer, ToBackend(GetDevice())->GetStagingBuffer(commandContext, size));
+ stagingBuffer->MarkUsedInPendingCommands();
+ DAWN_TRY(ToBackend(stagingBuffer)->WriteInternal(commandContext, 0, data, size));
+ DAWN_TRY(ToBackend(stagingBuffer.Get())
+ ->CopyToInternal(commandContext,
+ /*sourceOffset=*/0,
+ /*size=*/size, this, offset));
+ ToBackend(GetDevice())->ReturnStagingBuffer(std::move(stagingBuffer));
+
+ return {};
+}
+
// GPUOnlyBuffer
void GPUOnlyBuffer::DestroyImpl() {
// TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
@@ -670,7 +928,7 @@
// - It may be called when the last ref to the buffer is dropped and the buffer
// is implicitly destroyed. This case is thread-safe because there are no
// other threads using the buffer since there are no other live refs.
- Buffer::DestroyImpl();
+ GPUUsableBuffer::DestroyImpl();
mD3d11ConstantBuffer = nullptr;
mD3d11NonConstantBuffer = nullptr;
@@ -687,7 +945,7 @@
bool needsConstantBuffer = GetUsage() & wgpu::BufferUsage::Uniform;
bool onlyNeedsConstantBuffer =
- needsConstantBuffer && IsSubset(GetUsage(), kD3D11AllowedUniformBufferUsages);
+ needsConstantBuffer && IsSubset(GetUsage(), kD3D11GPUOnlyUniformBufferUsages);
if (!onlyNeedsConstantBuffer) {
// Create mD3d11NonConstantBuffer
@@ -729,78 +987,60 @@
return {};
}
-MaybeError GPUOnlyBuffer::MapInternal(const ScopedCommandRecordingContext* commandContext) {
- DAWN_UNREACHABLE();
-
- return {};
+MaybeError GPUOnlyBuffer::PredicatedClear(
+ const ScopedSwapStateCommandRecordingContext* commandContext,
+ ID3D11Predicate* predicate,
+ uint8_t clearValue,
+ uint64_t offset,
+ uint64_t size) {
+ // The clear will *NOT* be performed if the predicate's data is false.
+ commandContext->GetD3D11DeviceContext4()->SetPredication(predicate, false);
+ auto result = Clear(commandContext, clearValue, offset, size);
+ commandContext->GetD3D11DeviceContext4()->SetPredication(nullptr, false);
+ return result;
}
-void GPUOnlyBuffer::UnmapInternal(const ScopedCommandRecordingContext* commandContext) {
- DAWN_UNREACHABLE();
-}
-
-void GPUOnlyBuffer::MarkMutated() {
- mConstantBufferIsUpdated = false;
-}
-
-void GPUOnlyBuffer::EnsureConstantBufferIsUpdated(
+ResultOrError<ID3D11Buffer*> GPUOnlyBuffer::GetD3D11ConstantBuffer(
const ScopedCommandRecordingContext* commandContext) {
if (mConstantBufferIsUpdated) {
- return;
+ return mD3d11ConstantBuffer.Get();
}
DAWN_ASSERT(mD3d11NonConstantBuffer);
DAWN_ASSERT(mD3d11ConstantBuffer);
- commandContext->CopyResource(mD3d11ConstantBuffer.Get(), mD3d11NonConstantBuffer.Get());
+ if (commandContext) {
+ commandContext->CopyResource(mD3d11ConstantBuffer.Get(), mD3d11NonConstantBuffer.Get());
+ } else {
+ auto tempCommandContext =
+ ToBackend(GetDevice()->GetQueue())
+ ->GetScopedPendingCommandContext(QueueBase::SubmitMode::Normal);
+ tempCommandContext.CopyResource(mD3d11ConstantBuffer.Get(), mD3d11NonConstantBuffer.Get());
+ }
mConstantBufferIsUpdated = true;
+
+ return mD3d11ConstantBuffer.Get();
}
-ResultOrError<ComPtr<ID3D11ShaderResourceView>> GPUOnlyBuffer::CreateD3D11ShaderResourceView(
- uint64_t offset,
- uint64_t size) const {
- DAWN_ASSERT(IsAligned(offset, 4u));
- DAWN_ASSERT(IsAligned(size, 4u));
- UINT firstElement = static_cast<UINT>(offset / 4);
- UINT numElements = static_cast<UINT>(size / 4);
-
- D3D11_SHADER_RESOURCE_VIEW_DESC desc;
- desc.Format = DXGI_FORMAT_R32_TYPELESS;
- desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
- desc.BufferEx.FirstElement = firstElement;
- desc.BufferEx.NumElements = numElements;
- desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
- ComPtr<ID3D11ShaderResourceView> srv;
- DAWN_TRY(
- CheckHRESULT(ToBackend(GetDevice())
- ->GetD3D11Device()
- ->CreateShaderResourceView(mD3d11NonConstantBuffer.Get(), &desc, &srv),
- "ShaderResourceView creation"));
-
- return srv;
+ResultOrError<ID3D11Buffer*> GPUOnlyBuffer::GetD3D11NonConstantBuffer(
+ const ScopedCommandRecordingContext*) {
+ return mD3d11NonConstantBuffer.Get();
}
-ResultOrError<ComPtr<ID3D11UnorderedAccessView1>> GPUOnlyBuffer::CreateD3D11UnorderedAccessView1(
- uint64_t offset,
- uint64_t size) const {
- DAWN_ASSERT(IsAligned(offset, 4u));
- DAWN_ASSERT(IsAligned(size, 4u));
+ResultOrError<ComPtr<ID3D11ShaderResourceView>>
+GPUOnlyBuffer::UseAsSRV(const ScopedCommandRecordingContext*, uint64_t offset, uint64_t size) {
+ return CreateD3D11ShaderResourceViewFromD3DBuffer(mD3d11NonConstantBuffer.Get(), offset, size);
+}
- UINT firstElement = static_cast<UINT>(offset / 4);
- UINT numElements = static_cast<UINT>(size / 4);
-
- D3D11_UNORDERED_ACCESS_VIEW_DESC1 desc;
- desc.Format = DXGI_FORMAT_R32_TYPELESS;
- desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
- desc.Buffer.FirstElement = firstElement;
- desc.Buffer.NumElements = numElements;
- desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
-
+ResultOrError<ComPtr<ID3D11UnorderedAccessView1>>
+GPUOnlyBuffer::UseAsUAV(const ScopedCommandRecordingContext*, uint64_t offset, uint64_t size) {
ComPtr<ID3D11UnorderedAccessView1> uav;
- DAWN_TRY(
- CheckHRESULT(ToBackend(GetDevice())
- ->GetD3D11Device5()
- ->CreateUnorderedAccessView1(mD3d11NonConstantBuffer.Get(), &desc, &uav),
- "UnorderedAccessView creation"));
+ DAWN_TRY_ASSIGN(uav, CreateD3D11UnorderedAccessViewFromD3DBuffer(mD3d11NonConstantBuffer.Get(),
+ offset, size));
+
+ // Since UAV will modify the non-constant buffer's content, the constant buffer's content would
+ // also need to be updated afterwards.
+ mConstantBufferIsUpdated = false;
+
return uav;
}
@@ -846,52 +1086,8 @@
DAWN_ASSERT(mD3d11ConstantBuffer);
- // For a full size write, UpdateSubresource1(D3D11_COPY_DISCARD) can be used to update
- // mD3d11ConstantBuffer.
- // WriteInternal() can be called with GetAllocatedSize(). We treat it as a full buffer write as
- // well.
- if (size >= GetSize() && offset == 0) {
- // Offset and size must be aligned with 16 for using UpdateSubresource1() on constant
- // buffer.
- size_t alignedSize = Align(size, kConstantBufferUpdateAlignment);
- DAWN_ASSERT(alignedSize <= GetAllocatedSize());
- std::unique_ptr<uint8_t[]> alignedBuffer;
- if (size != alignedSize) {
- alignedBuffer.reset(new uint8_t[alignedSize]);
- std::memcpy(alignedBuffer.get(), data, size);
- data = alignedBuffer.get();
- }
-
- D3D11_BOX dstBox;
- dstBox.left = 0;
- dstBox.top = 0;
- dstBox.front = 0;
- dstBox.right = static_cast<UINT>(alignedSize);
- dstBox.bottom = 1;
- dstBox.back = 1;
- // For full buffer write, D3D11_COPY_DISCARD is used to avoid GPU CPU synchronization.
- commandContext->UpdateSubresource1(mD3d11ConstantBuffer.Get(), /*DstSubresource=*/0,
- &dstBox, data,
- /*SrcRowPitch=*/0,
- /*SrcDepthPitch=*/0,
- /*CopyFlags=*/D3D11_COPY_DISCARD);
- return {};
- }
-
- // If the mD3d11NonConstantBuffer is null and copy offset and size are not 16 bytes
- // aligned, we have to create a staging buffer for transfer the data to
- // mD3d11ConstantBuffer.
- Ref<BufferBase> stagingBuffer;
- DAWN_TRY_ASSIGN(stagingBuffer, ToBackend(GetDevice())->GetStagingBuffer(commandContext, size));
- stagingBuffer->MarkUsedInPendingCommands();
- DAWN_TRY(ToBackend(stagingBuffer)->WriteInternal(commandContext, 0, data, size));
- DAWN_TRY(ToBackend(stagingBuffer.Get())
- ->CopyToInternal(commandContext,
- /*sourceOffset=*/0,
- /*size=*/size, this, offset));
- ToBackend(GetDevice())->ReturnStagingBuffer(std::move(stagingBuffer));
-
- return {};
+ return UpdateD3D11ConstantBuffer(commandContext, mD3d11ConstantBuffer.Get(),
+ /*firstUpdate=*/false, offset, data, size);
}
MaybeError GPUOnlyBuffer::CopyToInternal(const ScopedCommandRecordingContext* commandContext,
@@ -956,26 +1152,16 @@
uint64_t clearOffset = GetSize();
// 'UpdateSubresource1' is more preferable for updating uniform buffers, as it incurs no
// GPU stall.
- if (GetUsage() & wgpu::BufferUsage::Uniform && !GetD3D11NonConstantBuffer()) {
+ if (mD3d11ConstantBuffer && !mD3d11NonConstantBuffer) {
clearSize = Align(paddingBytes, kConstantBufferUpdateAlignment);
clearOffset = GetAllocatedSize() - clearSize;
- D3D11_BOX dstBox;
- dstBox.left = clearOffset;
- dstBox.top = 0;
- dstBox.front = 0;
- dstBox.right = GetAllocatedSize();
- dstBox.bottom = 1;
- dstBox.back = 1;
-
std::vector<uint8_t> clearData(clearSize, 0);
- commandContext->UpdateSubresource1(GetD3D11ConstantBuffer(),
- /*DstSubresource=*/0, &dstBox, clearData.data(),
- /*SrcRowPitch=*/0,
- /*SrcDepthPitch=*/0,
- /*CopyFlags=*/D3D11_COPY_DISCARD);
+ DAWN_TRY(UpdateD3D11ConstantBuffer(commandContext, mD3d11ConstantBuffer.Get(),
+ /*firstTimeUpdate=*/true, clearOffset, clearData.data(),
+ clearSize));
} else {
- DAWN_TRY(ClearInternal(commandContext, 0, clearOffset, clearSize));
+ DAWN_TRY(ClearInternal(commandContext, 0, clearOffset, paddingBytes));
}
return {};
diff --git a/src/dawn/native/d3d11/BufferD3D11.h b/src/dawn/native/d3d11/BufferD3D11.h
index f8e1175..268ebbd9 100644
--- a/src/dawn/native/d3d11/BufferD3D11.h
+++ b/src/dawn/native/d3d11/BufferD3D11.h
@@ -41,6 +41,7 @@
class Device;
class ScopedCommandRecordingContext;
+class ScopedSwapStateCommandRecordingContext;
class Buffer : public BufferBase {
public:
@@ -76,7 +77,19 @@
// Actually map the buffer when its last usage serial has passed.
MaybeError FinalizeMap(ScopedCommandRecordingContext* commandContext,
- ExecutionSerial completedSerial);
+ ExecutionSerial completedSerial,
+ wgpu::MapMode mode);
+
+ bool IsCPUWritable() const;
+ bool IsCPUReadable() const;
+
+ // This performs GPU Clear. Unlike Clear(), this will always be affected by ID3D11Predicate.
+ // Whereas Clear() might be unaffected by ID3D11Predicate if it's pure CPU clear.
+ virtual MaybeError PredicatedClear(const ScopedSwapStateCommandRecordingContext* commandContext,
+ ID3D11Predicate* predicate,
+ uint8_t clearValue,
+ uint64_t offset,
+ uint64_t size);
// Write the buffer without checking if the buffer is initialized.
virtual MaybeError WriteInternal(const ScopedCommandRecordingContext* commandContext,
@@ -101,7 +114,8 @@
// Map buffer and return a ScopedMap object. If the buffer is not mappable,
// scopedMap.GetMappedData() will return nullptr.
static ResultOrError<ScopedMap> Create(const ScopedCommandRecordingContext* commandContext,
- Buffer* buffer);
+ Buffer* buffer,
+ wgpu::MapMode mode);
ScopedMap();
~ScopedMap();
@@ -125,16 +139,18 @@
};
protected:
- using BufferBase::BufferBase;
-
+ Buffer(DeviceBase* device,
+ const UnpackedPtr<BufferDescriptor>& descriptor,
+ wgpu::BufferUsage internalMappableFlags);
~Buffer() override;
void DestroyImpl() override;
virtual MaybeError InitializeInternal() = 0;
- virtual MaybeError MapInternal(const ScopedCommandRecordingContext* commandContext) = 0;
- virtual void UnmapInternal(const ScopedCommandRecordingContext* commandContext) = 0;
+ virtual MaybeError MapInternal(const ScopedCommandRecordingContext* commandContext,
+ wgpu::MapMode mode);
+ virtual void UnmapInternal(const ScopedCommandRecordingContext* commandContext);
// Clear the buffer without checking if the buffer is initialized.
MaybeError ClearWholeBuffer(const ScopedCommandRecordingContext* commandContext,
@@ -160,69 +176,58 @@
MaybeError InitializeToZero(const ScopedCommandRecordingContext* commandContext);
+ // Internal usage indicating the native buffer supports mapping for read and/or write or not.
+ const wgpu::BufferUsage mInternalMappableFlags;
ExecutionSerial mMapReadySerial = kMaxExecutionSerial;
};
-// Buffer that doesn't support mapping.
-class GPUOnlyBuffer final : public Buffer {
+// Buffer that can be used by GPU.
+class GPUUsableBuffer : public Buffer {
public:
- ID3D11Buffer* GetD3D11ConstantBuffer() const { return mD3d11ConstantBuffer.Get(); }
- ID3D11Buffer* GetD3D11NonConstantBuffer() const { return mD3d11NonConstantBuffer.Get(); }
+ virtual ResultOrError<ID3D11Buffer*> GetD3D11ConstantBuffer(
+ const ScopedCommandRecordingContext* commandContext) = 0;
+ virtual ResultOrError<ID3D11Buffer*> GetD3D11NonConstantBuffer(
+ const ScopedCommandRecordingContext* commandContext) = 0;
+ ID3D11Buffer* GetD3D11ConstantBufferForTesting();
+ ID3D11Buffer* GetD3D11NonConstantBufferForTesting();
- // Mark the mD3d11NonConstantBuffer is mutated by shaders, if mD3d11ConstantBuffer exists,
- // it will be synced with mD3d11NonConstantBuffer before binding it to the constant buffer slot.
- void MarkMutated();
- // Update content of the mD3d11ConstantBuffer from mD3d11NonConstantBuffer if needed.
- void EnsureConstantBufferIsUpdated(const ScopedCommandRecordingContext* commandContext);
- ResultOrError<ComPtr<ID3D11ShaderResourceView>> CreateD3D11ShaderResourceView(
+ virtual ResultOrError<ComPtr<ID3D11ShaderResourceView>> UseAsSRV(
+ const ScopedCommandRecordingContext* commandContext,
uint64_t offset,
- uint64_t size) const;
- ResultOrError<ComPtr<ID3D11UnorderedAccessView1>> CreateD3D11UnorderedAccessView1(
- uint64_t offset,
- uint64_t size) const;
+ uint64_t size) = 0;
- private:
+ // Use this buffer as UAV and mark it as being mutated by shader.
+ virtual ResultOrError<ComPtr<ID3D11UnorderedAccessView1>> UseAsUAV(
+ const ScopedCommandRecordingContext* commandContext,
+ uint64_t offset,
+ uint64_t size) = 0;
+
+ protected:
using Buffer::Buffer;
- // Dawn API
- void DestroyImpl() override;
- void SetLabelImpl() override;
+ ResultOrError<ComPtr<ID3D11ShaderResourceView>> CreateD3D11ShaderResourceViewFromD3DBuffer(
+ ID3D11Buffer* d3d11Buffer,
+ uint64_t offset,
+ uint64_t size);
+ ResultOrError<ComPtr<ID3D11UnorderedAccessView1>> CreateD3D11UnorderedAccessViewFromD3DBuffer(
+ ID3D11Buffer* d3d11Buffer,
+ uint64_t offset,
+ uint64_t size);
- // The buffer object for constant buffer usage.
- ComPtr<ID3D11Buffer> mD3d11ConstantBuffer;
- // The buffer object for non-constant buffer usages(e.g. storage buffer, vertex buffer, etc.)
- ComPtr<ID3D11Buffer> mD3d11NonConstantBuffer;
-
- MaybeError InitializeInternal() override;
- MaybeError MapInternal(const ScopedCommandRecordingContext* commandContext) override;
- void UnmapInternal(const ScopedCommandRecordingContext* commandContext) override;
- MaybeError CopyToInternal(const ScopedCommandRecordingContext* commandContext,
- uint64_t sourceOffset,
- size_t size,
- Buffer* destination,
- uint64_t destinationOffset) override;
- MaybeError CopyFromD3DInternal(const ScopedCommandRecordingContext* commandContext,
- ID3D11Buffer* srcD3D11Buffer,
- uint64_t sourceOffset,
- size_t size,
- uint64_t destinationOffset) override;
-
- MaybeError WriteInternal(const ScopedCommandRecordingContext* commandContext,
- uint64_t bufferOffset,
- const void* data,
- size_t size) override;
-
- MaybeError ClearPaddingInternal(const ScopedCommandRecordingContext* commandContext) override;
-
- bool mConstantBufferIsUpdated = true;
+ MaybeError UpdateD3D11ConstantBuffer(const ScopedCommandRecordingContext* commandContext,
+ ID3D11Buffer* d3d11Buffer,
+ bool firstTimeUpdate,
+ uint64_t bufferOffset,
+ const void* data,
+ size_t size);
};
-static inline GPUOnlyBuffer* ToGPUOnlyBuffer(BufferBase* buffer) {
- return static_cast<GPUOnlyBuffer*>(ToBackend(buffer));
+static inline GPUUsableBuffer* ToGPUUsableBuffer(BufferBase* buffer) {
+ return static_cast<GPUUsableBuffer*>(ToBackend(buffer));
}
-static inline Ref<GPUOnlyBuffer> ToGPUOnlyBuffer(Ref<BufferBase>&& buffer) {
- return std::move(buffer).Cast<Ref<GPUOnlyBuffer>>();
+static inline Ref<GPUUsableBuffer> ToGPUUsableBuffer(Ref<BufferBase>&& buffer) {
+ return std::move(buffer).Cast<Ref<GPUUsableBuffer>>();
}
} // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/CommandBufferD3D11.cpp b/src/dawn/native/d3d11/CommandBufferD3D11.cpp
index 4cee230..571289d 100644
--- a/src/dawn/native/d3d11/CommandBufferD3D11.cpp
+++ b/src/dawn/native/d3d11/CommandBufferD3D11.cpp
@@ -315,7 +315,7 @@
Ref<BufferBase> stagingBuffer;
// If the buffer is not mappable, we need to create a staging buffer and copy the
// data from the buffer to the staging buffer.
- if (!(buffer->GetUsage() & kMappableBufferUsages)) {
+ if (!buffer->IsCPUReadable()) {
const TexelBlockInfo& blockInfo =
ToBackend(dst.texture)->GetFormat().GetAspectInfo(dst.aspect).block;
// TODO(dawn:1768): use compute shader to copy data from buffer to texture.
@@ -335,7 +335,8 @@
}
Buffer::ScopedMap scopedMap;
- DAWN_TRY_ASSIGN(scopedMap, Buffer::ScopedMap::Create(commandContext, buffer));
+ DAWN_TRY_ASSIGN(scopedMap, Buffer::ScopedMap::Create(commandContext, buffer,
+ wgpu::MapMode::Read));
DAWN_TRY(buffer->EnsureDataInitialized(commandContext));
Texture* texture = ToBackend(dst.texture.Get());
@@ -370,7 +371,8 @@
Buffer* buffer = ToBackend(dst.buffer.Get());
Buffer::ScopedMap scopedDstMap;
- DAWN_TRY_ASSIGN(scopedDstMap, Buffer::ScopedMap::Create(commandContext, buffer));
+ DAWN_TRY_ASSIGN(scopedDstMap, Buffer::ScopedMap::Create(commandContext, buffer,
+ wgpu::MapMode::Write));
DAWN_TRY(buffer->EnsureDataInitializedAsDestination(commandContext, copy));
@@ -495,7 +497,7 @@
DAWN_TRY(bindGroupTracker.Apply());
- auto* indirectBuffer = ToGPUOnlyBuffer(dispatch->indirectBuffer.Get());
+ auto* indirectBuffer = ToGPUUsableBuffer(dispatch->indirectBuffer.Get());
if (lastPipeline->UsesNumWorkgroups()) {
// Copy indirect args into the uniform buffer for built-in workgroup variables.
@@ -504,9 +506,11 @@
0));
}
+ ID3D11Buffer* d3dBuffer;
+ DAWN_TRY_ASSIGN(d3dBuffer,
+ indirectBuffer->GetD3D11NonConstantBuffer(commandContext));
commandContext->GetD3D11DeviceContext4()->DispatchIndirect(
- indirectBuffer->GetD3D11NonConstantBuffer(), dispatch->indirectOffset);
-
+ d3dBuffer, dispatch->indirectOffset);
break;
}
@@ -667,7 +671,7 @@
case Command::DrawIndirect: {
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
- auto* indirectBuffer = ToGPUOnlyBuffer(draw->indirectBuffer.Get());
+ auto* indirectBuffer = ToGPUUsableBuffer(draw->indirectBuffer.Get());
DAWN_ASSERT(indirectBuffer != nullptr);
DAWN_TRY(bindGroupTracker.Apply());
@@ -684,8 +688,11 @@
0));
}
+ ID3D11Buffer* d3dBuffer;
+ DAWN_TRY_ASSIGN(d3dBuffer,
+ indirectBuffer->GetD3D11NonConstantBuffer(commandContext));
commandContext->GetD3D11DeviceContext4()->DrawInstancedIndirect(
- indirectBuffer->GetD3D11NonConstantBuffer(), draw->indirectOffset);
+ d3dBuffer, draw->indirectOffset);
break;
}
@@ -693,7 +700,7 @@
case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
- auto* indirectBuffer = ToGPUOnlyBuffer(draw->indirectBuffer.Get());
+ auto* indirectBuffer = ToGPUUsableBuffer(draw->indirectBuffer.Get());
DAWN_ASSERT(indirectBuffer != nullptr);
DAWN_TRY(bindGroupTracker.Apply());
@@ -710,8 +717,11 @@
0));
}
+ ID3D11Buffer* d3dBuffer;
+ DAWN_TRY_ASSIGN(d3dBuffer,
+ indirectBuffer->GetD3D11NonConstantBuffer(commandContext));
commandContext->GetD3D11DeviceContext4()->DrawIndexedInstancedIndirect(
- indirectBuffer->GetD3D11NonConstantBuffer(), draw->indirectOffset);
+ d3dBuffer, draw->indirectOffset);
break;
}
@@ -745,18 +755,21 @@
UINT indexBufferBaseOffset = cmd->offset;
DXGI_FORMAT indexBufferFormat = DXGIIndexFormat(cmd->format);
+ ID3D11Buffer* d3dBuffer;
+ DAWN_TRY_ASSIGN(d3dBuffer, ToGPUUsableBuffer(cmd->buffer.Get())
+ ->GetD3D11NonConstantBuffer(commandContext));
commandContext->GetD3D11DeviceContext4()->IASetIndexBuffer(
- ToGPUOnlyBuffer(cmd->buffer.Get())->GetD3D11NonConstantBuffer(),
- indexBufferFormat, indexBufferBaseOffset);
+ d3dBuffer, indexBufferFormat, indexBufferBaseOffset);
break;
}
case Command::SetVertexBuffer: {
SetVertexBufferCmd* cmd = iter->NextCommand<SetVertexBufferCmd>();
- ID3D11Buffer* buffer =
- ToGPUOnlyBuffer(cmd->buffer.Get())->GetD3D11NonConstantBuffer();
- vertexBufferTracker.OnSetVertexBuffer(cmd->slot, buffer, cmd->offset);
+ ID3D11Buffer* d3dBuffer;
+ DAWN_TRY_ASSIGN(d3dBuffer, ToGPUUsableBuffer(cmd->buffer.Get())
+ ->GetD3D11NonConstantBuffer(commandContext));
+ vertexBufferTracker.OnSetVertexBuffer(cmd->slot, d3dBuffer, cmd->offset);
break;
}
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
index 2c7e400..130e7ae 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
@@ -260,16 +260,19 @@
return device->CreateBuffer(&descriptor);
}
-void CommandRecordingContext::SetInternalUniformBuffer(Ref<BufferBase> uniformBuffer) {
- mUniformBuffer = ToGPUOnlyBuffer(std::move(uniformBuffer));
+MaybeError CommandRecordingContext::SetInternalUniformBuffer(Ref<BufferBase> uniformBuffer) {
+ mUniformBuffer = ToGPUUsableBuffer(std::move(uniformBuffer));
// Always bind the uniform buffer to the reserved slot for all pipelines.
// This buffer will be updated with the correct values before each draw or dispatch call.
- ID3D11Buffer* bufferPtr = mUniformBuffer->GetD3D11ConstantBuffer();
+ ID3D11Buffer* bufferPtr;
+ DAWN_TRY_ASSIGN(bufferPtr, mUniformBuffer->GetD3D11ConstantBuffer(nullptr));
mD3D11DeviceContext4->VSSetConstantBuffers(PipelineLayout::kReservedConstantBufferSlot, 1,
&bufferPtr);
mD3D11DeviceContext4->CSSetConstantBuffers(PipelineLayout::kReservedConstantBufferSlot, 1,
&bufferPtr);
+
+ return {};
}
void CommandRecordingContext::ReleaseKeyedMutexes() {
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
index 40370a2..6b4f2c9 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.h
@@ -40,7 +40,7 @@
class CommandAllocatorManager;
class Buffer;
-class GPUOnlyBuffer;
+class GPUUsableBuffer;
class Device;
class CommandRecordingContext;
@@ -84,7 +84,7 @@
void Destroy();
static ResultOrError<Ref<BufferBase>> CreateInternalUniformBuffer(DeviceBase* device);
- void SetInternalUniformBuffer(Ref<BufferBase> uniformBuffer);
+ MaybeError SetInternalUniformBuffer(Ref<BufferBase> uniformBuffer);
void ReleaseKeyedMutexes();
@@ -107,7 +107,7 @@
// The maximum number of builtin elements is 4 (vec4). It must be multiple of 4.
static constexpr size_t kMaxNumBuiltinElements = 4;
// The uniform buffer for built-in variables.
- Ref<GPUOnlyBuffer> mUniformBuffer;
+ Ref<GPUUsableBuffer> mUniformBuffer;
std::array<uint32_t, kMaxNumBuiltinElements> mUniformBufferData;
bool mUniformBufferDirty = true;
diff --git a/src/dawn/native/d3d11/QuerySetD3D11.cpp b/src/dawn/native/d3d11/QuerySetD3D11.cpp
index 38cddce..2948277 100644
--- a/src/dawn/native/d3d11/QuerySetD3D11.cpp
+++ b/src/dawn/native/d3d11/QuerySetD3D11.cpp
@@ -93,15 +93,12 @@
uint64_t offset) {
DAWN_TRY(destination->Clear(commandContext, 0, offset, queryCount * sizeof(uint64_t)));
const auto& queryAvailability = GetQueryAvailability();
- ID3D11DeviceContext* d3d11DeviceContext = commandContext->GetD3D11DeviceContext4();
for (uint32_t i = 0; i < queryCount; ++i) {
uint32_t queryIndex = i + firstQuery;
if (queryAvailability[queryIndex]) {
auto& predicate = mPredicates[queryIndex];
- d3d11DeviceContext->SetPredication(predicate.Get(), false);
- DAWN_TRY(destination->Clear(commandContext, 1, offset + i * sizeof(uint64_t),
- sizeof(uint64_t)));
- d3d11DeviceContext->SetPredication(nullptr, false);
+ DAWN_TRY(destination->PredicatedClear(commandContext, predicate.Get(), 1,
+ offset + i * sizeof(uint64_t), sizeof(uint64_t)));
}
}
return {};
diff --git a/src/dawn/native/d3d11/QueueD3D11.cpp b/src/dawn/native/d3d11/QueueD3D11.cpp
index e0ac29a..0b83880 100644
--- a/src/dawn/native/d3d11/QueueD3D11.cpp
+++ b/src/dawn/native/d3d11/QueueD3D11.cpp
@@ -144,7 +144,7 @@
Ref<BufferBase> uniformBuffer;
DAWN_TRY_ASSIGN(uniformBuffer,
CommandRecordingContext::CreateInternalUniformBuffer(GetDevice()));
- mPendingCommands->SetInternalUniformBuffer(std::move(uniformBuffer));
+ DAWN_TRY(mPendingCommands->SetInternalUniformBuffer(std::move(uniformBuffer)));
return {};
}
@@ -219,15 +219,18 @@
MaybeError Queue::CheckAndMapReadyBuffers(ExecutionSerial completedSerial) {
auto commandContext = GetScopedPendingCommandContext(QueueBase::SubmitMode::Passive);
- for (auto buffer : mPendingMapBuffers.IterateUpTo(completedSerial)) {
- DAWN_TRY(buffer->FinalizeMap(&commandContext, completedSerial));
+ for (const auto& bufferEntry : mPendingMapBuffers.IterateUpTo(completedSerial)) {
+ DAWN_TRY(
+ bufferEntry.buffer->FinalizeMap(&commandContext, completedSerial, bufferEntry.mode));
}
mPendingMapBuffers.ClearUpTo(completedSerial);
return {};
}
-void Queue::TrackPendingMapBuffer(Ref<Buffer>&& buffer, ExecutionSerial readySerial) {
- mPendingMapBuffers.Enqueue(buffer, readySerial);
+void Queue::TrackPendingMapBuffer(Ref<Buffer>&& buffer,
+ wgpu::MapMode mode,
+ ExecutionSerial readySerial) {
+ mPendingMapBuffers.Enqueue({buffer, mode}, readySerial);
}
MaybeError Queue::WriteBufferImpl(BufferBase* buffer,
diff --git a/src/dawn/native/d3d11/QueueD3D11.h b/src/dawn/native/d3d11/QueueD3D11.h
index 657e5ad..3c8bb0e 100644
--- a/src/dawn/native/d3d11/QueueD3D11.h
+++ b/src/dawn/native/d3d11/QueueD3D11.h
@@ -54,7 +54,9 @@
MaybeError InitializePendingContext();
// Register the pending map buffer to be checked.
- void TrackPendingMapBuffer(Ref<Buffer>&& buffer, ExecutionSerial readySerial);
+ void TrackPendingMapBuffer(Ref<Buffer>&& buffer,
+ wgpu::MapMode mode,
+ ExecutionSerial readySerial);
protected:
using d3d::Queue::Queue;
@@ -88,7 +90,12 @@
Ref<SharedFence> mSharedFence;
MutexProtected<CommandRecordingContext, CommandRecordingContextGuard> mPendingCommands;
std::atomic<bool> mPendingCommandsNeedSubmit = false;
- SerialMap<ExecutionSerial, Ref<Buffer>> mPendingMapBuffers;
+
+ struct BufferMapEntry {
+ Ref<Buffer> buffer;
+ wgpu::MapMode mode;
+ };
+ SerialMap<ExecutionSerial, BufferMapEntry> mPendingMapBuffers;
};
} // namespace dawn::native::d3d11
diff --git a/src/dawn/tests/white_box/D3D11BufferTests.cpp b/src/dawn/tests/white_box/D3D11BufferTests.cpp
index eb21c0a..8b19545 100644
--- a/src/dawn/tests/white_box/D3D11BufferTests.cpp
+++ b/src/dawn/tests/white_box/D3D11BufferTests.cpp
@@ -109,66 +109,66 @@
{
wgpu::BufferUsage usage = wgpu::BufferUsage::Uniform;
wgpu::Buffer buffer = CreateBuffer(4, usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_EQ(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_EQ(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
}
{
wgpu::BufferUsage usage =
wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = CreateBuffer(4, usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_EQ(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_EQ(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
}
{
wgpu::BufferUsage usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::Vertex;
wgpu::Buffer buffer = CreateBuffer(4, usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
}
{
wgpu::BufferUsage usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::Index;
wgpu::Buffer buffer = CreateBuffer(4, usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
}
{
wgpu::BufferUsage usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::Indirect;
wgpu::Buffer buffer = CreateBuffer(4, usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
}
{
wgpu::BufferUsage usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::Storage;
wgpu::Buffer buffer = CreateBuffer(4, usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
}
{
wgpu::BufferUsage usage = wgpu::BufferUsage::Storage;
wgpu::Buffer buffer = CreateBuffer(4, usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_EQ(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_EQ(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
}
}
@@ -179,34 +179,34 @@
wgpu::BufferUsage usage =
wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = CreateBuffer(data.size(), usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_EQ(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_EQ(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
queue.WriteBuffer(buffer, 0, data.data(), data.size());
EXPECT_BUFFER_U8_RANGE_EQ(data.data(), buffer, 0, data.size());
- CheckBuffer(d3d11Buffer->GetD3D11ConstantBuffer(), data);
+ CheckBuffer(d3d11Buffer->GetD3D11ConstantBufferForTesting(), data);
}
{
std::vector<uint8_t> data = {0x12, 0x34, 0x56, 0x78};
wgpu::BufferUsage usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::Vertex |
wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = CreateBuffer(data.size(), usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
queue.WriteBuffer(buffer, 0, data.data(), data.size());
EXPECT_BUFFER_U8_RANGE_EQ(data.data(), buffer, 0, data.size());
// both buffers should be updated.
- CheckBuffer(d3d11Buffer->GetD3D11NonConstantBuffer(), data);
- CheckBuffer(d3d11Buffer->GetD3D11ConstantBuffer(), data);
+ CheckBuffer(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), data);
+ CheckBuffer(d3d11Buffer->GetD3D11ConstantBufferForTesting(), data);
}
}
@@ -218,17 +218,17 @@
wgpu::BufferUsage usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::Storage |
wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
wgpu::Buffer buffer = CreateBuffer(bufferSize, usage);
- native::d3d11::GPUOnlyBuffer* d3d11Buffer =
- native::d3d11::ToGPUOnlyBuffer(native::FromAPI(buffer.Get()));
+ native::d3d11::GPUUsableBuffer* d3d11Buffer =
+ native::d3d11::ToGPUUsableBuffer(native::FromAPI(buffer.Get()));
- EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBuffer(), nullptr);
- EXPECT_NE(d3d11Buffer->GetD3D11ConstantBuffer(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), nullptr);
+ EXPECT_NE(d3d11Buffer->GetD3D11ConstantBufferForTesting(), nullptr);
queue.WriteBuffer(buffer, 0, data.data(), bufferSize);
EXPECT_BUFFER_U32_RANGE_EQ(data.data(), buffer, 0, data.size());
- CheckBuffer(d3d11Buffer->GetD3D11NonConstantBuffer(), data);
- CheckBuffer(d3d11Buffer->GetD3D11ConstantBuffer(), data);
+ CheckBuffer(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), data);
+ CheckBuffer(d3d11Buffer->GetD3D11ConstantBufferForTesting(), data);
// Fill the buffer with 0x11223344 with a compute shader
{
@@ -268,9 +268,9 @@
std::vector<uint32_t> expectedData(kNumValues, 0x11223344);
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), buffer, 0, expectedData.size());
// The non-constant buffer should be updated.
- CheckBuffer(d3d11Buffer->GetD3D11NonConstantBuffer(), expectedData);
- // The constant buffer should not be updated, until the constant buffer is used a pipeline
- CheckBuffer(d3d11Buffer->GetD3D11ConstantBuffer(), data);
+ CheckBuffer(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), expectedData);
+ // The constant buffer should be updated too.
+ CheckBuffer(d3d11Buffer->GetD3D11ConstantBufferForTesting(), expectedData);
}
// Copy the uniform buffer content to a new buffer with Compute shader
@@ -316,9 +316,9 @@
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), newBuffer, 0, expectedData.size());
// The non-constant buffer should be updated.
- CheckBuffer(d3d11Buffer->GetD3D11NonConstantBuffer(), expectedData);
+ CheckBuffer(d3d11Buffer->GetD3D11NonConstantBufferForTesting(), expectedData);
// The constant buffer should be updated too.
- CheckBuffer(d3d11Buffer->GetD3D11ConstantBuffer(), expectedData);
+ CheckBuffer(d3d11Buffer->GetD3D11ConstantBufferForTesting(), expectedData);
}
}