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:
parent
e7c06367d4
commit
9e9c456075
|
@ -435,6 +435,8 @@ source_set("sources") {
|
|||
"d3d11/BindGroupLayoutD3D11.h",
|
||||
"d3d11/BufferD3D11.cpp",
|
||||
"d3d11/BufferD3D11.h",
|
||||
"d3d11/CommandBufferD3D11.cpp",
|
||||
"d3d11/CommandBufferD3D11.h",
|
||||
"d3d11/CommandRecordingContextD3D11.cpp",
|
||||
"d3d11/CommandRecordingContextD3D11.h",
|
||||
"d3d11/ComputePipelineD3D11.cpp",
|
||||
|
|
|
@ -292,6 +292,8 @@ if (DAWN_ENABLE_D3D11)
|
|||
"d3d11/BindGroupLayoutD3D11.h"
|
||||
"d3d11/BufferD3D11.cpp"
|
||||
"d3d11/BufferD3D11.h"
|
||||
"d3d11/CommandBufferD3D11.cpp"
|
||||
"d3d11/CommandBufferD3D11.h"
|
||||
"d3d11/CommandRecordingContextD3D11.cpp"
|
||||
"d3d11/CommandRecordingContextD3D11.h"
|
||||
"d3d11/ComputePipelineD3D11.cpp"
|
||||
|
|
|
@ -471,18 +471,18 @@ MaybeError Buffer::WriteInternal(CommandRecordingContext* commandContext,
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError Buffer::CopyFromBuffer(CommandRecordingContext* commandContext,
|
||||
uint64_t offset,
|
||||
size_t size,
|
||||
// static
|
||||
MaybeError Buffer::Copy(CommandRecordingContext* commandContext,
|
||||
Buffer* source,
|
||||
uint64_t sourceOffset) {
|
||||
if (size == 0) {
|
||||
// Skip no-op copies.
|
||||
return {};
|
||||
}
|
||||
uint64_t sourceOffset,
|
||||
size_t size,
|
||||
Buffer* destination,
|
||||
uint64_t destinationOffset) {
|
||||
DAWN_ASSERT(size != 0);
|
||||
|
||||
DAWN_TRY(source->EnsureDataInitialized(commandContext));
|
||||
DAWN_TRY(EnsureDataInitializedAsDestination(commandContext, offset, size));
|
||||
DAWN_TRY(
|
||||
destination->EnsureDataInitializedAsDestination(commandContext, destinationOffset, size));
|
||||
|
||||
D3D11_BOX srcBox;
|
||||
srcBox.left = sourceOffset;
|
||||
|
@ -492,8 +492,9 @@ MaybeError Buffer::CopyFromBuffer(CommandRecordingContext* commandContext,
|
|||
srcBox.front = 0;
|
||||
srcBox.back = 1;
|
||||
commandContext->GetD3D11DeviceContext()->CopySubresourceRegion(
|
||||
GetD3D11Buffer(), /*DstSubresource=*/0, /*DstX=*/offset, /*DstY=*/0, /*DstZ=*/0,
|
||||
source->GetD3D11Buffer(), /*SrcSubresource=*/0, &srcBox);
|
||||
destination->mD3d11Buffer.Get(), /*DstSubresource=*/0, /*DstX=*/destinationOffset,
|
||||
/*DstY=*/0,
|
||||
/*DstZ=*/0, source->mD3d11Buffer.Get(), /*SrcSubresource=*/0, &srcBox);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -56,11 +56,13 @@ class Buffer final : public BufferBase {
|
|||
uint64_t offset,
|
||||
const void* data,
|
||||
size_t size);
|
||||
MaybeError CopyFromBuffer(CommandRecordingContext* commandContext,
|
||||
uint64_t offset,
|
||||
size_t size,
|
||||
|
||||
static MaybeError Copy(CommandRecordingContext* commandContext,
|
||||
Buffer* source,
|
||||
uint64_t sourceOffset);
|
||||
uint64_t sourceOffset,
|
||||
size_t size,
|
||||
Buffer* destination,
|
||||
uint64_t destinationOffset);
|
||||
|
||||
class ScopedMap : public NonCopyable {
|
||||
public:
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -20,19 +20,16 @@
|
|||
#include <utility>
|
||||
|
||||
#include "dawn/common/GPUInfo.h"
|
||||
#include "dawn/native/Buffer.h"
|
||||
#include "dawn/native/ComputePipeline.h"
|
||||
#include "dawn/native/D3D11Backend.h"
|
||||
#include "dawn/native/DynamicUploader.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/d3d11/AdapterD3D11.h"
|
||||
#include "dawn/native/d3d11/BackendD3D11.h"
|
||||
#include "dawn/native/d3d11/BindGroupD3D11.h"
|
||||
#include "dawn/native/d3d11/BindGroupLayoutD3D11.h"
|
||||
#include "dawn/native/d3d11/BufferD3D11.h"
|
||||
#include "dawn/native/d3d11/CommandBufferD3D11.h"
|
||||
#include "dawn/native/d3d11/ComputePipelineD3D11.h"
|
||||
#include "dawn/native/d3d11/PipelineLayoutD3D11.h"
|
||||
#include "dawn/native/d3d11/PlatformFunctionsD3D11.h"
|
||||
|
@ -259,7 +256,7 @@ ResultOrError<Ref<BufferBase>> Device::CreateBufferImpl(const BufferDescriptor*
|
|||
ResultOrError<Ref<CommandBufferBase>> Device::CreateCommandBuffer(
|
||||
CommandEncoder* encoder,
|
||||
const CommandBufferDescriptor* descriptor) {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("CreateCommandBuffer");
|
||||
return CommandBuffer::Create(encoder, descriptor);
|
||||
}
|
||||
|
||||
Ref<ComputePipelineBase> Device::CreateUninitializedComputePipelineImpl(
|
||||
|
@ -327,8 +324,8 @@ MaybeError Device::CopyFromStagingToBufferImpl(BufferBase* source,
|
|||
uint64_t destinationOffset,
|
||||
uint64_t size) {
|
||||
CommandRecordingContext* commandContext = GetPendingCommandContext();
|
||||
return ToBackend(destination)
|
||||
->CopyFromBuffer(commandContext, destinationOffset, size, ToBackend(source), sourceOffset);
|
||||
return Buffer::Copy(commandContext, ToBackend(source), sourceOffset, size,
|
||||
ToBackend(destination), destinationOffset);
|
||||
}
|
||||
|
||||
MaybeError Device::CopyFromStagingToTextureImpl(const BufferBase* source,
|
||||
|
|
|
@ -15,8 +15,11 @@
|
|||
#include "dawn/native/d3d11/QueueD3D11.h"
|
||||
|
||||
#include "dawn/native/d3d11/BufferD3D11.h"
|
||||
#include "dawn/native/d3d11/CommandBufferD3D11.h"
|
||||
#include "dawn/native/d3d11/DeviceD3D11.h"
|
||||
#include "dawn/native/d3d11/TextureD3D11.h"
|
||||
#include "dawn/platform/DawnPlatform.h"
|
||||
#include "dawn/platform/tracing/TraceEvent.h"
|
||||
|
||||
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) {
|
||||
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,
|
||||
|
@ -40,7 +53,26 @@ MaybeError Queue::WriteTextureImpl(const ImageCopyTexture& destination,
|
|||
const void* data,
|
||||
const TextureDataLayout& dataLayout,
|
||||
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
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "dawn/common/Constants.h"
|
||||
#include "dawn/common/Math.h"
|
||||
#include "dawn/native/CommandBuffer.h"
|
||||
#include "dawn/native/DynamicUploader.h"
|
||||
#include "dawn/native/EnumMaskIterator.h"
|
||||
#include "dawn/native/IntegerTypes.h"
|
||||
|
@ -136,8 +137,7 @@ MaybeError Texture::InitializeAsInternalTexture() {
|
|||
|
||||
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
|
||||
CommandRecordingContext* commandContext = device->GetPendingCommandContext();
|
||||
DAWN_TRY(
|
||||
ClearTexture(commandContext, GetAllSubresources(), TextureBase::ClearValue::NonZero));
|
||||
DAWN_TRY(Clear(commandContext, GetAllSubresources(), TextureBase::ClearValue::NonZero));
|
||||
}
|
||||
|
||||
SetLabelImpl();
|
||||
|
@ -261,11 +261,49 @@ D3D11_DEPTH_STENCIL_VIEW_DESC Texture::GetDSVDescriptor(const SubresourceRange&
|
|||
return dsvDesc;
|
||||
}
|
||||
|
||||
MaybeError Texture::ClearTexture(CommandRecordingContext* commandContext,
|
||||
MaybeError Texture::Clear(CommandRecordingContext* commandContext,
|
||||
const SubresourceRange& range,
|
||||
TextureBase::ClearValue clearValue) {
|
||||
// TODO(dawn:1740): Implement this.
|
||||
return DAWN_UNIMPLEMENTED_ERROR("ClearTexture");
|
||||
// TODO(dawn:1740): Clear non-renderable texture.
|
||||
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) {
|
||||
|
@ -284,11 +322,91 @@ MaybeError Texture::EnsureSubresourceContentInitialized(CommandRecordingContext*
|
|||
if (!IsSubresourceContentInitialized(range)) {
|
||||
// If subresource has not been initialized, clear it to black as it could contain
|
||||
// dirty bits from recycled memory
|
||||
DAWN_TRY(ClearTexture(commandContext, range, TextureBase::ClearValue::Zero));
|
||||
DAWN_TRY(Clear(commandContext, range, TextureBase::ClearValue::Zero));
|
||||
}
|
||||
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
|
||||
Ref<TextureView> TextureView::Create(TextureBase* texture,
|
||||
const TextureViewDescriptor* descriptor) {
|
||||
|
@ -301,7 +419,7 @@ DXGI_FORMAT TextureView::GetD3D11Format() const {
|
|||
return d3d::DXGITextureFormat(GetFormat().format);
|
||||
}
|
||||
|
||||
ResultOrError<ComPtr<ID3D11ShaderResourceView>> TextureView::GetD3D11ShaderResourceView() const {
|
||||
ResultOrError<ComPtr<ID3D11ShaderResourceView>> TextureView::CreateD3D11ShaderResourceView() const {
|
||||
Device* device = ToBackend(GetDevice());
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
srvDesc.Format = d3d::DXGITextureFormat(GetFormat().format);
|
||||
|
@ -436,7 +554,7 @@ ResultOrError<ComPtr<ID3D11ShaderResourceView>> TextureView::GetD3D11ShaderResou
|
|||
return srv;
|
||||
}
|
||||
|
||||
ResultOrError<ComPtr<ID3D11RenderTargetView>> TextureView::GetD3D11RenderTargetView() const {
|
||||
ResultOrError<ComPtr<ID3D11RenderTargetView>> TextureView::CreateD3D11RenderTargetView() const {
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc =
|
||||
ToBackend(GetTexture())->GetRTVDescriptor(GetFormat(), GetSubresourceRange());
|
||||
ComPtr<ID3D11RenderTargetView> rtv;
|
||||
|
@ -448,7 +566,7 @@ ResultOrError<ComPtr<ID3D11RenderTargetView>> TextureView::GetD3D11RenderTargetV
|
|||
return rtv;
|
||||
}
|
||||
|
||||
ResultOrError<ComPtr<ID3D11DepthStencilView>> TextureView::GetD3D11DepthStencilView(
|
||||
ResultOrError<ComPtr<ID3D11DepthStencilView>> TextureView::CreateD3D11DepthStencilView(
|
||||
bool depthReadOnly,
|
||||
bool stencilReadOnly) const {
|
||||
ComPtr<ID3D11DepthStencilView> dsv;
|
||||
|
@ -463,7 +581,8 @@ ResultOrError<ComPtr<ID3D11DepthStencilView>> TextureView::GetD3D11DepthStencilV
|
|||
return dsv;
|
||||
}
|
||||
|
||||
ResultOrError<ComPtr<ID3D11UnorderedAccessView>> TextureView::GetD3D11UnorderedAccessView() const {
|
||||
ResultOrError<ComPtr<ID3D11UnorderedAccessView>> TextureView::CreateD3D11UnorderedAccessView()
|
||||
const {
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
|
||||
uavDesc.Format = GetD3D11Format();
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#include "dawn/native/Texture.h"
|
||||
#include "dawn/native/d3d/d3d_platform.h"
|
||||
|
||||
namespace dawn::native {
|
||||
struct CopyTextureToTextureCmd;
|
||||
} // namespace dawn::native
|
||||
|
||||
namespace dawn::native::d3d11 {
|
||||
|
||||
class CommandRecordingContext;
|
||||
|
@ -48,6 +52,15 @@ class Texture final : public TextureBase {
|
|||
MaybeError EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
|
||||
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:
|
||||
Texture(Device* device, const TextureDescriptor* descriptor, TextureState state);
|
||||
~Texture() override;
|
||||
|
@ -62,12 +75,10 @@ class Texture final : public TextureBase {
|
|||
void SetLabelImpl() override;
|
||||
void DestroyImpl() override;
|
||||
|
||||
MaybeError ClearTexture(CommandRecordingContext* commandContext,
|
||||
MaybeError Clear(CommandRecordingContext* commandContext,
|
||||
const SubresourceRange& range,
|
||||
TextureBase::ClearValue clearValue);
|
||||
|
||||
MaybeError WriteTexture();
|
||||
|
||||
ComPtr<ID3D11Resource> mD3d11Resource;
|
||||
};
|
||||
|
||||
|
@ -76,12 +87,12 @@ class TextureView final : public TextureViewBase {
|
|||
static Ref<TextureView> Create(TextureBase* texture, const TextureViewDescriptor* descriptor);
|
||||
|
||||
DXGI_FORMAT GetD3D11Format() const;
|
||||
ResultOrError<ComPtr<ID3D11ShaderResourceView>> GetD3D11ShaderResourceView() const;
|
||||
ResultOrError<ComPtr<ID3D11RenderTargetView>> GetD3D11RenderTargetView() const;
|
||||
ResultOrError<ComPtr<ID3D11DepthStencilView>> GetD3D11DepthStencilView(
|
||||
ResultOrError<ComPtr<ID3D11ShaderResourceView>> CreateD3D11ShaderResourceView() const;
|
||||
ResultOrError<ComPtr<ID3D11RenderTargetView>> CreateD3D11RenderTargetView() const;
|
||||
ResultOrError<ComPtr<ID3D11DepthStencilView>> CreateD3D11DepthStencilView(
|
||||
bool depthReadOnly,
|
||||
bool stencilReadOnly) const;
|
||||
ResultOrError<ComPtr<ID3D11UnorderedAccessView>> GetD3D11UnorderedAccessView() const;
|
||||
ResultOrError<ComPtr<ID3D11UnorderedAccessView>> CreateD3D11UnorderedAccessView() const;
|
||||
|
||||
private:
|
||||
using TextureViewBase::TextureViewBase;
|
||||
|
|
|
@ -553,6 +553,7 @@ TEST_P(BufferMappingTests, RegressChromium1421170) {
|
|||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(BufferMappingTests,
|
||||
D3D11Backend(),
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
OpenGLBackend(),
|
||||
|
@ -633,6 +634,11 @@ TEST_P(BufferMappingCallbackTests, EmptySubmissionAndThenMap) {
|
|||
}
|
||||
|
||||
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);
|
||||
MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, wgpu::kWholeMapSize);
|
||||
buffer.Unmap();
|
||||
|
@ -672,6 +678,11 @@ TEST_P(BufferMappingCallbackTests, UseTheBufferAndThenMap) {
|
|||
}
|
||||
|
||||
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);
|
||||
MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, wgpu::kWholeMapSize);
|
||||
buffer.Unmap();
|
||||
|
@ -713,7 +724,11 @@ TEST_P(BufferMappingCallbackTests, EmptySubmissionWriteAndThenMap) {
|
|||
buffer.Unmap();
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(BufferMappingCallbackTests, D3D12Backend(), MetalBackend(), VulkanBackend());
|
||||
DAWN_INSTANTIATE_TEST(BufferMappingCallbackTests,
|
||||
D3D11Backend(),
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
VulkanBackend());
|
||||
|
||||
class BufferMappedAtCreationTests : public DawnTest {
|
||||
protected:
|
||||
|
@ -961,6 +976,7 @@ TEST_P(BufferMappedAtCreationTests, GetMappedRangeZeroSized) {
|
|||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(BufferMappedAtCreationTests,
|
||||
D3D11Backend(),
|
||||
D3D12Backend(),
|
||||
D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
|
||||
MetalBackend(),
|
||||
|
@ -1111,6 +1127,7 @@ TEST_P(BufferTests, CreateBufferOOMMapAsync) {
|
|||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(BufferTests,
|
||||
D3D11Backend(),
|
||||
D3D12Backend(),
|
||||
MetalBackend(),
|
||||
OpenGLBackend(),
|
||||
|
@ -1143,6 +1160,7 @@ TEST_P(BufferNoSuballocationTests, WriteBufferThenDestroy) {
|
|||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(BufferNoSuballocationTests,
|
||||
D3D11Backend({"disable_resource_suballocation"}),
|
||||
D3D12Backend({"disable_resource_suballocation"}),
|
||||
MetalBackend({"disable_resource_suballocation"}),
|
||||
OpenGLBackend({"disable_resource_suballocation"}),
|
||||
|
|
Loading…
Reference in New Issue