Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
Renderer.cpp
Go to the documentation of this file.
1
2
3#include "Headers/Renderer.h"
4
8
11
13
18
19namespace Divide {
20
21 namespace
22 {
23 constexpr bool g_rebuildLightGridEachFrame = false;
24 }
25
28{
29 const Configuration& config = context.config();
33
34 ShaderModuleDescriptor computeDescriptor = {};
35 computeDescriptor._moduleType = ShaderType::COMPUTE;
36
37 {
38 computeDescriptor._sourceFile = "lightCull.glsl";
39 ShaderProgramDescriptor cullDescritpor = {};
40 cullDescritpor._modules.push_back(computeDescriptor);
41
42 ResourceDescriptor<ShaderProgram> cullShaderDesc("lightCull", cullDescritpor );
44
45 PipelineDescriptor pipelineDescriptor = {};
49 }
50 {
51 ShaderProgramDescriptor cullDescritpor = {};
52 computeDescriptor._variant = "ResetCounter";
53 cullDescritpor._modules.push_back(computeDescriptor);
54
55 ResourceDescriptor<ShaderProgram> cullShaderDesc("lightCounterReset", cullDescritpor );
57
58 PipelineDescriptor pipelineDescriptor = {};
62 }
63 {
64 computeDescriptor._sourceFile = "lightBuildClusteredAABBs.glsl";
65 computeDescriptor._variant = "";
66 ShaderProgramDescriptor buildDescritpor = {};
67 buildDescritpor._modules.push_back(computeDescriptor);
68 buildDescritpor._globalDefines.emplace_back( "inverseProjectionMatrix PushData0" );
69 buildDescritpor._globalDefines.emplace_back( "viewport ivec4(PushData1[0])" );
70 buildDescritpor._globalDefines.emplace_back( "_zPlanes PushData1[1].xy" );
71 _lightBuildClusteredAABBsComputeShader = CreateResource( ResourceDescriptor<ShaderProgram>( "lightBuildClusteredAABBs", buildDescritpor ) );
72
73 PipelineDescriptor pipelineDescriptor = {};
77 }
78
79 ShaderBufferDescriptor bufferDescriptor = {};
80 bufferDescriptor._ringBufferLength = 1;
84
85 { //Light Index Buffer
86 const U32 totalLights = numClusters * to_U32(config.rendering.numLightsPerCluster);
87 bufferDescriptor._bufferParams._elementCount = totalLights;
88 bufferDescriptor._bufferParams._elementSize = sizeof(U32);
89 for (U8 i = 0u; i < to_base(RenderStage::COUNT) - 1; ++i) {
90 Util::StringFormat( bufferDescriptor._name, "LIGHT_INDEX_SSBO_{}", TypeUtil::RenderStageToString(static_cast<RenderStage>(i)));
91 _lightDataPerStage[i]._lightIndexBuffer = _context.gfx().newSB(bufferDescriptor);
92 }
93 }
94 { // Cluster AABBs
95 bufferDescriptor._bufferParams._elementCount = numClusters;
96 bufferDescriptor._bufferParams._elementSize = 2 * (4 * sizeof(F32));
97 for (U8 i = 0u; i < to_base(RenderStage::COUNT) - 1; ++i) {
98 Util::StringFormat( bufferDescriptor._name, "GLOBAL_CLUSTER_AABB_SSBO_{}", TypeUtil::RenderStageToString(static_cast<RenderStage>(i)));
99 _lightDataPerStage[i]._lightClusterAABBsBuffer = _context.gfx().newSB(bufferDescriptor);
100 }
101 }
102 { // Light Grid Buffer
103 bufferDescriptor._bufferParams._elementCount = numClusters;
104 bufferDescriptor._bufferParams._elementSize = sizeof(vec4<U32>);
105 for (U8 i = 0u; i < to_base(RenderStage::COUNT) - 1; ++i) {
106 Util::StringFormat( bufferDescriptor._name, "LIGHT_GRID_SSBO_{}", TypeUtil::RenderStageToString(static_cast<RenderStage>(i)));
107 _lightDataPerStage[i]._lightGridBuffer = _context.gfx().newSB(bufferDescriptor);
108 }
109 }
110
111 { // Global Index Count
112 bufferDescriptor._bufferParams._elementCount = 1u;
113 bufferDescriptor._bufferParams._elementSize = sizeof(vec4<U32>);
114 for (U8 i = 0u; i < to_base(RenderStage::COUNT) - 1; ++i) {
115 Util::StringFormat( bufferDescriptor._name, "GLOBAL_INDEX_COUNT_SSBO_{}", TypeUtil::RenderStageToString(static_cast<RenderStage>(i)));
116 _lightDataPerStage[i]._globalIndexCountBuffer = _context.gfx().newSB(bufferDescriptor);
117 }
118 }
119
120 _postFX = std::make_unique<PostFX>(context);
121
122 if (config.rendering.postFX.postAA.qualityLevel > 0) {
124 }
125 if (config.rendering.postFX.ssr.enabled) {
127 }
128 if (config.rendering.postFX.ssao.enable) {
130 }
131 if (config.rendering.postFX.dof.enabled) {
133 }
136 }
137 if (config.rendering.postFX.bloom.enabled) {
139 }
140
143}
144
146{
150}
151
153 const Rect<I32>& viewport,
154 const CameraSnapshot& cameraSnapshot,
155 GFX::CommandBuffer& bufferInOut)
156{
157 if (stage == RenderStage::SHADOW) {
158 // Nothing to do in the shadow pass
159 return;
160 }
161
163
164 GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>(bufferInOut)->_scopeName = "Renderer Cull Lights";
165 {
167 {
168 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>( bufferInOut );
169 cmd->_usage = DescriptorSetUsage::PER_PASS;
170
171 const size_t stageIndex = to_size( stage );
172 {
174 Set(binding._data, LightPool::SceneBuffer(), {stageIndex, 1u});
175 }
176 {
178 Set(binding._data, LightPool::LightBuffer(), {stageIndex * Config::Lighting::MAX_ACTIVE_LIGHTS_PER_FRAME, Config::Lighting::MAX_ACTIVE_LIGHTS_PER_FRAME } );
179 }
180 {
182 Set(binding._data, data._lightIndexBuffer.get(), { 0u, data._lightIndexBuffer->getPrimitiveCount() } );
183 }
184 {
186 Set(binding._data, data._lightGridBuffer.get(), { 0u, data._lightGridBuffer->getPrimitiveCount() } );
187 }
188 {
190 Set(binding._data, data._lightClusterAABBsBuffer.get(), { 0u, data._lightClusterAABBsBuffer->getPrimitiveCount() } );
191 }
192 {
194 Set(binding._data, data._globalIndexCountBuffer.get(), { 0u, data._globalIndexCountBuffer->getPrimitiveCount() } );
195 }
196 }
197 {
198 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
199 cmd->_usage = DescriptorSetUsage::PER_DRAW;
200 }
201
202 {
203 GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>( bufferInOut )->_scopeName = "Renderer Reset Global Index Count";
204
205 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_bufferLocks.emplace_back( BufferLock
206 {
207 ._range = { 0u, U32_MAX },
209 ._buffer = data._globalIndexCountBuffer->getBufferImpl()
210 });
212 GFX::EnqueueCommand<GFX::DispatchComputeCommand>( bufferInOut )->_computeGroupSize = { 1u, 1u, 1u };
213 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_bufferLocks.emplace_back( BufferLock
214 {
215 ._range = { 0u, U32_MAX },
217 ._buffer = data._globalIndexCountBuffer->getBufferImpl()
218 });
219
220 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>( bufferInOut );
221 }
222
223 bool needRebuild = data._invalidated || g_rebuildLightGridEachFrame;
224 if (!needRebuild )
225 {
227 tempData._invProjectionMatrix = cameraSnapshot._invProjectionMatrix;
228 tempData._viewport = viewport;
229 tempData._zPlanes = cameraSnapshot._zPlanes;
230
231 needRebuild = data._gridData != tempData;
232 if (needRebuild)
233 {
234 data._gridData = tempData;
235 }
236 }
237
238 if ( needRebuild )
239 {
240 data._invalidated = false;
241
242 GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>( bufferInOut )->_scopeName = "Renderer Rebuild Light Grid";
243
244 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_bufferLocks.emplace_back( BufferLock
245 {
246 ._range = { 0u, U32_MAX },
248 ._buffer = data._lightClusterAABBsBuffer->getBufferImpl()
249 });
250
252 PushConstantsStruct& pushConstants = GFX::EnqueueCommand<GFX::SendPushConstantsCommand>( bufferInOut )->_fastData;
253 pushConstants.data[0] = data._gridData._invProjectionMatrix;
254 pushConstants.data[1]._vec[0] = data._gridData._viewport;
255 pushConstants.data[1]._vec[1].xy = data._gridData._zPlanes;
256 GFX::EnqueueCommand<GFX::DispatchComputeCommand>(bufferInOut)->_computeGroupSize =
257 {
261 };
262
263 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_bufferLocks.emplace_back( BufferLock
264 {
265 ._range = { 0u, U32_MAX },
267 ._buffer = data._lightClusterAABBsBuffer->getBufferImpl()
268 });
269
270 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>( bufferInOut );
271 }
272
273
274 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_bufferLocks.emplace_back( BufferLock
275 {
276 ._range = { 0u, U32_MAX },
278 ._buffer = data._lightGridBuffer->getBufferImpl()
279 });
280
282 GFX::EnqueueCommand<GFX::DispatchComputeCommand>(bufferInOut)->_computeGroupSize =
283 {
287 };
288
289 {
290 auto memCmd = GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut );
291 memCmd->_bufferLocks.emplace_back( BufferLock
292 {
293 ._range = { 0u, U32_MAX },
295 ._buffer = data._lightGridBuffer->getBufferImpl()
296 });
297 memCmd->_bufferLocks.emplace_back( BufferLock
298 {
299 ._range = { 0u, U32_MAX },
301 ._buffer = data._lightIndexBuffer->getBufferImpl()
302 });
303 memCmd->_bufferLocks.emplace_back( BufferLock
304 {
305 ._range = { 0u, U32_MAX },
307 ._buffer = data._globalIndexCountBuffer->getBufferImpl()
308 });
309 }
310 }
311
312 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>(bufferInOut);
313}
314
315void Renderer::idle(const U64 deltaTimeUSGame) const
316{
318
319 _postFX->idle(_context.config(), deltaTimeUSGame);
320}
321
322void Renderer::updateResolution(const U16 newWidth, const U16 newHeight) const {
323 _postFX->updateResolution(newWidth, newHeight);
324}
325
327{
328 return _zPlanes != other._zPlanes ||
329 _viewport != other._viewport ||
330 _invProjectionMatrix != other._invProjectionMatrix;
331}
332
333} //namespace Divide
#define WAIT_FOR_CONDITION(...)
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
ShaderBuffer_uptr newSB(const ShaderBufferDescriptor &descriptor)
Definition: GFXDevice.inl:214
Pipeline * newPipeline(const PipelineDescriptor &descriptor)
Create and return a new graphics pipeline. This is only used for caching and doesn't use the object a...
Definition: GFXDevice.cpp:3074
static ShaderBuffer * LightBuffer()
Definition: LightPool.h:196
static ShaderBuffer * SceneBuffer()
Definition: LightPool.h:197
PlatformContext & context() noexcept
GFXDevice & gfx() noexcept
Configuration & config() noexcept
void updateResolution(U16 newWidth, U16 newHeight) const
Definition: Renderer.cpp:322
Renderer(PlatformContext &context)
Definition: Renderer.cpp:26
Handle< ShaderProgram > _lightCullComputeShader
Definition: Renderer.h:84
Handle< ShaderProgram > _lightCounterResetComputeShader
Definition: Renderer.h:85
void idle(const U64 deltaTimeUSGame) const
Definition: Renderer.cpp:315
void prepareLighting(RenderStage stage, const Rect< I32 > &viewport, const CameraSnapshot &cameraSnapshot, GFX::CommandBuffer &bufferInOut)
Definition: Renderer.cpp:152
std::array< PerRenderStageData, to_base(RenderStage::COUNT) - 1 > _lightDataPerStage
Definition: Renderer.h:82
Handle< ShaderProgram > _lightBuildClusteredAABBsComputeShader
Definition: Renderer.h:86
GFX::BindPipelineCommand _lightCullPipelineCmd
Definition: Renderer.h:89
GFX::BindPipelineCommand _lightResetCounterPipelineCmd
Definition: Renderer.h:90
PostFX_uptr _postFX
Definition: Renderer.h:87
GFX::BindPipelineCommand _lightBuildClusteredAABBsPipelineCmd
Definition: Renderer.h:91
~Renderer() override
Definition: Renderer.cpp:145
vec4< T > _vec[4]
Definition: MathMatrices.h:709
vec2< T > xy
Definition: MathVectors.h:1366
constexpr U8 CLUSTERS_X
Controls compute shader dispatch. e.g. Dispatch Z count = CLUSTERS_Z / CLUSTERS_Z_THREADS.
Definition: config.h:170
FORCE_INLINE T * EnqueueCommand(CommandBuffer &buffer)
constexpr Optick::Category::Type Graphics
Definition: Profiler.h:60
const char * RenderStageToString(const RenderStage stage) noexcept
Definition: GFXDevice.cpp:54
Str StringFormat(const char *fmt, Args &&...args)
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U32 to_U32(const T value)
FORCE_INLINE void DestroyResource(Handle< T > &handle, const bool immediate=false)
uint8_t U8
uint16_t U16
void Set(DescriptorSetBindingData &dataInOut, ShaderBuffer *buffer, const BufferRange range) noexcept
DescriptorSetBinding & AddBinding(DescriptorSet &setInOut, U8 slot, U16 stageVisibilityMask)
FORCE_INLINE Handle< T > CreateResource(const ResourceDescriptor< T > &descriptor, bool &wasInCache, std::atomic_uint &taskCounter)
constexpr U32 U32_MAX
constexpr size_t to_size(const T value)
uint32_t U32
uint64_t U64
constexpr auto to_base(const Type value) -> Type
BufferUpdateUsage _updateUsage
Definition: BufferParams.h:40
BufferUsageType _usageType
Definition: BufferParams.h:41
BufferUpdateFrequency _updateFrequency
Definition: BufferParams.h:39
BufferRange _range
Definition: BufferLocks.h:57
size_t _elementSize
Buffer primitive size in bytes.
Definition: BufferParams.h:50
BufferFlags _flags
Definition: BufferParams.h:48
mat4< F32 > _invProjectionMatrix
bool enabled
bool enabled
bool enablePerObject
U8 qualityLevel
bool enable
bool enabled
struct Divide::Configuration::Rendering::PostFX::SSAO ssao
struct Divide::Configuration::Rendering::PostFX::DOF dof
struct Divide::Configuration::Rendering::PostFX::MotionBlur motionBlur
struct Divide::Configuration::Rendering::PostFX::PostAA postAA
struct Divide::Configuration::Rendering::PostFX::Bloom bloom
struct Divide::Configuration::Rendering::PostFX::SSR ssr
struct Divide::Configuration::Rendering::PostFX postFX
struct Divide::Configuration::Rendering rendering
DescriptorSetBindingData _data
PrimitiveTopology _primitiveTopology
Definition: Pipeline.h:48
Handle< ShaderProgram > _shaderProgramHandle
Definition: Pipeline.h:47
vector< ShaderModuleDescriptor > _modules
bool operator!=(const GridBuildData &other) const noexcept
Definition: Renderer.cpp:326
ShaderBuffer_uptr _globalIndexCountBuffer
Definition: Renderer.h:77
ShaderBuffer_uptr _lightClusterAABBsBuffer
Definition: Renderer.h:78
ShaderBuffer_uptr _lightGridBuffer
Definition: Renderer.h:76
ShaderBuffer_uptr _lightIndexBuffer
Definition: Renderer.h:75
struct Divide::Renderer::PerRenderStageData::GridBuildData _gridData