Foundation
Loading...
Searching...
No Matches
CSMipGeneration.hpp
Go to the documentation of this file.
1#pragma once
3#include "RHICore/Device.hpp"
5{
6 using namespace RenderCore;
15 uint32_t numMips, uint32_t layer = 0)
16 {
17 using namespace Math;
18 for (uint32 i = 1; i < numMips; ++i)
19 {
20 renderer->CreatePass(
21 fmt::format("Mip Gen {} {}", i, name), queue, 0u,
23 {
24 r->BindTextureSampler(self, srcSampler, "sampler");
25 r->BindShader(self, RHIShaderStageBits::Compute, "csMain", "data/shaders/CSMipGeneration.spv");
27 if (src != dst)
29 if (i == 1)
30 r->BindTextureSRV(self, src, "srcTexture", RHIPipelineStageBits::ComputeShader,
31 {.format = srcFormat,
32 .range = RHITextureSubresourceRange::Create(srcAspect, 0, 1, layer, 1)});
33 else
34 r->BindTextureSRV(
35 self, dst, "srcTexture", RHIPipelineStageBits::ComputeShader,
36 {.format = dstFormat,
37 .range = RHITextureSubresourceRange::Create(dstAspect, dstMipLevel - 1, 1, layer, 1)});
38 r->BindTextureUAV(
39 self, dst, "dstTexture", RHIPipelineStageBits::ComputeShader,
40 {.format = dstFormat,
42 r->BindPushConstant(self, RHIShaderStageBits::Compute, 0, sizeof(float2));
43 },
45 {
46 RHITexture* dstTex = r->DerefResource(dst).Get<RHITexture*>();
48 r->CmdSetPipeline(self, cmd);
50 if (src != dst)
51 mipIndex--;
52 uint32_t w = std::max(1u, extent.x >> mipIndex);
53 uint32_t h = std::max(1u, extent.y >> mipIndex);
54 r->CmdSetPushConstant(self, cmd, RHIShaderStageBits::Compute, 0, float2{w, h});
55 r->CmdDispatch(self, cmd, {w, h, 1});
56 });
57 }
58 }
67 RHIDeviceSampler::SamplerDesc::Reduction reduction = RHIDeviceSampler::SamplerDesc::Reduction::WeightedAverage)
68 {
69 using namespace Math;
70 struct PushConstants
71 {
72 uint2 extents;
73 uint mips;
74 uint numWorkGroups;
75 };
76 // From ffx_spd.h
77 auto SpdSetup = [](uint2& dispatchThreadGroupCountXY, // CPU side: dispatch thread group count xy
78 uint& numWorkGroups, // GPU side: pass in as constant
79 uint2 extent // width, height
80 )
81 {
82 uint endIndexX = (extent[0] - 1) / 64; // rectInfo[0] = left, rectInfo[2] = width
83 uint endIndexY = (extent[1] - 1) / 64; // rectInfo[1] = top, rectInfo[3] = height
84
87
89 };
90 auto SpdCounter = renderer->CreateResource(
91 fmt::format("{} SPD Atomics", name),
93 .usage = RHIBufferUsageBits::StorageBuffer | RHIBufferUsageBits::TransferDestination,
94 .size = sizeof(uint) * 6,
95 });
96 renderer->CreatePass(
97 name, queue, 0u,
99 {
100 int reductionMode = 0;
101 switch (reduction)
102 {
103 case RHIDeviceSampler::SamplerDesc::Reduction::WeightedAverage:
104 reductionMode = 0;
105 break;
106 case RHIDeviceSampler::SamplerDesc::Reduction::Min:
107 reductionMode = 1;
108 break;
109 case RHIDeviceSampler::SamplerDesc::Reduction::Max:
110 reductionMode = 2;
111 break;
112 }
113 r->BindShader(self, RHIShaderStageBits::Compute, "csMain", "data/shaders/CSMipGenerationSinglePass.spv",
115 r->BindPushConstant(self, RHIShaderStageBits::Compute, 0, sizeof(PushConstants));
116 r->BindTextureSampler(self, srcSampler, "srcSampler");
117 r->BindBufferUnordered(self, SpdCounter, RHIPipelineStageBits::ComputeShader, "spdGlobalAtomic");
118 CHECK_MSG(numMips <= 12, "Single Pass CS Mip generation supports up to 12 mips.");
119 CHECK_MSG(numMips > 1, "Single Pass CS Mip generation requires at least 2 mips.");
120 r->BindTextureSRV(self, src, "imgSrc", RHIPipelineStageBits::ComputeShader,
121 {
122 .format = srcFormat,
123 .dimension = RHITextureDimension::E2DArray,
125 });
126 for (uint mip = 1; mip <= 12; mip++)
127 {
128 uint32_t dstMipLevel = mip;
129 if (src != dst)
130 dstMipLevel--;
131 dstMipLevel = std::min(dstMipLevel, numMips - 1);
132 r->BindTextureUAV(
133 self, dst, "imgDst", RHIPipelineStageBits::ComputeShader,
134 {
135 .format = dstFormat,
136 .dimension = RHITextureDimension::E2DArray,
138 });
139 if (mip == 6)
140 r->BindTextureUAV(
141 self, dst, "imgDst6", RHIPipelineStageBits::ComputeShader,
142 {
143 .format = dstFormat,
144 .dimension = RHITextureDimension::E2DArray,
146 });
147 }
148 },
150 {
151 auto* dstTex = r->DerefResource(dst).Get<RHITexture*>();
152 PushConstants pc{.extents = {dstTex->mDesc.extent.x, dstTex->mDesc.extent.y}, .mips = numMips};
153 if (src != dst) // Work starts from src mip 0
154 pc.extents *= 2, pc.mips++;
156 SpdSetup(dispatchThreadGroupCountXY, pc.numWorkGroups, pc.extents);
157 if (r->GetFrame() == 0)
158 {
159 auto* ctr = r->DerefResource(SpdCounter).Get<RHIBuffer*>();
160 cmd->FillBuffer(ctr, 0u);
161 cmd->BeginTransition();
162 cmd->SetBufferTransition(
163 ctr,
164 {
165 .srcAccess = RHIResourceAccessBits::TransferWrite,
166 .dstAccess = RHIResourceAccessBits::ShaderWrite,
167 .srcStage = RHIPipelineStageBits::ComputeShader | RHIPipelineStageBits::Transfer,
168 .dstStage = RHIPipelineStageBits::ComputeShader,
169 });
170 cmd->EndTransition();
171 }
172 r->CmdSetPipeline(self, cmd);
173 r->CmdSetPushConstant(self, cmd, RHIShaderStageBits::Compute, 0, pc);
175 });
176 }
177} // namespace Foundation::RenderUtils
#define CHECK_MSG(expr, format_str,...)
Definition Logging.hpp:46
Definition Resource.hpp:57
Definition Command.hpp:42
Definition Resource.hpp:190
const RHITextureDesc mDesc
Definition Resource.hpp:195
Renderer implementing a Frame Graph system with automatic resource tracking and synchronization.
Definition Renderer.hpp:89
Span< const T > AsSpan(T const &data)
Helper to construct one const r-value as a single element span.
Definition Container.hpp:69
std::basic_string_view< char > StringView
Alias for std::basic_string_view<char>
Definition Container.hpp:55
Span< const char > AsBytes(Span< T > data)
Definition Container.hpp:62
T * Construct(Allocator *resource, Args &&...args)
Convenience placement new with object of type T using a Foundation::Core::Allocator.
Definition Allocator.hpp:149
glm::vec< 3, uint32_t > RHIExtent3D
Definition Common.hpp:11
RHIDeviceQueueType
Definition Common.hpp:109
RHIResourceFormat
Definition Common.hpp:20
Handle ResourceHandle
Definition RenderPass.hpp:11
Handle PassHandle
Definition RenderPass.hpp:10
Definition CSClearBuffer.hpp:5
void createCSMipGenerationPasses(Renderer *renderer, StringView name, RHIDeviceQueueType queue, ResourceHandle src, ResourceHandle dst, RHIResourceFormat srcFormat, RHIResourceFormat dstFormat, RHITextureAspectFlagBits srcAspect, RHITextureAspectFlagBits dstAspect, ResourceHandle srcSampler, uint32_t numMips, uint32_t layer=0)
Generates full mip-chain with multiple compute dispatches.
Definition CSMipGeneration.hpp:11
void createCSMipGenerationSinglePass(Renderer *renderer, StringView name, RHIDeviceQueueType queue, ResourceHandle src, ResourceHandle dst, RHIResourceFormat srcFormat, RHIResourceFormat dstFormat, RHITextureAspectFlag srcAspect, RHITextureAspectFlag dstAspect, ResourceHandle srcSampler, uint numMips, uint numLayer=1, RHIDeviceSampler::SamplerDesc::Reduction reduction=RHIDeviceSampler::SamplerDesc::Reduction::WeightedAverage)
Generates full mip-chain with a single compute dispatch.
Definition CSMipGeneration.hpp:63
Definition Resource.hpp:28
RHIBufferUsage usage
How the buffer can be used by the device, initially.
Definition Resource.hpp:31
RHIExtent3D extent
Definition Resource.hpp:120
static RHITextureSubresourceRange Create(RHITextureAspectFlag aspect=RHITextureAspectFlagBits::Color, uint32_t base_mip_level=0, uint32_t mip_count=1, uint32_t base_array_layer=0, uint32_t layer_count=1)
Helper function to create a Subresource Range with default parameters.
Definition Resource.hpp:165
Definition ImGui.cpp:188