d3d11: CommandBuffer: implement buffer and texture related cmd

This CL also enables several buffer end2end tests

Bug: dawn:1705
Change-Id: I16c23346a60f3f15dbfbb96b2cb8dc0f5ba8c89c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/127405
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
This commit is contained in:
Peng Huang 2023-04-20 03:24:55 +00:00 committed by Dawn LUCI CQ
parent e7c06367d4
commit 9e9c456075
11 changed files with 542 additions and 48 deletions

View File

@ -435,6 +435,8 @@ source_set("sources") {
"d3d11/BindGroupLayoutD3D11.h", "d3d11/BindGroupLayoutD3D11.h",
"d3d11/BufferD3D11.cpp", "d3d11/BufferD3D11.cpp",
"d3d11/BufferD3D11.h", "d3d11/BufferD3D11.h",
"d3d11/CommandBufferD3D11.cpp",
"d3d11/CommandBufferD3D11.h",
"d3d11/CommandRecordingContextD3D11.cpp", "d3d11/CommandRecordingContextD3D11.cpp",
"d3d11/CommandRecordingContextD3D11.h", "d3d11/CommandRecordingContextD3D11.h",
"d3d11/ComputePipelineD3D11.cpp", "d3d11/ComputePipelineD3D11.cpp",

View File

@ -292,6 +292,8 @@ if (DAWN_ENABLE_D3D11)
"d3d11/BindGroupLayoutD3D11.h" "d3d11/BindGroupLayoutD3D11.h"
"d3d11/BufferD3D11.cpp" "d3d11/BufferD3D11.cpp"
"d3d11/BufferD3D11.h" "d3d11/BufferD3D11.h"
"d3d11/CommandBufferD3D11.cpp"
"d3d11/CommandBufferD3D11.h"
"d3d11/CommandRecordingContextD3D11.cpp" "d3d11/CommandRecordingContextD3D11.cpp"
"d3d11/CommandRecordingContextD3D11.h" "d3d11/CommandRecordingContextD3D11.h"
"d3d11/ComputePipelineD3D11.cpp" "d3d11/ComputePipelineD3D11.cpp"

View File

@ -471,18 +471,18 @@ MaybeError Buffer::WriteInternal(CommandRecordingContext* commandContext,
return {}; return {};
} }
MaybeError Buffer::CopyFromBuffer(CommandRecordingContext* commandContext, // static
uint64_t offset, MaybeError Buffer::Copy(CommandRecordingContext* commandContext,
size_t size,
Buffer* source, Buffer* source,
uint64_t sourceOffset) { uint64_t sourceOffset,
if (size == 0) { size_t size,
// Skip no-op copies. Buffer* destination,
return {}; uint64_t destinationOffset) {
} DAWN_ASSERT(size != 0);
DAWN_TRY(source->EnsureDataInitialized(commandContext)); DAWN_TRY(source->EnsureDataInitialized(commandContext));
DAWN_TRY(EnsureDataInitializedAsDestination(commandContext, offset, size)); DAWN_TRY(
destination->EnsureDataInitializedAsDestination(commandContext, destinationOffset, size));
D3D11_BOX srcBox; D3D11_BOX srcBox;
srcBox.left = sourceOffset; srcBox.left = sourceOffset;
@ -492,8 +492,9 @@ MaybeError Buffer::CopyFromBuffer(CommandRecordingContext* commandContext,
srcBox.front = 0; srcBox.front = 0;
srcBox.back = 1; srcBox.back = 1;
commandContext->GetD3D11DeviceContext()->CopySubresourceRegion( commandContext->GetD3D11DeviceContext()->CopySubresourceRegion(
GetD3D11Buffer(), /*DstSubresource=*/0, /*DstX=*/offset, /*DstY=*/0, /*DstZ=*/0, destination->mD3d11Buffer.Get(), /*DstSubresource=*/0, /*DstX=*/destinationOffset,
source->GetD3D11Buffer(), /*SrcSubresource=*/0, &srcBox); /*DstY=*/0,
/*DstZ=*/0, source->mD3d11Buffer.Get(), /*SrcSubresource=*/0, &srcBox);
return {}; return {};
} }

View File

@ -56,11 +56,13 @@ class Buffer final : public BufferBase {
uint64_t offset, uint64_t offset,
const void* data, const void* data,
size_t size); size_t size);
MaybeError CopyFromBuffer(CommandRecordingContext* commandContext,
uint64_t offset, static MaybeError Copy(CommandRecordingContext* commandContext,
size_t size,
Buffer* source, Buffer* source,
uint64_t sourceOffset); uint64_t sourceOffset,
size_t size,
Buffer* destination,
uint64_t destinationOffset);
class ScopedMap : public NonCopyable { class ScopedMap : public NonCopyable {
public: public:

View File

@ -0,0 +1,269 @@
// Copyright 2023 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn/native/d3d11/CommandBufferD3D11.h"
#include <algorithm>
#include <array>
#include <string>
#include <vector>
#include "dawn/common/WindowsUtils.h"
#include "dawn/native/BindGroup.h"
#include "dawn/native/BindGroupTracker.h"
#include "dawn/native/CommandEncoder.h"
#include "dawn/native/Commands.h"
#include "dawn/native/ExternalTexture.h"
#include "dawn/native/RenderBundle.h"
#include "dawn/native/VertexFormat.h"
#include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d11/BufferD3D11.h"
#include "dawn/native/d3d11/ComputePipelineD3D11.h"
#include "dawn/native/d3d11/DeviceD3D11.h"
#include "dawn/native/d3d11/Forward.h"
#include "dawn/native/d3d11/PipelineLayoutD3D11.h"
#include "dawn/native/d3d11/RenderPipelineD3D11.h"
#include "dawn/native/d3d11/SamplerD3D11.h"
#include "dawn/native/d3d11/TextureD3D11.h"
#include "dawn/native/d3d11/UtilsD3D11.h"
namespace dawn::native::d3d11 {
// Create CommandBuffer
Ref<CommandBuffer> CommandBuffer::Create(CommandEncoder* encoder,
const CommandBufferDescriptor* descriptor) {
return AcquireRef(new CommandBuffer(encoder, descriptor));
}
MaybeError CommandBuffer::Execute() {
CommandRecordingContext* commandContext = ToBackend(GetDevice())->GetPendingCommandContext();
ID3D11DeviceContext1* d3d11DeviceContext1 = commandContext->GetD3D11DeviceContext1();
Command type;
while (mCommands.NextCommandId(&type)) {
switch (type) {
case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>();
return DAWN_UNIMPLEMENTED_ERROR("Compute pass not implemented");
}
case Command::BeginRenderPass: {
[[maybe_unused]] auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
return DAWN_UNIMPLEMENTED_ERROR("Render pass not implemented");
}
case Command::CopyBufferToBuffer: {
CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
if (copy->size == 0) {
// Skip no-op copies.
break;
}
Buffer* source = ToBackend(copy->source.Get());
Buffer* destination = ToBackend(copy->destination.Get());
// Buffer::Copy() will ensure the source and destination buffers are initialized.
DAWN_TRY(Buffer::Copy(commandContext, source, copy->sourceOffset, copy->size,
destination, copy->destinationOffset));
break;
}
case Command::CopyBufferToTexture: {
CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
copy->copySize.depthOrArrayLayers == 0) {
// Skip no-op copies.
continue;
}
Buffer* buffer = ToBackend(copy->source.buffer.Get());
Buffer::ScopedMap scopedMap;
DAWN_TRY_ASSIGN(scopedMap, Buffer::ScopedMap::Create(buffer));
DAWN_TRY(buffer->EnsureDataInitialized(commandContext));
if (!scopedMap.GetMappedData()) {
// TODO(dawn:1768): implement CopyBufferToTexture with non-mappable buffers.
return DAWN_UNIMPLEMENTED_ERROR(
"CopyBufferToTexture isn't implemented with non-mappable buffers");
}
Texture* texture = ToBackend(copy->destination.texture.Get());
SubresourceRange subresources =
GetSubresourcesAffectedByCopy(copy->destination, copy->copySize);
const uint8_t* data = scopedMap.GetMappedData() + copy->source.offset;
DAWN_TRY(texture->Write(commandContext, subresources, copy->destination.origin,
copy->copySize, data, copy->source.bytesPerRow,
copy->source.rowsPerImage));
break;
}
case Command::CopyTextureToBuffer: {
CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
copy->copySize.depthOrArrayLayers == 0) {
// Skip no-op copies.
continue;
}
auto& src = copy->source;
auto& dst = copy->destination;
SubresourceRange subresources = GetSubresourcesAffectedByCopy(src, copy->copySize);
DAWN_TRY(ToBackend(src.texture)
->EnsureSubresourceContentInitialized(commandContext, subresources));
// Create a staging texture.
D3D11_TEXTURE2D_DESC stagingTextureDesc;
stagingTextureDesc.Width = copy->copySize.width;
stagingTextureDesc.Height = copy->copySize.height;
stagingTextureDesc.MipLevels = 1;
stagingTextureDesc.ArraySize = copy->copySize.depthOrArrayLayers;
stagingTextureDesc.Format = ToBackend(src.texture)->GetD3D11Format();
stagingTextureDesc.SampleDesc.Count = 1;
stagingTextureDesc.SampleDesc.Quality = 0;
stagingTextureDesc.Usage = D3D11_USAGE_STAGING;
stagingTextureDesc.BindFlags = 0;
stagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
stagingTextureDesc.MiscFlags = 0;
ComPtr<ID3D11Texture2D> stagingTexture;
DAWN_TRY(CheckHRESULT(commandContext->GetD3D11Device()->CreateTexture2D(
&stagingTextureDesc, nullptr, &stagingTexture),
"D3D11 create staging texture"));
uint32_t subresource =
src.texture->GetSubresourceIndex(src.mipLevel, src.origin.z, src.aspect);
if (src.texture->GetDimension() != wgpu::TextureDimension::e2D) {
return DAWN_UNIMPLEMENTED_ERROR(
"CopyTextureToBuffer is not implemented for non-2D textures");
} else {
for (uint32_t z = 0; z < copy->copySize.depthOrArrayLayers; ++z) {
// Copy the texture to the staging texture.
if (src.texture->GetFormat().HasDepthOrStencil()) {
d3d11DeviceContext1->CopySubresourceRegion(
stagingTexture.Get(), z, 0, 0, 0,
ToBackend(src.texture)->GetD3D11Resource(), subresource, nullptr);
} else {
D3D11_BOX srcBox;
srcBox.left = src.origin.x;
srcBox.right = src.origin.x + copy->copySize.width;
srcBox.top = src.origin.y;
srcBox.bottom = src.origin.y + copy->copySize.height;
srcBox.front = 0;
srcBox.back = 1;
d3d11DeviceContext1->CopySubresourceRegion(
stagingTexture.Get(), z, 0, 0, 0,
ToBackend(src.texture)->GetD3D11Resource(), subresource, &srcBox);
}
}
}
for (uint32_t z = 0; z < copy->copySize.depthOrArrayLayers; ++z) {
// Copy the staging texture to the buffer.
// The Map() will block until the GPU is done with the texture.
// TODO(dawn:1705): avoid blocking the CPU.
D3D11_MAPPED_SUBRESOURCE mappedResource;
DAWN_TRY(
CheckHRESULT(d3d11DeviceContext1->Map(stagingTexture.Get(), z,
D3D11_MAP_READ, 0, &mappedResource),
"D3D11 map staging texture"));
Buffer* buffer = ToBackend(dst.buffer.Get());
Buffer::ScopedMap scopedMap;
DAWN_TRY_ASSIGN(scopedMap, Buffer::ScopedMap::Create(buffer));
DAWN_TRY(buffer->EnsureDataInitializedAsDestination(
commandContext, dst.offset, dst.bytesPerRow * copy->copySize.height));
uint8_t* pSrcData = reinterpret_cast<uint8_t*>(mappedResource.pData);
const TexelBlockInfo& blockInfo =
ToBackend(src.texture)->GetFormat().GetAspectInfo(src.aspect).block;
uint32_t memcpySize = blockInfo.byteSize * copy->copySize.width;
uint8_t* pDstData = scopedMap.GetMappedData() + dst.offset +
dst.bytesPerRow * dst.rowsPerImage * z;
for (uint32_t y = 0; y < copy->copySize.height; ++y) {
memcpy(pDstData, pSrcData, memcpySize);
pDstData += dst.bytesPerRow;
pSrcData += mappedResource.RowPitch;
}
d3d11DeviceContext1->Unmap(stagingTexture.Get(), z);
}
break;
}
case Command::CopyTextureToTexture: {
CopyTextureToTextureCmd* copy = mCommands.NextCommand<CopyTextureToTextureCmd>();
if (copy->copySize.width == 0 || copy->copySize.height == 0 ||
copy->copySize.depthOrArrayLayers == 0) {
// Skip no-op copies.
continue;
}
DAWN_TRY(Texture::Copy(commandContext, copy));
break;
}
case Command::ClearBuffer: {
ClearBufferCmd* cmd = mCommands.NextCommand<ClearBufferCmd>();
if (cmd->size == 0) {
// Skip no-op fills.
break;
}
Buffer* buffer = ToBackend(cmd->buffer.Get());
DAWN_TRY(buffer->Clear(commandContext, 0, cmd->offset, cmd->size));
break;
}
case Command::ResolveQuerySet: {
return DAWN_UNIMPLEMENTED_ERROR("ResolveQuerySet unimplemented");
}
case Command::WriteTimestamp: {
return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");
}
case Command::WriteBuffer: {
WriteBufferCmd* cmd = mCommands.NextCommand<WriteBufferCmd>();
if (cmd->size == 0) {
// Skip no-op writes.
continue;
}
Buffer* dstBuffer = ToBackend(cmd->buffer.Get());
uint8_t* data = mCommands.NextData<uint8_t>(cmd->size);
DAWN_TRY(dstBuffer->Write(commandContext, cmd->offset, data, cmd->size));
break;
}
case Command::InsertDebugMarker:
case Command::PopDebugGroup:
case Command::PushDebugGroup: {
return DAWN_UNIMPLEMENTED_ERROR("Debug markers unimplemented");
}
default:
return DAWN_FORMAT_INTERNAL_ERROR("Unknown command type: %d", type);
}
}
return {};
}
} // namespace dawn::native::d3d11

View File

@ -0,0 +1,41 @@
// Copyright 2023 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_DAWN_NATIVE_D3D11_COMMANDBUFFERD3D11_H_
#define SRC_DAWN_NATIVE_D3D11_COMMANDBUFFERD3D11_H_
#include "dawn/native/CommandBuffer.h"
namespace dawn::native {
enum class Command;
struct BeginRenderPassCmd;
} // namespace dawn::native
namespace dawn::native::d3d11 {
class CommandRecordingContext;
class CommandBuffer final : public CommandBufferBase {
public:
static Ref<CommandBuffer> Create(CommandEncoder* encoder,
const CommandBufferDescriptor* descriptor);
MaybeError Execute();
private:
using CommandBufferBase::CommandBufferBase;
};
} // namespace dawn::native::d3d11
#endif // SRC_DAWN_NATIVE_D3D11_COMMANDBUFFERD3D11_H_

View File

@ -20,19 +20,16 @@
#include <utility> #include <utility>
#include "dawn/common/GPUInfo.h" #include "dawn/common/GPUInfo.h"
#include "dawn/native/Buffer.h"
#include "dawn/native/ComputePipeline.h"
#include "dawn/native/D3D11Backend.h" #include "dawn/native/D3D11Backend.h"
#include "dawn/native/DynamicUploader.h" #include "dawn/native/DynamicUploader.h"
#include "dawn/native/Instance.h" #include "dawn/native/Instance.h"
#include "dawn/native/RenderPipeline.h"
#include "dawn/native/Texture.h"
#include "dawn/native/d3d/D3DError.h" #include "dawn/native/d3d/D3DError.h"
#include "dawn/native/d3d11/AdapterD3D11.h" #include "dawn/native/d3d11/AdapterD3D11.h"
#include "dawn/native/d3d11/BackendD3D11.h" #include "dawn/native/d3d11/BackendD3D11.h"
#include "dawn/native/d3d11/BindGroupD3D11.h" #include "dawn/native/d3d11/BindGroupD3D11.h"
#include "dawn/native/d3d11/BindGroupLayoutD3D11.h" #include "dawn/native/d3d11/BindGroupLayoutD3D11.h"
#include "dawn/native/d3d11/BufferD3D11.h" #include "dawn/native/d3d11/BufferD3D11.h"
#include "dawn/native/d3d11/CommandBufferD3D11.h"
#include "dawn/native/d3d11/ComputePipelineD3D11.h" #include "dawn/native/d3d11/ComputePipelineD3D11.h"
#include "dawn/native/d3d11/PipelineLayoutD3D11.h" #include "dawn/native/d3d11/PipelineLayoutD3D11.h"
#include "dawn/native/d3d11/PlatformFunctionsD3D11.h" #include "dawn/native/d3d11/PlatformFunctionsD3D11.h"
@ -259,7 +256,7 @@ ResultOrError<Ref<BufferBase>> Device::CreateBufferImpl(const BufferDescriptor*
ResultOrError<Ref<CommandBufferBase>> Device::CreateCommandBuffer( ResultOrError<Ref<CommandBufferBase>> Device::CreateCommandBuffer(
CommandEncoder* encoder, CommandEncoder* encoder,
const CommandBufferDescriptor* descriptor) { const CommandBufferDescriptor* descriptor) {
return DAWN_UNIMPLEMENTED_ERROR("CreateCommandBuffer"); return CommandBuffer::Create(encoder, descriptor);
} }
Ref<ComputePipelineBase> Device::CreateUninitializedComputePipelineImpl( Ref<ComputePipelineBase> Device::CreateUninitializedComputePipelineImpl(
@ -327,8 +324,8 @@ MaybeError Device::CopyFromStagingToBufferImpl(BufferBase* source,
uint64_t destinationOffset, uint64_t destinationOffset,
uint64_t size) { uint64_t size) {
CommandRecordingContext* commandContext = GetPendingCommandContext(); CommandRecordingContext* commandContext = GetPendingCommandContext();
return ToBackend(destination) return Buffer::Copy(commandContext, ToBackend(source), sourceOffset, size,
->CopyFromBuffer(commandContext, destinationOffset, size, ToBackend(source), sourceOffset); ToBackend(destination), destinationOffset);
} }
MaybeError Device::CopyFromStagingToTextureImpl(const BufferBase* source, MaybeError Device::CopyFromStagingToTextureImpl(const BufferBase* source,

View File

@ -15,8 +15,11 @@
#include "dawn/native/d3d11/QueueD3D11.h" #include "dawn/native/d3d11/QueueD3D11.h"
#include "dawn/native/d3d11/BufferD3D11.h" #include "dawn/native/d3d11/BufferD3D11.h"
#include "dawn/native/d3d11/CommandBufferD3D11.h"
#include "dawn/native/d3d11/DeviceD3D11.h" #include "dawn/native/d3d11/DeviceD3D11.h"
#include "dawn/native/d3d11/TextureD3D11.h"
#include "dawn/platform/DawnPlatform.h" #include "dawn/platform/DawnPlatform.h"
#include "dawn/platform/tracing/TraceEvent.h"
namespace dawn::native::d3d11 { namespace dawn::native::d3d11 {
@ -25,7 +28,17 @@ Ref<Queue> Queue::Create(Device* device, const QueueDescriptor* descriptor) {
} }
MaybeError Queue::SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) { MaybeError Queue::SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) {
return DAWN_UNIMPLEMENTED_ERROR("Submit is not implemented for D3D11"); Device* device = ToBackend(GetDevice());
TRACE_EVENT_BEGIN0(GetDevice()->GetPlatform(), Recording, "CommandBufferD3D11::Execute");
for (uint32_t i = 0; i < commandCount; ++i) {
DAWN_TRY(ToBackend(commands[i])->Execute());
}
TRACE_EVENT_END0(GetDevice()->GetPlatform(), Recording, "CommandBufferD3D11::Execute");
DAWN_TRY(device->NextSerial());
return {};
} }
MaybeError Queue::WriteBufferImpl(BufferBase* buffer, MaybeError Queue::WriteBufferImpl(BufferBase* buffer,
@ -40,7 +53,26 @@ MaybeError Queue::WriteTextureImpl(const ImageCopyTexture& destination,
const void* data, const void* data,
const TextureDataLayout& dataLayout, const TextureDataLayout& dataLayout,
const Extent3D& writeSizePixel) { const Extent3D& writeSizePixel) {
return DAWN_UNIMPLEMENTED_ERROR("WriteTexture is not implemented for D3D11"); if (writeSizePixel.width == 0 || writeSizePixel.height == 0 ||
writeSizePixel.depthOrArrayLayers == 0) {
return {};
}
CommandRecordingContext* commandContext = ToBackend(GetDevice())->GetPendingCommandContext();
TextureCopy textureCopy;
textureCopy.texture = destination.texture;
textureCopy.mipLevel = destination.mipLevel;
textureCopy.origin = destination.origin;
textureCopy.aspect = SelectFormatAspects(destination.texture->GetFormat(), destination.aspect);
SubresourceRange subresources = GetSubresourcesAffectedByCopy(textureCopy, writeSizePixel);
Texture* texture = ToBackend(destination.texture);
return texture->Write(commandContext, subresources, destination.origin, writeSizePixel,
static_cast<const uint8_t*>(data), dataLayout.bytesPerRow,
dataLayout.rowsPerImage);
} }
} // namespace dawn::native::d3d11 } // namespace dawn::native::d3d11

View File

@ -20,6 +20,7 @@
#include "dawn/common/Constants.h" #include "dawn/common/Constants.h"
#include "dawn/common/Math.h" #include "dawn/common/Math.h"
#include "dawn/native/CommandBuffer.h"
#include "dawn/native/DynamicUploader.h" #include "dawn/native/DynamicUploader.h"
#include "dawn/native/EnumMaskIterator.h" #include "dawn/native/EnumMaskIterator.h"
#include "dawn/native/IntegerTypes.h" #include "dawn/native/IntegerTypes.h"
@ -136,8 +137,7 @@ MaybeError Texture::InitializeAsInternalTexture() {
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) { if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
CommandRecordingContext* commandContext = device->GetPendingCommandContext(); CommandRecordingContext* commandContext = device->GetPendingCommandContext();
DAWN_TRY( DAWN_TRY(Clear(commandContext, GetAllSubresources(), TextureBase::ClearValue::NonZero));
ClearTexture(commandContext, GetAllSubresources(), TextureBase::ClearValue::NonZero));
} }
SetLabelImpl(); SetLabelImpl();
@ -261,11 +261,49 @@ D3D11_DEPTH_STENCIL_VIEW_DESC Texture::GetDSVDescriptor(const SubresourceRange&
return dsvDesc; return dsvDesc;
} }
MaybeError Texture::ClearTexture(CommandRecordingContext* commandContext, MaybeError Texture::Clear(CommandRecordingContext* commandContext,
const SubresourceRange& range, const SubresourceRange& range,
TextureBase::ClearValue clearValue) { TextureBase::ClearValue clearValue) {
// TODO(dawn:1740): Implement this. // TODO(dawn:1740): Clear non-renderable texture.
return DAWN_UNIMPLEMENTED_ERROR("ClearTexture"); if ((GetUsage() & wgpu::TextureUsage::RenderAttachment) == 0) {
return DAWN_UNIMPLEMENTED_ERROR("Clearing non-renderable textures is not implemented");
}
TextureViewDescriptor desc;
desc.format = GetFormat().format;
switch (GetDimension()) {
case wgpu::TextureDimension::e1D:
desc.dimension = wgpu::TextureViewDimension::e1D;
break;
case wgpu::TextureDimension::e2D:
desc.dimension = wgpu::TextureViewDimension::e2D;
break;
case wgpu::TextureDimension::e3D:
desc.dimension = wgpu::TextureViewDimension::e3D;
break;
}
// TODO(dawn:1740): support clearing multiple layers.
if (range.levelCount != 1 || range.layerCount != 1) {
return DAWN_UNIMPLEMENTED_ERROR("Clearing multiple layers is not implemented");
}
desc.baseMipLevel = range.baseMipLevel;
desc.mipLevelCount = range.levelCount;
desc.baseArrayLayer = range.baseArrayLayer;
desc.arrayLayerCount = range.layerCount;
desc.aspect = wgpu::TextureAspect::All;
Ref<TextureView> view = TextureView::Create(this, &desc);
ComPtr<ID3D11RenderTargetView> d3d11RTV;
DAWN_TRY_ASSIGN(d3d11RTV, view->CreateD3D11RenderTargetView());
static constexpr std::array<float, 4> zero = {0.0f, 0.0f, 0.0f, 0.0f};
static constexpr std::array<float, 4> nonZero = {1.0f, 1.0f, 1.0f, 1.0f};
commandContext->GetD3D11DeviceContext()->ClearRenderTargetView(
d3d11RTV.Get(), clearValue == TextureBase::ClearValue::Zero ? zero.data() : nonZero.data());
return {};
} }
void Texture::SetLabelHelper(const char* prefix) { void Texture::SetLabelHelper(const char* prefix) {
@ -284,11 +322,91 @@ MaybeError Texture::EnsureSubresourceContentInitialized(CommandRecordingContext*
if (!IsSubresourceContentInitialized(range)) { if (!IsSubresourceContentInitialized(range)) {
// If subresource has not been initialized, clear it to black as it could contain // If subresource has not been initialized, clear it to black as it could contain
// dirty bits from recycled memory // dirty bits from recycled memory
DAWN_TRY(ClearTexture(commandContext, range, TextureBase::ClearValue::Zero)); DAWN_TRY(Clear(commandContext, range, TextureBase::ClearValue::Zero));
} }
return {}; return {};
} }
MaybeError Texture::Write(CommandRecordingContext* commandContext,
const SubresourceRange& subresources,
const Origin3D& origin,
const Extent3D& size,
const uint8_t* data,
uint32_t bytesPerRow,
uint32_t rowsPerImage) {
DAWN_ASSERT(size.width != 0 && size.height != 0 && size.depthOrArrayLayers != 0);
if (IsCompleteSubresourceCopiedTo(this, size, subresources.baseMipLevel)) {
SetIsSubresourceContentInitialized(true, subresources);
} else {
DAWN_TRY(EnsureSubresourceContentInitialized(commandContext, subresources));
}
D3D11_BOX dstBox;
dstBox.left = origin.x;
dstBox.right = origin.x + size.width;
dstBox.top = origin.y;
dstBox.bottom = origin.y + size.height;
if (GetDimension() == wgpu::TextureDimension::e3D) {
dstBox.front = origin.z;
dstBox.back = origin.z + size.depthOrArrayLayers;
uint32_t subresource =
GetSubresourceIndex(subresources.baseMipLevel, origin.z, subresources.aspects);
commandContext->GetD3D11DeviceContext1()->UpdateSubresource(GetD3D11Resource(), subresource,
&dstBox, data, bytesPerRow, 0);
} else {
dstBox.front = 0;
dstBox.back = 1;
for (uint32_t z = origin.z; z < size.depthOrArrayLayers; ++z) {
uint32_t subresource =
GetSubresourceIndex(subresources.baseMipLevel, z, subresources.aspects);
commandContext->GetD3D11DeviceContext1()->UpdateSubresource(
GetD3D11Resource(), subresource, &dstBox, data, bytesPerRow, 0);
data += rowsPerImage * bytesPerRow;
}
}
return {};
}
// static
MaybeError Texture::Copy(CommandRecordingContext* commandContext, CopyTextureToTextureCmd* copy) {
ASSERT(copy->copySize.width != 0 && copy->copySize.height != 0 &&
copy->copySize.depthOrArrayLayers != 0);
auto& src = copy->source;
auto& dst = copy->destination;
SubresourceRange subresources = GetSubresourcesAffectedByCopy(src, copy->copySize);
DAWN_TRY(
ToBackend(src.texture)->EnsureSubresourceContentInitialized(commandContext, subresources));
subresources = GetSubresourcesAffectedByCopy(dst, copy->copySize);
if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize, dst.mipLevel)) {
dst.texture->SetIsSubresourceContentInitialized(true, subresources);
} else {
DAWN_TRY(ToBackend(dst.texture)
->EnsureSubresourceContentInitialized(commandContext, subresources));
}
D3D11_BOX srcBox;
srcBox.left = src.origin.x;
srcBox.right = src.origin.x + copy->copySize.width;
srcBox.top = src.origin.y;
srcBox.bottom = src.origin.y + copy->copySize.height;
srcBox.front = 0;
srcBox.back = 1;
uint32_t subresource = src.texture->GetSubresourceIndex(src.mipLevel, src.origin.z, src.aspect);
commandContext->GetD3D11DeviceContext1()->CopySubresourceRegion(
ToBackend(dst.texture)->GetD3D11Resource(), dst.mipLevel, dst.origin.x, dst.origin.y,
dst.origin.z, ToBackend(src.texture)->GetD3D11Resource(), subresource, &srcBox);
return {};
}
// static // static
Ref<TextureView> TextureView::Create(TextureBase* texture, Ref<TextureView> TextureView::Create(TextureBase* texture,
const TextureViewDescriptor* descriptor) { const TextureViewDescriptor* descriptor) {
@ -301,7 +419,7 @@ DXGI_FORMAT TextureView::GetD3D11Format() const {
return d3d::DXGITextureFormat(GetFormat().format); return d3d::DXGITextureFormat(GetFormat().format);
} }
ResultOrError<ComPtr<ID3D11ShaderResourceView>> TextureView::GetD3D11ShaderResourceView() const { ResultOrError<ComPtr<ID3D11ShaderResourceView>> TextureView::CreateD3D11ShaderResourceView() const {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = d3d::DXGITextureFormat(GetFormat().format); srvDesc.Format = d3d::DXGITextureFormat(GetFormat().format);
@ -436,7 +554,7 @@ ResultOrError<ComPtr<ID3D11ShaderResourceView>> TextureView::GetD3D11ShaderResou
return srv; return srv;
} }
ResultOrError<ComPtr<ID3D11RenderTargetView>> TextureView::GetD3D11RenderTargetView() const { ResultOrError<ComPtr<ID3D11RenderTargetView>> TextureView::CreateD3D11RenderTargetView() const {
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = D3D11_RENDER_TARGET_VIEW_DESC rtvDesc =
ToBackend(GetTexture())->GetRTVDescriptor(GetFormat(), GetSubresourceRange()); ToBackend(GetTexture())->GetRTVDescriptor(GetFormat(), GetSubresourceRange());
ComPtr<ID3D11RenderTargetView> rtv; ComPtr<ID3D11RenderTargetView> rtv;
@ -448,7 +566,7 @@ ResultOrError<ComPtr<ID3D11RenderTargetView>> TextureView::GetD3D11RenderTargetV
return rtv; return rtv;
} }
ResultOrError<ComPtr<ID3D11DepthStencilView>> TextureView::GetD3D11DepthStencilView( ResultOrError<ComPtr<ID3D11DepthStencilView>> TextureView::CreateD3D11DepthStencilView(
bool depthReadOnly, bool depthReadOnly,
bool stencilReadOnly) const { bool stencilReadOnly) const {
ComPtr<ID3D11DepthStencilView> dsv; ComPtr<ID3D11DepthStencilView> dsv;
@ -463,7 +581,8 @@ ResultOrError<ComPtr<ID3D11DepthStencilView>> TextureView::GetD3D11DepthStencilV
return dsv; return dsv;
} }
ResultOrError<ComPtr<ID3D11UnorderedAccessView>> TextureView::GetD3D11UnorderedAccessView() const { ResultOrError<ComPtr<ID3D11UnorderedAccessView>> TextureView::CreateD3D11UnorderedAccessView()
const {
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
uavDesc.Format = GetD3D11Format(); uavDesc.Format = GetD3D11Format();

View File

@ -22,6 +22,10 @@
#include "dawn/native/Texture.h" #include "dawn/native/Texture.h"
#include "dawn/native/d3d/d3d_platform.h" #include "dawn/native/d3d/d3d_platform.h"
namespace dawn::native {
struct CopyTextureToTextureCmd;
} // namespace dawn::native
namespace dawn::native::d3d11 { namespace dawn::native::d3d11 {
class CommandRecordingContext; class CommandRecordingContext;
@ -48,6 +52,15 @@ class Texture final : public TextureBase {
MaybeError EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext, MaybeError EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
const SubresourceRange& range); const SubresourceRange& range);
MaybeError Write(CommandRecordingContext* commandContext,
const SubresourceRange& subresources,
const Origin3D& origin,
const Extent3D& size,
const uint8_t* data,
uint32_t bytesPerRow,
uint32_t rowsPerImage);
static MaybeError Copy(CommandRecordingContext* commandContext, CopyTextureToTextureCmd* copy);
private: private:
Texture(Device* device, const TextureDescriptor* descriptor, TextureState state); Texture(Device* device, const TextureDescriptor* descriptor, TextureState state);
~Texture() override; ~Texture() override;
@ -62,12 +75,10 @@ class Texture final : public TextureBase {
void SetLabelImpl() override; void SetLabelImpl() override;
void DestroyImpl() override; void DestroyImpl() override;
MaybeError ClearTexture(CommandRecordingContext* commandContext, MaybeError Clear(CommandRecordingContext* commandContext,
const SubresourceRange& range, const SubresourceRange& range,
TextureBase::ClearValue clearValue); TextureBase::ClearValue clearValue);
MaybeError WriteTexture();
ComPtr<ID3D11Resource> mD3d11Resource; ComPtr<ID3D11Resource> mD3d11Resource;
}; };
@ -76,12 +87,12 @@ class TextureView final : public TextureViewBase {
static Ref<TextureView> Create(TextureBase* texture, const TextureViewDescriptor* descriptor); static Ref<TextureView> Create(TextureBase* texture, const TextureViewDescriptor* descriptor);
DXGI_FORMAT GetD3D11Format() const; DXGI_FORMAT GetD3D11Format() const;
ResultOrError<ComPtr<ID3D11ShaderResourceView>> GetD3D11ShaderResourceView() const; ResultOrError<ComPtr<ID3D11ShaderResourceView>> CreateD3D11ShaderResourceView() const;
ResultOrError<ComPtr<ID3D11RenderTargetView>> GetD3D11RenderTargetView() const; ResultOrError<ComPtr<ID3D11RenderTargetView>> CreateD3D11RenderTargetView() const;
ResultOrError<ComPtr<ID3D11DepthStencilView>> GetD3D11DepthStencilView( ResultOrError<ComPtr<ID3D11DepthStencilView>> CreateD3D11DepthStencilView(
bool depthReadOnly, bool depthReadOnly,
bool stencilReadOnly) const; bool stencilReadOnly) const;
ResultOrError<ComPtr<ID3D11UnorderedAccessView>> GetD3D11UnorderedAccessView() const; ResultOrError<ComPtr<ID3D11UnorderedAccessView>> CreateD3D11UnorderedAccessView() const;
private: private:
using TextureViewBase::TextureViewBase; using TextureViewBase::TextureViewBase;

View File

@ -553,6 +553,7 @@ TEST_P(BufferMappingTests, RegressChromium1421170) {
} }
DAWN_INSTANTIATE_TEST(BufferMappingTests, DAWN_INSTANTIATE_TEST(BufferMappingTests,
D3D11Backend(),
D3D12Backend(), D3D12Backend(),
MetalBackend(), MetalBackend(),
OpenGLBackend(), OpenGLBackend(),
@ -633,6 +634,11 @@ TEST_P(BufferMappingCallbackTests, EmptySubmissionAndThenMap) {
} }
TEST_P(BufferMappingCallbackTests, UseTheBufferAndThenMap) { TEST_P(BufferMappingCallbackTests, UseTheBufferAndThenMap) {
// TODO(dawn:1705): enable this test for D3D11. D3D11 MapAsync() calls
// ID3D11DeviceContext::Map() which will synchronize with GPU. so the callback will always be
// called earlier comparing to other backends.
DAWN_SUPPRESS_TEST_IF(IsD3D11());
wgpu::Buffer buffer = CreateMapWriteBuffer(4); wgpu::Buffer buffer = CreateMapWriteBuffer(4);
MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, wgpu::kWholeMapSize); MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, wgpu::kWholeMapSize);
buffer.Unmap(); buffer.Unmap();
@ -672,6 +678,11 @@ TEST_P(BufferMappingCallbackTests, UseTheBufferAndThenMap) {
} }
TEST_P(BufferMappingCallbackTests, EmptySubmissionWriteAndThenMap) { TEST_P(BufferMappingCallbackTests, EmptySubmissionWriteAndThenMap) {
// TODO(dawn:1705): enable this test for D3D11. D3D11 MapAsync() calls
// ID3D11DeviceContext::Map() which will synchronize with GPU. so the callback will always be
// called earlier comparing to other backends.
DAWN_SUPPRESS_TEST_IF(IsD3D11());
wgpu::Buffer buffer = CreateMapReadBuffer(4); wgpu::Buffer buffer = CreateMapReadBuffer(4);
MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, wgpu::kWholeMapSize); MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, wgpu::kWholeMapSize);
buffer.Unmap(); buffer.Unmap();
@ -713,7 +724,11 @@ TEST_P(BufferMappingCallbackTests, EmptySubmissionWriteAndThenMap) {
buffer.Unmap(); buffer.Unmap();
} }
DAWN_INSTANTIATE_TEST(BufferMappingCallbackTests, D3D12Backend(), MetalBackend(), VulkanBackend()); DAWN_INSTANTIATE_TEST(BufferMappingCallbackTests,
D3D11Backend(),
D3D12Backend(),
MetalBackend(),
VulkanBackend());
class BufferMappedAtCreationTests : public DawnTest { class BufferMappedAtCreationTests : public DawnTest {
protected: protected:
@ -961,6 +976,7 @@ TEST_P(BufferMappedAtCreationTests, GetMappedRangeZeroSized) {
} }
DAWN_INSTANTIATE_TEST(BufferMappedAtCreationTests, DAWN_INSTANTIATE_TEST(BufferMappedAtCreationTests,
D3D11Backend(),
D3D12Backend(), D3D12Backend(),
D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}), D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
MetalBackend(), MetalBackend(),
@ -1111,6 +1127,7 @@ TEST_P(BufferTests, CreateBufferOOMMapAsync) {
} }
DAWN_INSTANTIATE_TEST(BufferTests, DAWN_INSTANTIATE_TEST(BufferTests,
D3D11Backend(),
D3D12Backend(), D3D12Backend(),
MetalBackend(), MetalBackend(),
OpenGLBackend(), OpenGLBackend(),
@ -1143,6 +1160,7 @@ TEST_P(BufferNoSuballocationTests, WriteBufferThenDestroy) {
} }
DAWN_INSTANTIATE_TEST(BufferNoSuballocationTests, DAWN_INSTANTIATE_TEST(BufferNoSuballocationTests,
D3D11Backend({"disable_resource_suballocation"}),
D3D12Backend({"disable_resource_suballocation"}), D3D12Backend({"disable_resource_suballocation"}),
MetalBackend({"disable_resource_suballocation"}), MetalBackend({"disable_resource_suballocation"}),
OpenGLBackend({"disable_resource_suballocation"}), OpenGLBackend({"disable_resource_suballocation"}),