Skip to content

Commit f6ac12e

Browse files
committed
Use newly added Texture API for depth stencil target. Add depth stencil support to both MTL and DX backend to align with behaviour of VK backend
1 parent 6bb2b65 commit f6ac12e

5 files changed

Lines changed: 130 additions & 89 deletions

File tree

include/API/Device.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ initializeDevices(const DeviceConfig Config);
109109
llvm::Expected<std::shared_ptr<Texture>>
110110
createRenderTargetFromCPUBuffer(Device &Dev, const CPUBuffer &Buf);
111111

112+
// Creates a depth/stencil texture matching the dimensions of a render target.
113+
llvm::Expected<std::shared_ptr<Texture>>
114+
createDefaultDepthStencilTarget(Device &Dev, uint32_t Width, uint32_t Height);
115+
112116
} // namespace offloadtest
113117

114118
#endif // OFFLOADTEST_API_DEVICE_H

lib/API/DX/Device.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,7 @@ class DXDevice : public offloadtest::Device {
450450
// Resources for graphics pipelines.
451451
std::shared_ptr<DXTexture> RT;
452452
std::shared_ptr<DXBuffer> RTReadback;
453+
std::shared_ptr<DXTexture> DS;
453454
ComPtr<ID3D12Resource> VB;
454455

455456
llvm::SmallVector<DescriptorTable> DescTables;
@@ -1570,6 +1571,16 @@ class DXDevice : public offloadtest::Device {
15701571
return llvm::Error::success();
15711572
}
15721573

1574+
llvm::Error createDepthStencil(Pipeline &P, InvocationState &IS) {
1575+
auto TexOrErr = offloadtest::createDefaultDepthStencilTarget(
1576+
*this, P.Bindings.RTargetBufferPtr->OutputProps.Width,
1577+
P.Bindings.RTargetBufferPtr->OutputProps.Height);
1578+
if (!TexOrErr)
1579+
return TexOrErr.takeError();
1580+
IS.DS = std::static_pointer_cast<DXTexture>(*TexOrErr);
1581+
return llvm::Error::success();
1582+
}
1583+
15731584
llvm::Error createVertexBuffer(Pipeline &P, InvocationState &IS) {
15741585
if (!P.Bindings.VertexBufferPtr)
15751586
return llvm::createStringError(
@@ -1645,8 +1656,11 @@ class DXDevice : public offloadtest::Device {
16451656

16461657
PSODesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
16471658
PSODesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
1648-
PSODesc.DepthStencilState.DepthEnable = false;
1659+
PSODesc.DepthStencilState.DepthEnable = true;
1660+
PSODesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
1661+
PSODesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS;
16491662
PSODesc.DepthStencilState.StencilEnable = false;
1663+
PSODesc.DSVFormat = getDXGIFormat(IS.DS->Desc.Format);
16501664
PSODesc.SampleMask = UINT_MAX;
16511665
PSODesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
16521666
PSODesc.NumRenderTargets = 1;
@@ -1675,6 +1689,16 @@ class DXDevice : public offloadtest::Device {
16751689
IS.CmdList->OMSetRenderTargets(1, &IS.RT->ViewHandle, false,
16761690
&IS.DS->ViewHandle);
16771691

1692+
const auto *DepthCV =
1693+
std::get_if<ClearDepthStencil>(&*IS.DS->Desc.OptimizedClearValue);
1694+
if (!DepthCV)
1695+
return llvm::createStringError(
1696+
std::errc::invalid_argument,
1697+
"Depth/stencil clear value must be a ClearDepthStencil.");
1698+
IS.CmdList->ClearDepthStencilView(
1699+
IS.DS->ViewHandle, D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL,
1700+
DepthCV->Depth, DepthCV->Stencil, 0, nullptr);
1701+
16781702
D3D12_VIEWPORT VP = {};
16791703
VP.Width =
16801704
static_cast<float>(P.Bindings.RTargetBufferPtr->OutputProps.Width);
@@ -1812,10 +1836,16 @@ class DXDevice : public offloadtest::Device {
18121836
llvm::outs() << "Compute command list created.\n";
18131837

18141838
} else {
1815-
// Create render target, readback and vertex buffer and PSO.
1839+
// Create render target, depth/stencil, readback and vertex buffer and
1840+
// PSO.
18161841
if (auto Err = createRenderTarget(P, State))
18171842
return Err;
18181843
llvm::outs() << "Render target created.\n";
1844+
// TODO: Always created for graphics pipelines. Consider making this
1845+
// conditional on the pipeline definition.
1846+
if (auto Err = createDepthStencil(P, State))
1847+
return Err;
1848+
llvm::outs() << "Depth stencil created.\n";
18191849
if (auto Err = createVertexBuffer(P, State))
18201850
return Err;
18211851
llvm::outs() << "Vertex buffer created.\n";

lib/API/Device.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,17 @@ offloadtest::createRenderTargetFromCPUBuffer(Device &Dev,
6969
return Dev.createTexture("RenderTarget", Desc);
7070
}
7171

72+
llvm::Expected<std::shared_ptr<Texture>>
73+
offloadtest::createDefaultDepthStencilTarget(Device &Dev, uint32_t Width,
74+
uint32_t Height) {
75+
TextureCreateDesc Desc = {};
76+
Desc.Location = MemoryLocation::GpuOnly;
77+
Desc.Usage = TextureUsage::DepthStencil;
78+
Desc.Format = Format::D32FloatS8Uint;
79+
Desc.Width = Width;
80+
Desc.Height = Height;
81+
Desc.MipLevels = 1;
82+
Desc.OptimizedClearValue = ClearDepthStencil{1.0f, 0};
83+
84+
return Dev.createTexture("DepthStencil", Desc);
85+
}

lib/API/MTL/MTLDevice.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,12 @@ class MTLDevice : public offloadtest::Device {
316316
MTL::RenderPipelineColorAttachmentDescriptor::alloc()->init();
317317
RPCA->setPixelFormat(PF);
318318
Desc->colorAttachments()->setObject(RPCA, 0);
319+
320+
// Set the depth/stencil format on the pipeline descriptor.
321+
const MTL::PixelFormat DepthFmt =
322+
getMetalPixelFormat(Format::D32FloatS8Uint);
323+
Desc->setDepthAttachmentPixelFormat(DepthFmt);
324+
Desc->setStencilAttachmentPixelFormat(DepthFmt);
319325
}
320326

321327
IS.RenderPipeline = Device->newRenderPipelineState(Desc, &Error);
@@ -505,6 +511,17 @@ class MTLDevice : public offloadtest::Device {
505511
if (!BufOrErr)
506512
return BufOrErr.takeError();
507513
IS.FrameBufferReadback = std::static_pointer_cast<MTLBuffer>(*BufOrErr);
514+
515+
return llvm::Error::success();
516+
}
517+
518+
llvm::Error createDepthStencil(Pipeline &P, InvocationState &IS) {
519+
auto TexOrErr = offloadtest::createDefaultDepthStencilTarget(
520+
*this, P.Bindings.RTargetBufferPtr->OutputProps.Width,
521+
P.Bindings.RTargetBufferPtr->OutputProps.Height);
522+
if (!TexOrErr)
523+
return TexOrErr.takeError();
524+
IS.DepthStencil = std::static_pointer_cast<MTLTexture>(*TexOrErr);
508525
return llvm::Error::success();
509526
}
510527

@@ -513,6 +530,11 @@ class MTLDevice : public offloadtest::Device {
513530

514531
if (auto Err = createRenderTarget(P, IS))
515532
return Err;
533+
// TODO: Always created for graphics pipelines. Consider making this
534+
// conditional on the pipeline definition.
535+
if (auto Err = createDepthStencil(P, IS))
536+
return Err;
537+
516538
MTL::RenderPassDescriptor *Desc =
517539
MTL::RenderPassDescriptor::alloc()->init();
518540

@@ -535,10 +557,41 @@ class MTLDevice : public offloadtest::Device {
535557
CADesc->setStoreAction(MTL::StoreActionStore);
536558
Desc->colorAttachments()->setObject(CADesc, 0);
537559

560+
// Depth/stencil attachment.
561+
const auto *DepthCV = std::get_if<ClearDepthStencil>(
562+
&*IS.DepthStencil->Desc.OptimizedClearValue);
563+
if (!DepthCV)
564+
return llvm::createStringError(
565+
std::errc::invalid_argument,
566+
"Depth/stencil clear value must be a ClearDepthStencil.");
567+
568+
auto *DADesc = Desc->depthAttachment();
569+
DADesc->setTexture(IS.DepthStencil->Tex);
570+
DADesc->setLoadAction(MTL::LoadActionClear);
571+
DADesc->setClearDepth(DepthCV->Depth);
572+
DADesc->setStoreAction(MTL::StoreActionDontCare);
573+
574+
auto *SADesc = Desc->stencilAttachment();
575+
SADesc->setTexture(IS.DepthStencil->Tex);
576+
SADesc->setLoadAction(MTL::LoadActionClear);
577+
SADesc->setClearStencil(DepthCV->Stencil);
578+
SADesc->setStoreAction(MTL::StoreActionDontCare);
579+
538580
MTL::RenderCommandEncoder *CmdEncoder =
539581
IS.CmdBuffer->renderCommandEncoder(Desc);
540582

541583
CmdEncoder->setRenderPipelineState(IS.RenderPipeline);
584+
585+
// Configure depth stencil state: depth test enabled, write all, less.
586+
MTL::DepthStencilDescriptor *DSDesc =
587+
MTL::DepthStencilDescriptor::alloc()->init();
588+
DSDesc->setDepthCompareFunction(MTL::CompareFunctionLess);
589+
DSDesc->setDepthWriteEnabled(true);
590+
MTL::DepthStencilState *DSState = Device->newDepthStencilState(DSDesc);
591+
CmdEncoder->setDepthStencilState(DSState);
592+
DSDesc->release();
593+
DSState->release();
594+
542595
// Explicitly set viewport to texture dimensions.
543596
CmdEncoder->setViewport(
544597
MTL::Viewport{0.0, 0.0, (double)Width, (double)Height, 0.0, 1.0});

lib/API/VK/Device.cpp

Lines changed: 27 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -570,9 +570,9 @@ class VulkanDevice : public offloadtest::Device {
570570

571571
// FrameBuffer associated data for offscreen rendering.
572572
VkFramebuffer FrameBuffer = VK_NULL_HANDLE;
573-
ImageRef DepthStencil = {0, 0, 0};
574573
std::shared_ptr<VulkanTexture> RenderTarget;
575574
std::shared_ptr<VulkanBuffer> RTReadback;
575+
std::shared_ptr<VulkanTexture> DepthStencil;
576576
std::optional<ResourceRef> VertexBuffer = std::nullopt;
577577

578578
VkRenderPass RenderPass = VK_NULL_HANDLE;
@@ -1215,46 +1215,12 @@ class VulkanDevice : public offloadtest::Device {
12151215
}
12161216

12171217
llvm::Error createDepthStencil(Pipeline &P, InvocationState &IS) {
1218-
// Create an optimal image used as the depth stencil attachment
1219-
VkImageCreateInfo ImageCi = {};
1220-
ImageCi.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1221-
ImageCi.imageType = getVKImageType(ResourceKind::Texture2D);
1222-
ImageCi.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
1223-
// Use example's height and width
1224-
ImageCi.extent = {
1225-
static_cast<uint32_t>(P.Bindings.RTargetBufferPtr->OutputProps.Width),
1226-
static_cast<uint32_t>(P.Bindings.RTargetBufferPtr->OutputProps.Height),
1227-
1};
1228-
ImageCi.mipLevels = 1;
1229-
ImageCi.arrayLayers = 1;
1230-
ImageCi.samples = VK_SAMPLE_COUNT_1_BIT;
1231-
ImageCi.tiling = VK_IMAGE_TILING_OPTIMAL;
1232-
ImageCi.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1233-
ImageCi.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1234-
if (vkCreateImage(Device, &ImageCi, nullptr, &IS.DepthStencil.Image))
1235-
return llvm::createStringError(std::errc::device_or_resource_busy,
1236-
"Depth stencil creation failed.");
1237-
1238-
// Allocate memory for the image (device local) and bind it to our image
1239-
VkMemoryAllocateInfo MemAlloc{};
1240-
MemAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1241-
VkMemoryRequirements MemReqs;
1242-
vkGetImageMemoryRequirements(Device, IS.DepthStencil.Image, &MemReqs);
1243-
MemAlloc.allocationSize = MemReqs.size;
1244-
llvm::Expected<uint32_t> MemIdx =
1245-
getMemoryIndex(PhysicalDevice, MemReqs.memoryTypeBits,
1246-
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1247-
if (!MemIdx)
1248-
return MemIdx.takeError();
1249-
1250-
MemAlloc.memoryTypeIndex = *MemIdx;
1251-
if (vkAllocateMemory(Device, &MemAlloc, nullptr, &IS.DepthStencil.Memory))
1252-
return llvm::createStringError(std::errc::not_enough_memory,
1253-
"Depth stencil memory allocation failed.");
1254-
if (vkBindImageMemory(Device, IS.DepthStencil.Image, IS.DepthStencil.Memory,
1255-
0))
1256-
return llvm::createStringError(std::errc::not_enough_memory,
1257-
"Depth stencil memory binding failed.");
1218+
auto TexOrErr = offloadtest::createDefaultDepthStencilTarget(
1219+
*this, P.Bindings.RTargetBufferPtr->OutputProps.Width,
1220+
P.Bindings.RTargetBufferPtr->OutputProps.Height);
1221+
if (!TexOrErr)
1222+
return TexOrErr.takeError();
1223+
IS.DepthStencil = std::static_pointer_cast<VulkanTexture>(*TexOrErr);
12581224
return llvm::Error::success();
12591225
}
12601226

@@ -1657,7 +1623,7 @@ class VulkanDevice : public offloadtest::Device {
16571623
Attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
16581624
Attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
16591625

1660-
Attachments[1].format = VK_FORMAT_D32_SFLOAT_S8_UINT;
1626+
Attachments[1].format = getVulkanFormat(IS.DepthStencil->Desc.Format);
16611627
Attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
16621628
Attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
16631629
Attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
@@ -1727,53 +1693,17 @@ class VulkanDevice : public offloadtest::Device {
17271693
return llvm::Error::success();
17281694
}
17291695

1730-
llvm::Error createFrameBuffer(Pipeline &P, InvocationState &IS) {
1731-
std::array<VkImageView, 2> Views = {};
1732-
VkImageViewCreateInfo ViewCreateInfo = {};
1733-
ViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1734-
ViewCreateInfo.viewType = getImageViewType(ResourceKind::Texture2D);
1735-
ViewCreateInfo.format = getVKFormat(P.Bindings.RTargetBufferPtr->Format,
1736-
P.Bindings.RTargetBufferPtr->Channels);
1737-
ViewCreateInfo.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
1738-
VK_COMPONENT_SWIZZLE_B,
1739-
VK_COMPONENT_SWIZZLE_A};
1740-
ViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1741-
ViewCreateInfo.subresourceRange.baseMipLevel = 0;
1742-
ViewCreateInfo.subresourceRange.baseArrayLayer = 0;
1743-
ViewCreateInfo.subresourceRange.layerCount = 1;
1744-
ViewCreateInfo.subresourceRange.levelCount = 1;
1745-
ViewCreateInfo.image = IS.FrameBufferResource.ResourceRefs[0].Image.Image;
1746-
if (vkCreateImageView(Device, &ViewCreateInfo, nullptr, &Views[0]))
1747-
return llvm::createStringError(
1748-
std::errc::device_or_resource_busy,
1749-
"Failed to create frame buffer image view.");
1750-
IS.ImageViews.push_back(Views[0]);
1751-
1752-
VkImageViewCreateInfo DepthStencilViewCi = {};
1753-
DepthStencilViewCi.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1754-
DepthStencilViewCi.viewType = getImageViewType(ResourceKind::Texture2D);
1755-
DepthStencilViewCi.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
1756-
DepthStencilViewCi.subresourceRange = {};
1757-
DepthStencilViewCi.subresourceRange.aspectMask =
1758-
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1759-
DepthStencilViewCi.subresourceRange.baseMipLevel = 0;
1760-
DepthStencilViewCi.subresourceRange.levelCount = 1;
1761-
DepthStencilViewCi.subresourceRange.baseArrayLayer = 0;
1762-
DepthStencilViewCi.subresourceRange.layerCount = 1;
1763-
DepthStencilViewCi.image = IS.DepthStencil.Image;
1764-
if (vkCreateImageView(Device, &DepthStencilViewCi, nullptr, &Views[1]))
1765-
return llvm::createStringError(
1766-
std::errc::device_or_resource_busy,
1767-
"Failed to create depth stencil image view.");
1768-
IS.ImageViews.push_back(Views[1]);
1696+
llvm::Error createFrameBuffer(InvocationState &IS) {
1697+
std::array<VkImageView, 2> Views = {IS.RenderTarget->View,
1698+
IS.DepthStencil->View};
17691699

17701700
VkFramebufferCreateInfo FbufCreateInfo = {};
17711701
FbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
17721702
FbufCreateInfo.renderPass = IS.RenderPass;
17731703
FbufCreateInfo.attachmentCount = Views.size();
17741704
FbufCreateInfo.pAttachments = Views.data();
1775-
FbufCreateInfo.width = P.Bindings.RTargetBufferPtr->OutputProps.Width;
1776-
FbufCreateInfo.height = P.Bindings.RTargetBufferPtr->OutputProps.Height;
1705+
FbufCreateInfo.width = IS.RenderTarget->Desc.Width;
1706+
FbufCreateInfo.height = IS.RenderTarget->Desc.Height;
17771707
FbufCreateInfo.layers = 1;
17781708

17791709
if (vkCreateFramebuffer(Device, &FbufCreateInfo, nullptr, &IS.FrameBuffer))
@@ -2319,9 +2249,21 @@ class VulkanDevice : public offloadtest::Device {
23192249
copyResourceDataToDevice(IS, R);
23202250

23212251
if (P.isGraphics()) {
2252+
const auto *ColorCV =
2253+
std::get_if<ClearColor>(&*IS.RenderTarget->Desc.OptimizedClearValue);
2254+
if (!ColorCV)
2255+
return llvm::createStringError(
2256+
std::errc::invalid_argument,
2257+
"Render target clear value must be a ClearColor.");
2258+
const auto *DepthCV = std::get_if<ClearDepthStencil>(
2259+
&*IS.DepthStencil->Desc.OptimizedClearValue);
2260+
if (!DepthCV)
2261+
return llvm::createStringError(
2262+
std::errc::invalid_argument,
2263+
"Depth/stencil clear value must be a ClearDepthStencil.");
23222264
VkClearValue ClearValues[2] = {};
2323-
ClearValues[0].color = {{0.0f, 0.0f, 0.0f, 0.0f}};
2324-
ClearValues[1].depthStencil = {1.0f, 0};
2265+
ClearValues[0].color = {{ColorCV->R, ColorCV->G, ColorCV->B, ColorCV->A}};
2266+
ClearValues[1].depthStencil = {DepthCV->Depth, DepthCV->Stencil};
23252267

23262268
VkRenderPassBeginInfo RenderPassBeginInfo = {};
23272269
RenderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
@@ -2502,8 +2444,6 @@ class VulkanDevice : public offloadtest::Device {
25022444
vkDestroyBuffer(Device, IS.VertexBuffer->Host.Buffer, nullptr);
25032445
vkFreeMemory(Device, IS.VertexBuffer->Host.Memory, nullptr);
25042446
}
2505-
vkDestroyImage(Device, IS.DepthStencil.Image, nullptr);
2506-
vkFreeMemory(Device, IS.DepthStencil.Memory, nullptr);
25072447
vkDestroyFramebuffer(Device, IS.FrameBuffer, nullptr);
25082448
vkDestroyRenderPass(Device, IS.RenderPass, nullptr);
25092449
}

0 commit comments

Comments
 (0)