Implement D3D12 Native Render Passes
Uses D3D12 native render pass API when possible. On pre-RS5 builds of Windows, Dawn will fall back to a software emulated render pass. A toggle was added to provide test coverage to the emulated render pass implementation and used in tests that test render pass functionality in particular. Bug: dawn:36 Change-Id: I297a3ec7655b68d28204db2d3ab78cb82bb4e7a5 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/13082 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Brandon Jones <brandon1.jones@intel.com>
This commit is contained in:
parent
eac7382eb2
commit
700cfe7664
2
BUILD.gn
2
BUILD.gn
|
@ -291,6 +291,8 @@ source_set("libdawn_native_sources") {
|
|||
"src/dawn_native/d3d12/PlatformFunctions.h",
|
||||
"src/dawn_native/d3d12/QueueD3D12.cpp",
|
||||
"src/dawn_native/d3d12/QueueD3D12.h",
|
||||
"src/dawn_native/d3d12/RenderPassBuilderD3D12.cpp",
|
||||
"src/dawn_native/d3d12/RenderPassBuilderD3D12.h",
|
||||
"src/dawn_native/d3d12/RenderPipelineD3D12.cpp",
|
||||
"src/dawn_native/d3d12/RenderPipelineD3D12.h",
|
||||
"src/dawn_native/d3d12/ResourceAllocatorManagerD3D12.cpp",
|
||||
|
|
|
@ -75,8 +75,12 @@ namespace dawn_native {
|
|||
{"use_d3d12_resource_heap_tier2",
|
||||
"Enable support for resource heap tier 2. Resource heap tier 2 allows mixing of "
|
||||
"texture and buffers in the same heap. This allows better heap re-use and reduces "
|
||||
"fragmentation."}}}};
|
||||
|
||||
"fragmentation."}},
|
||||
{Toggle::UseD3D12RenderPass,
|
||||
{"use_d3d12_render_pass",
|
||||
"Use the D3D12 render pass API introduced in Windows build 1809 by default. On "
|
||||
"versions of Windows prior to build 1809, or when this toggle is turned off, Dawn "
|
||||
"will emulate a render pass."}}}};
|
||||
} // anonymous namespace
|
||||
|
||||
void TogglesSet::SetToggle(Toggle toggle, bool enabled) {
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace dawn_native {
|
|||
TurnOffVsync,
|
||||
UseTemporaryBufferInCompressedTextureToTextureCopy,
|
||||
UseD3D12ResourceHeapTier2,
|
||||
UseD3D12RenderPass,
|
||||
|
||||
EnumCount,
|
||||
InvalidEnum = EnumCount,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "dawn_native/d3d12/DeviceD3D12.h"
|
||||
#include "dawn_native/d3d12/PipelineLayoutD3D12.h"
|
||||
#include "dawn_native/d3d12/PlatformFunctions.h"
|
||||
#include "dawn_native/d3d12/RenderPassBuilderD3D12.h"
|
||||
#include "dawn_native/d3d12/RenderPipelineD3D12.h"
|
||||
#include "dawn_native/d3d12/SamplerD3D12.h"
|
||||
#include "dawn_native/d3d12/TextureCopySplitter.h"
|
||||
|
@ -65,12 +66,6 @@ namespace dawn_native { namespace d3d12 {
|
|||
return false;
|
||||
}
|
||||
|
||||
struct OMSetRenderTargetArgs {
|
||||
unsigned int numRTVs = 0;
|
||||
std::array<D3D12_CPU_DESCRIPTOR_HANDLE, kMaxColorAttachments> RTVs = {};
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dsv = {};
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class BindGroupStateTracker : public BindGroupAndStorageBarrierTrackerBase<false, uint64_t> {
|
||||
|
@ -601,11 +596,13 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
// Records the necessary barriers for the resource usage pre-computed by the frontend
|
||||
auto TransitionForPass = [](CommandRecordingContext* commandContext,
|
||||
const PassResourceUsage& usages) {
|
||||
const PassResourceUsage& usages) -> bool {
|
||||
std::vector<D3D12_RESOURCE_BARRIER> barriers;
|
||||
|
||||
ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList();
|
||||
|
||||
wgpu::BufferUsage bufferUsages = wgpu::BufferUsage::None;
|
||||
|
||||
for (size_t i = 0; i < usages.buffers.size(); ++i) {
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
if (ToBackend(usages.buffers[i])
|
||||
|
@ -613,6 +610,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
usages.bufferUsages[i])) {
|
||||
barriers.push_back(barrier);
|
||||
}
|
||||
bufferUsages |= usages.bufferUsages[i];
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < usages.textures.size(); ++i) {
|
||||
|
@ -627,6 +625,8 @@ namespace dawn_native { namespace d3d12 {
|
|||
}
|
||||
}
|
||||
|
||||
wgpu::TextureUsage textureUsages = wgpu::TextureUsage::None;
|
||||
|
||||
for (size_t i = 0; i < usages.textures.size(); ++i) {
|
||||
D3D12_RESOURCE_BARRIER barrier;
|
||||
if (ToBackend(usages.textures[i])
|
||||
|
@ -634,11 +634,15 @@ namespace dawn_native { namespace d3d12 {
|
|||
usages.textureUsages[i])) {
|
||||
barriers.push_back(barrier);
|
||||
}
|
||||
textureUsages |= usages.textureUsages[i];
|
||||
}
|
||||
|
||||
if (barriers.size()) {
|
||||
commandList->ResourceBarrier(barriers.size(), barriers.data());
|
||||
}
|
||||
|
||||
return (bufferUsages & wgpu::BufferUsage::Storage ||
|
||||
textureUsages & wgpu::TextureUsage::Storage);
|
||||
};
|
||||
|
||||
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass;
|
||||
|
@ -661,10 +665,11 @@ namespace dawn_native { namespace d3d12 {
|
|||
BeginRenderPassCmd* beginRenderPassCmd =
|
||||
mCommands.NextCommand<BeginRenderPassCmd>();
|
||||
|
||||
TransitionForPass(commandContext, passResourceUsages[nextPassNumber]);
|
||||
const bool passHasUAV =
|
||||
TransitionForPass(commandContext, passResourceUsages[nextPassNumber]);
|
||||
bindingTracker.SetInComputePass(false);
|
||||
RecordRenderPass(commandContext, &bindingTracker, &renderPassTracker,
|
||||
beginRenderPassCmd);
|
||||
beginRenderPassCmd, passHasUAV);
|
||||
|
||||
nextPassNumber++;
|
||||
} break;
|
||||
|
@ -912,126 +917,194 @@ namespace dawn_native { namespace d3d12 {
|
|||
}
|
||||
}
|
||||
|
||||
void CommandBuffer::RecordRenderPass(CommandRecordingContext* commandContext,
|
||||
BindGroupStateTracker* bindingTracker,
|
||||
RenderPassDescriptorHeapTracker* renderPassTracker,
|
||||
BeginRenderPassCmd* renderPass) {
|
||||
OMSetRenderTargetArgs args = renderPassTracker->GetSubpassOMSetRenderTargetArgs(renderPass);
|
||||
void CommandBuffer::SetupRenderPass(CommandRecordingContext* commandContext,
|
||||
BeginRenderPassCmd* renderPass,
|
||||
RenderPassBuilder* renderPassBuilder) {
|
||||
for (uint32_t i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
||||
RenderPassColorAttachmentInfo& attachmentInfo = renderPass->colorAttachments[i];
|
||||
TextureView* view = ToBackend(attachmentInfo.view.Get());
|
||||
Texture* texture = ToBackend(view->GetTexture());
|
||||
|
||||
// Load operation is changed to clear when the texture is uninitialized.
|
||||
if (!texture->IsSubresourceContentInitialized(view->GetBaseMipLevel(), 1,
|
||||
view->GetBaseArrayLayer(), 1) &&
|
||||
attachmentInfo.loadOp == wgpu::LoadOp::Load) {
|
||||
attachmentInfo.loadOp = wgpu::LoadOp::Clear;
|
||||
attachmentInfo.clearColor = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
}
|
||||
|
||||
// Set color load operation.
|
||||
renderPassBuilder->SetRenderTargetBeginningAccess(
|
||||
i, attachmentInfo.loadOp, attachmentInfo.clearColor, view->GetD3D12Format());
|
||||
|
||||
// Set color store operation.
|
||||
if (attachmentInfo.resolveTarget.Get() != nullptr) {
|
||||
TextureView* resolveDestinationView = ToBackend(attachmentInfo.resolveTarget.Get());
|
||||
Texture* resolveDestinationTexture =
|
||||
ToBackend(resolveDestinationView->GetTexture());
|
||||
|
||||
resolveDestinationTexture->TransitionUsageNow(commandContext,
|
||||
D3D12_RESOURCE_STATE_RESOLVE_DEST);
|
||||
|
||||
// Mark resolve target as initialized to prevent clearing later.
|
||||
resolveDestinationTexture->SetIsSubresourceContentInitialized(
|
||||
true, resolveDestinationView->GetBaseMipLevel(), 1,
|
||||
resolveDestinationView->GetBaseArrayLayer(), 1);
|
||||
|
||||
renderPassBuilder->SetRenderTargetEndingAccessResolve(i, attachmentInfo.storeOp,
|
||||
view, resolveDestinationView);
|
||||
} else {
|
||||
renderPassBuilder->SetRenderTargetEndingAccess(i, attachmentInfo.storeOp);
|
||||
}
|
||||
|
||||
// Set whether or not the texture requires initialization after the pass.
|
||||
bool isInitialized = attachmentInfo.storeOp == wgpu::StoreOp::Store;
|
||||
texture->SetIsSubresourceContentInitialized(isInitialized, view->GetBaseMipLevel(), 1,
|
||||
view->GetBaseArrayLayer(), 1);
|
||||
}
|
||||
|
||||
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
|
||||
RenderPassDepthStencilAttachmentInfo& attachmentInfo =
|
||||
renderPass->depthStencilAttachment;
|
||||
TextureView* view = ToBackend(renderPass->depthStencilAttachment.view.Get());
|
||||
Texture* texture = ToBackend(view->GetTexture());
|
||||
|
||||
const bool hasDepth = view->GetTexture()->GetFormat().HasDepth();
|
||||
const bool hasStencil = view->GetTexture()->GetFormat().HasStencil();
|
||||
|
||||
// Load operations are changed to clear when the texture is uninitialized.
|
||||
if (!view->GetTexture()->IsSubresourceContentInitialized(
|
||||
view->GetBaseMipLevel(), view->GetLevelCount(), view->GetBaseArrayLayer(),
|
||||
view->GetLayerCount())) {
|
||||
if (hasDepth && attachmentInfo.depthLoadOp == wgpu::LoadOp::Load) {
|
||||
attachmentInfo.clearDepth = 0.0f;
|
||||
attachmentInfo.depthLoadOp = wgpu::LoadOp::Clear;
|
||||
}
|
||||
if (hasStencil && attachmentInfo.stencilLoadOp == wgpu::LoadOp::Load) {
|
||||
attachmentInfo.clearStencil = 0u;
|
||||
attachmentInfo.stencilLoadOp = wgpu::LoadOp::Clear;
|
||||
}
|
||||
}
|
||||
|
||||
// Set depth/stencil load operations.
|
||||
if (hasDepth) {
|
||||
renderPassBuilder->SetDepthAccess(
|
||||
attachmentInfo.depthLoadOp, attachmentInfo.depthStoreOp,
|
||||
attachmentInfo.clearDepth, view->GetD3D12Format());
|
||||
} else {
|
||||
renderPassBuilder->SetDepthNoAccess();
|
||||
}
|
||||
|
||||
if (hasStencil) {
|
||||
renderPassBuilder->SetStencilAccess(
|
||||
attachmentInfo.stencilLoadOp, attachmentInfo.stencilStoreOp,
|
||||
attachmentInfo.clearStencil, view->GetD3D12Format());
|
||||
} else {
|
||||
renderPassBuilder->SetStencilNoAccess();
|
||||
}
|
||||
|
||||
// Set whether or not the texture requires initialization.
|
||||
ASSERT(!hasDepth || !hasStencil ||
|
||||
attachmentInfo.depthStoreOp == attachmentInfo.stencilStoreOp);
|
||||
bool isInitialized = attachmentInfo.depthStoreOp == wgpu::StoreOp::Store;
|
||||
texture->SetIsSubresourceContentInitialized(isInitialized, view->GetBaseMipLevel(), 1,
|
||||
view->GetBaseArrayLayer(), 1);
|
||||
} else {
|
||||
renderPassBuilder->SetDepthStencilNoAccess();
|
||||
}
|
||||
}
|
||||
|
||||
void CommandBuffer::EmulateBeginRenderPass(CommandRecordingContext* commandContext,
|
||||
const RenderPassBuilder* renderPassBuilder) const {
|
||||
ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList();
|
||||
|
||||
// Clear framebuffer attachments as needed and transition to render target
|
||||
// Clear framebuffer attachments as needed.
|
||||
{
|
||||
for (uint32_t i :
|
||||
IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
|
||||
auto& attachmentInfo = renderPass->colorAttachments[i];
|
||||
TextureView* view = ToBackend(attachmentInfo.view.Get());
|
||||
|
||||
for (uint32_t i = 0; i < renderPassBuilder->GetColorAttachmentCount(); i++) {
|
||||
// Load op - color
|
||||
ASSERT(view->GetLevelCount() == 1);
|
||||
ASSERT(view->GetLayerCount() == 1);
|
||||
if (attachmentInfo.loadOp == wgpu::LoadOp::Clear ||
|
||||
(attachmentInfo.loadOp == wgpu::LoadOp::Load &&
|
||||
!view->GetTexture()->IsSubresourceContentInitialized(
|
||||
view->GetBaseMipLevel(), 1, view->GetBaseArrayLayer(), 1))) {
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = args.RTVs[i];
|
||||
commandList->ClearRenderTargetView(handle, &attachmentInfo.clearColor.r, 0,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
TextureView* resolveView = ToBackend(attachmentInfo.resolveTarget.Get());
|
||||
if (resolveView != nullptr) {
|
||||
// We need to set the resolve target to initialized so that it does not get
|
||||
// cleared later in the pipeline. The texture will be resolved from the source
|
||||
// color attachment, which will be correctly initialized.
|
||||
ToBackend(resolveView->GetTexture())
|
||||
->SetIsSubresourceContentInitialized(
|
||||
true, resolveView->GetBaseMipLevel(), resolveView->GetLevelCount(),
|
||||
resolveView->GetBaseArrayLayer(), resolveView->GetLayerCount());
|
||||
}
|
||||
|
||||
switch (attachmentInfo.storeOp) {
|
||||
case wgpu::StoreOp::Store: {
|
||||
view->GetTexture()->SetIsSubresourceContentInitialized(
|
||||
true, view->GetBaseMipLevel(), 1, view->GetBaseArrayLayer(), 1);
|
||||
} break;
|
||||
|
||||
case wgpu::StoreOp::Clear: {
|
||||
view->GetTexture()->SetIsSubresourceContentInitialized(
|
||||
false, view->GetBaseMipLevel(), 1, view->GetBaseArrayLayer(), 1);
|
||||
} break;
|
||||
|
||||
default: { UNREACHABLE(); } break;
|
||||
if (renderPassBuilder->GetRenderPassRenderTargetDescriptors()[i]
|
||||
.BeginningAccess.Type == D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR) {
|
||||
commandList->ClearRenderTargetView(
|
||||
renderPassBuilder->GetRenderPassRenderTargetDescriptors()[i].cpuDescriptor,
|
||||
renderPassBuilder->GetRenderPassRenderTargetDescriptors()[i]
|
||||
.BeginningAccess.Clear.ClearValue.Color,
|
||||
0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (renderPass->attachmentState->HasDepthStencilAttachment()) {
|
||||
auto& attachmentInfo = renderPass->depthStencilAttachment;
|
||||
Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture());
|
||||
TextureView* view = ToBackend(attachmentInfo.view.Get());
|
||||
float clearDepth = attachmentInfo.clearDepth;
|
||||
if (renderPassBuilder->HasDepth()) {
|
||||
D3D12_CLEAR_FLAGS clearFlags = {};
|
||||
float depthClear = 0.0f;
|
||||
uint8_t stencilClear = 0u;
|
||||
|
||||
if (renderPassBuilder->GetRenderPassDepthStencilDescriptor()
|
||||
->DepthBeginningAccess.Type ==
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR) {
|
||||
clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
|
||||
depthClear = renderPassBuilder->GetRenderPassDepthStencilDescriptor()
|
||||
->DepthBeginningAccess.Clear.ClearValue.DepthStencil.Depth;
|
||||
}
|
||||
if (renderPassBuilder->GetRenderPassDepthStencilDescriptor()
|
||||
->StencilBeginningAccess.Type ==
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR) {
|
||||
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
|
||||
stencilClear =
|
||||
renderPassBuilder->GetRenderPassDepthStencilDescriptor()
|
||||
->StencilBeginningAccess.Clear.ClearValue.DepthStencil.Stencil;
|
||||
}
|
||||
|
||||
// TODO(kainino@chromium.org): investigate: should the Dawn clear
|
||||
// stencil type be uint8_t?
|
||||
uint8_t clearStencil = static_cast<uint8_t>(attachmentInfo.clearStencil);
|
||||
|
||||
// Load op - depth/stencil
|
||||
bool doDepthClear = texture->GetFormat().HasDepth() &&
|
||||
(attachmentInfo.depthLoadOp == wgpu::LoadOp::Clear);
|
||||
bool doStencilClear = texture->GetFormat().HasStencil() &&
|
||||
(attachmentInfo.stencilLoadOp == wgpu::LoadOp::Clear);
|
||||
|
||||
D3D12_CLEAR_FLAGS clearFlags = {};
|
||||
if (doDepthClear) {
|
||||
clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
|
||||
}
|
||||
if (doStencilClear) {
|
||||
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
|
||||
}
|
||||
// If the depth stencil texture has not been initialized, we want to use loadop
|
||||
// clear to init the contents to 0's
|
||||
if (!texture->IsSubresourceContentInitialized(
|
||||
view->GetBaseMipLevel(), view->GetLevelCount(), view->GetBaseArrayLayer(),
|
||||
view->GetLayerCount())) {
|
||||
if (texture->GetFormat().HasDepth() &&
|
||||
attachmentInfo.depthLoadOp == wgpu::LoadOp::Load) {
|
||||
clearDepth = 0.0f;
|
||||
clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
|
||||
}
|
||||
if (texture->GetFormat().HasStencil() &&
|
||||
attachmentInfo.stencilLoadOp == wgpu::LoadOp::Load) {
|
||||
clearStencil = 0u;
|
||||
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (clearFlags) {
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = args.dsv;
|
||||
commandList->ClearDepthStencilView(handle, clearFlags, clearDepth, clearStencil,
|
||||
0, nullptr);
|
||||
}
|
||||
|
||||
if (attachmentInfo.depthStoreOp == wgpu::StoreOp::Store &&
|
||||
attachmentInfo.stencilStoreOp == wgpu::StoreOp::Store) {
|
||||
texture->SetIsSubresourceContentInitialized(
|
||||
true, view->GetBaseMipLevel(), view->GetLevelCount(),
|
||||
view->GetBaseArrayLayer(), view->GetLayerCount());
|
||||
} else if (attachmentInfo.depthStoreOp == wgpu::StoreOp::Clear &&
|
||||
attachmentInfo.stencilStoreOp == wgpu::StoreOp::Clear) {
|
||||
texture->SetIsSubresourceContentInitialized(
|
||||
false, view->GetBaseMipLevel(), view->GetLevelCount(),
|
||||
view->GetBaseArrayLayer(), view->GetLayerCount());
|
||||
commandList->ClearDepthStencilView(
|
||||
renderPassBuilder->GetRenderPassDepthStencilDescriptor()->cpuDescriptor,
|
||||
clearFlags, depthClear, stencilClear, 0, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up render targets
|
||||
{
|
||||
if (args.dsv.ptr) {
|
||||
commandList->OMSetRenderTargets(args.numRTVs, args.RTVs.data(), FALSE, &args.dsv);
|
||||
} else {
|
||||
commandList->OMSetRenderTargets(args.numRTVs, args.RTVs.data(), FALSE, nullptr);
|
||||
}
|
||||
commandList->OMSetRenderTargets(
|
||||
renderPassBuilder->GetColorAttachmentCount(), renderPassBuilder->GetRenderTargetViews(),
|
||||
FALSE,
|
||||
renderPassBuilder->HasDepth()
|
||||
? &renderPassBuilder->GetRenderPassDepthStencilDescriptor()->cpuDescriptor
|
||||
: nullptr);
|
||||
}
|
||||
|
||||
void CommandBuffer::RecordRenderPass(
|
||||
CommandRecordingContext* commandContext,
|
||||
BindGroupStateTracker* bindingTracker,
|
||||
RenderPassDescriptorHeapTracker* renderPassDescriptorHeapTracker,
|
||||
BeginRenderPassCmd* renderPass,
|
||||
const bool passHasUAV) {
|
||||
OMSetRenderTargetArgs args =
|
||||
renderPassDescriptorHeapTracker->GetSubpassOMSetRenderTargetArgs(renderPass);
|
||||
|
||||
const bool useRenderPass = GetDevice()->IsToggleEnabled(Toggle::UseD3D12RenderPass);
|
||||
|
||||
// renderPassBuilder must be scoped to RecordRenderPass because any underlying
|
||||
// D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS structs must remain
|
||||
// valid until after EndRenderPass() has been called.
|
||||
RenderPassBuilder renderPassBuilder(args, passHasUAV);
|
||||
|
||||
SetupRenderPass(commandContext, renderPass, &renderPassBuilder);
|
||||
|
||||
// Use D3D12's native render pass API if it's available, otherwise emulate the
|
||||
// beginning and ending access operations.
|
||||
if (useRenderPass) {
|
||||
commandContext->GetCommandList4()->BeginRenderPass(
|
||||
renderPassBuilder.GetColorAttachmentCount(),
|
||||
renderPassBuilder.GetRenderPassRenderTargetDescriptors(),
|
||||
renderPassBuilder.HasDepth()
|
||||
? renderPassBuilder.GetRenderPassDepthStencilDescriptor()
|
||||
: nullptr,
|
||||
renderPassBuilder.GetRenderPassFlags());
|
||||
} else {
|
||||
EmulateBeginRenderPass(commandContext, &renderPassBuilder);
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList* commandList = commandContext->GetCommandList();
|
||||
|
||||
// Set up default dynamic state
|
||||
{
|
||||
uint32_t width = renderPass->width;
|
||||
|
@ -1189,10 +1262,9 @@ namespace dawn_native { namespace d3d12 {
|
|||
switch (type) {
|
||||
case Command::EndRenderPass: {
|
||||
mCommands.NextCommand<EndRenderPassCmd>();
|
||||
|
||||
// TODO(brandon1.jones@intel.com): avoid calling this function and enable MSAA
|
||||
// resolve in D3D12 render pass on the platforms that support this feature.
|
||||
if (renderPass->attachmentState->GetSampleCount() > 1) {
|
||||
if (useRenderPass) {
|
||||
commandContext->GetCommandList4()->EndRenderPass();
|
||||
} else if (renderPass->attachmentState->GetSampleCount() > 1) {
|
||||
ResolveMultisampledRenderPass(commandContext, renderPass);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -31,10 +31,17 @@ namespace dawn_native {
|
|||
|
||||
namespace dawn_native { namespace d3d12 {
|
||||
|
||||
struct OMSetRenderTargetArgs {
|
||||
unsigned int numRTVs = 0;
|
||||
std::array<D3D12_CPU_DESCRIPTOR_HANDLE, kMaxColorAttachments> RTVs = {};
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE dsv = {};
|
||||
};
|
||||
|
||||
class BindGroupStateTracker;
|
||||
class CommandRecordingContext;
|
||||
class Device;
|
||||
class RenderPassDescriptorHeapTracker;
|
||||
class RenderPassBuilder;
|
||||
class RenderPipeline;
|
||||
|
||||
class CommandBuffer : public CommandBufferBase {
|
||||
|
@ -49,8 +56,14 @@ namespace dawn_native { namespace d3d12 {
|
|||
BindGroupStateTracker* bindingTracker);
|
||||
void RecordRenderPass(CommandRecordingContext* commandContext,
|
||||
BindGroupStateTracker* bindingTracker,
|
||||
RenderPassDescriptorHeapTracker* renderPassTracker,
|
||||
BeginRenderPassCmd* renderPass);
|
||||
RenderPassDescriptorHeapTracker* renderPassDescriptorHeapTracker,
|
||||
BeginRenderPassCmd* renderPass,
|
||||
bool passHasUAV);
|
||||
void SetupRenderPass(CommandRecordingContext* commandContext,
|
||||
BeginRenderPassCmd* renderPass,
|
||||
RenderPassBuilder* renderPassBuilder);
|
||||
void EmulateBeginRenderPass(CommandRecordingContext* commandContext,
|
||||
const RenderPassBuilder* renderPassBuilder) const;
|
||||
|
||||
CommandIterator mCommands;
|
||||
};
|
||||
|
|
|
@ -41,6 +41,9 @@ namespace dawn_native { namespace d3d12 {
|
|||
nullptr, IID_PPV_ARGS(&d3d12GraphicsCommandList)),
|
||||
"D3D12 creating direct command list"));
|
||||
mD3d12CommandList = std::move(d3d12GraphicsCommandList);
|
||||
// Store a cast to ID3D12GraphicsCommandList4. This is required to use the D3D12 render
|
||||
// pass APIs introduced in Windows build 1809.
|
||||
mD3d12CommandList.As(&mD3d12CommandList4);
|
||||
}
|
||||
|
||||
mIsOpen = true;
|
||||
|
@ -80,8 +83,17 @@ namespace dawn_native { namespace d3d12 {
|
|||
return mD3d12CommandList.Get();
|
||||
}
|
||||
|
||||
// This function will fail on Windows versions prior to 1809. Support must be queried through
|
||||
// the device before calling.
|
||||
ID3D12GraphicsCommandList4* CommandRecordingContext::GetCommandList4() const {
|
||||
ASSERT(IsOpen());
|
||||
ASSERT(mD3d12CommandList.Get() != nullptr);
|
||||
return mD3d12CommandList4.Get();
|
||||
}
|
||||
|
||||
void CommandRecordingContext::Release() {
|
||||
mD3d12CommandList.Reset();
|
||||
mD3d12CommandList4.Reset();
|
||||
mIsOpen = false;
|
||||
mSharedTextures.clear();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
CommandAllocatorManager* commandAllocationManager);
|
||||
|
||||
ID3D12GraphicsCommandList* GetCommandList() const;
|
||||
ID3D12GraphicsCommandList4* GetCommandList4() const;
|
||||
void Release();
|
||||
bool IsOpen() const;
|
||||
|
||||
|
@ -38,6 +39,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
|
||||
private:
|
||||
ComPtr<ID3D12GraphicsCommandList> mD3d12CommandList;
|
||||
ComPtr<ID3D12GraphicsCommandList4> mD3d12CommandList4;
|
||||
bool mIsOpen = false;
|
||||
std::set<Texture*> mSharedTextures;
|
||||
};
|
||||
|
|
|
@ -24,25 +24,33 @@ namespace dawn_native { namespace d3d12 {
|
|||
ResultOrError<D3D12DeviceInfo> GatherDeviceInfo(const Adapter& adapter) {
|
||||
D3D12DeviceInfo info = {};
|
||||
|
||||
// Gather info about device memory
|
||||
{
|
||||
// Newer builds replace D3D_FEATURE_DATA_ARCHITECTURE with
|
||||
// D3D_FEATURE_DATA_ARCHITECTURE1. However, D3D_FEATURE_DATA_ARCHITECTURE can be used
|
||||
// for backwards compat.
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_feature
|
||||
D3D12_FEATURE_DATA_ARCHITECTURE arch = {};
|
||||
DAWN_TRY(CheckHRESULT(adapter.GetDevice()->CheckFeatureSupport(
|
||||
D3D12_FEATURE_ARCHITECTURE, &arch, sizeof(arch)),
|
||||
"ID3D12Device::CheckFeatureSupport"));
|
||||
// Newer builds replace D3D_FEATURE_DATA_ARCHITECTURE with
|
||||
// D3D_FEATURE_DATA_ARCHITECTURE1. However, D3D_FEATURE_DATA_ARCHITECTURE can be used
|
||||
// for backwards compat.
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_feature
|
||||
D3D12_FEATURE_DATA_ARCHITECTURE arch = {};
|
||||
DAWN_TRY(CheckHRESULT(adapter.GetDevice()->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE,
|
||||
&arch, sizeof(arch)),
|
||||
"ID3D12Device::CheckFeatureSupport"));
|
||||
|
||||
info.isUMA = arch.UMA;
|
||||
info.isUMA = arch.UMA;
|
||||
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
|
||||
DAWN_TRY(CheckHRESULT(adapter.GetDevice()->CheckFeatureSupport(
|
||||
D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)),
|
||||
"ID3D12Device::CheckFeatureSupport"));
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
|
||||
DAWN_TRY(CheckHRESULT(adapter.GetDevice()->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS,
|
||||
&options, sizeof(options)),
|
||||
"ID3D12Device::CheckFeatureSupport"));
|
||||
|
||||
info.resourceHeapTier = options.ResourceHeapTier;
|
||||
info.resourceHeapTier = options.ResourceHeapTier;
|
||||
|
||||
// Windows builds 1809 and above can use the D3D12 render pass API. If we query
|
||||
// CheckFeatureSupport for D3D12_FEATURE_D3D12_OPTIONS5 successfully, then we can use
|
||||
// the render pass API.
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS5 featureOptions5 = {};
|
||||
if (SUCCEEDED(adapter.GetDevice()->CheckFeatureSupport(
|
||||
D3D12_FEATURE_D3D12_OPTIONS5, &featureOptions5, sizeof(featureOptions5)))) {
|
||||
info.supportsRenderPass = true;
|
||||
} else {
|
||||
info.supportsRenderPass = false;
|
||||
}
|
||||
|
||||
return info;
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
struct D3D12DeviceInfo {
|
||||
bool isUMA;
|
||||
uint32_t resourceHeapTier;
|
||||
bool supportsRenderPass;
|
||||
};
|
||||
|
||||
ResultOrError<D3D12DeviceInfo> GatherDeviceInfo(const Adapter& adapter);
|
||||
|
|
|
@ -414,6 +414,7 @@ namespace dawn_native { namespace d3d12 {
|
|||
void Device::InitTogglesFromDriver() {
|
||||
const bool useResourceHeapTier2 = (GetDeviceInfo().resourceHeapTier >= 2);
|
||||
SetToggle(Toggle::UseD3D12ResourceHeapTier2, useResourceHeapTier2);
|
||||
SetToggle(Toggle::UseD3D12RenderPass, GetDeviceInfo().supportsRenderPass);
|
||||
}
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
// 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/RenderPassBuilderD3D12.h"
|
||||
|
||||
#include "dawn_native/Format.h"
|
||||
#include "dawn_native/d3d12/CommandBufferD3D12.h"
|
||||
#include "dawn_native/d3d12/Forward.h"
|
||||
#include "dawn_native/d3d12/TextureD3D12.h"
|
||||
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
||||
namespace dawn_native { namespace d3d12 {
|
||||
|
||||
namespace {
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE D3D12BeginningAccessType(wgpu::LoadOp loadOp) {
|
||||
switch (loadOp) {
|
||||
case wgpu::LoadOp::Clear:
|
||||
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR;
|
||||
case wgpu::LoadOp::Load:
|
||||
return D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE D3D12EndingAccessType(wgpu::StoreOp storeOp) {
|
||||
switch (storeOp) {
|
||||
case wgpu::StoreOp::Clear:
|
||||
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD;
|
||||
case wgpu::StoreOp::Store:
|
||||
return D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS D3D12EndingAccessResolveParameters(
|
||||
wgpu::StoreOp storeOp,
|
||||
TextureView* resolveSource,
|
||||
TextureView* resolveDestination) {
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS resolveParameters;
|
||||
|
||||
resolveParameters.Format = resolveDestination->GetD3D12Format();
|
||||
resolveParameters.pSrcResource =
|
||||
ToBackend(resolveSource->GetTexture())->GetD3D12Resource();
|
||||
resolveParameters.pDstResource =
|
||||
ToBackend(resolveDestination->GetTexture())->GetD3D12Resource();
|
||||
|
||||
// Clear or preserve the resolve source.
|
||||
if (storeOp == wgpu::StoreOp::Clear) {
|
||||
resolveParameters.PreserveResolveSource = false;
|
||||
} else if (storeOp == wgpu::StoreOp::Store) {
|
||||
resolveParameters.PreserveResolveSource = true;
|
||||
}
|
||||
|
||||
// RESOLVE_MODE_AVERAGE is only valid for non-integer formats.
|
||||
// TODO: Investigate and determine how integer format resolves should work in WebGPU.
|
||||
switch (resolveDestination->GetFormat().type) {
|
||||
case Format::Type::Sint:
|
||||
case Format::Type::Uint:
|
||||
resolveParameters.ResolveMode = D3D12_RESOLVE_MODE_MAX;
|
||||
break;
|
||||
default:
|
||||
resolveParameters.ResolveMode = D3D12_RESOLVE_MODE_AVERAGE;
|
||||
break;
|
||||
}
|
||||
|
||||
resolveParameters.SubresourceCount = 1;
|
||||
|
||||
return resolveParameters;
|
||||
}
|
||||
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS
|
||||
D3D12EndingAccessResolveSubresourceParameters(TextureView* resolveDestination) {
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS subresourceParameters;
|
||||
Texture* resolveDestinationTexture = ToBackend(resolveDestination->GetTexture());
|
||||
|
||||
subresourceParameters.DstX = 0;
|
||||
subresourceParameters.DstY = 0;
|
||||
subresourceParameters.SrcSubresource = 0;
|
||||
subresourceParameters.DstSubresource = resolveDestinationTexture->GetSubresourceIndex(
|
||||
resolveDestination->GetBaseMipLevel(), resolveDestination->GetBaseArrayLayer());
|
||||
subresourceParameters.SrcRect = {0, 0, resolveDestinationTexture->GetSize().width,
|
||||
resolveDestinationTexture->GetSize().height};
|
||||
|
||||
return subresourceParameters;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
RenderPassBuilder::RenderPassBuilder(const OMSetRenderTargetArgs& args, bool hasUAV)
|
||||
: mColorAttachmentCount(args.numRTVs), mRenderTargetViews(args.RTVs.data()) {
|
||||
for (uint32_t i = 0; i < mColorAttachmentCount; i++) {
|
||||
mRenderPassRenderTargetDescriptors[i].cpuDescriptor = args.RTVs[i];
|
||||
}
|
||||
|
||||
mRenderPassDepthStencilDesc.cpuDescriptor = args.dsv;
|
||||
|
||||
if (hasUAV) {
|
||||
mRenderPassFlags = D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RenderPassBuilder::GetColorAttachmentCount() const {
|
||||
return mColorAttachmentCount;
|
||||
}
|
||||
|
||||
bool RenderPassBuilder::HasDepth() const {
|
||||
return mHasDepth;
|
||||
}
|
||||
|
||||
const D3D12_RENDER_PASS_RENDER_TARGET_DESC*
|
||||
RenderPassBuilder::GetRenderPassRenderTargetDescriptors() const {
|
||||
return mRenderPassRenderTargetDescriptors.data();
|
||||
}
|
||||
|
||||
const D3D12_RENDER_PASS_DEPTH_STENCIL_DESC*
|
||||
RenderPassBuilder::GetRenderPassDepthStencilDescriptor() const {
|
||||
return &mRenderPassDepthStencilDesc;
|
||||
}
|
||||
|
||||
D3D12_RENDER_PASS_FLAGS RenderPassBuilder::GetRenderPassFlags() const {
|
||||
return mRenderPassFlags;
|
||||
}
|
||||
|
||||
const D3D12_CPU_DESCRIPTOR_HANDLE* RenderPassBuilder::GetRenderTargetViews() const {
|
||||
return mRenderTargetViews;
|
||||
}
|
||||
|
||||
void RenderPassBuilder::SetRenderTargetBeginningAccess(uint32_t attachment,
|
||||
wgpu::LoadOp loadOp,
|
||||
dawn_native::Color clearColor,
|
||||
DXGI_FORMAT format) {
|
||||
mRenderPassRenderTargetDescriptors[attachment].BeginningAccess.Type =
|
||||
D3D12BeginningAccessType(loadOp);
|
||||
if (loadOp == wgpu::LoadOp::Clear) {
|
||||
mRenderPassRenderTargetDescriptors[attachment]
|
||||
.BeginningAccess.Clear.ClearValue.Color[0] = clearColor.r;
|
||||
mRenderPassRenderTargetDescriptors[attachment]
|
||||
.BeginningAccess.Clear.ClearValue.Color[1] = clearColor.g;
|
||||
mRenderPassRenderTargetDescriptors[attachment]
|
||||
.BeginningAccess.Clear.ClearValue.Color[2] = clearColor.b;
|
||||
mRenderPassRenderTargetDescriptors[attachment]
|
||||
.BeginningAccess.Clear.ClearValue.Color[3] = clearColor.a;
|
||||
mRenderPassRenderTargetDescriptors[attachment].BeginningAccess.Clear.ClearValue.Format =
|
||||
format;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPassBuilder::SetRenderTargetEndingAccess(uint32_t attachment,
|
||||
wgpu::StoreOp storeOp) {
|
||||
mRenderPassRenderTargetDescriptors[attachment].EndingAccess.Type =
|
||||
D3D12EndingAccessType(storeOp);
|
||||
}
|
||||
|
||||
void RenderPassBuilder::SetRenderTargetEndingAccessResolve(uint32_t attachment,
|
||||
wgpu::StoreOp storeOp,
|
||||
TextureView* resolveSource,
|
||||
TextureView* resolveDestination) {
|
||||
mRenderPassRenderTargetDescriptors[attachment].EndingAccess.Type =
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE;
|
||||
mRenderPassRenderTargetDescriptors[attachment].EndingAccess.Resolve =
|
||||
D3D12EndingAccessResolveParameters(storeOp, resolveSource, resolveDestination);
|
||||
|
||||
mSubresourceParams[attachment] =
|
||||
D3D12EndingAccessResolveSubresourceParameters(resolveDestination);
|
||||
|
||||
mRenderPassRenderTargetDescriptors[attachment].EndingAccess.Resolve.pSubresourceParameters =
|
||||
&mSubresourceParams[attachment];
|
||||
}
|
||||
|
||||
void RenderPassBuilder::SetDepthAccess(wgpu::LoadOp loadOp,
|
||||
wgpu::StoreOp storeOp,
|
||||
float clearDepth,
|
||||
DXGI_FORMAT format) {
|
||||
mHasDepth = true;
|
||||
mRenderPassDepthStencilDesc.DepthBeginningAccess.Type = D3D12BeginningAccessType(loadOp);
|
||||
if (loadOp == wgpu::LoadOp::Clear) {
|
||||
mRenderPassDepthStencilDesc.DepthBeginningAccess.Clear.ClearValue.DepthStencil.Depth =
|
||||
clearDepth;
|
||||
mRenderPassDepthStencilDesc.DepthBeginningAccess.Clear.ClearValue.Format = format;
|
||||
}
|
||||
mRenderPassDepthStencilDesc.DepthEndingAccess.Type = D3D12EndingAccessType(storeOp);
|
||||
}
|
||||
|
||||
void RenderPassBuilder::SetStencilAccess(wgpu::LoadOp loadOp,
|
||||
wgpu::StoreOp storeOp,
|
||||
uint8_t clearStencil,
|
||||
DXGI_FORMAT format) {
|
||||
mRenderPassDepthStencilDesc.StencilBeginningAccess.Type = D3D12BeginningAccessType(loadOp);
|
||||
if (loadOp == wgpu::LoadOp::Clear) {
|
||||
mRenderPassDepthStencilDesc.StencilBeginningAccess.Clear.ClearValue.DepthStencil
|
||||
.Stencil = clearStencil;
|
||||
mRenderPassDepthStencilDesc.StencilBeginningAccess.Clear.ClearValue.Format = format;
|
||||
}
|
||||
mRenderPassDepthStencilDesc.StencilEndingAccess.Type = D3D12EndingAccessType(storeOp);
|
||||
}
|
||||
|
||||
void RenderPassBuilder::SetDepthNoAccess() {
|
||||
mRenderPassDepthStencilDesc.DepthBeginningAccess.Type =
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS;
|
||||
mRenderPassDepthStencilDesc.DepthEndingAccess.Type =
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS;
|
||||
}
|
||||
|
||||
void RenderPassBuilder::SetDepthStencilNoAccess() {
|
||||
SetDepthNoAccess();
|
||||
SetStencilNoAccess();
|
||||
}
|
||||
|
||||
void RenderPassBuilder::SetStencilNoAccess() {
|
||||
mRenderPassDepthStencilDesc.StencilBeginningAccess.Type =
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS;
|
||||
mRenderPassDepthStencilDesc.StencilEndingAccess.Type =
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS;
|
||||
}
|
||||
|
||||
}} // namespace dawn_native::d3d12
|
|
@ -0,0 +1,89 @@
|
|||
// 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_RENDERPASSBUILDERD3D12_H_
|
||||
#define DAWNNATIVE_D3D12_RENDERPASSBUILDERD3D12_H_
|
||||
|
||||
#include "common/Constants.h"
|
||||
#include "dawn_native/d3d12/d3d12_platform.h"
|
||||
#include "dawn_native/dawn_platform.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace dawn_native { namespace d3d12 {
|
||||
|
||||
class TextureView;
|
||||
|
||||
struct OMSetRenderTargetArgs;
|
||||
|
||||
// RenderPassBuilder stores parameters related to render pass load and store operations.
|
||||
// When the D3D12 render pass API is available, the needed descriptors can be fetched
|
||||
// directly from the RenderPassBuilder. When the D3D12 render pass API is not available, the
|
||||
// descriptors are still fetched and any information necessary to emulate the load and store
|
||||
// operations is extracted from the descriptors.
|
||||
class RenderPassBuilder {
|
||||
public:
|
||||
RenderPassBuilder(const OMSetRenderTargetArgs& args, bool hasUAV);
|
||||
|
||||
uint32_t GetColorAttachmentCount() const;
|
||||
|
||||
// Returns descriptors that are fed directly to BeginRenderPass, or are used as parameter
|
||||
// storage if D3D12 render pass API is unavailable.
|
||||
const D3D12_RENDER_PASS_RENDER_TARGET_DESC* GetRenderPassRenderTargetDescriptors() const;
|
||||
const D3D12_RENDER_PASS_DEPTH_STENCIL_DESC* GetRenderPassDepthStencilDescriptor() const;
|
||||
|
||||
D3D12_RENDER_PASS_FLAGS GetRenderPassFlags() const;
|
||||
|
||||
// Returns attachment RTVs to use with OMSetRenderTargets.
|
||||
const D3D12_CPU_DESCRIPTOR_HANDLE* GetRenderTargetViews() const;
|
||||
|
||||
bool HasDepth() const;
|
||||
|
||||
// Functions that set the appropriate values in the render pass descriptors.
|
||||
void SetDepthAccess(wgpu::LoadOp loadOp,
|
||||
wgpu::StoreOp storeOp,
|
||||
float clearDepth,
|
||||
DXGI_FORMAT format);
|
||||
void SetDepthNoAccess();
|
||||
void SetDepthStencilNoAccess();
|
||||
void SetRenderTargetBeginningAccess(uint32_t attachment,
|
||||
wgpu::LoadOp loadOp,
|
||||
dawn_native::Color clearColor,
|
||||
DXGI_FORMAT format);
|
||||
void SetRenderTargetEndingAccess(uint32_t attachment, wgpu::StoreOp storeOp);
|
||||
void SetRenderTargetEndingAccessResolve(uint32_t attachment,
|
||||
wgpu::StoreOp storeOp,
|
||||
TextureView* resolveSource,
|
||||
TextureView* resolveDestination);
|
||||
void SetStencilAccess(wgpu::LoadOp loadOp,
|
||||
wgpu::StoreOp storeOp,
|
||||
uint8_t clearStencil,
|
||||
DXGI_FORMAT format);
|
||||
void SetStencilNoAccess();
|
||||
|
||||
private:
|
||||
uint32_t mColorAttachmentCount = 0;
|
||||
bool mHasDepth = false;
|
||||
D3D12_RENDER_PASS_FLAGS mRenderPassFlags = D3D12_RENDER_PASS_FLAG_NONE;
|
||||
D3D12_RENDER_PASS_DEPTH_STENCIL_DESC mRenderPassDepthStencilDesc;
|
||||
std::array<D3D12_RENDER_PASS_RENDER_TARGET_DESC, kMaxColorAttachments>
|
||||
mRenderPassRenderTargetDescriptors;
|
||||
const D3D12_CPU_DESCRIPTOR_HANDLE* mRenderTargetViews;
|
||||
std::array<D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS,
|
||||
kMaxColorAttachments>
|
||||
mSubresourceParams;
|
||||
};
|
||||
}} // namespace dawn_native::d3d12
|
||||
|
||||
#endif // DAWNNATIVE_D3D12_RENDERPASSBUILDERD3D12_H_
|
|
@ -506,6 +506,7 @@ TEST_P(MultisampledRenderingTest, ResolveInto2DArrayTexture) {
|
|||
DAWN_INSTANTIATE_TEST(MultisampledRenderingTest,
|
||||
D3D12Backend,
|
||||
ForceWorkarounds(D3D12Backend, {}, {"use_d3d12_resource_heap_tier2"}),
|
||||
ForceWorkarounds(D3D12Backend, {}, {"use_d3d12_render_pass"}),
|
||||
MetalBackend,
|
||||
OpenGLBackend,
|
||||
VulkanBackend,
|
||||
|
|
|
@ -171,4 +171,9 @@ TEST_P(RenderPassTest, NoCorrespondingFragmentShaderOutputs) {
|
|||
EXPECT_PIXEL_RGBA8_EQ(kRed, renderTarget, kRTSize - 1, 1);
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(RenderPassTest, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);
|
||||
DAWN_INSTANTIATE_TEST(RenderPassTest,
|
||||
D3D12Backend,
|
||||
ForceWorkarounds(D3D12Backend, {}, {"use_d3d12_render_pass"}),
|
||||
MetalBackend,
|
||||
OpenGLBackend,
|
||||
VulkanBackend);
|
||||
|
|
|
@ -779,5 +779,8 @@ TEST_P(TextureZeroInitTest, RenderingLoadingDepthStencilStoreOpClear) {
|
|||
DAWN_INSTANTIATE_TEST(
|
||||
TextureZeroInitTest,
|
||||
ForceWorkarounds(D3D12Backend, {"nonzero_clear_resources_on_creation_for_testing"}),
|
||||
ForceWorkarounds(D3D12Backend,
|
||||
{"nonzero_clear_resources_on_creation_for_testing"},
|
||||
{"use_d3d12_render_pass"}),
|
||||
ForceWorkarounds(OpenGLBackend, {"nonzero_clear_resources_on_creation_for_testing"}),
|
||||
ForceWorkarounds(VulkanBackend, {"nonzero_clear_resources_on_creation_for_testing"}));
|
||||
|
|
Loading…
Reference in New Issue