Skip to content

Commit 6da4502

Browse files
committed
rewrite depth stencil using createTexture and align usages of depth stencil target through all backends (vk was using depth stencil, dx and metal weren't)
1 parent 6ac908a commit 6da4502

5 files changed

Lines changed: 137 additions & 60 deletions

File tree

include/API/Device.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,6 @@ llvm::Expected<std::shared_ptr<Texture>>
9292
createRenderTarget(Device &Dev, const CPUBuffer &Buf);
9393

9494
// Creates a depth/stencil texture matching the dimensions of a render target.
95-
// TODO: Currently always created for graphics pipelines. Consider making this
96-
// conditional on the pipeline definition (e.g. a flag in Pipeline).
9795
llvm::Expected<std::shared_ptr<Texture>>
9896
createDepthStencil(Device &Dev, uint32_t Width, uint32_t Height);
9997

lib/API/DX/Device.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,9 @@ class DXDevice : public offloadtest::Device {
369369
// Resources for graphics pipelines.
370370
std::shared_ptr<DXTexture> RT;
371371
std::shared_ptr<DXBuffer> RTReadback;
372+
std::shared_ptr<DXTexture> DS;
372373
ComPtr<ID3D12DescriptorHeap> RTVHeap;
374+
ComPtr<ID3D12DescriptorHeap> DSVHeap;
373375
ComPtr<ID3D12Resource> VB;
374376

375377
llvm::SmallVector<DescriptorTable> DescTables;
@@ -1482,6 +1484,16 @@ class DXDevice : public offloadtest::Device {
14821484
return llvm::Error::success();
14831485
}
14841486

1487+
llvm::Error createDepthStencil(Pipeline &P, InvocationState &IS) {
1488+
auto TexOrErr = offloadtest::createDepthStencil(
1489+
*this, P.Bindings.RTargetBufferPtr->OutputProps.Width,
1490+
P.Bindings.RTargetBufferPtr->OutputProps.Height);
1491+
if (!TexOrErr)
1492+
return TexOrErr.takeError();
1493+
IS.DS = std::static_pointer_cast<DXTexture>(*TexOrErr);
1494+
return llvm::Error::success();
1495+
}
1496+
14851497
llvm::Error createVertexBuffer(Pipeline &P, InvocationState &IS) {
14861498
if (!P.Bindings.VertexBufferPtr)
14871499
return llvm::createStringError(
@@ -1557,8 +1569,11 @@ class DXDevice : public offloadtest::Device {
15571569

15581570
PSODesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
15591571
PSODesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
1560-
PSODesc.DepthStencilState.DepthEnable = false;
1572+
PSODesc.DepthStencilState.DepthEnable = true;
1573+
PSODesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
1574+
PSODesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
15611575
PSODesc.DepthStencilState.StencilEnable = false;
1576+
PSODesc.DSVFormat = getDXGIFormat(IS.DS->Desc.Format);
15621577
PSODesc.SampleMask = UINT_MAX;
15631578
PSODesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
15641579
PSODesc.NumRenderTargets = 1;
@@ -1590,6 +1605,19 @@ class DXDevice : public offloadtest::Device {
15901605
IS.RTVHeap->GetCPUDescriptorHandleForHeapStart();
15911606
Device->CreateRenderTargetView(IS.RT->Resource.Get(), nullptr, RTVHandle);
15921607

1608+
// Create descriptor heap and view for the depth/stencil buffer.
1609+
D3D12_DESCRIPTOR_HEAP_DESC DSVHeapDesc = {};
1610+
DSVHeapDesc.NumDescriptors = 1;
1611+
DSVHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
1612+
DSVHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
1613+
if (auto Err = HR::toError(Device->CreateDescriptorHeap(
1614+
&DSVHeapDesc, IID_PPV_ARGS(&IS.DSVHeap)),
1615+
"Failed to create DSV heap"))
1616+
return Err;
1617+
const D3D12_CPU_DESCRIPTOR_HANDLE DSVHandle =
1618+
IS.DSVHeap->GetCPUDescriptorHandleForHeapStart();
1619+
Device->CreateDepthStencilView(IS.DS->Resource.Get(), nullptr, DSVHandle);
1620+
15931621
IS.CmdList->SetGraphicsRootSignature(IS.RootSig.Get());
15941622
if (IS.DescHeap) {
15951623
ID3D12DescriptorHeap *const Heaps[] = {IS.DescHeap.Get()};
@@ -1599,7 +1627,17 @@ class DXDevice : public offloadtest::Device {
15991627
}
16001628
IS.CmdList->SetPipelineState(IS.PSO.Get());
16011629

1602-
IS.CmdList->OMSetRenderTargets(1, &RTVHandle, false, nullptr);
1630+
IS.CmdList->OMSetRenderTargets(1, &RTVHandle, false, &DSVHandle);
1631+
1632+
const auto *DepthCV =
1633+
std::get_if<ClearDepthStencil>(&*IS.DS->Desc.OptimizedClearValue);
1634+
if (!DepthCV)
1635+
return llvm::createStringError(
1636+
std::errc::invalid_argument,
1637+
"Depth/stencil clear value must be a ClearDepthStencil.");
1638+
IS.CmdList->ClearDepthStencilView(
1639+
DSVHandle, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL,
1640+
DepthCV->Depth, DepthCV->Stencil, 0, nullptr);
16031641

16041642
D3D12_VIEWPORT VP = {};
16051643
VP.Width =
@@ -1736,10 +1774,15 @@ class DXDevice : public offloadtest::Device {
17361774
llvm::outs() << "Compute command list created.\n";
17371775

17381776
} else {
1739-
// Create render target, readback and vertex buffer and PSO.
1777+
// Create render target, depth/stencil, readback and vertex buffer and PSO.
17401778
if (auto Err = createRenderTarget(P, State))
17411779
return Err;
17421780
llvm::outs() << "Render target created.\n";
1781+
// TODO: Always created for graphics pipelines. Consider making this
1782+
// conditional on the pipeline definition.
1783+
if (auto Err = createDepthStencil(P, State))
1784+
return Err;
1785+
llvm::outs() << "Depth stencil created.\n";
17431786
if (auto Err = createVertexBuffer(P, State))
17441787
return Err;
17451788
llvm::outs() << "Vertex buffer created.\n";

lib/API/Device.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ offloadtest::createRenderTarget(Device &Dev, const CPUBuffer &Buf) {
6868
}
6969

7070
llvm::Expected<std::shared_ptr<Texture>>
71-
createDepthStencil(Device &Dev, uint32_t Width, uint32_t Height) {
71+
offloadtest::createDepthStencil(Device &Dev, uint32_t Width, uint32_t Height) {
7272
TextureCreateDesc Desc = {};
7373
Desc.Location = MemoryLocation::GpuOnly;
7474
Desc.Usage = TextureUsage::DepthStencil;

lib/API/MTL/MTLDevice.cpp

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class MTLDevice : public offloadtest::Device {
146146
llvm::SmallVector<MTL::Buffer *> Buffers;
147147
std::shared_ptr<MTLTexture> FrameBufferTexture;
148148
std::shared_ptr<MTLBuffer> FrameBufferReadback;
149+
std::shared_ptr<MTLTexture> DepthStencil;
149150
MTL::CommandBuffer *CmdBuffer = nullptr;
150151
};
151152

@@ -283,6 +284,12 @@ class MTLDevice : public offloadtest::Device {
283284
MTL::RenderPipelineColorAttachmentDescriptor::alloc()->init();
284285
RPCA->setPixelFormat(PF);
285286
Desc->colorAttachments()->setObject(RPCA, 0);
287+
288+
// Set the depth/stencil format on the pipeline descriptor.
289+
const MTL::PixelFormat DepthFmt =
290+
getMetalFormat(TextureFormat::D32FloatS8Uint);
291+
Desc->setDepthAttachmentPixelFormat(DepthFmt);
292+
Desc->setStencilAttachmentPixelFormat(DepthFmt);
286293
}
287294

288295
IS.RenderPipeline = Device->newRenderPipelineState(Desc, &Error);
@@ -476,31 +483,82 @@ class MTLDevice : public offloadtest::Device {
476483
return llvm::Error::success();
477484
}
478485

486+
llvm::Error createDepthStencil(Pipeline &P, InvocationState &IS) {
487+
auto TexOrErr = offloadtest::createDepthStencil(
488+
*this, P.Bindings.RTargetBufferPtr->OutputProps.Width,
489+
P.Bindings.RTargetBufferPtr->OutputProps.Height);
490+
if (!TexOrErr)
491+
return TexOrErr.takeError();
492+
IS.DepthStencil = std::static_pointer_cast<MTLTexture>(*TexOrErr);
493+
return llvm::Error::success();
494+
}
495+
479496
llvm::Error createGraphicsCommands(Pipeline &P, InvocationState &IS) {
480497
IS.CmdBuffer = GraphicsQueue.Queue->commandBuffer();
481498

482499
if (auto Err = createRenderTarget(P, IS))
483500
return Err;
501+
// TODO: Always created for graphics pipelines. Consider making this
502+
// conditional on the pipeline definition.
503+
if (auto Err = createDepthStencil(P, IS))
504+
return Err;
484505

485506
MTL::RenderPassDescriptor *Desc =
486507
MTL::RenderPassDescriptor::alloc()->init();
487508

488509
const uint64_t Width = P.Bindings.RTargetBufferPtr->OutputProps.Width;
489510
const uint64_t Height = P.Bindings.RTargetBufferPtr->OutputProps.Height;
490511

512+
// Color attachment.
491513
auto *CADesc = MTL::RenderPassColorAttachmentDescriptor::alloc()->init();
492514
CADesc->setTexture(IS.FrameBufferTexture->Tex);
493515
CADesc->setLoadAction(MTL::LoadActionClear);
494-
const auto &CV =
495-
std::get<ClearColor>(*IS.FrameBufferTexture->Desc.OptimizedClearValue);
496-
CADesc->setClearColor(MTL::ClearColor(CV.R, CV.G, CV.B, CV.A));
516+
const auto *ColorCV =
517+
std::get_if<ClearColor>(&*IS.FrameBufferTexture->Desc.OptimizedClearValue);
518+
if (!ColorCV)
519+
return llvm::createStringError(
520+
std::errc::invalid_argument,
521+
"Render target clear value must be a ClearColor.");
522+
523+
CADesc->setClearColor(MTL::ClearColor(ColorCV->R, ColorCV->G, ColorCV->B, ColorCV->A));
497524
CADesc->setStoreAction(MTL::StoreActionStore);
498525
Desc->colorAttachments()->setObject(CADesc, 0);
499526

527+
// Depth/stencil attachment.
528+
const auto *DepthCV =
529+
std::get_if<ClearDepthStencil>(&*IS.DepthStencil->Desc.OptimizedClearValue);
530+
if (!DepthCV)
531+
return llvm::createStringError(
532+
std::errc::invalid_argument,
533+
"Depth/stencil clear value must be a ClearDepthStencil.");
534+
535+
auto *DADesc = Desc->depthAttachment();
536+
DADesc->setTexture(IS.DepthStencil->Tex);
537+
DADesc->setLoadAction(MTL::LoadActionClear);
538+
DADesc->setClearDepth(DepthCV->Depth);
539+
DADesc->setStoreAction(MTL::StoreActionDontCare);
540+
541+
auto *SADesc = Desc->stencilAttachment();
542+
SADesc->setTexture(IS.DepthStencil->Tex);
543+
SADesc->setLoadAction(MTL::LoadActionClear);
544+
SADesc->setClearStencil(DepthCV->Stencil);
545+
SADesc->setStoreAction(MTL::StoreActionDontCare);
546+
500547
MTL::RenderCommandEncoder *CmdEncoder =
501548
IS.CmdBuffer->renderCommandEncoder(Desc);
502549

503550
CmdEncoder->setRenderPipelineState(IS.RenderPipeline);
551+
552+
// Configure depth stencil state: depth test enabled, write all, less.
553+
MTL::DepthStencilDescriptor *DSDesc =
554+
MTL::DepthStencilDescriptor::alloc()->init();
555+
DSDesc->setDepthCompareFunction(MTL::CompareFunctionLess);
556+
DSDesc->setDepthWriteEnabled(true);
557+
MTL::DepthStencilState *DSState = Device->newDepthStencilState(DSDesc);
558+
CmdEncoder->setDepthStencilState(DSState);
559+
DSDesc->release();
560+
DSState->release();
561+
504562
// Explicitly set viewport to texture dimensions.
505563
CmdEncoder->setViewport(
506564
MTL::Viewport{0.0, 0.0, (double)Width, (double)Height, 0.0, 1.0});

lib/API/VK/Device.cpp

Lines changed: 29 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ class VulkanDevice : public offloadtest::Device {
510510
VkFramebuffer FrameBuffer = VK_NULL_HANDLE;
511511
std::shared_ptr<VulkanTexture> RenderTarget;
512512
std::shared_ptr<VulkanBuffer> RTReadback;
513-
ImageRef DepthStencil = {0, 0, 0};
513+
std::shared_ptr<VulkanTexture> DepthStencil;
514514
std::optional<ResourceRef> VertexBuffer = std::nullopt;
515515

516516
VkRenderPass RenderPass = VK_NULL_HANDLE;
@@ -1118,46 +1118,12 @@ class VulkanDevice : public offloadtest::Device {
11181118
}
11191119

11201120
llvm::Error createDepthStencil(Pipeline &P, InvocationState &IS) {
1121-
// Create an optimal image used as the depth stencil attachment
1122-
VkImageCreateInfo ImageCi = {};
1123-
ImageCi.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1124-
ImageCi.imageType = getVKImageType(ResourceKind::Texture2D);
1125-
ImageCi.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
1126-
// Use example's height and width
1127-
ImageCi.extent = {
1128-
static_cast<uint32_t>(P.Bindings.RTargetBufferPtr->OutputProps.Width),
1129-
static_cast<uint32_t>(P.Bindings.RTargetBufferPtr->OutputProps.Height),
1130-
1};
1131-
ImageCi.mipLevels = 1;
1132-
ImageCi.arrayLayers = 1;
1133-
ImageCi.samples = VK_SAMPLE_COUNT_1_BIT;
1134-
ImageCi.tiling = VK_IMAGE_TILING_OPTIMAL;
1135-
ImageCi.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1136-
ImageCi.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1137-
if (vkCreateImage(Device, &ImageCi, nullptr, &IS.DepthStencil.Image))
1138-
return llvm::createStringError(std::errc::device_or_resource_busy,
1139-
"Depth stencil creation failed.");
1140-
1141-
// Allocate memory for the image (device local) and bind it to our image
1142-
VkMemoryAllocateInfo MemAlloc{};
1143-
MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1144-
VkMemoryRequirements MemReqs;
1145-
vkGetImageMemoryRequirements(Device, IS.DepthStencil.Image, &MemReqs);
1146-
MemAlloc.allocationSize = MemReqs.size;
1147-
llvm::Expected<uint32_t> MemIdx =
1148-
getMemoryIndex(PhysicalDevice, MemReqs.memoryTypeBits,
1149-
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1150-
if (!MemIdx)
1151-
return MemIdx.takeError();
1152-
1153-
MemAlloc.memoryTypeIndex = *MemIdx;
1154-
if (vkAllocateMemory(Device, &MemAlloc, nullptr, &IS.DepthStencil.Memory))
1155-
return llvm::createStringError(std::errc::not_enough_memory,
1156-
"Depth stencil memory allocation failed.");
1157-
if (vkBindImageMemory(Device, IS.DepthStencil.Image, IS.DepthStencil.Memory,
1158-
0))
1159-
return llvm::createStringError(std::errc::not_enough_memory,
1160-
"Depth stencil memory binding failed.");
1121+
auto TexOrErr = offloadtest::createDepthStencil(
1122+
*this, P.Bindings.RTargetBufferPtr->OutputProps.Width,
1123+
P.Bindings.RTargetBufferPtr->OutputProps.Height);
1124+
if (!TexOrErr)
1125+
return TexOrErr.takeError();
1126+
IS.DepthStencil = std::static_pointer_cast<VulkanTexture>(*TexOrErr);
11611127
return llvm::Error::success();
11621128
}
11631129

@@ -1172,6 +1138,8 @@ class VulkanDevice : public offloadtest::Device {
11721138
if (P.isGraphics()) {
11731139
if (auto Err = createRenderTarget(P, IS))
11741140
return Err;
1141+
// TODO: Always created for graphics pipelines. Consider making this
1142+
// conditional on the pipeline definition.
11751143
if (auto Err = createDepthStencil(P, IS))
11761144
return Err;
11771145

@@ -1655,7 +1623,7 @@ class VulkanDevice : public offloadtest::Device {
16551623
DepthStencilViewCi.subresourceRange.levelCount = 1;
16561624
DepthStencilViewCi.subresourceRange.baseArrayLayer = 0;
16571625
DepthStencilViewCi.subresourceRange.layerCount = 1;
1658-
DepthStencilViewCi.image = IS.DepthStencil.Image;
1626+
DepthStencilViewCi.image = IS.DepthStencil->Image;
16591627
if (vkCreateImageView(Device, &DepthStencilViewCi, nullptr, &Views[1]))
16601628
return llvm::createStringError(
16611629
std::errc::device_or_resource_busy,
@@ -2041,8 +2009,9 @@ class VulkanDevice : public offloadtest::Device {
20412009
VkImageLayout OldLayout,
20422010
VkAccessFlags SrcAccessMask,
20432011
VkPipelineStageFlags SrcStageMask) {
2044-
VkImageAspectFlags AspectMask =
2045-
isDepth(Tex.Desc.Format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
2012+
VkImageAspectFlags AspectMask = isDepth(Tex.Desc.Format)
2013+
? VK_IMAGE_ASPECT_DEPTH_BIT
2014+
: VK_IMAGE_ASPECT_COLOR_BIT;
20462015

20472016
// Transition texture to transfer source.
20482017
VkImageSubresourceRange SubRange = {};
@@ -2213,11 +2182,21 @@ class VulkanDevice : public offloadtest::Device {
22132182
copyResourceDataToDevice(IS, R);
22142183

22152184
if (P.isGraphics()) {
2216-
const auto &CV =
2217-
std::get<ClearColor>(*IS.RenderTarget->Desc.OptimizedClearValue);
2185+
const auto *ColorCV =
2186+
std::get_if<ClearColor>(&*IS.RenderTarget->Desc.OptimizedClearValue);
2187+
if (!ColorCV)
2188+
return llvm::createStringError(
2189+
std::errc::invalid_argument,
2190+
"Render target clear value must be a ClearColor.");
2191+
const auto *DepthCV = std::get_if<ClearDepthStencil>(
2192+
&*IS.DepthStencil->Desc.OptimizedClearValue);
2193+
if (!DepthCV)
2194+
return llvm::createStringError(
2195+
std::errc::invalid_argument,
2196+
"Depth/stencil clear value must be a ClearDepthStencil.");
22182197
VkClearValue ClearValues[2] = {};
2219-
ClearValues[0].color = {{CV.R, CV.G, CV.B, CV.A}};
2220-
ClearValues[1].depthStencil = {1.0f, 0};
2198+
ClearValues[0].color = {{ColorCV->R, ColorCV->G, ColorCV->B, ColorCV->A}};
2199+
ClearValues[1].depthStencil = {DepthCV->Depth, DepthCV->Stencil};
22212200

22222201
VkRenderPassBeginInfo RenderPassBeginInfo = {};
22232202
RenderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@@ -2399,9 +2378,8 @@ class VulkanDevice : public offloadtest::Device {
23992378
vkFreeMemory(Device, IS.VertexBuffer->Host.Memory, nullptr);
24002379
}
24012380
// Render target image and readback buffer are owned by
2402-
// IS.RenderTarget and IS.RTReadback (shared_ptrs).
2403-
vkDestroyImage(Device, IS.DepthStencil.Image, nullptr);
2404-
vkFreeMemory(Device, IS.DepthStencil.Memory, nullptr);
2381+
// Render target, readback buffer, and depth stencil are owned by
2382+
// shared_ptrs (IS.RenderTarget, IS.RTReadback, IS.DepthStencil).
24052383
vkDestroyFramebuffer(Device, IS.FrameBuffer, nullptr);
24062384
vkDestroyRenderPass(Device, IS.RenderPass, nullptr);
24072385
}

0 commit comments

Comments
 (0)