Add CommandRecordingContext to D3D12

This change refactors D3D12 backend to have CommandRecordingContext
CommandRecordingContext allows us to, in a future, add additional
data to the context such as textures that need to be acquired and
released before command lists are executed.

The Device's pending command list and the command list which resides
in the Queue object were converted to use CommandRecordingContext.

Bug=dawn:234

Change-Id: Ic13a229fc1f15895ef71117ce638c942de224743
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11940
Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Rafael Cintron 2019-10-10 18:06:58 +00:00 committed by Commit Bot service account
parent d285525d4a
commit 8bde031abe
15 changed files with 292 additions and 144 deletions

View File

@ -254,6 +254,8 @@ source_set("libdawn_native_sources") {
"src/dawn_native/d3d12/CommandAllocatorManager.h", "src/dawn_native/d3d12/CommandAllocatorManager.h",
"src/dawn_native/d3d12/CommandBufferD3D12.cpp", "src/dawn_native/d3d12/CommandBufferD3D12.cpp",
"src/dawn_native/d3d12/CommandBufferD3D12.h", "src/dawn_native/d3d12/CommandBufferD3D12.h",
"src/dawn_native/d3d12/CommandRecordingContext.cpp",
"src/dawn_native/d3d12/CommandRecordingContext.h",
"src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp", "src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp",
"src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h", "src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h",
"src/dawn_native/d3d12/ComputePipelineD3D12.cpp", "src/dawn_native/d3d12/ComputePipelineD3D12.cpp",

View File

@ -104,6 +104,12 @@ namespace dawn_native {
return mPointee; return mPointee;
} }
T* Detach() {
T* pointee = mPointee;
mPointee = nullptr;
return pointee;
}
private: private:
void Reference() const { void Reference() const {
if (mPointee != nullptr) { if (mPointee != nullptr) {

View File

@ -17,6 +17,7 @@
#include "common/Assert.h" #include "common/Assert.h"
#include "common/Constants.h" #include "common/Constants.h"
#include "common/Math.h" #include "common/Math.h"
#include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/DeviceD3D12.h"
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
@ -130,7 +131,8 @@ namespace dawn_native { namespace d3d12 {
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a // When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can // ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors. // cause subsequent errors.
bool Buffer::TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier, bool Buffer::TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
dawn::BufferUsage newUsage) { dawn::BufferUsage newUsage) {
// Resources in upload and readback heaps must be kept in the COPY_SOURCE/DEST state // Resources in upload and readback heaps must be kept in the COPY_SOURCE/DEST state
if (mFixedResourceState) { if (mFixedResourceState) {
@ -187,12 +189,12 @@ namespace dawn_native { namespace d3d12 {
return true; return true;
} }
void Buffer::TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList, void Buffer::TransitionUsageNow(CommandRecordingContext* commandContext,
dawn::BufferUsage usage) { dawn::BufferUsage usage) {
D3D12_RESOURCE_BARRIER barrier; D3D12_RESOURCE_BARRIER barrier;
if (TransitionUsageAndGetResourceBarrier(&barrier, usage)) { if (TransitionUsageAndGetResourceBarrier(commandContext, &barrier, usage)) {
commandList->ResourceBarrier(1, &barrier); commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
} }
} }

View File

@ -23,6 +23,7 @@
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
class CommandRecordingContext;
class Device; class Device;
class Buffer : public BufferBase { class Buffer : public BufferBase {
@ -36,10 +37,10 @@ namespace dawn_native { namespace d3d12 {
ComPtr<ID3D12Resource> GetD3D12Resource() const; ComPtr<ID3D12Resource> GetD3D12Resource() const;
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const; D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite); void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite);
bool TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier, bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
dawn::BufferUsage newUsage); dawn::BufferUsage newUsage);
void TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList, void TransitionUsageNow(CommandRecordingContext* commandContext, dawn::BufferUsage usage);
dawn::BufferUsage usage);
private: private:
// Dawn API // Dawn API

View File

@ -22,6 +22,7 @@
#include "dawn_native/d3d12/BindGroupD3D12.h" #include "dawn_native/d3d12/BindGroupD3D12.h"
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h" #include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
#include "dawn_native/d3d12/BufferD3D12.h" #include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/ComputePipelineD3D12.h" #include "dawn_native/d3d12/ComputePipelineD3D12.h"
#include "dawn_native/d3d12/DescriptorHeapAllocator.h" #include "dawn_native/d3d12/DescriptorHeapAllocator.h"
#include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/DeviceD3D12.h"
@ -502,7 +503,7 @@ namespace dawn_native { namespace d3d12 {
return {}; return {};
} }
void ResolveMultisampledRenderPass(ComPtr<ID3D12GraphicsCommandList> commandList, void ResolveMultisampledRenderPass(CommandRecordingContext* commandContext,
BeginRenderPassCmd* renderPass) { BeginRenderPassCmd* renderPass) {
ASSERT(renderPass != nullptr); ASSERT(renderPass != nullptr);
@ -519,8 +520,10 @@ namespace dawn_native { namespace d3d12 {
Texture* resolveTexture = ToBackend(resolveTarget->GetTexture()); Texture* resolveTexture = ToBackend(resolveTarget->GetTexture());
// Transition the usages of the color attachment and resolve target. // Transition the usages of the color attachment and resolve target.
colorTexture->TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_RESOLVE_SOURCE); colorTexture->TransitionUsageNow(commandContext,
resolveTexture->TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_RESOLVE_DEST); D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
resolveTexture->TransitionUsageNow(commandContext,
D3D12_RESOURCE_STATE_RESOLVE_DEST);
// Do MSAA resolve with ResolveSubResource(). // Do MSAA resolve with ResolveSubResource().
ID3D12Resource* colorTextureHandle = colorTexture->GetD3D12Resource(); ID3D12Resource* colorTextureHandle = colorTexture->GetD3D12Resource();
@ -528,7 +531,7 @@ namespace dawn_native { namespace d3d12 {
const uint32_t resolveTextureSubresourceIndex = resolveTexture->GetSubresourceIndex( const uint32_t resolveTextureSubresourceIndex = resolveTexture->GetSubresourceIndex(
resolveTarget->GetBaseMipLevel(), resolveTarget->GetBaseArrayLayer()); resolveTarget->GetBaseMipLevel(), resolveTarget->GetBaseArrayLayer());
constexpr uint32_t kColorTextureSubresourceIndex = 0; constexpr uint32_t kColorTextureSubresourceIndex = 0;
commandList->ResolveSubresource( commandContext->GetCommandList()->ResolveSubresource(
resolveTextureHandle, resolveTextureSubresourceIndex, colorTextureHandle, resolveTextureHandle, resolveTextureSubresourceIndex, colorTextureHandle,
kColorTextureSubresourceIndex, colorTexture->GetD3D12Format()); kColorTextureSubresourceIndex, colorTexture->GetD3D12Format());
} }
@ -545,12 +548,14 @@ namespace dawn_native { namespace d3d12 {
FreeCommands(&mCommands); FreeCommands(&mCommands);
} }
MaybeError CommandBuffer::RecordCommands(ComPtr<ID3D12GraphicsCommandList> commandList, MaybeError CommandBuffer::RecordCommands(CommandRecordingContext* commandContext,
uint32_t indexInSubmit) { uint32_t indexInSubmit) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
BindGroupStateTracker bindingTracker(device); BindGroupStateTracker bindingTracker(device);
RenderPassDescriptorHeapTracker renderPassTracker(device); RenderPassDescriptorHeapTracker renderPassTracker(device);
ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList();
// Precompute the allocation of bindgroups in descriptor heaps // Precompute the allocation of bindgroups in descriptor heaps
// TODO(cwallez@chromium.org): Iterating over all the commands here is inefficient. We // TODO(cwallez@chromium.org): Iterating over all the commands here is inefficient. We
// should have a system where commands and descriptors are recorded in parallel then the // should have a system where commands and descriptors are recorded in parallel then the
@ -563,14 +568,17 @@ namespace dawn_native { namespace d3d12 {
} }
// Records the necessary barriers for the resource usage pre-computed by the frontend // Records the necessary barriers for the resource usage pre-computed by the frontend
auto TransitionForPass = [](ComPtr<ID3D12GraphicsCommandList> commandList, auto TransitionForPass = [](CommandRecordingContext* commandContext,
const PassResourceUsage& usages) { const PassResourceUsage& usages) {
std::vector<D3D12_RESOURCE_BARRIER> barriers; std::vector<D3D12_RESOURCE_BARRIER> barriers;
ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList();
for (size_t i = 0; i < usages.buffers.size(); ++i) { for (size_t i = 0; i < usages.buffers.size(); ++i) {
D3D12_RESOURCE_BARRIER barrier; D3D12_RESOURCE_BARRIER barrier;
if (ToBackend(usages.buffers[i]) if (ToBackend(usages.buffers[i])
->TransitionUsageAndGetResourceBarrier(&barrier, usages.bufferUsages[i])) { ->TransitionUsageAndGetResourceBarrier(commandContext, &barrier,
usages.bufferUsages[i])) {
barriers.push_back(barrier); barriers.push_back(barrier);
} }
} }
@ -581,15 +589,17 @@ namespace dawn_native { namespace d3d12 {
// cleared during record render pass if the texture subresource has not been // cleared during record render pass if the texture subresource has not been
// initialized before the render pass. // initialized before the render pass.
if (!(usages.textureUsages[i] & dawn::TextureUsage::OutputAttachment)) { if (!(usages.textureUsages[i] & dawn::TextureUsage::OutputAttachment)) {
texture->EnsureSubresourceContentInitialized( texture->EnsureSubresourceContentInitialized(commandContext, 0,
commandList, 0, texture->GetNumMipLevels(), 0, texture->GetArrayLayers()); texture->GetNumMipLevels(), 0,
texture->GetArrayLayers());
} }
} }
for (size_t i = 0; i < usages.textures.size(); ++i) { for (size_t i = 0; i < usages.textures.size(); ++i) {
D3D12_RESOURCE_BARRIER barrier; D3D12_RESOURCE_BARRIER barrier;
if (ToBackend(usages.textures[i]) if (ToBackend(usages.textures[i])
->TransitionUsageAndGetResourceBarrier(&barrier, usages.textureUsages[i])) { ->TransitionUsageAndGetResourceBarrier(commandContext, &barrier,
usages.textureUsages[i])) {
barriers.push_back(barrier); barriers.push_back(barrier);
} }
} }
@ -608,7 +618,7 @@ namespace dawn_native { namespace d3d12 {
case Command::BeginComputePass: { case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>(); mCommands.NextCommand<BeginComputePassCmd>();
TransitionForPass(commandList, passResourceUsages[nextPassNumber]); TransitionForPass(commandContext, passResourceUsages[nextPassNumber]);
bindingTracker.SetInComputePass(true); bindingTracker.SetInComputePass(true);
RecordComputePass(commandList, &bindingTracker); RecordComputePass(commandList, &bindingTracker);
@ -619,9 +629,9 @@ namespace dawn_native { namespace d3d12 {
BeginRenderPassCmd* beginRenderPassCmd = BeginRenderPassCmd* beginRenderPassCmd =
mCommands.NextCommand<BeginRenderPassCmd>(); mCommands.NextCommand<BeginRenderPassCmd>();
TransitionForPass(commandList, passResourceUsages[nextPassNumber]); TransitionForPass(commandContext, passResourceUsages[nextPassNumber]);
bindingTracker.SetInComputePass(false); bindingTracker.SetInComputePass(false);
RecordRenderPass(commandList, &bindingTracker, &renderPassTracker, RecordRenderPass(commandContext, &bindingTracker, &renderPassTracker,
beginRenderPassCmd); beginRenderPassCmd);
nextPassNumber++; nextPassNumber++;
@ -632,8 +642,8 @@ namespace dawn_native { namespace d3d12 {
Buffer* srcBuffer = ToBackend(copy->source.Get()); Buffer* srcBuffer = ToBackend(copy->source.Get());
Buffer* dstBuffer = ToBackend(copy->destination.Get()); Buffer* dstBuffer = ToBackend(copy->destination.Get());
srcBuffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopySrc); srcBuffer->TransitionUsageNow(commandContext, dawn::BufferUsage::CopySrc);
dstBuffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopyDst); dstBuffer->TransitionUsageNow(commandContext, dawn::BufferUsage::CopyDst);
commandList->CopyBufferRegion( commandList->CopyBufferRegion(
dstBuffer->GetD3D12Resource().Get(), copy->destinationOffset, dstBuffer->GetD3D12Resource().Get(), copy->destinationOffset,
@ -651,12 +661,12 @@ namespace dawn_native { namespace d3d12 {
true, copy->destination.mipLevel, 1, copy->destination.arrayLayer, 1); true, copy->destination.mipLevel, 1, copy->destination.arrayLayer, 1);
} else { } else {
texture->EnsureSubresourceContentInitialized( texture->EnsureSubresourceContentInitialized(
commandList, copy->destination.mipLevel, 1, commandContext, copy->destination.mipLevel, 1,
copy->destination.arrayLayer, 1); copy->destination.arrayLayer, 1);
} }
buffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopySrc); buffer->TransitionUsageNow(commandContext, dawn::BufferUsage::CopySrc);
texture->TransitionUsageNow(commandList, dawn::TextureUsage::CopyDst); texture->TransitionUsageNow(commandContext, dawn::TextureUsage::CopyDst);
auto copySplit = ComputeTextureCopySplit( auto copySplit = ComputeTextureCopySplit(
copy->destination.origin, copy->copySize, texture->GetFormat(), copy->destination.origin, copy->copySize, texture->GetFormat(),
@ -687,11 +697,11 @@ namespace dawn_native { namespace d3d12 {
Texture* texture = ToBackend(copy->source.texture.Get()); Texture* texture = ToBackend(copy->source.texture.Get());
Buffer* buffer = ToBackend(copy->destination.buffer.Get()); Buffer* buffer = ToBackend(copy->destination.buffer.Get());
texture->EnsureSubresourceContentInitialized(commandList, copy->source.mipLevel, texture->EnsureSubresourceContentInitialized(
1, copy->source.arrayLayer, 1); commandContext, copy->source.mipLevel, 1, copy->source.arrayLayer, 1);
texture->TransitionUsageNow(commandList, dawn::TextureUsage::CopySrc); texture->TransitionUsageNow(commandContext, dawn::TextureUsage::CopySrc);
buffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopyDst); buffer->TransitionUsageNow(commandContext, dawn::BufferUsage::CopyDst);
TextureCopySplit copySplit = ComputeTextureCopySplit( TextureCopySplit copySplit = ComputeTextureCopySplit(
copy->source.origin, copy->copySize, texture->GetFormat(), copy->source.origin, copy->copySize, texture->GetFormat(),
@ -726,19 +736,19 @@ namespace dawn_native { namespace d3d12 {
Texture* source = ToBackend(copy->source.texture.Get()); Texture* source = ToBackend(copy->source.texture.Get());
Texture* destination = ToBackend(copy->destination.texture.Get()); Texture* destination = ToBackend(copy->destination.texture.Get());
source->EnsureSubresourceContentInitialized(commandList, copy->source.mipLevel, source->EnsureSubresourceContentInitialized(
1, copy->source.arrayLayer, 1); commandContext, copy->source.mipLevel, 1, copy->source.arrayLayer, 1);
if (IsCompleteSubresourceCopiedTo(destination, copy->copySize, if (IsCompleteSubresourceCopiedTo(destination, copy->copySize,
copy->destination.mipLevel)) { copy->destination.mipLevel)) {
destination->SetIsSubresourceContentInitialized( destination->SetIsSubresourceContentInitialized(
true, copy->destination.mipLevel, 1, copy->destination.arrayLayer, 1); true, copy->destination.mipLevel, 1, copy->destination.arrayLayer, 1);
} else { } else {
destination->EnsureSubresourceContentInitialized( destination->EnsureSubresourceContentInitialized(
commandList, copy->destination.mipLevel, 1, commandContext, copy->destination.mipLevel, 1,
copy->destination.arrayLayer, 1); copy->destination.arrayLayer, 1);
} }
source->TransitionUsageNow(commandList, dawn::TextureUsage::CopySrc); source->TransitionUsageNow(commandContext, dawn::TextureUsage::CopySrc);
destination->TransitionUsageNow(commandList, dawn::TextureUsage::CopyDst); destination->TransitionUsageNow(commandContext, dawn::TextureUsage::CopyDst);
if (CanUseCopyResource(source->GetNumMipLevels(), source->GetSize(), if (CanUseCopyResource(source->GetNumMipLevels(), source->GetSize(),
destination->GetSize(), copy->copySize)) { destination->GetSize(), copy->copySize)) {
@ -771,7 +781,7 @@ namespace dawn_native { namespace d3d12 {
return {}; return {};
} }
void CommandBuffer::RecordComputePass(ComPtr<ID3D12GraphicsCommandList> commandList, void CommandBuffer::RecordComputePass(ID3D12GraphicsCommandList* commandList,
BindGroupStateTracker* bindingTracker) { BindGroupStateTracker* bindingTracker) {
PipelineLayout* lastLayout = nullptr; PipelineLayout* lastLayout = nullptr;
@ -781,14 +791,14 @@ namespace dawn_native { namespace d3d12 {
case Command::Dispatch: { case Command::Dispatch: {
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>(); DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
bindingTracker->Apply(commandList.Get()); bindingTracker->Apply(commandList);
commandList->Dispatch(dispatch->x, dispatch->y, dispatch->z); commandList->Dispatch(dispatch->x, dispatch->y, dispatch->z);
} break; } break;
case Command::DispatchIndirect: { case Command::DispatchIndirect: {
DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>(); DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>();
bindingTracker->Apply(commandList.Get()); bindingTracker->Apply(commandList);
Buffer* buffer = ToBackend(dispatch->indirectBuffer.Get()); Buffer* buffer = ToBackend(dispatch->indirectBuffer.Get());
ComPtr<ID3D12CommandSignature> signature = ComPtr<ID3D12CommandSignature> signature =
ToBackend(GetDevice())->GetDispatchIndirectSignature(); ToBackend(GetDevice())->GetDispatchIndirectSignature();
@ -837,7 +847,7 @@ namespace dawn_native { namespace d3d12 {
constexpr uint64_t kPIXBlackColor = 0xff000000; constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice()) ToBackend(GetDevice())
->GetFunctions() ->GetFunctions()
->pixSetMarkerOnCommandList(commandList.Get(), kPIXBlackColor, label); ->pixSetMarkerOnCommandList(commandList, kPIXBlackColor, label);
} }
} break; } break;
@ -847,7 +857,7 @@ namespace dawn_native { namespace d3d12 {
if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) { if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
ToBackend(GetDevice()) ToBackend(GetDevice())
->GetFunctions() ->GetFunctions()
->pixEndEventOnCommandList(commandList.Get()); ->pixEndEventOnCommandList(commandList);
} }
} break; } break;
@ -860,7 +870,7 @@ namespace dawn_native { namespace d3d12 {
constexpr uint64_t kPIXBlackColor = 0xff000000; constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice()) ToBackend(GetDevice())
->GetFunctions() ->GetFunctions()
->pixBeginEventOnCommandList(commandList.Get(), kPIXBlackColor, label); ->pixBeginEventOnCommandList(commandList, kPIXBlackColor, label);
} }
} break; } break;
@ -869,11 +879,12 @@ namespace dawn_native { namespace d3d12 {
} }
} }
void CommandBuffer::RecordRenderPass(ComPtr<ID3D12GraphicsCommandList> commandList, void CommandBuffer::RecordRenderPass(CommandRecordingContext* commandContext,
BindGroupStateTracker* bindingTracker, BindGroupStateTracker* bindingTracker,
RenderPassDescriptorHeapTracker* renderPassTracker, RenderPassDescriptorHeapTracker* renderPassTracker,
BeginRenderPassCmd* renderPass) { BeginRenderPassCmd* renderPass) {
OMSetRenderTargetArgs args = renderPassTracker->GetSubpassOMSetRenderTargetArgs(renderPass); OMSetRenderTargetArgs args = renderPassTracker->GetSubpassOMSetRenderTargetArgs(renderPass);
ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList();
// Clear framebuffer attachments as needed and transition to render target // Clear framebuffer attachments as needed and transition to render target
{ {
@ -1012,8 +1023,8 @@ namespace dawn_native { namespace d3d12 {
case Command::Draw: { case Command::Draw: {
DrawCmd* draw = iter->NextCommand<DrawCmd>(); DrawCmd* draw = iter->NextCommand<DrawCmd>();
bindingTracker->Apply(commandList.Get()); bindingTracker->Apply(commandList);
vertexBufferTracker.Apply(commandList.Get(), lastPipeline); vertexBufferTracker.Apply(commandList, lastPipeline);
commandList->DrawInstanced(draw->vertexCount, draw->instanceCount, commandList->DrawInstanced(draw->vertexCount, draw->instanceCount,
draw->firstVertex, draw->firstInstance); draw->firstVertex, draw->firstInstance);
} break; } break;
@ -1021,9 +1032,9 @@ namespace dawn_native { namespace d3d12 {
case Command::DrawIndexed: { case Command::DrawIndexed: {
DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>(); DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
bindingTracker->Apply(commandList.Get()); bindingTracker->Apply(commandList);
indexBufferTracker.Apply(commandList.Get()); indexBufferTracker.Apply(commandList);
vertexBufferTracker.Apply(commandList.Get(), lastPipeline); vertexBufferTracker.Apply(commandList, lastPipeline);
commandList->DrawIndexedInstanced(draw->indexCount, draw->instanceCount, commandList->DrawIndexedInstanced(draw->indexCount, draw->instanceCount,
draw->firstIndex, draw->baseVertex, draw->firstIndex, draw->baseVertex,
draw->firstInstance); draw->firstInstance);
@ -1032,8 +1043,8 @@ namespace dawn_native { namespace d3d12 {
case Command::DrawIndirect: { case Command::DrawIndirect: {
DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>(); DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
bindingTracker->Apply(commandList.Get()); bindingTracker->Apply(commandList);
vertexBufferTracker.Apply(commandList.Get(), lastPipeline); vertexBufferTracker.Apply(commandList, lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get()); Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
ComPtr<ID3D12CommandSignature> signature = ComPtr<ID3D12CommandSignature> signature =
ToBackend(GetDevice())->GetDrawIndirectSignature(); ToBackend(GetDevice())->GetDrawIndirectSignature();
@ -1045,9 +1056,9 @@ namespace dawn_native { namespace d3d12 {
case Command::DrawIndexedIndirect: { case Command::DrawIndexedIndirect: {
DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>(); DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
bindingTracker->Apply(commandList.Get()); bindingTracker->Apply(commandList);
indexBufferTracker.Apply(commandList.Get()); indexBufferTracker.Apply(commandList);
vertexBufferTracker.Apply(commandList.Get(), lastPipeline); vertexBufferTracker.Apply(commandList, lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get()); Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
ComPtr<ID3D12CommandSignature> signature = ComPtr<ID3D12CommandSignature> signature =
ToBackend(GetDevice())->GetDrawIndexedIndirectSignature(); ToBackend(GetDevice())->GetDrawIndexedIndirectSignature();
@ -1065,7 +1076,7 @@ namespace dawn_native { namespace d3d12 {
constexpr uint64_t kPIXBlackColor = 0xff000000; constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice()) ToBackend(GetDevice())
->GetFunctions() ->GetFunctions()
->pixSetMarkerOnCommandList(commandList.Get(), kPIXBlackColor, label); ->pixSetMarkerOnCommandList(commandList, kPIXBlackColor, label);
} }
} break; } break;
@ -1075,7 +1086,7 @@ namespace dawn_native { namespace d3d12 {
if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) { if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
ToBackend(GetDevice()) ToBackend(GetDevice())
->GetFunctions() ->GetFunctions()
->pixEndEventOnCommandList(commandList.Get()); ->pixEndEventOnCommandList(commandList);
} }
} break; } break;
@ -1088,7 +1099,7 @@ namespace dawn_native { namespace d3d12 {
constexpr uint64_t kPIXBlackColor = 0xff000000; constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice()) ToBackend(GetDevice())
->GetFunctions() ->GetFunctions()
->pixBeginEventOnCommandList(commandList.Get(), kPIXBlackColor, label); ->pixBeginEventOnCommandList(commandList, kPIXBlackColor, label);
} }
} break; } break;
@ -1149,7 +1160,7 @@ namespace dawn_native { namespace d3d12 {
// TODO(brandon1.jones@intel.com): avoid calling this function and enable MSAA // TODO(brandon1.jones@intel.com): avoid calling this function and enable MSAA
// resolve in D3D12 render pass on the platforms that support this feature. // resolve in D3D12 render pass on the platforms that support this feature.
if (renderPass->attachmentState->GetSampleCount() > 1) { if (renderPass->attachmentState->GetSampleCount() > 1) {
ResolveMultisampledRenderPass(commandList, renderPass); ResolveMultisampledRenderPass(commandContext, renderPass);
} }
return; return;
} break; } break;

View File

@ -32,6 +32,7 @@ namespace dawn_native {
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
class BindGroupStateTracker; class BindGroupStateTracker;
class CommandRecordingContext;
class Device; class Device;
class RenderPassDescriptorHeapTracker; class RenderPassDescriptorHeapTracker;
class RenderPipeline; class RenderPipeline;
@ -41,13 +42,12 @@ namespace dawn_native { namespace d3d12 {
CommandBuffer(CommandEncoderBase* encoder, const CommandBufferDescriptor* descriptor); CommandBuffer(CommandEncoderBase* encoder, const CommandBufferDescriptor* descriptor);
~CommandBuffer(); ~CommandBuffer();
MaybeError RecordCommands(ComPtr<ID3D12GraphicsCommandList> commandList, MaybeError RecordCommands(CommandRecordingContext* commandContext, uint32_t indexInSubmit);
uint32_t indexInSubmit);
private: private:
void RecordComputePass(ComPtr<ID3D12GraphicsCommandList> commandList, void RecordComputePass(ID3D12GraphicsCommandList* commandList,
BindGroupStateTracker* bindingTracker); BindGroupStateTracker* bindingTracker);
void RecordRenderPass(ComPtr<ID3D12GraphicsCommandList> commandList, void RecordRenderPass(CommandRecordingContext* commandContext,
BindGroupStateTracker* bindingTracker, BindGroupStateTracker* bindingTracker,
RenderPassDescriptorHeapTracker* renderPassTracker, RenderPassDescriptorHeapTracker* renderPassTracker,
BeginRenderPassCmd* renderPass); BeginRenderPassCmd* renderPass);

View File

@ -0,0 +1,72 @@
// Copyright 2019 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/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/CommandAllocatorManager.h"
namespace dawn_native { namespace d3d12 {
MaybeError CommandRecordingContext::Open(ID3D12Device* d3d12Device,
CommandAllocatorManager* commandAllocationManager) {
ASSERT(!IsOpen());
if (mD3d12CommandList != nullptr) {
const HRESULT hr = mD3d12CommandList->Reset(
commandAllocationManager->ReserveCommandAllocator().Get(), nullptr);
if (FAILED(hr)) {
mD3d12CommandList.Reset();
return DAWN_DEVICE_LOST_ERROR("Error resetting command list.");
}
} else {
ComPtr<ID3D12GraphicsCommandList> d3d12GraphicsCommandList;
const HRESULT hr = d3d12Device->CreateCommandList(
0, D3D12_COMMAND_LIST_TYPE_DIRECT,
commandAllocationManager->ReserveCommandAllocator().Get(), nullptr,
IID_PPV_ARGS(&d3d12GraphicsCommandList));
if (FAILED(hr)) {
return DAWN_DEVICE_LOST_ERROR("Error creating a direct command list.");
}
mD3d12CommandList = std::move(d3d12GraphicsCommandList);
}
mIsOpen = true;
return {};
}
ResultOrError<ID3D12GraphicsCommandList*> CommandRecordingContext::Close() {
ASSERT(IsOpen());
mIsOpen = false;
const HRESULT hr = mD3d12CommandList->Close();
if (FAILED(hr)) {
mD3d12CommandList.Reset();
return DAWN_DEVICE_LOST_ERROR("Error closing pending command list.");
}
return mD3d12CommandList.Get();
}
ID3D12GraphicsCommandList* CommandRecordingContext::GetCommandList() const {
ASSERT(mD3d12CommandList != nullptr);
ASSERT(IsOpen());
return mD3d12CommandList.Get();
}
void CommandRecordingContext::Release() {
mD3d12CommandList.Reset();
mIsOpen = false;
}
bool CommandRecordingContext::IsOpen() const {
return mIsOpen;
}
}} // namespace dawn_native::d3d12

View File

@ -0,0 +1,38 @@
// Copyright 2019 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 DAWNNATIVE_D3D12_COMMANDRECORDINGCONTEXT_H_
#define DAWNNATIVE_D3D12_COMMANDRECORDINGCONTEXT_H_
#include "dawn_native/Error.h"
#include "dawn_native/d3d12/d3d12_platform.h"
namespace dawn_native { namespace d3d12 {
class CommandAllocatorManager;
class CommandRecordingContext {
public:
MaybeError Open(ID3D12Device* d3d12Device,
CommandAllocatorManager* commandAllocationManager);
ResultOrError<ID3D12GraphicsCommandList*> Close();
ID3D12GraphicsCommandList* GetCommandList() const;
void Release();
bool IsOpen() const;
private:
ComPtr<ID3D12GraphicsCommandList> mD3d12CommandList;
bool mIsOpen = false;
};
}} // namespace dawn_native::d3d12
#endif // DAWNNATIVE_D3D12_COMMANDRECORDINGCONTEXT_H_

View File

@ -101,11 +101,8 @@ namespace dawn_native { namespace d3d12 {
Device::~Device() { Device::~Device() {
// Immediately forget about all pending commands // Immediately forget about all pending commands
if (mPendingCommands.open) { mPendingCommands.Release();
mPendingCommands.commandList->Close();
mPendingCommands.open = false;
mPendingCommands.commandList = nullptr;
}
NextSerial(); NextSerial();
WaitForSerial(mLastSubmittedSerial); // Wait for all in-flight commands to finish executing WaitForSerial(mLastSubmittedSerial); // Wait for all in-flight commands to finish executing
@ -133,7 +130,7 @@ namespace dawn_native { namespace d3d12 {
mUsedComObjectRefs.ClearUpTo(mCompletedSerial); mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
ASSERT(mUsedComObjectRefs.Empty()); ASSERT(mUsedComObjectRefs.Empty());
ASSERT(mPendingCommands.commandList == nullptr); ASSERT(!mPendingCommands.IsOpen());
} }
ComPtr<ID3D12Device> Device::GetD3D12Device() const { ComPtr<ID3D12Device> Device::GetD3D12Device() const {
@ -176,27 +173,17 @@ namespace dawn_native { namespace d3d12 {
return mResourceAllocator.get(); return mResourceAllocator.get();
} }
void Device::OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList) { CommandAllocatorManager* Device::GetCommandAllocatorManager() const {
ComPtr<ID3D12GraphicsCommandList>& cmdList = *commandList; return mCommandAllocatorManager.get();
if (!cmdList) {
ASSERT_SUCCESS(mD3d12Device->CreateCommandList(
0, D3D12_COMMAND_LIST_TYPE_DIRECT,
mCommandAllocatorManager->ReserveCommandAllocator().Get(), nullptr,
IID_PPV_ARGS(&cmdList)));
} else {
ASSERT_SUCCESS(
cmdList->Reset(mCommandAllocatorManager->ReserveCommandAllocator().Get(), nullptr));
}
} }
ComPtr<ID3D12GraphicsCommandList> Device::GetPendingCommandList() { ResultOrError<CommandRecordingContext*> Device::GetPendingCommandContext() {
// Callers of GetPendingCommandList do so to record commands. Only reserve a command // Callers of GetPendingCommandList do so to record commands. Only reserve a command
// allocator when it is needed so we don't submit empty command lists // allocator when it is needed so we don't submit empty command lists
if (!mPendingCommands.open) { if (!mPendingCommands.IsOpen()) {
OpenCommandList(&mPendingCommands.commandList); DAWN_TRY(mPendingCommands.Open(mD3d12Device.Get(), mCommandAllocatorManager.get()));
mPendingCommands.open = true;
} }
return mPendingCommands.commandList; return &mPendingCommands;
} }
Serial Device::GetCompletedCommandSerial() const { Serial Device::GetCompletedCommandSerial() const {
@ -224,7 +211,7 @@ namespace dawn_native { namespace d3d12 {
mDescriptorHeapAllocator->Deallocate(mCompletedSerial); mDescriptorHeapAllocator->Deallocate(mCompletedSerial);
mMapRequestTracker->Tick(mCompletedSerial); mMapRequestTracker->Tick(mCompletedSerial);
mUsedComObjectRefs.ClearUpTo(mCompletedSerial); mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
DAWN_TRY(ExecuteCommandList(nullptr)); DAWN_TRY(ExecuteCommandContext(nullptr));
NextSerial(); NextSerial();
return {}; return {};
@ -247,27 +234,23 @@ namespace dawn_native { namespace d3d12 {
mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial()); mUsedComObjectRefs.Enqueue(object, GetPendingCommandSerial());
} }
MaybeError Device::ExecuteCommandList(ID3D12CommandList* d3d12CommandList) { MaybeError Device::ExecuteCommandContext(CommandRecordingContext* commandContext) {
UINT numLists = 0; UINT numLists = 0;
std::array<ID3D12CommandList*, 2> d3d12CommandLists; std::array<ID3D12CommandList*, 2> d3d12CommandLists;
// If there are pending commands, prepend them to ExecuteCommandLists // If there are pending commands, prepend them to ExecuteCommandLists
if (mPendingCommands.open) { if (mPendingCommands.IsOpen()) {
const HRESULT hr = mPendingCommands.commandList->Close(); ID3D12GraphicsCommandList* d3d12CommandList;
if (FAILED(hr)) { DAWN_TRY_ASSIGN(d3d12CommandList, mPendingCommands.Close());
mPendingCommands.open = false; d3d12CommandLists[numLists++] = d3d12CommandList;
mPendingCommands.commandList.Reset();
return DAWN_DEVICE_LOST_ERROR("Error closing pending command list.");
}
mPendingCommands.open = false;
d3d12CommandLists[numLists++] = mPendingCommands.commandList.Get();
} }
if (d3d12CommandList != nullptr) { if (commandContext != nullptr) {
ID3D12GraphicsCommandList* d3d12CommandList;
DAWN_TRY_ASSIGN(d3d12CommandList, commandContext->Close());
d3d12CommandLists[numLists++] = d3d12CommandList; d3d12CommandLists[numLists++] = d3d12CommandList;
} }
if (numLists > 0) { if (numLists > 0) {
mCommandQueue->ExecuteCommandLists(numLists, d3d12CommandLists.data()); mCommandQueue->ExecuteCommandLists(numLists, d3d12CommandLists.data());
mPendingCommands.commandList.Reset();
} }
return {}; return {};
@ -317,7 +300,7 @@ namespace dawn_native { namespace d3d12 {
return new SwapChain(this, descriptor); return new SwapChain(this, descriptor);
} }
ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) { ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) {
return new Texture(this, descriptor); return Texture::Create(this, descriptor);
} }
ResultOrError<TextureViewBase*> Device::CreateTextureViewImpl( ResultOrError<TextureViewBase*> Device::CreateTextureViewImpl(
TextureBase* texture, TextureBase* texture,
@ -337,10 +320,13 @@ namespace dawn_native { namespace d3d12 {
BufferBase* destination, BufferBase* destination,
uint64_t destinationOffset, uint64_t destinationOffset,
uint64_t size) { uint64_t size) {
ToBackend(destination) CommandRecordingContext* commandRecordingContext;
->TransitionUsageNow(GetPendingCommandList(), dawn::BufferUsage::CopyDst); DAWN_TRY_ASSIGN(commandRecordingContext, GetPendingCommandContext());
GetPendingCommandList()->CopyBufferRegion( ToBackend(destination)
->TransitionUsageNow(commandRecordingContext, dawn::BufferUsage::CopyDst);
commandRecordingContext->GetCommandList()->CopyBufferRegion(
ToBackend(destination)->GetD3D12Resource().Get(), destinationOffset, ToBackend(destination)->GetD3D12Resource().Get(), destinationOffset,
ToBackend(source)->GetResource(), sourceOffset, size); ToBackend(source)->GetResource(), sourceOffset, size);
@ -381,6 +367,6 @@ namespace dawn_native { namespace d3d12 {
return nullptr; return nullptr;
} }
return new Texture(this, descriptor, d3d12Resource.Get()); return new Texture(this, descriptor, std::move(d3d12Resource));
} }
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -19,9 +19,9 @@
#include "common/SerialQueue.h" #include "common/SerialQueue.h"
#include "dawn_native/Device.h" #include "dawn_native/Device.h"
#include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/Forward.h" #include "dawn_native/d3d12/Forward.h"
#include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h" #include "dawn_native/d3d12/ResourceHeapAllocationD3D12.h"
#include "dawn_native/d3d12/d3d12_platform.h"
#include <memory> #include <memory>
@ -65,12 +65,12 @@ namespace dawn_native { namespace d3d12 {
DescriptorHeapAllocator* GetDescriptorHeapAllocator() const; DescriptorHeapAllocator* GetDescriptorHeapAllocator() const;
MapRequestTracker* GetMapRequestTracker() const; MapRequestTracker* GetMapRequestTracker() const;
ResourceAllocator* GetResourceAllocator() const; ResourceAllocator* GetResourceAllocator() const;
CommandAllocatorManager* GetCommandAllocatorManager() const;
const PlatformFunctions* GetFunctions() const; const PlatformFunctions* GetFunctions() const;
ComPtr<IDXGIFactory4> GetFactory() const; ComPtr<IDXGIFactory4> GetFactory() const;
void OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList); ResultOrError<CommandRecordingContext*> GetPendingCommandContext();
ComPtr<ID3D12GraphicsCommandList> GetPendingCommandList();
Serial GetPendingCommandSerial() const override; Serial GetPendingCommandSerial() const override;
void NextSerial(); void NextSerial();
@ -78,7 +78,7 @@ namespace dawn_native { namespace d3d12 {
void ReferenceUntilUnused(ComPtr<IUnknown> object); void ReferenceUntilUnused(ComPtr<IUnknown> object);
MaybeError ExecuteCommandList(ID3D12CommandList* d3d12CommandList); MaybeError ExecuteCommandContext(CommandRecordingContext* commandContext);
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override; ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, MaybeError CopyFromStagingToBuffer(StagingBufferBase* source,
@ -132,10 +132,7 @@ namespace dawn_native { namespace d3d12 {
ComPtr<ID3D12CommandSignature> mDrawIndirectSignature; ComPtr<ID3D12CommandSignature> mDrawIndirectSignature;
ComPtr<ID3D12CommandSignature> mDrawIndexedIndirectSignature; ComPtr<ID3D12CommandSignature> mDrawIndexedIndirectSignature;
struct PendingCommandList { CommandRecordingContext mPendingCommands;
ComPtr<ID3D12GraphicsCommandList> commandList;
bool open = false;
} mPendingCommands;
SerialQueue<ComPtr<IUnknown>> mUsedComObjectRefs; SerialQueue<ComPtr<IUnknown>> mUsedComObjectRefs;

View File

@ -27,13 +27,13 @@ namespace dawn_native { namespace d3d12 {
device->Tick(); device->Tick();
device->OpenCommandList(&mCommandList); DAWN_TRY(mCommandContext.Open(device->GetD3D12Device().Get(),
device->GetCommandAllocatorManager()));
for (uint32_t i = 0; i < commandCount; ++i) { for (uint32_t i = 0; i < commandCount; ++i) {
DAWN_TRY(ToBackend(commands[i])->RecordCommands(mCommandList, i)); DAWN_TRY(ToBackend(commands[i])->RecordCommands(&mCommandContext, i));
} }
ASSERT_SUCCESS(mCommandList->Close());
DAWN_TRY(device->ExecuteCommandList(mCommandList.Get())); DAWN_TRY(device->ExecuteCommandContext(&mCommandContext));
device->NextSerial(); device->NextSerial();
return {}; return {};

View File

@ -17,6 +17,7 @@
#include "dawn_native/Queue.h" #include "dawn_native/Queue.h"
#include "dawn_native/d3d12/CommandRecordingContext.h"
#include "dawn_native/d3d12/d3d12_platform.h" #include "dawn_native/d3d12/d3d12_platform.h"
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
@ -31,7 +32,7 @@ namespace dawn_native { namespace d3d12 {
private: private:
MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override;
ComPtr<ID3D12GraphicsCommandList> mCommandList; CommandRecordingContext mCommandContext;
}; };
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -51,10 +51,13 @@ namespace dawn_native { namespace d3d12 {
MaybeError SwapChain::OnBeforePresent(TextureBase* texture) { MaybeError SwapChain::OnBeforePresent(TextureBase* texture) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
// Perform the necessary transition for the texture to be presented. CommandRecordingContext* commandContext;
ToBackend(texture)->TransitionUsageNow(device->GetPendingCommandList(), mTextureUsage); DAWN_TRY_ASSIGN(commandContext, device->GetPendingCommandContext());
DAWN_TRY(device->ExecuteCommandList(nullptr)); // Perform the necessary transition for the texture to be presented.
ToBackend(texture)->TransitionUsageNow(commandContext, mTextureUsage);
DAWN_TRY(device->ExecuteCommandContext(nullptr));
return {}; return {};
} }

View File

@ -270,8 +270,18 @@ namespace dawn_native { namespace d3d12 {
return {}; return {};
} }
ResultOrError<TextureBase*> Texture::Create(Device* device,
const TextureDescriptor* descriptor) {
Ref<Texture> dawnTexture = AcquireRef(new Texture(device, descriptor));
DAWN_TRY(dawnTexture->InitializeAsInternalTexture());
return dawnTexture.Detach();
}
Texture::Texture(Device* device, const TextureDescriptor* descriptor) Texture::Texture(Device* device, const TextureDescriptor* descriptor)
: TextureBase(device, descriptor, TextureState::OwnedInternal) { : TextureBase(device, descriptor, TextureState::OwnedInternal) {
}
MaybeError Texture::InitializeAsInternalTexture() {
D3D12_RESOURCE_DESC resourceDescriptor; D3D12_RESOURCE_DESC resourceDescriptor;
resourceDescriptor.Dimension = D3D12TextureDimension(GetDimension()); resourceDescriptor.Dimension = D3D12TextureDimension(GetDimension());
resourceDescriptor.Alignment = 0; resourceDescriptor.Alignment = 0;
@ -283,7 +293,7 @@ namespace dawn_native { namespace d3d12 {
resourceDescriptor.DepthOrArraySize = GetDepthOrArraySize(); resourceDescriptor.DepthOrArraySize = GetDepthOrArraySize();
resourceDescriptor.MipLevels = static_cast<UINT16>(GetNumMipLevels()); resourceDescriptor.MipLevels = static_cast<UINT16>(GetNumMipLevels());
resourceDescriptor.Format = D3D12TextureFormat(GetFormat().format); resourceDescriptor.Format = D3D12TextureFormat(GetFormat().format);
resourceDescriptor.SampleDesc.Count = descriptor->sampleCount; resourceDescriptor.SampleDesc.Count = GetSampleCount();
// TODO(bryan.bernhart@intel.com): investigate how to specify standard MSAA sample pattern. // TODO(bryan.bernhart@intel.com): investigate how to specify standard MSAA sample pattern.
resourceDescriptor.SampleDesc.Quality = 0; resourceDescriptor.SampleDesc.Quality = 0;
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
@ -295,18 +305,25 @@ namespace dawn_native { namespace d3d12 {
->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor, ->Allocate(D3D12_HEAP_TYPE_DEFAULT, resourceDescriptor,
D3D12_RESOURCE_STATE_COMMON); D3D12_RESOURCE_STATE_COMMON);
Device* device = ToBackend(GetDevice());
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) { if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
device->ConsumedError(ClearTexture(device->GetPendingCommandList(), 0, CommandRecordingContext* commandContext;
GetNumMipLevels(), 0, GetArrayLayers(), DAWN_TRY_ASSIGN(commandContext, device->GetPendingCommandContext());
TextureBase::ClearValue::NonZero));
DAWN_TRY(ClearTexture(commandContext, 0, GetNumMipLevels(), 0, GetArrayLayers(),
TextureBase::ClearValue::NonZero));
} }
return {};
} }
// With this constructor, the lifetime of the ID3D12Resource is externally managed. // With this constructor, the lifetime of the ID3D12Resource is externally managed.
Texture::Texture(Device* device, Texture::Texture(Device* device,
const TextureDescriptor* descriptor, const TextureDescriptor* descriptor,
ID3D12Resource* nativeTexture) ComPtr<ID3D12Resource> nativeTexture)
: TextureBase(device, descriptor, TextureState::OwnedExternal), mResource(nativeTexture) { : TextureBase(device, descriptor, TextureState::OwnedExternal),
mResource(std::move(nativeTexture)) {
SetIsSubresourceContentInitialized(true, 0, descriptor->mipLevelCount, 0, SetIsSubresourceContentInitialized(true, 0, descriptor->mipLevelCount, 0,
descriptor->arrayLayerCount); descriptor->arrayLayerCount);
} }
@ -341,16 +358,18 @@ namespace dawn_native { namespace d3d12 {
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a // When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can // ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors. // cause subsequent errors.
bool Texture::TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier, bool Texture::TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
dawn::TextureUsage newUsage) { dawn::TextureUsage newUsage) {
return TransitionUsageAndGetResourceBarrier(barrier, return TransitionUsageAndGetResourceBarrier(commandContext, barrier,
D3D12TextureUsage(newUsage, GetFormat())); D3D12TextureUsage(newUsage, GetFormat()));
} }
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a // When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can // ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors. // cause subsequent errors.
bool Texture::TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier, bool Texture::TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState) { D3D12_RESOURCE_STATES newState) {
// Avoid transitioning the texture when it isn't needed. // Avoid transitioning the texture when it isn't needed.
// TODO(cwallez@chromium.org): Need some form of UAV barriers at some point. // TODO(cwallez@chromium.org): Need some form of UAV barriers at some point.
@ -417,17 +436,17 @@ namespace dawn_native { namespace d3d12 {
return true; return true;
} }
void Texture::TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList, void Texture::TransitionUsageNow(CommandRecordingContext* commandContext,
dawn::TextureUsage usage) { dawn::TextureUsage usage) {
TransitionUsageNow(commandList, D3D12TextureUsage(usage, GetFormat())); TransitionUsageNow(commandContext, D3D12TextureUsage(usage, GetFormat()));
} }
void Texture::TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList, void Texture::TransitionUsageNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState) { D3D12_RESOURCE_STATES newState) {
D3D12_RESOURCE_BARRIER barrier; D3D12_RESOURCE_BARRIER barrier;
if (TransitionUsageAndGetResourceBarrier(&barrier, newState)) { if (TransitionUsageAndGetResourceBarrier(commandContext, &barrier, newState)) {
commandList->ResourceBarrier(1, &barrier); commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
} }
} }
@ -475,7 +494,7 @@ namespace dawn_native { namespace d3d12 {
return dsvDesc; return dsvDesc;
} }
MaybeError Texture::ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList, MaybeError Texture::ClearTexture(CommandRecordingContext* commandContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
@ -488,12 +507,14 @@ namespace dawn_native { namespace d3d12 {
return {}; return {};
} }
ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList();
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
DescriptorHeapAllocator* descriptorHeapAllocator = device->GetDescriptorHeapAllocator(); DescriptorHeapAllocator* descriptorHeapAllocator = device->GetDescriptorHeapAllocator();
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1; uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
if (GetFormat().isRenderable) { if (GetFormat().isRenderable) {
if (GetFormat().HasDepthOrStencil()) { if (GetFormat().HasDepthOrStencil()) {
TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_DEPTH_WRITE); TransitionUsageNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE);
DescriptorHeapHandle dsvHeap; DescriptorHeapHandle dsvHeap;
DAWN_TRY_ASSIGN(dsvHeap, descriptorHeapAllocator->AllocateCPUHeap( DAWN_TRY_ASSIGN(dsvHeap, descriptorHeapAllocator->AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1)); D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1));
@ -513,7 +534,7 @@ namespace dawn_native { namespace d3d12 {
commandList->ClearDepthStencilView(dsvHandle, clearFlags, clearColor, clearColor, 0, commandList->ClearDepthStencilView(dsvHandle, clearFlags, clearColor, clearColor, 0,
nullptr); nullptr);
} else { } else {
TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_RENDER_TARGET); TransitionUsageNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET);
DescriptorHeapHandle rtvHeap; DescriptorHeapHandle rtvHeap;
DAWN_TRY_ASSIGN(rtvHeap, descriptorHeapAllocator->AllocateCPUHeap( DAWN_TRY_ASSIGN(rtvHeap, descriptorHeapAllocator->AllocateCPUHeap(
D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1)); D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1));
@ -548,7 +569,7 @@ namespace dawn_native { namespace d3d12 {
reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer + bufferSize), reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer + bufferSize),
clearColor); clearColor);
TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_COPY_DEST); TransitionUsageNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST);
// compute d3d12 texture copy locations for texture and buffer // compute d3d12 texture copy locations for texture and buffer
Extent3D copySize = {GetSize().width, GetSize().height, 1}; Extent3D copySize = {GetSize().width, GetSize().height, 1};
@ -586,7 +607,7 @@ namespace dawn_native { namespace d3d12 {
return {}; return {};
} }
void Texture::EnsureSubresourceContentInitialized(ComPtr<ID3D12GraphicsCommandList> commandList, void Texture::EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
@ -598,7 +619,7 @@ namespace dawn_native { namespace d3d12 {
layerCount)) { layerCount)) {
// 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
GetDevice()->ConsumedError(ClearTexture(commandList, baseMipLevel, levelCount, GetDevice()->ConsumedError(ClearTexture(commandContext, baseMipLevel, levelCount,
baseArrayLayer, layerCount, baseArrayLayer, layerCount,
TextureBase::ClearValue::Zero)); TextureBase::ClearValue::Zero));
} }

View File

@ -22,6 +22,7 @@
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
class CommandRecordingContext;
class Device; class Device;
DXGI_FORMAT D3D12TextureFormat(dawn::TextureFormat format); DXGI_FORMAT D3D12TextureFormat(dawn::TextureFormat format);
@ -31,33 +32,39 @@ namespace dawn_native { namespace d3d12 {
class Texture : public TextureBase { class Texture : public TextureBase {
public: public:
Texture(Device* device, const TextureDescriptor* descriptor); static ResultOrError<TextureBase*> Create(Device* device,
Texture(Device* device, const TextureDescriptor* descriptor, ID3D12Resource* nativeTexture); const TextureDescriptor* descriptor);
Texture(Device* device,
const TextureDescriptor* descriptor,
ComPtr<ID3D12Resource> nativeTexture);
~Texture(); ~Texture();
DXGI_FORMAT GetD3D12Format() const; DXGI_FORMAT GetD3D12Format() const;
ID3D12Resource* GetD3D12Resource() const; ID3D12Resource* GetD3D12Resource() const;
bool TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier, bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
dawn::TextureUsage newUsage); dawn::TextureUsage newUsage);
void TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList, void TransitionUsageNow(CommandRecordingContext* commandContext, dawn::TextureUsage usage);
dawn::TextureUsage usage); void TransitionUsageNow(CommandRecordingContext* commandContext,
void TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList,
D3D12_RESOURCE_STATES newState); D3D12_RESOURCE_STATES newState);
D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor(uint32_t baseMipLevel, D3D12_RENDER_TARGET_VIEW_DESC GetRTVDescriptor(uint32_t baseMipLevel,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
uint32_t layerCount) const; uint32_t layerCount) const;
D3D12_DEPTH_STENCIL_VIEW_DESC GetDSVDescriptor(uint32_t baseMipLevel) const; D3D12_DEPTH_STENCIL_VIEW_DESC GetDSVDescriptor(uint32_t baseMipLevel) const;
void EnsureSubresourceContentInitialized(ComPtr<ID3D12GraphicsCommandList> commandList, void EnsureSubresourceContentInitialized(CommandRecordingContext* commandContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
uint32_t layerCount); uint32_t layerCount);
private: private:
Texture(Device* device, const TextureDescriptor* descriptor);
MaybeError InitializeAsInternalTexture();
// Dawn API // Dawn API
void DestroyImpl() override; void DestroyImpl() override;
MaybeError ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList, MaybeError ClearTexture(CommandRecordingContext* commandContext,
uint32_t baseMipLevel, uint32_t baseMipLevel,
uint32_t levelCount, uint32_t levelCount,
uint32_t baseArrayLayer, uint32_t baseArrayLayer,
@ -66,7 +73,8 @@ namespace dawn_native { namespace d3d12 {
UINT16 GetDepthOrArraySize(); UINT16 GetDepthOrArraySize();
bool TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier, bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState); D3D12_RESOURCE_STATES newState);
ComPtr<ID3D12Resource> mResource; ComPtr<ID3D12Resource> mResource;