Skip to content

Commit 62c07cb

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 b4678a8 commit 62c07cb

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
@@ -105,8 +105,6 @@ llvm::Expected<std::shared_ptr<Texture>>
105105
createRenderTarget(Device &Dev, const CPUBuffer &Buf);
106106

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

lib/API/DX/Device.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,9 @@ class DXDevice : public offloadtest::Device {
358358
// Resources for graphics pipelines.
359359
std::shared_ptr<DXTexture> RT;
360360
std::shared_ptr<DXBuffer> RTReadback;
361+
std::shared_ptr<DXTexture> DS;
361362
ComPtr<ID3D12DescriptorHeap> RTVHeap;
363+
ComPtr<ID3D12DescriptorHeap> DSVHeap;
362364
ComPtr<ID3D12Resource> VB;
363365

364366
llvm::SmallVector<DescriptorTable> DescTables;
@@ -1471,6 +1473,16 @@ class DXDevice : public offloadtest::Device {
14711473
return llvm::Error::success();
14721474
}
14731475

1476+
llvm::Error createDepthStencil(Pipeline &P, InvocationState &IS) {
1477+
auto TexOrErr = offloadtest::createDepthStencil(
1478+
*this, P.Bindings.RTargetBufferPtr->OutputProps.Width,
1479+
P.Bindings.RTargetBufferPtr->OutputProps.Height);
1480+
if (!TexOrErr)
1481+
return TexOrErr.takeError();
1482+
IS.DS = std::static_pointer_cast<DXTexture>(*TexOrErr);
1483+
return llvm::Error::success();
1484+
}
1485+
14741486
llvm::Error createVertexBuffer(Pipeline &P, InvocationState &IS) {
14751487
if (!P.Bindings.VertexBufferPtr)
14761488
return llvm::createStringError(
@@ -1546,8 +1558,11 @@ class DXDevice : public offloadtest::Device {
15461558

15471559
PSODesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
15481560
PSODesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
1549-
PSODesc.DepthStencilState.DepthEnable = false;
1561+
PSODesc.DepthStencilState.DepthEnable = true;
1562+
PSODesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
1563+
PSODesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
15501564
PSODesc.DepthStencilState.StencilEnable = false;
1565+
PSODesc.DSVFormat = getDXGIFormat(IS.DS->Desc.Format);
15511566
PSODesc.SampleMask = UINT_MAX;
15521567
PSODesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
15531568
PSODesc.NumRenderTargets = 1;
@@ -1579,6 +1594,19 @@ class DXDevice : public offloadtest::Device {
15791594
IS.RTVHeap->GetCPUDescriptorHandleForHeapStart();
15801595
Device->CreateRenderTargetView(IS.RT->Resource.Get(), nullptr, RTVHandle);
15811596

1597+
// Create descriptor heap and view for the depth/stencil buffer.
1598+
D3D12_DESCRIPTOR_HEAP_DESC DSVHeapDesc = {};
1599+
DSVHeapDesc.NumDescriptors = 1;
1600+
DSVHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
1601+
DSVHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
1602+
if (auto Err = HR::toError(Device->CreateDescriptorHeap(
1603+
&DSVHeapDesc, IID_PPV_ARGS(&IS.DSVHeap)),
1604+
"Failed to create DSV heap"))
1605+
return Err;
1606+
const D3D12_CPU_DESCRIPTOR_HANDLE DSVHandle =
1607+
IS.DSVHeap->GetCPUDescriptorHandleForHeapStart();
1608+
Device->CreateDepthStencilView(IS.DS->Resource.Get(), nullptr, DSVHandle);
1609+
15821610
IS.CmdList->SetGraphicsRootSignature(IS.RootSig.Get());
15831611
if (IS.DescHeap) {
15841612
ID3D12DescriptorHeap *const Heaps[] = {IS.DescHeap.Get()};
@@ -1588,7 +1616,17 @@ class DXDevice : public offloadtest::Device {
15881616
}
15891617
IS.CmdList->SetPipelineState(IS.PSO.Get());
15901618

1591-
IS.CmdList->OMSetRenderTargets(1, &RTVHandle, false, nullptr);
1619+
IS.CmdList->OMSetRenderTargets(1, &RTVHandle, false, &DSVHandle);
1620+
1621+
const auto *DepthCV =
1622+
std::get_if<ClearDepthStencil>(&*IS.DS->Desc.OptimizedClearValue);
1623+
if (!DepthCV)
1624+
return llvm::createStringError(
1625+
std::errc::invalid_argument,
1626+
"Depth/stencil clear value must be a ClearDepthStencil.");
1627+
IS.CmdList->ClearDepthStencilView(
1628+
DSVHandle, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL,
1629+
DepthCV->Depth, DepthCV->Stencil, 0, nullptr);
15921630

15931631
D3D12_VIEWPORT VP = {};
15941632
VP.Width =
@@ -1725,10 +1763,15 @@ class DXDevice : public offloadtest::Device {
17251763
llvm::outs() << "Compute command list created.\n";
17261764

17271765
} else {
1728-
// Create render target, readback and vertex buffer and PSO.
1766+
// Create render target, depth/stencil, readback and vertex buffer and PSO.
17291767
if (auto Err = createRenderTarget(P, State))
17301768
return Err;
17311769
llvm::outs() << "Render target created.\n";
1770+
// TODO: Always created for graphics pipelines. Consider making this
1771+
// conditional on the pipeline definition.
1772+
if (auto Err = createDepthStencil(P, State))
1773+
return Err;
1774+
llvm::outs() << "Depth stencil created.\n";
17321775
if (auto Err = createVertexBuffer(P, State))
17331776
return Err;
17341777
llvm::outs() << "Vertex buffer created.\n";

lib/API/Device.cpp

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

110110
llvm::Expected<std::shared_ptr<Texture>>
111-
createDepthStencil(Device &Dev, uint32_t Width, uint32_t Height) {
111+
offloadtest::createDepthStencil(Device &Dev, uint32_t Width, uint32_t Height) {
112112
TextureCreateDesc Desc = {};
113113
Desc.Location = MemoryLocation::GpuOnly;
114114
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);
@@ -475,31 +482,82 @@ class MTLDevice : public offloadtest::Device {
475482
return llvm::Error::success();
476483
}
477484

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

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

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

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

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

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

502549
CmdEncoder->setRenderPipelineState(IS.RenderPipeline);
550+
551+
// Configure depth stencil state: depth test enabled, write all, less.
552+
MTL::DepthStencilDescriptor *DSDesc =
553+
MTL::DepthStencilDescriptor::alloc()->init();
554+
DSDesc->setDepthCompareFunction(MTL::CompareFunctionLess);
555+
DSDesc->setDepthWriteEnabled(true);
556+
MTL::DepthStencilState *DSState = Device->newDepthStencilState(DSDesc);
557+
CmdEncoder->setDepthStencilState(DSState);
558+
DSDesc->release();
559+
DSState->release();
560+
503561
// Explicitly set viewport to texture dimensions.
504562
CmdEncoder->setViewport(
505563
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
@@ -474,7 +474,7 @@ class VulkanDevice : public offloadtest::Device {
474474
VkFramebuffer FrameBuffer;
475475
std::shared_ptr<VulkanTexture> RenderTarget;
476476
std::shared_ptr<VulkanBuffer> RTReadback;
477-
ImageRef DepthStencil = {0, 0, 0};
477+
std::shared_ptr<VulkanTexture> DepthStencil;
478478
std::optional<ResourceRef> VertexBuffer = std::nullopt;
479479

480480
VkRenderPass RenderPass;
@@ -1070,46 +1070,12 @@ class VulkanDevice : public offloadtest::Device {
10701070
}
10711071

10721072
llvm::Error createDepthStencil(Pipeline &P, InvocationState &IS) {
1073-
// Create an optimal image used as the depth stencil attachment
1074-
VkImageCreateInfo ImageCi = {};
1075-
ImageCi.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1076-
ImageCi.imageType = VK_IMAGE_TYPE_2D;
1077-
ImageCi.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
1078-
// Use example's height and width
1079-
ImageCi.extent = {
1080-
static_cast<uint32_t>(P.Bindings.RTargetBufferPtr->OutputProps.Width),
1081-
static_cast<uint32_t>(P.Bindings.RTargetBufferPtr->OutputProps.Height),
1082-
1};
1083-
ImageCi.mipLevels = 1;
1084-
ImageCi.arrayLayers = 1;
1085-
ImageCi.samples = VK_SAMPLE_COUNT_1_BIT;
1086-
ImageCi.tiling = VK_IMAGE_TILING_OPTIMAL;
1087-
ImageCi.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1088-
ImageCi.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1089-
if (vkCreateImage(Device, &ImageCi, nullptr, &IS.DepthStencil.Image))
1090-
return llvm::createStringError(std::errc::device_or_resource_busy,
1091-
"Depth stencil creation failed.");
1092-
1093-
// Allocate memory for the image (device local) and bind it to our image
1094-
VkMemoryAllocateInfo MemAlloc{};
1095-
MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1096-
VkMemoryRequirements MemReqs;
1097-
vkGetImageMemoryRequirements(Device, IS.DepthStencil.Image, &MemReqs);
1098-
MemAlloc.allocationSize = MemReqs.size;
1099-
llvm::Expected<uint32_t> MemIdx =
1100-
getMemoryIndex(PhysicalDevice, MemReqs.memoryTypeBits,
1101-
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1102-
if (!MemIdx)
1103-
return MemIdx.takeError();
1104-
1105-
MemAlloc.memoryTypeIndex = *MemIdx;
1106-
if (vkAllocateMemory(Device, &MemAlloc, nullptr, &IS.DepthStencil.Memory))
1107-
return llvm::createStringError(std::errc::not_enough_memory,
1108-
"Depth stencil memory allocation failed.");
1109-
if (vkBindImageMemory(Device, IS.DepthStencil.Image, IS.DepthStencil.Memory,
1110-
0))
1111-
return llvm::createStringError(std::errc::not_enough_memory,
1112-
"Depth stencil memory binding failed.");
1073+
auto TexOrErr = offloadtest::createDepthStencil(
1074+
*this, P.Bindings.RTargetBufferPtr->OutputProps.Width,
1075+
P.Bindings.RTargetBufferPtr->OutputProps.Height);
1076+
if (!TexOrErr)
1077+
return TexOrErr.takeError();
1078+
IS.DepthStencil = std::static_pointer_cast<VulkanTexture>(*TexOrErr);
11131079
return llvm::Error::success();
11141080
}
11151081

@@ -1124,6 +1090,8 @@ class VulkanDevice : public offloadtest::Device {
11241090
if (P.isGraphics()) {
11251091
if (auto Err = createRenderTarget(P, IS))
11261092
return Err;
1093+
// TODO: Always created for graphics pipelines. Consider making this
1094+
// conditional on the pipeline definition.
11271095
if (auto Err = createDepthStencil(P, IS))
11281096
return Err;
11291097

@@ -1607,7 +1575,7 @@ class VulkanDevice : public offloadtest::Device {
16071575
DepthStencilViewCi.subresourceRange.levelCount = 1;
16081576
DepthStencilViewCi.subresourceRange.baseArrayLayer = 0;
16091577
DepthStencilViewCi.subresourceRange.layerCount = 1;
1610-
DepthStencilViewCi.image = IS.DepthStencil.Image;
1578+
DepthStencilViewCi.image = IS.DepthStencil->Image;
16111579
if (vkCreateImageView(Device, &DepthStencilViewCi, nullptr, &Views[1]))
16121580
return llvm::createStringError(
16131581
std::errc::device_or_resource_busy,
@@ -1993,8 +1961,9 @@ class VulkanDevice : public offloadtest::Device {
19931961
VkImageLayout OldLayout,
19941962
VkAccessFlags SrcAccessMask,
19951963
VkPipelineStageFlags SrcStageMask) {
1996-
VkImageAspectFlags AspectMask =
1997-
isDepth(Tex.Desc.Format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
1964+
VkImageAspectFlags AspectMask = isDepth(Tex.Desc.Format)
1965+
? VK_IMAGE_ASPECT_DEPTH_BIT
1966+
: VK_IMAGE_ASPECT_COLOR_BIT;
19981967

19991968
// Transition texture to transfer source.
20001969
VkImageSubresourceRange SubRange = {};
@@ -2165,11 +2134,21 @@ class VulkanDevice : public offloadtest::Device {
21652134
copyResourceDataToDevice(IS, R);
21662135

21672136
if (P.isGraphics()) {
2168-
const auto &CV =
2169-
std::get<ClearColor>(*IS.RenderTarget->Desc.OptimizedClearValue);
2137+
const auto *ColorCV =
2138+
std::get_if<ClearColor>(&*IS.RenderTarget->Desc.OptimizedClearValue);
2139+
if (!ColorCV)
2140+
return llvm::createStringError(
2141+
std::errc::invalid_argument,
2142+
"Render target clear value must be a ClearColor.");
2143+
const auto *DepthCV = std::get_if<ClearDepthStencil>(
2144+
&*IS.DepthStencil->Desc.OptimizedClearValue);
2145+
if (!DepthCV)
2146+
return llvm::createStringError(
2147+
std::errc::invalid_argument,
2148+
"Depth/stencil clear value must be a ClearDepthStencil.");
21702149
VkClearValue ClearValues[2] = {};
2171-
ClearValues[0].color = {{CV.R, CV.G, CV.B, CV.A}};
2172-
ClearValues[1].depthStencil = {1.0f, 0};
2150+
ClearValues[0].color = {{ColorCV->R, ColorCV->G, ColorCV->B, ColorCV->A}};
2151+
ClearValues[1].depthStencil = {DepthCV->Depth, DepthCV->Stencil};
21732152

21742153
VkRenderPassBeginInfo RenderPassBeginInfo = {};
21752154
RenderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@@ -2346,9 +2325,8 @@ class VulkanDevice : public offloadtest::Device {
23462325
vkFreeMemory(Device, IS.VertexBuffer->Host.Memory, nullptr);
23472326
}
23482327
// Render target image and readback buffer are owned by
2349-
// IS.RenderTarget and IS.RTReadback (shared_ptrs).
2350-
vkDestroyImage(Device, IS.DepthStencil.Image, nullptr);
2351-
vkFreeMemory(Device, IS.DepthStencil.Memory, nullptr);
2328+
// Render target, readback buffer, and depth stencil are owned by
2329+
// shared_ptrs (IS.RenderTarget, IS.RTReadback, IS.DepthStencil).
23522330
vkDestroyFramebuffer(Device, IS.FrameBuffer, nullptr);
23532331
vkDestroyRenderPass(Device, IS.RenderPass, nullptr);
23542332
}

0 commit comments

Comments
 (0)