Foundation
Loading...
Searching...
No Matches
CSMipGeneration.hpp
Go to the documentation of this file.
1#pragma once
2#include <Core/Paths.hpp>
4#include <RHICore/Device.hpp>
5#include <Math/Math.hpp>
7{
8 using namespace RenderCore;
17 uint32_t numMips, uint32_t layer = 0)
18 {
19 using namespace Math;
20 for (uint32 i = 1; i < numMips; ++i)
21 {
22 renderer->CreatePass(
23 fmt::format("Mip Gen {} {}", i, name), queue, 0u,
25 {
26 r->BindTextureSampler(self, srcSampler, "sampler");
27 r->BindShader(self, RHIShaderStageBits::Compute, "csMain", Foundation::Core::PathsResolve("Data/Shaders/CSMipGeneration.spv"));
29 if (src != dst)
31 if (i == 1)
32 r->BindTextureSRV(self, src, "srcTexture", RHIPipelineStageBits::ComputeShader,
33 {.format = srcFormat,
34 .range = RHITextureSubresourceRange::Create(srcAspect, 0, 1, layer, 1)});
35 else
36 r->BindTextureSRV(
37 self, dst, "srcTexture", RHIPipelineStageBits::ComputeShader,
38 {.format = dstFormat,
39 .range = RHITextureSubresourceRange::Create(dstAspect, dstMipLevel - 1, 1, layer, 1)});
40 r->BindTextureUAV(
41 self, dst, "dstTexture", RHIPipelineStageBits::ComputeShader,
42 {.format = dstFormat,
44 r->BindPushConstant(self, RHIShaderStageBits::Compute, 0, sizeof(float2));
45 },
47 {
48 RHITexture* dstTex = r->DerefResource(dst).Get<RHITexture*>();
50 r->CmdSetPipeline(self, cmd);
52 if (src != dst)
53 mipIndex--;
54 uint32_t w = std::max(1u, extent.x >> mipIndex);
55 uint32_t h = std::max(1u, extent.y >> mipIndex);
56 r->CmdSetPushConstant(self, cmd, RHIShaderStageBits::Compute, 0, float2{w, h});
57 r->CmdDispatch(self, cmd, {w, h, 1});
58 });
59 }
60 }
69 RHIDeviceSampler::SamplerDesc::Reduction reduction = RHIDeviceSampler::SamplerDesc::Reduction::WeightedAverage)
70 {
71 using namespace Math;
72 struct PushConstants
73 {
74 uint2 extents;
75 uint32_t mips;
76 uint32_t numWorkGroups;
77 };
78 // From ffx_spd.h
79 auto SpdSetup = [](uint2& dispatchThreadGroupCountXY, // CPU side: dispatch thread group count xy
80 uint32_t& numWorkGroups, // GPU side: pass in as constant
81 uint2 extent // width, height
82 )
83 {
84 uint32_t endIndexX = (extent[0] - 1) / 64; // rectInfo[0] = left, rectInfo[2] = width
85 uint32_t endIndexY = (extent[1] - 1) / 64; // rectInfo[1] = top, rectInfo[3] = height
86
89
91 };
92 auto SpdCounter = renderer->CreateResource(
93 fmt::format("{} SPD Atomics", name),
95 .usage = RHIBufferUsageBits::StorageBuffer | RHIBufferUsageBits::TransferDestination,
96 .size = sizeof(uint32_t) * 6,
97 });
98 renderer->CreatePass(
99 name, queue, 0u,
101 {
102 int reductionMode = 0;
103 switch (reduction)
104 {
105 case RHIDeviceSampler::SamplerDesc::Reduction::WeightedAverage:
106 reductionMode = 0;
107 break;
108 case RHIDeviceSampler::SamplerDesc::Reduction::Min:
109 reductionMode = 1;
110 break;
111 case RHIDeviceSampler::SamplerDesc::Reduction::Max:
112 reductionMode = 2;
113 break;
114 }
115 r->BindShader(self, RHIShaderStageBits::Compute, "csMain", Foundation::Core::PathsResolve("Data/Shaders/CSMipGenerationSinglePass.spv"),
117 r->BindPushConstant(self, RHIShaderStageBits::Compute, 0, sizeof(PushConstants));
118 r->BindTextureSampler(self, srcSampler, "srcSampler");
119 r->BindBufferUnordered(self, SpdCounter, RHIPipelineStageBits::ComputeShader, "spdGlobalAtomic");
120 CHECK_MSG(numMips <= 12, "Single Pass CS Mip generation supports up to 12 mips.");
121 CHECK_MSG(numMips > 1, "Single Pass CS Mip generation requires at least 2 mips.");
122 r->BindTextureSRV(self, src, "imgSrc", RHIPipelineStageBits::ComputeShader,
123 {
124 .format = srcFormat,
125 .dimension = RHITextureDimension::E2DArray,
127 });
128 for (uint32_t mip = 1; mip <= 12; mip++)
129 {
130 uint32_t dstMipLevel = mip;
131 if (src != dst)
132 dstMipLevel--;
133 dstMipLevel = std::min(dstMipLevel, numMips - 1);
134 r->BindTextureUAV(
135 self, dst, "imgDst", RHIPipelineStageBits::ComputeShader,
136 {
137 .format = dstFormat,
138 .dimension = RHITextureDimension::E2DArray,
140 });
141 if (mip == 6)
142 r->BindTextureUAV(
143 self, dst, "imgDst6", RHIPipelineStageBits::ComputeShader,
144 {
145 .format = dstFormat,
146 .dimension = RHITextureDimension::E2DArray,
148 });
149 }
150 },
152 {
153 auto* dstTex = r->DerefResource(dst).Get<RHITexture*>();
154 PushConstants pc{.extents = {dstTex->mDesc.extent.x, dstTex->mDesc.extent.y}, .mips = numMips};
155 if (src != dst) // Work starts from src mip 0
156 pc.extents *= 2, pc.mips++;
158 SpdSetup(dispatchThreadGroupCountXY, pc.numWorkGroups, pc.extents);
159 if (r->GetFrame() == 0)
160 {
161 auto* ctr = r->DerefResource(SpdCounter).Get<RHIBuffer*>();
162 cmd->FillBuffer(ctr, 0u);
163 cmd->BeginTransition();
164 cmd->SetBufferTransition(
165 ctr,
166 {
167 .srcAccess = RHIResourceAccessBits::TransferWrite,
168 .dstAccess = RHIResourceAccessBits::ShaderWrite,
169 .srcStage = RHIPipelineStageBits::ComputeShader | RHIPipelineStageBits::Transfer,
170 .dstStage = RHIPipelineStageBits::ComputeShader,
171 });
172 cmd->EndTransition();
173 }
174 r->CmdSetPipeline(self, cmd);
175 r->CmdSetPushConstant(self, cmd, RHIShaderStageBits::Compute, 0, pc);
177 });
178 }
179} // namespace Foundation::RenderUtils
#define CHECK_MSG(expr, format_str,...)
Definition Logging.hpp:62
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: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:153
String PathsResolve(StringView relPath)
Definition Paths.cpp:18
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:164
RHIResourceFormat
Definition Common.hpp:34
Handle ResourceHandle
Definition RenderPass.hpp:11
Handle PassHandle
Definition RenderPass.hpp:10
Definition CSClearBuffer.hpp:6
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:13
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:65
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:187