Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
RenderPassManager.cpp
Go to the documentation of this file.
1
2
4
12
13#include "GUI/Headers/GUI.h"
28
29namespace Divide {
30
32{
36}
37
40 , _context(context)
41 , _renderPassTimer(&Time::ADD_TIMER("Render Passes"))
42 , _buildCommandBufferTimer(&Time::ADD_TIMER("Build Command Buffers"))
43 , _processGUITimer(&Time::ADD_TIMER("Process GUI"))
44 , _flushCommandBufferTimer(&Time::ADD_TIMER("Flush Command Buffers"))
45 , _postFxRenderTimer(&Time::ADD_TIMER("PostFX Timer"))
46 , _blitToDisplayTimer(&Time::ADD_TIMER("Flush To Display Timer"))
47{
49
50 for (U8 i = 0u; i < to_base(RenderStage::COUNT); ++i)
51 {
52 _processCommandBufferTimer[i] = &Time::ADD_TIMER( Util::StringFormat( "Process Command Buffers [ {} ]", TypeUtil::RenderStageToString( static_cast<RenderStage>(i) ) ).c_str());
54 }
55
58}
59
61{
65}
66
68{
69 const ShaderModuleDescriptor vertModule{ ShaderType::VERTEX, "baseVertexShaders.glsl", "FullScreenQuad" };
70 {
71 const ShaderModuleDescriptor fragModule{ ShaderType::FRAGMENT, "OITComposition.glsl" };
72
73 ShaderProgramDescriptor shaderDescriptor = {};
74 shaderDescriptor._modules.push_back(vertModule);
75 shaderDescriptor._modules.push_back(fragModule);
76
77 {
78 ResourceDescriptor<ShaderProgram> shaderResDesc("OITComposition", shaderDescriptor );
80 }
81 {
82 shaderDescriptor._modules.back()._defines.emplace_back("USE_MSAA_TARGET");
83
84 ResourceDescriptor<ShaderProgram> shaderResMSDesc("OITCompositionMS", shaderDescriptor );
85 _oitCompositionShaderMS = CreateResource(shaderResMSDesc);
86 }
87 }
88 {
89 const Configuration& config = _parent.platformContext().config();
90
91 ShaderModuleDescriptor fragModule{ ShaderType::FRAGMENT, "display.glsl", "ResolveGBuffer"};
92 fragModule._defines.emplace_back(Util::StringFormat("NUM_SAMPLES {}", config.rendering.MSAASamples));
93
94 ResourceDescriptor<ShaderProgram> shaderResolveDesc("GBufferResolveShader");
95 ShaderProgramDescriptor& shaderDescriptor = shaderResolveDesc._propertyDescriptor;
96 shaderDescriptor._modules.push_back(vertModule);
97 shaderDescriptor._modules.push_back(fragModule);
98
99 _gbufferResolveShader = CreateResource(shaderResolveDesc);
100 }
101
102 for (auto& executor : _executors)
103 {
104 if (executor != nullptr)
105 {
107 }
108 }
109}
110
111void RenderPassManager::startRenderTasks(const RenderParams& params, TaskPool& pool, Task* parentTask)
112{
114
116
117 GFXDevice& gfx = _context;
118 for ( auto& state : _renderPassCompleted )
119 {
120 state.store(false);
121 }
122
123 //All of our render passes should run in parallel
124 for (I8 i = to_base(RenderStage::COUNT) - 1; i >= 0; i-- )
125 {
126 RenderPassData& passData = _renderPassData[i];
127 passData._workTask = CreateTask( parentTask,
128 [&, i](const Task& parentTask) {
129 PROFILE_SCOPE("RenderPass: BuildCommandBuffer", Profiler::Category::Scene );
130 PROFILE_TAG("Pass IDX", i);
131
133 GFX::CommandBuffer* cmdBuffer = GFX::Get(cmdBufferHandle);
134
135 passData._memCmd = {};
136 passData._pass->render(params._playerPass, parentTask, *params._sceneRenderState, *cmdBuffer, passData._memCmd);
137
139 cmdBuffer->batch();
140
141 if (!passData._pass->dependencies().empty())
142 {
144 _waitForDependencies.wait(lock, [&]() noexcept
145 {
146 for ( const RenderStage dep : passData._pass->dependencies() )
147 {
148 if ( !_renderPassCompleted[to_base( dep )] )
149 {
150 return false;
151 }
152 }
153
154 return true;
155 });
156 }
157
158 gfx.flushCommandBuffer( MOV(cmdBufferHandle) );
159 _renderPassCompleted[i].store(true);
160
162 _waitForDependencies.notify_all();
163 },
164 false);
165
166 Start(*passData._workTask, pool, TaskPriority::DONT_CARE);
167 }
168}
169
170void RenderPassManager::render(const RenderParams& params)
171{
172 PROFILE_SCOPE_AUTO( Profiler::Category::Scene );
173
174 if (params._parentTimer != nullptr && !params._parentTimer->hasChildTimer(*_renderPassTimer))
175 {
176 params._parentTimer->addChildTimer(*_renderPassTimer);
177 params._parentTimer->addChildTimer(*_postFxRenderTimer);
178 params._parentTimer->addChildTimer(*_flushCommandBufferTimer);
179 }
180
181 GFXDevice& gfx = _context;
182 PlatformContext& context = parent().platformContext();
183 ProjectManager* projectManager = parent().projectManager().get();
184
185 const Camera* cam = Attorney::ProjectManagerRenderPass::playerCamera(projectManager);
186
187 LightPool& activeLightPool = Attorney::ProjectManagerRenderPass::lightPool(projectManager);
188
189 const CameraSnapshot& prevSnapshot = _context.getCameraSnapshot(params._playerPass);
190 _context.setPreviousViewProjectionMatrix( params._playerPass, prevSnapshot._viewMatrix, prevSnapshot._projectionMatrix);
191
192 activeLightPool.preRenderAllPasses(cam);
193
194 Handle<GFX::CommandBuffer> skyLightRenderBufferHandle = GFX::AllocateCommandBuffer( "Sky Light" );
195 Handle<GFX::CommandBuffer> postFXCmdBufferHandle = GFX::AllocateCommandBuffer( "PostFX" );
196 Handle<GFX::CommandBuffer> postRenderBufferHandle = GFX::AllocateCommandBuffer( "Post Render" );
197
198 GFX::CommandBuffer* skyLightRenderBuffer = GFX::Get( skyLightRenderBufferHandle );
199 GFX::CommandBuffer* postFXCmdBuffer = GFX::Get( postFXCmdBufferHandle );
200 GFX::CommandBuffer* postRenderBuffer = GFX::Get( postRenderBufferHandle );
201
202 {
203 Time::ScopedTimer timeCommandsBuild(*_buildCommandBufferTimer);
205 {
206 PROFILE_SCOPE("RenderPassManager::update sky light", Profiler::Category::Scene );
207 gfx.updateSceneDescriptorSet(*skyLightRenderBuffer, memCmd );
208 SceneEnvironmentProbePool::UpdateSkyLight(gfx, *skyLightRenderBuffer, memCmd );
209 }
210
211 const Rect<I32>& targetViewport = params._targetViewport;
212 context.gui().preDraw( gfx, targetViewport, *postFXCmdBuffer, memCmd );
213 {
214 GFX::BeginRenderPassCommand beginRenderPassCmd{};
215 beginRenderPassCmd._name = "Flush Display";
216 beginRenderPassCmd._clearDescriptor[to_base( RTColourAttachmentSlot::SLOT_0 )] = { DefaultColours::BLACK, true };
217 beginRenderPassCmd._descriptor._drawMask[to_base( RTColourAttachmentSlot::SLOT_0 )] = true;
218 beginRenderPassCmd._target = RenderTargetNames::BACK_BUFFER;
219 GFX::EnqueueCommand(*postFXCmdBuffer, beginRenderPassCmd);
220
221 const auto& screenAtt = gfx.renderTargetPool().getRenderTarget(RenderTargetNames::SCREEN)->getAttachment(RTAttachmentType::COLOUR, GFXDevice::ScreenTargets::ALBEDO);
222 const auto& texData = Get(screenAtt->texture())->getView();
223
224 gfx.drawTextureInViewport(texData, screenAtt->_descriptor._sampler, targetViewport, false, false, false, *postFXCmdBuffer );
225
226 {
227 Time::ScopedTimer timeGUIBuffer(*_processGUITimer);
228 Attorney::ProjectManagerRenderPass::drawCustomUI(projectManager, targetViewport, *postFXCmdBuffer, memCmd);
229 if constexpr(Config::Build::ENABLE_EDITOR)
230 {
231 context.editor().drawScreenOverlay(cam, targetViewport, *postFXCmdBuffer, memCmd);
232 }
233 context.gui().draw(gfx, targetViewport, *postFXCmdBuffer, memCmd);
234 projectManager->getEnvProbes()->prepareDebugData();
235 gfx.renderDebugUI(targetViewport, *postFXCmdBuffer, memCmd);
236 }
237
238 GFX::EnqueueCommand<GFX::EndRenderPassCommand>( *postFXCmdBuffer );
239 }
240
241 Attorney::ProjectManagerRenderPass::postRender( projectManager, *postFXCmdBuffer, memCmd );
242 GFX::EnqueueCommand( *postFXCmdBuffer, memCmd );
243 }
244
245 TaskPool& pool = context.taskPool(TaskPoolType::RENDERER);
246 Task* renderTask = CreateTask( TASK_NOP );
247 startRenderTasks(params, pool, renderTask);
248 Start( *renderTask, pool );
249
250 GFX::MemoryBarrierCommand flushMemCmd{};
251 {
252 PROFILE_SCOPE("RenderPassManager::FlushCommandBuffers", Profiler::Category::Scene );
253 Time::ScopedTimer timeCommands(*_flushCommandBufferTimer);
254
255 gfx.flushCommandBuffer(MOV(skyLightRenderBufferHandle));
256
257 { //PostFX should be pretty fast
258 PROFILE_SCOPE( "PostFX: CommandBuffer build", Profiler::Category::Scene );
259
260 Time::ScopedTimer time( *_postFxRenderTimer );
261 _context.getRenderer().postFX().apply( params._playerPass, cam->snapshot(), *postFXCmdBuffer );
262
263 postFXCmdBuffer->batch();
264 }
265
266 WAIT_FOR_CONDITION( Finished( *renderTask ) );
267
268 if constexpr ( Config::Build::ENABLE_EDITOR )
269 {
270 Attorney::EditorRenderPassExecutor::getCommandBuffer(context.editor(), *postRenderBuffer, flushMemCmd);
271 }
272 _parent.platformContext().idle();
273
274 for ( RenderPassData& passData : _renderPassData )
275 {
276 if ( !GFX::Merge( &flushMemCmd, &passData._memCmd ) )
277 {
278 NOP();
279 }
280 }
281 }
282 {
283 PROFILE_SCOPE( "PostFX: CommandBuffer flush", Profiler::Category::Scene );
284 _context.flushCommandBuffer( MOV(postFXCmdBufferHandle) );
285 }
286 {
287 Time::ScopedTimer time(*_blitToDisplayTimer);
288 GFX::EnqueueCommand( *postRenderBuffer, flushMemCmd );
289 gfx.flushCommandBuffer( MOV(postRenderBufferHandle) );
290 }
291
292 _context.setCameraSnapshot(params._playerPass, cam->snapshot());
293
294 {
295 PROFILE_SCOPE("Executor post-render", Profiler::Category::Scene );
296 Task* sortTask = CreateTask( TASK_NOP );
297 for (auto& executor : _executors)
298 {
299 if ( executor != nullptr )
300 {
301 Start( *CreateTask( sortTask,
302 [&executor](const Task&)
303 {
304 executor->postRender();
305 }), pool);
306 }
307 }
308 Start( *sortTask, pool );
309 Wait( *sortTask, pool );
310 }
311}
312
313RenderPass& RenderPassManager::setRenderPass(const RenderStage renderStage, const vector<RenderStage>& dependencies)
314{
315 DIVIDE_ASSERT(Runtime::isMainThread());
316
317 RenderPass* item = nullptr;
318
319 if (_executors[to_base(renderStage)] == nullptr)
320 {
321 _executors[to_base(renderStage)] = std::make_unique<RenderPassExecutor>(*this, _context, renderStage);
322 _renderPassData[to_base(renderStage)]._pass = std::make_unique<RenderPass>( *this, _context, renderStage, dependencies );
323 }
324
325 item = _renderPassData[to_base( renderStage )]._pass.get();
326 item->dependencies( dependencies );
327 return *item;
328}
329
330U32 RenderPassManager::getLastTotalBinSize(const RenderStage renderStage) const noexcept
331{
332 return getPassForStage(renderStage).getLastTotalBinSize();
333}
334
335const RenderPass& RenderPassManager::getPassForStage(const RenderStage renderStage) const noexcept
336{
337 return *_renderPassData[to_base(renderStage)]._pass;
338}
339
340void RenderPassManager::doCustomPass(Camera* const camera, const RenderPassParams params, GFX::CommandBuffer& bufferInOut, GFX::MemoryBarrierCommand& memCmdInOut)
341{
342 const PlayerIndex playerPass = _parent.projectManager()->playerPass();
343 _executors[to_base(params._stagePass._stage)]->doCustomPass(playerPass, camera, params, bufferInOut, memCmdInOut);
344}
345
346}
#define WAIT_FOR_CONDITION(...)
#define MOV(...)
#define DIVIDE_ASSERT(...)
#define NOP()
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
#define PROFILE_TAG(NAME,...)
Definition: Profiler.h:88
#define PROFILE_SCOPE(NAME, CATEGORY)
Definition: Profiler.h:86
const CameraSnapshot & snapshot() const noexcept
Returns the internal camera snapshot data (eye, orientation, etc)
Definition: Camera.inl:43
void drawScreenOverlay(const Camera *camera, const Rect< I32 > &targetViewport, GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut) const
Render any editor specific element that needs to be part of the scene (e.g. Control Gizmo)
Definition: Editor.cpp:1289
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
Definition: GFXDevice.h:215
void drawTextureInViewport(const ImageView &texture, SamplerDescriptor sampler, const Rect< I32 > &viewport, bool convertToSrgb, bool drawToDepthOnly, bool drawBlend, GFX::CommandBuffer &bufferInOut)
Definition: GFXDevice.cpp:2435
GFXRTPool & renderTargetPool() noexcept
Definition: GFXDevice.inl:133
void renderDebugUI(const Rect< I32 > &targetViewport, GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut)
Definition: GFXDevice.cpp:2461
void updateSceneDescriptorSet(GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut) const
Definition: GFXDevice.cpp:525
void flushCommandBuffer(Handle< GFX::CommandBuffer > &&commandBuffer)
Definition: GFXDevice.cpp:2120
RenderTarget * getRenderTarget(const RenderTargetID target) const
Definition: GFXRTPool.cpp:50
void preDraw(GFXDevice &context, const Rect< I32 > &viewport, GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut)
Render all elements that need their own internal render targets (e.g. CEGUI)
Definition: GUI.cpp:277
void draw(GFXDevice &context, const Rect< I32 > &viewport, GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut)
Go through all of the registered scene gui elements and gather all of the render commands.
Definition: GUI.cpp:302
The kernel is the main system that connects all of our various systems: windows, gfx,...
Definition: Kernel.h:81
FORCE_INLINE PlatformContext & platformContext() noexcept
Definition: Kernel.h:129
void preRenderAllPasses(const Camera *playerCamera)
Definition: LightPool.cpp:537
Editor & editor() noexcept
TaskPool & taskPool(const TaskPoolType type) noexcept
Configuration & config() noexcept
SceneEnvironmentProbePool * getEnvProbes() const noexcept
U32 getLastTotalBinSize() const noexcept
Definition: RenderPass.h:79
Handle< ShaderProgram > _gbufferResolveShader
Handle< ShaderProgram > _oitCompositionShader
Time::ProfileTimer * _processGUITimer
RenderPassManager(Kernel &parent, GFXDevice &context)
void startRenderTasks(const RenderParams &params, TaskPool &pool, Task *parentTask)
Time::ProfileTimer * _buildCommandBufferTimer
Time::ProfileTimer * _flushCommandBufferTimer
Handle< ShaderProgram > _oitCompositionShaderMS
std::array< RenderPassExecutor_uptr, to_base(RenderStage::COUNT)> _executors
Time::ProfileTimer * _renderPassTimer
std::array< std::atomic_bool, to_base(RenderStage::COUNT)> _renderPassCompleted
Time::ProfileTimer * _blitToDisplayTimer
std::array< RenderPassData, to_base(RenderStage::COUNT)> _renderPassData
std::array< Time::ProfileTimer *, to_base(RenderStage::COUNT)> _processCommandBufferTimer
std::condition_variable _waitForDependencies
RTAttachment * getAttachment(RTAttachmentType type, RTColourAttachmentSlot slot=RTColourAttachmentSlot::SLOT_0) const
void addChildTimer(ProfileTimer &child)
bool hasChildTimer(const ProfileTimer &child) const
FColour4 WHITE
Random stuff added for convenience.
Definition: Colours.cpp:8
CommandBuffer * Get(Handle< CommandBuffer > handle)
Handle< CommandBuffer > AllocateCommandBuffer(const char *name, const size_t reservedCmdCount)
constexpr Optick::Category::Type Scene
Definition: Profiler.h:66
ProfileTimer & ADD_TIMER(const char *timerName)
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
std::lock_guard< mutex > LockGuard
Definition: SharedMutex.h:55
FORCE_INLINE void DestroyResource(Handle< T > &handle, const bool immediate=false)
static constexpr U32 RT_DEPTH_ATTACHMENT_IDX
Definition: RTAttachment.h:71
void Wait(const Task &task, TaskPool &pool)
Definition: Task.cpp:20
void SetDefaultDrawDescriptor(RenderPassParams &params)
uint8_t U8
Task * CreateTask(Predicate &&threadedFunction, bool allowedInIdle=true)
Definition: TaskPool.inl:45
bool Finished(const Task &task) noexcept
Definition: Task.inl:38
constexpr auto TASK_NOP
Definition: Task.h:57
std::unique_lock< mutex > UniqueLock
Definition: SharedMutex.h:52
eastl::vector< Type > vector
Definition: Vector.h:42
Project & parent
Definition: DefaultScene.h:41
FORCE_INLINE Handle< T > CreateResource(const ResourceDescriptor< T > &descriptor, bool &wasInCache, std::atomic_uint &taskCounter)
void Start(Task &task, TaskPool &pool, TaskPriority priority=TaskPriority::DONT_CARE, const DELEGATE< void > &onCompletionFunction={})
Definition: Task.cpp:9
RTClearEntry DEFAULT_CLEAR_ENTRY
FORCE_INLINE T * Get(const Handle< T > handle)
uint32_t U32
constexpr auto to_base(const Type value) -> Type
mat4< F32 > _projectionMatrix
struct Divide::Configuration::Rendering rendering
vector< ShaderModuleDescriptor > _modules
RTClearDescriptor _clearDescriptorPrePass
RTDrawDescriptor _targetDescriptorMainPass
RTClearDescriptor _clearDescriptorMainPass
PropertyDescriptor< T > _propertyDescriptor
Definition: Resource.h:151