Foundation
Loading...
Searching...
No Matches
CSMipGeneration.hpp
Go to the documentation of this file.
1#pragma once
3#include <RHICore/Device.hpp>
4#include <Math/Math.hpp>
6{
7 using namespace RenderCore;
14 RHIResourceFormat dstFormat, RHITextureAspectFlagBits srcAspect,
15 RHITextureAspectFlagBits dstAspect, ResourceHandle srcSampler,
16 uint32_t numMips, uint32_t layer = 0)
17 {
18 using namespace Math;
19 for (uint32 i = 1; i < numMips; ++i)
20 {
21 renderer->CreatePass(
22 Format("Mip Gen {} {}", i, name), queue, 0u,
23 [=](PassHandle self, Renderer* r)
24 {
25 r->BindTextureSampler(self, srcSampler, "sampler");
26 r->BindShader(self, RHIShaderStageBits::Compute, "csMain", r->GetApplication()->ResolveRelativePathBase("Data/Shaders/CSMipGeneration.spv"));
27 uint32_t dstMipLevel = i;
28 if (src != dst)
29 dstMipLevel--;
30 if (i == 1)
31 r->BindTextureSRV(self, src, "srcTexture", RHIPipelineStageBits::ComputeShader,
32 {.format = srcFormat,
33 .range = RHITextureSubresourceRange::Create(srcAspect, 0, 1, layer, 1)});
34 else
36 self, dst, "srcTexture", RHIPipelineStageBits::ComputeShader,
37 {.format = dstFormat,
38 .range = RHITextureSubresourceRange::Create(dstAspect, dstMipLevel - 1, 1, layer, 1)});
40 self, dst, "dstTexture", RHIPipelineStageBits::ComputeShader,
41 {.format = dstFormat,
42 .range = RHITextureSubresourceRange::Create(dstAspect, dstMipLevel, 1, layer, 1)});
43 r->BindPushConstant(self, RHIShaderStageBits::Compute, 0, sizeof(float2));
44 },
45 [=](PassHandle self, Renderer* r, RHICommandList* cmd)
46 {
47 RHITexture* dstTex = r->DerefResource(dst).Get<RHITexture*>();
48 RHIExtent3D extent = dstTex->mDesc.extent;
49 r->CmdSetPipeline(self, cmd);
50 uint32_t mipIndex = i;
51 if (src != dst)
52 mipIndex--;
53 uint32_t w = std::max(1u, extent.x >> mipIndex);
54 uint32_t h = std::max(1u, extent.y >> mipIndex);
55 r->CmdSetPushConstant(self, cmd, RHIShaderStageBits::Compute, 0, float2{w, h});
56 r->CmdDispatch(self, cmd, {w, h, 1});
57 });
58 }
59 }
66 RHIResourceFormat srcFormat, RHIResourceFormat dstFormat, RHITextureAspectFlag srcAspect,
67 RHITextureAspectFlag dstAspect, ResourceHandle srcSampler, uint32_t numMips, uint32_t numLayer = 1,
68 RHIDeviceSampler::SamplerDesc::Reduction reduction = RHIDeviceSampler::SamplerDesc::Reduction::WeightedAverage)
69 {
70 using namespace Math;
71 struct PushConstants
72 {
73 uint2 extents;
74 uint32_t mips;
75 uint32_t numWorkGroups;
76 };
77 // From ffx_spd.h
78 auto SpdSetup = [](uint2& dispatchThreadGroupCountXY, // CPU side: dispatch thread group count xy
79 uint32_t& numWorkGroups, // GPU side: pass in as constant
80 uint2 extent // width, height
81 )
82 {
83 uint32_t endIndexX = (extent[0] - 1) / 64; // rectInfo[0] = left, rectInfo[2] = width
84 uint32_t endIndexY = (extent[1] - 1) / 64; // rectInfo[1] = top, rectInfo[3] = height
85
86 dispatchThreadGroupCountXY[0] = endIndexX + 1;
87 dispatchThreadGroupCountXY[1] = endIndexY + 1;
88
89 numWorkGroups = (dispatchThreadGroupCountXY[0]) * (dispatchThreadGroupCountXY[1]);
90 };
91 auto SpdCounter = renderer->CreateResource(
92 Format("{} SPD Atomics", name),
94 .usage = RHIBufferUsageBits::StorageBuffer | RHIBufferUsageBits::TransferDestination,
95 .size = sizeof(uint32_t) * 6,
96 });
97 renderer->CreatePass(
98 name, queue, 0u,
99 [=](PassHandle self, Renderer* r)
100 {
101 int reductionMode = 0;
102 switch (reduction)
103 {
104 case RHIDeviceSampler::SamplerDesc::Reduction::WeightedAverage:
105 reductionMode = 0;
106 break;
107 case RHIDeviceSampler::SamplerDesc::Reduction::Min:
108 reductionMode = 1;
109 break;
110 case RHIDeviceSampler::SamplerDesc::Reduction::Max:
111 reductionMode = 2;
112 break;
113 }
114 r->BindShader(self, RHIShaderStageBits::Compute, "csMain", r->GetApplication()->ResolveRelativePathBase("Data/Shaders/CSMipGenerationSinglePass.spv"),
115 AsBytes(AsSpan(reductionMode)));
116 r->BindPushConstant(self, RHIShaderStageBits::Compute, 0, sizeof(PushConstants));
117 r->BindTextureSampler(self, srcSampler, "srcSampler");
118 r->BindBufferUnordered(self, SpdCounter, RHIPipelineStageBits::ComputeShader, "spdGlobalAtomic");
119 CHECK_MSG(numMips <= 12, "Single Pass CS Mip version supports up to 12 mips.");
120 CHECK_MSG(numMips > 1, "Single Pass CS Mip version requires at least 2 mips.");
121 r->BindTextureSRV(self, src, "imgSrc", RHIPipelineStageBits::ComputeShader,
122 {
123 .format = srcFormat,
124 .dimension = RHITextureDimension::E2DArray,
125 .range = RHITextureSubresourceRange::Create(srcAspect, 0, 1, 0, numLayer),
126 });
127 for (uint32_t mip = 1; mip <= 12; mip++)
128 {
129 uint32_t dstMipLevel = mip;
130 if (src != dst)
131 dstMipLevel--;
132 dstMipLevel = std::min(dstMipLevel, numMips - 1);
134 self, dst, "imgDst", RHIPipelineStageBits::ComputeShader,
135 {
136 .format = dstFormat,
137 .dimension = RHITextureDimension::E2DArray,
138 .range = RHITextureSubresourceRange::Create(dstAspect, dstMipLevel, 1, 0, numLayer),
139 });
140 if (mip == 6)
142 self, dst, "imgDst6", RHIPipelineStageBits::ComputeShader,
143 {
144 .format = dstFormat,
145 .dimension = RHITextureDimension::E2DArray,
146 .range = RHITextureSubresourceRange::Create(dstAspect, dstMipLevel, 1, 0, numLayer),
147 });
148 }
149 },
150 [=](PassHandle self, Renderer* r, RHICommandList* cmd)
151 {
152 auto* dstTex = r->DerefResource(dst).Get<RHITexture*>();
153 PushConstants pc{.extents = {dstTex->mDesc.extent.x, dstTex->mDesc.extent.y}, .mips = numMips};
154 if (src != dst) // Work starts from src mip 0
155 pc.extents *= 2, pc.mips++;
156 uint2 dispatchThreadGroupCountXY;
157 SpdSetup(dispatchThreadGroupCountXY, pc.numWorkGroups, pc.extents);
158 if (r->GetFrame() == 0)
159 {
160 auto* ctr = r->DerefResource(SpdCounter).Get<RHIBuffer*>();
161 cmd->FillBuffer(ctr, 0u);
162 cmd->BeginTransition();
163 cmd->SetBufferTransition(
164 ctr,
165 {
166 .srcAccess = RHIResourceAccessBits::TransferWrite,
167 .dstAccess = RHIResourceAccessBits::ShaderWrite,
168 .srcStage = RHIPipelineStageBits::ComputeShader | RHIPipelineStageBits::Transfer,
169 .dstStage = RHIPipelineStageBits::ComputeShader,
170 });
171 cmd->EndTransition();
172 }
173 r->CmdSetPipeline(self, cmd);
174 r->CmdSetPushConstant(self, cmd, RHIShaderStageBits::Compute, 0, pc);
175 cmd->Dispatch(dispatchThreadGroupCountXY.x, dispatchThreadGroupCountXY.y, 1);
176 });
177 }
178} // namespace Foundation::RenderUtils
#define CHECK_MSG(expr, format_str,...)
virtual String ResolveRelativePathBase(StringView path="") const =0
Retrives path relative to the application executable.
Definition Resource.hpp:57
Definition Command.hpp:42
Definition Resource.hpp:216
const RHITextureDesc mDesc
Definition Resource.hpp:221
Renderer implementing a Frame Graph system with automatic resource tracking and synchronization.
Definition Renderer.hpp:377
PassHandle CreatePass(StringView name, RHIDeviceQueueType queue, size_t priority, FSetup &&setup, FRecord &&record)
Create a render pass from a Setup(Renderer*, PassHandle) and Record(Renderer*, PassHandle,...
Definition Renderer.hpp:680
Variant< RHIBuffer *, RHITexture *, RHIAccelerationStructure * > DerefResource(const ResourceHandle handle) const
Dereference a resource handle to its underlying RHI resource.
Definition Renderer.hpp:1068
void BindTextureSRV(PassHandle pass, ResourceHandle texture, StringView bind_point, RHIPipelineStage stage, RHITextureViewDesc const &desc) const
Binds a texture as a Shader Resource View (read-only sampling / fetch).
Definition Renderer.cpp:351
void BindTextureSampler(PassHandle pass, ResourceHandle sampler, StringView bind_point) const
Binds a sampler to the shader.
Definition Renderer.cpp:303
const RHIApplication * GetApplication() const
Get the RHIApplication this Renderer was constructed with.
Definition Renderer.hpp:1034
void CmdDispatch(PassHandle pass, RHICommandList *cmd, RHIExtent3D thread_size) const
Helper that dispatches a compute shader with the specified THREAD count.
Definition Renderer.cpp:2272
void CmdSetPipeline(PassHandle pass, RHICommandList *cmd) const
Helper that sets the current pass's PSO and descriptor sets to the current command list.
Definition Renderer.cpp:2174
void BindTextureUAV(PassHandle pass, ResourceHandle texture, StringView bind_point, RHIPipelineStage stage, RHITextureViewDesc const &desc) const
Binds a texture for unordered (UAV) read-write access in shaders.
Definition Renderer.cpp:364
void BindPushConstant(PassHandle pass, RHIShaderStage stage, size_t offset, size_t size) const
Declares a range of Push Constant used in a stage.
Definition Renderer.cpp:241
void BindBufferUnordered(PassHandle pass, ResourceHandle buffer, RHIPipelineStage stage, StringView bind_point) const
Binds a buffer for unordered (UAV) access from shaders (read and/or write in any order).
Definition Renderer.cpp:270
void BindShader(PassHandle pass, RHIShaderStage stage, StringView entry_point, StringView shader_path, Span< const char > specializationData={}, uint32_t rtHitGroupIndex=0, RHIPipelineState::PipelineStateDesc::RayTracingHitGroupType rtHitGroupType=RHIPipelineState::PipelineStateDesc::RayTracingHitGroupType::Triangles) const
Binds shader file path to a certain pass at a certain stage.
Definition Renderer.cpp:221
void CmdSetPushConstant(PassHandle pass, RHICommandList *cmd, RHIShaderStage stage, size_t offset, T const &data)
Helper that sets a Push Constant range data with a single l-value.
Definition Renderer.hpp:1184
uint64_t GetFrame() const
Retrieves the current frame number.
Definition Renderer.hpp:1208
ResourceHandle CreateResource(StringView name, T const &desc)
Create a new resource to be used in the render graph.
Definition Renderer.hpp:705
constexpr String Format(fmt::format_string< Args... > format, Args &&... args)
String wrapper for Format().
Definition Container.hpp:126
Span< const T > AsSpan(T const &data)
Helper to construct one const r-value as a single element span.
Definition Container.hpp:73
std::basic_string_view< char > StringView
Alias for std::basic_string_view<char>
Definition Container.hpp:56
Span< const char > AsBytes(Span< T > data)
Definition Container.hpp:65
vec2 float2
Definition Math.hpp:27
uvec2 uint2
Definition Math.hpp:33
glm::vec< 3, uint32_t > RHIExtent3D
Definition Common.hpp:11
RHIDeviceQueueType
Definition Common.hpp:179
RHIResourceFormat
Definition Common.hpp:34
Handle ResourceHandle
Definition Renderer.hpp:22
Handle PassHandle
Definition Renderer.hpp:21
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:12
void createCSMipGenerationSinglePass(Renderer *renderer, StringView name, RHIDeviceQueueType queue, ResourceHandle src, ResourceHandle dst, RHIResourceFormat srcFormat, RHIResourceFormat dstFormat, RHITextureAspectFlag srcAspect, RHITextureAspectFlag dstAspect, ResourceHandle srcSampler, uint32_t numMips, uint32_t numLayer=1, RHIDeviceSampler::SamplerDesc::Reduction reduction=RHIDeviceSampler::SamplerDesc::Reduction::WeightedAverage)
Generates full mip-chain with a single compute dispatch.
Definition CSMipGeneration.hpp:64
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:146
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:191
Definition ImGui.cpp:179