Async render passes

This commit is contained in:
2021-11-24 12:10:23 +01:00
parent 94be513538
commit 5fafdda770
23 changed files with 199 additions and 162 deletions
+1 -3
View File
@@ -30,15 +30,13 @@
"UNICODE",
"_UNICODE"
],
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.cmake-tools",
"cppStandard": "c++20",
"browse": {
"path": [
"external/**"
]
},
"compilerPath": "/usr/bin/g++"
}
}
],
"version": 4
-1
View File
@@ -15,7 +15,6 @@
"console": "internalConsole",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable break on all exceptions",
+3 -2
View File
@@ -208,9 +208,10 @@ public:
deallocateNode(tmp->prev);
}
deallocateNode(tail);
markIteratorDirty();
tail = nullptr;
root = nullptr;
markIteratorDirty();
_size = 0;
}
//Insert at the end
iterator add(const T &value)
@@ -291,7 +292,7 @@ public:
{
value_type temp = std::move(root->data);
popFront();
return std::move(temp);
return temp;
}
iterator remove(iterator pos)
{
+18 -8
View File
@@ -20,13 +20,13 @@ BasePassMeshProcessor::~BasePassMeshProcessor()
{
}
void BasePassMeshProcessor::addMeshBatch(
Job BasePassMeshProcessor::processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass renderPass,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet>& descriptorSets,
Array<Gfx::PDescriptorSet> descriptorSets,
int32 /*staticMeshId*/)
{
PMaterialAsset material = batch.material;
@@ -34,11 +34,12 @@ void BasePassMeshProcessor::addMeshBatch(
const PVertexShaderInput vertexInput = batch.vertexInput;
const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType());
const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType());
assert(collection != nullptr);
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
renderCommand->setViewport(target);
pipelineLayout->addDescriptorLayout(BasePass::INDEX_MATERIAL, material->getDescriptorLayout());
pipelineLayout->create();
Gfx::PDescriptorSet materialSet = material->createDescriptorSet();
@@ -63,6 +64,7 @@ void BasePassMeshProcessor::addMeshBatch(
false);
}
renderCommands.add(renderCommand);
co_return;
}
Array<Gfx::PRenderCommand> BasePassMeshProcessor::getRenderCommands()
@@ -120,7 +122,7 @@ BasePass::~BasePass()
{
}
void BasePass::beginFrame()
Job BasePass::beginFrame()
{
processor->clearCommands();
primitiveLayout->reset();
@@ -140,9 +142,10 @@ void BasePass::beginFrame()
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet();
descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer);
descriptorSets[INDEX_VIEW_PARAMS]->writeChanges();
co_return;
}
void BasePass::render()
Job BasePass::render()
{
oLightIndexList->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
@@ -159,16 +162,23 @@ void BasePass::render()
descriptorSets[INDEX_LIGHT_ENV]->updateTexture(5, oLightGrid);
descriptorSets[INDEX_LIGHT_ENV]->writeChanges();
graphics->beginRenderPass(renderPass);
List<Job> jobs;
for (auto &&meshBatch : passData.staticDrawList)
{
processor->addMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets);
jobs.add(processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets));
}
for(auto& job : jobs)
{
co_await job;
}
graphics->executeCommands(processor->getRenderCommands());
graphics->endRenderPass();
co_return;
}
void BasePass::endFrame()
Job BasePass::endFrame()
{
co_return;
}
void BasePass::publishOutputs()
+6 -6
View File
@@ -11,13 +11,13 @@ public:
BasePassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics, uint8 translucentBasePass);
virtual ~BasePassMeshProcessor();
virtual void addMeshBatch(
virtual Job processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass renderPass,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet>& descriptorSets,
Array<Gfx::PDescriptorSet> descriptorSets,
int32 staticMeshId = -1) override;
Array<Gfx::PRenderCommand> getRenderCommands();
void clearCommands();
@@ -40,9 +40,9 @@ class BasePass : public RenderPass<BasePassData>
public:
BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source);
virtual ~BasePass();
virtual void beginFrame() override;
virtual void render() override;
virtual void endFrame() override;
virtual Job beginFrame() override;
virtual Job render() override;
virtual Job endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
static void modifyRenderPassMacros(Map<const char*, const char*>& defines);
@@ -18,13 +18,13 @@ DepthPrepassMeshProcessor::~DepthPrepassMeshProcessor()
{
}
void DepthPrepassMeshProcessor::addMeshBatch(
Job DepthPrepassMeshProcessor::processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass renderPass,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet>& descriptorSets,
Array<Gfx::PDescriptorSet> descriptorSets,
int32 /*staticMeshId*/)
{
PMaterialAsset material = batch.material;
@@ -61,6 +61,7 @@ void DepthPrepassMeshProcessor::addMeshBatch(
true);
}
renderCommands.add(renderCommand);
co_return;
}
Array<Gfx::PRenderCommand> DepthPrepassMeshProcessor::getRenderCommands()
@@ -104,7 +105,7 @@ DepthPrepass::~DepthPrepass()
{
}
void DepthPrepass::beginFrame()
Job DepthPrepass::beginFrame()
{
processor->clearCommands();
primitiveLayout->reset();
@@ -122,26 +123,33 @@ void DepthPrepass::beginFrame()
descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet();
descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer);
descriptorSets[INDEX_VIEW_PARAMS]->writeChanges();
co_return;
}
void DepthPrepass::render()
Job DepthPrepass::render()
{
depthAttachment->getTexture()->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS);
graphics->beginRenderPass(renderPass);
List<Job> jobs;
for (auto &&meshBatch : passData.staticDrawList)
{
processor->addMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets);
jobs.add(processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets));
}
for(auto& job : jobs)
{
co_await job;
}
graphics->executeCommands(processor->getRenderCommands());
graphics->endRenderPass();
co_return;
}
void DepthPrepass::endFrame()
Job DepthPrepass::endFrame()
{
co_return;
}
void DepthPrepass::publishOutputs()
@@ -11,12 +11,12 @@ public:
DepthPrepassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics);
virtual ~DepthPrepassMeshProcessor();
virtual void addMeshBatch(
virtual Job processMeshBatch(
const MeshBatch& batch,
const Gfx::PRenderPass renderPass,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet>& descriptorSets,
Array<Gfx::PDescriptorSet> descriptorSets,
int32 staticMeshId = -1) override;
Array<Gfx::PRenderCommand> getRenderCommands();
@@ -39,9 +39,9 @@ class DepthPrepass : public RenderPass<DepthPrepassData>
public:
DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source);
~DepthPrepass();
virtual void beginFrame() override;
virtual void render() override;
virtual void endFrame() override;
virtual Job beginFrame() override;
virtual Job render() override;
virtual Job endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
static void modifyRenderPassMacros(Map<const char*, const char*>& defines);
@@ -18,7 +18,7 @@ LightCullingPass::~LightCullingPass()
}
void LightCullingPass::beginFrame()
Job LightCullingPass::beginFrame()
{
uint32_t viewportWidth = viewport->getSizeX();
uint32_t viewportHeight = viewport->getSizeY();
@@ -75,9 +75,10 @@ void LightCullingPass::beginFrame()
lightEnvDescriptorSet->updateBuffer(2, pointLightBuffer);
lightEnvDescriptorSet->updateBuffer(3, numPointLightBuffer);
lightEnvDescriptorSet->writeChanges();
co_return;
}
void LightCullingPass::render()
Job LightCullingPass::render()
{
oLightIndexList->pipelineBarrier(
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
@@ -101,11 +102,12 @@ void LightCullingPass::render()
graphics->executeCommands(commands);
depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
depthAttachment->transferOwnership(Gfx::QueueType::GRAPHICS);
co_return;
}
void LightCullingPass::endFrame()
Job LightCullingPass::endFrame()
{
co_return;
}
void LightCullingPass::publishOutputs()
@@ -18,9 +18,9 @@ class LightCullingPass : public RenderPass<LightCullingPassData>
public:
LightCullingPass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor camera);
virtual ~LightCullingPass();
virtual void beginFrame() override;
virtual void render() override;
virtual void endFrame() override;
virtual Job beginFrame() override;
virtual Job render() override;
virtual Job endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
static void modifyRenderPassMacros(Map<const char*, const char*>& defines);
@@ -3,6 +3,7 @@
#include "Scene/Scene.h"
#include "Graphics/GraphicsResources.h"
#include "Graphics/MeshBatch.h"
#include "ThreadPool.h"
namespace Seele
{
@@ -14,13 +15,13 @@ public:
protected:
PScene scene;
Gfx::PGraphics graphics;
virtual void addMeshBatch(
const MeshBatch& meshBatch,
virtual Job processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass renderPass,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet>& descriptorSets,
Array<Gfx::PDescriptorSet> descriptorSets,
int32 staticMeshId = -1) = 0;
void buildMeshDrawCommand(
const MeshBatch& meshBatch,
+4 -3
View File
@@ -2,6 +2,7 @@
#include "MinimalEngine.h"
#include "Math/Math.h"
#include "RenderGraph.h"
#include "ThreadPool.h"
namespace Seele
{
@@ -21,9 +22,9 @@ public:
void updateViewFrame(RenderPassDataType viewFrame) {
passData = std::move(viewFrame);
}
virtual void beginFrame() = 0;
virtual void render() = 0;
virtual void endFrame() = 0;
virtual Job beginFrame() = 0;
virtual Job render() = 0;
virtual Job endFrame() = 0;
virtual void publishOutputs() = 0;
virtual void createRenderPass() = 0;
void setResources(PRenderGraphResources resources) { this->resources = resources; }
+6 -5
View File
@@ -15,12 +15,12 @@ UIPass::~UIPass()
}
void UIPass::beginFrame()
Job UIPass::beginFrame()
{
co_return;
}
void UIPass::render()
Job UIPass::render()
{
graphics->beginRenderPass(renderPass);
Gfx::PRenderCommand command = graphics->createRenderCommand("UIPassCommand");
@@ -29,11 +29,12 @@ void UIPass::render()
command->draw(4, 1, 0, 0);
graphics->executeCommands(Array<Gfx::PRenderCommand>({command}));
graphics->endRenderPass();
co_return;
}
void UIPass::endFrame()
Job UIPass::endFrame()
{
co_return;
}
void UIPass::publishOutputs()
+3 -3
View File
@@ -16,9 +16,9 @@ class UIPass : public RenderPass<UIPassData>
public:
UIPass(Gfx::PGraphics graphics, Gfx::PViewport viewport, Gfx::PRenderTargetAttachment renderTarget);
virtual ~UIPass();
virtual void beginFrame() override;
virtual void render() override;
virtual void endFrame() override;
virtual Job beginFrame() override;
virtual Job render() override;
virtual Job endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
private:
+1 -1
View File
@@ -12,7 +12,7 @@ Actor::~Actor()
{
}
void Actor::tick(float deltaTime)
void Actor::tick(float)
{
}
void Actor::notifySceneAttach(PScene scene)
+1 -1
View File
@@ -33,7 +33,7 @@ Scene::~Scene()
{
}
void Scene::tick(double deltaTime)
void Scene::tick(double)
{
}
+26 -17
View File
@@ -14,7 +14,7 @@ Event::Event(const std::string& name)
void Event::raise()
{
flag->store(1);
getGlobalThreadPool().notify(this);
getGlobalThreadPool().notify(*this);
}
void Event::reset()
{
@@ -47,51 +47,56 @@ ThreadPool::~ThreadPool()
void ThreadPool::addJob(Job&& job)
{
std::unique_lock lock(jobQueueLock);
std::cout << "Adding job " << job.id << std::endl;
//std::cout << "Adding job " << job.id << std::endl;
jobQueue.add(std::move(job));
jobQueueCV.notify_one();
}
void ThreadPool::addJob(MainJob&& job)
{
std::unique_lock lock(mainJobLock);
std::cout << "Adding main job " << job.id << std::endl;
//std::cout << "Adding main job " << job.id << std::endl;
mainJobs.add(std::move(job));
mainJobCV.notify_one();
}
void ThreadPool::enqueueWaiting(Event* event, Job&& job)
void ThreadPool::enqueueWaiting(Event& event, Job job)
{
std::cout << job.id << " waiting for event " << event->name << std::endl;
//std::cout << job.id << " waiting for event " << event.name << std::endl;
std::unique_lock lock(waitingLock);
waitingJobs[*event].add(std::move(job));
waitingJobs[event].add(std::move(job));
}
void ThreadPool::enqueueWaiting(Event* event, MainJob&& job)
void ThreadPool::enqueueWaiting(Event& event, MainJob job)
{
std::cout << job.id << " main waiting for event " << event->name << std::endl;
//std::cout << job.id << " main waiting for event " << event.name << std::endl;
std::unique_lock lock(waitingMainLock);
waitingMainJobs[*event].add(std::move(job));
waitingMainJobs[event].add(std::move(job));
}
void ThreadPool::notify(Event* event)
void ThreadPool::notify(Event& event)
{
{
std::unique_lock lock(jobQueueLock);
std::unique_lock lock2(waitingLock);
while(!waitingJobs[*event].empty())
List<Job>& jobs = waitingJobs[event];
for(auto& job : jobs)
{
std::cout << "Waking up job " << waitingJobs[*event].front().id << std::endl;
Job job = std::move(waitingJobs[*event].retrieve());
//assert(job.id != -1ull);
//std::cout << "Waking up job " << job.id << std::endl;
jobQueue.add(std::move(job));
jobQueueCV.notify_one();
}
jobs.clear();
}
{
std::unique_lock lock(mainJobLock);
std::unique_lock lock2(waitingMainLock);
while(!waitingMainJobs[*event].empty())
List<MainJob>& jobs = waitingMainJobs[event];
for(auto& job : jobs)
{
std::cout << "Waking up main job " << waitingMainJobs[*event].front().id << std::endl;
mainJobs.add(std::move(waitingMainJobs[*event].retrieve()));
//assert(job.id != -1ull);
//std::cout << "Waking up main job " << job.id << std::endl;
mainJobs.add(std::move(job));
mainJobCV.notify_one();
}
jobs.clear();
}
}
void ThreadPool::tryMainJob()
@@ -134,8 +139,12 @@ void ThreadPool::threadLoop(const bool mainThread)
continue;
}
}
std::cout << "Starting job " << job.id << std::endl;
//std::cout << "Starting job " << job.id << std::endl;
job.resume();
if(job.done())
{
job.signal();
}
}
}
+61 -68
View File
@@ -25,69 +25,6 @@ struct JobPromiseBase
exit(1);
};
};
static std::atomic_uint64_t globalCounter;
template<bool MainJob>
struct JobBase
{
public:
using promise_type = JobPromiseBase<MainJob>;
explicit JobBase()
: id(-1)
{}
explicit JobBase(std::coroutine_handle<promise_type> handle)
: handle(handle)
, id(globalCounter++)
{
std::cout << "Creating job " << id << std::endl;
/*if constexpr(MainJob)
{
std::cout << "Creating mainjob " << handle.address() << std::endl;
}
else
{
std::cout << "Creating job " << handle.address() << std::endl;
}*/
}
JobBase(const JobBase & rhs) = delete;
JobBase(JobBase&& rhs)
: handle(std::move(rhs.handle))
, id(std::move(rhs.id))
{
rhs.id = -1;
rhs.handle = nullptr;
}
~JobBase()
{
if(handle)
{
std::cout << "Destroying job " << id << std::endl;
handle.destroy();
}
}
JobBase& operator=(const JobBase& rhs) = delete;
JobBase& operator=(JobBase&& rhs)
{
if(this != &rhs)
{
handle = std::move(rhs.handle);
id = std::move(rhs.id);
rhs.id = -1;
rhs.handle = nullptr;
}
return *this;
}
void resume()
{
handle.resume();
}
std::coroutine_handle<promise_type> handle;
uint64 id;
private:
};
using MainJob = JobBase<true>;
using Job = JobBase<false>;
struct Event
{
@@ -119,16 +56,72 @@ private:
friend class ThreadPool;
};
static std::atomic_uint64_t globalCounter;
template<bool MainJob>
struct JobBase
{
public:
using promise_type = JobPromiseBase<MainJob>;
explicit JobBase()
: id(-1)
{}
explicit JobBase(std::coroutine_handle<promise_type> handle)
: handle(handle)
, id(globalCounter++)
{
//std::cout << "Creating job " << id << std::endl;
}
JobBase(const JobBase & rhs) = delete;
JobBase(JobBase&& rhs)
: handle(std::move(rhs.handle))
, id(std::move(rhs.id))
{
rhs.id = -1;
rhs.handle = nullptr;
}
~JobBase()
{
if(handle && handle.done())
{
//std::cout << "Destroying job " << id << std::endl;
handle.destroy();
}
}
JobBase& operator=(const JobBase& rhs) = delete;
JobBase& operator=(JobBase&& rhs)
{
if(this != &rhs)
{
handle = std::move(rhs.handle);
id = std::move(rhs.id);
rhs.id = -1;
rhs.handle = nullptr;
}
return *this;
}
void resume()
{
handle.resume();
}
private:
std::coroutine_handle<promise_type> handle;
uint64 id;
};
using MainJob = JobBase<true>;
using Job = JobBase<false>;
class ThreadPool
{
public:
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency());
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency() + 1);
virtual ~ThreadPool();
void addJob(Job&& job);
void addJob(MainJob&& job);
void enqueueWaiting(Event* event, Job&& job);
void enqueueWaiting(Event* event, MainJob&& job);
void notify(Event* event);
void enqueueWaiting(Event& event, Job job);
void enqueueWaiting(Event& event, MainJob job);
void notify(Event& event);
private:
std::atomic_bool running;
std::thread* mainThread;
@@ -176,7 +169,7 @@ inline auto JobPromiseBase<MainJob>::initial_suspend() const noexcept
template<bool MainJob>
inline constexpr void Event::await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h)
{
getGlobalThreadPool().enqueueWaiting(this, std::move(JobBase<MainJob>(h)));
getGlobalThreadPool().enqueueWaiting(*this, std::move(JobBase<MainJob>(h)));
}
} // namespace Seele
+11 -6
View File
@@ -34,31 +34,36 @@ void InspectorView::prepareRender()
}
void InspectorView::render()
Job InspectorView::render()
{
co_await uiPass.beginFrame();
co_await uiPass.render();
co_await uiPass.endFrame();
renderFinishedEvent.raise();
}
void InspectorView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier)
void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier)
{
}
void InspectorView::mouseMoveCallback(double xPos, double yPos)
void InspectorView::mouseMoveCallback(double, double)
{
}
void InspectorView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier)
void InspectorView::mouseButtonCallback(MouseButton, InputAction, KeyModifier)
{
}
void InspectorView::scrollCallback(double xOffset, double yOffset)
void InspectorView::scrollCallback(double, double)
{
}
void InspectorView::fileCallback(int count, const char** paths)
void InspectorView::fileCallback(int, const char**)
{
}
+1 -1
View File
@@ -18,7 +18,7 @@ public:
virtual void commitUpdate() override;
virtual void prepareRender() override;
virtual void render() override;
virtual Job render() override;
void selectActor();
protected:
UIPass uiPass;
+12 -10
View File
@@ -83,19 +83,21 @@ void SceneView::prepareRender()
basePass.updateViewFrame(basePassData);
}
void SceneView::render()
Job SceneView::render()
{
depthPrepass.beginFrame();
lightCullingPass.beginFrame();
basePass.beginFrame();
co_await depthPrepass.beginFrame();
co_await lightCullingPass.beginFrame();
co_await basePass.beginFrame();
depthPrepass.render();
lightCullingPass.render();
basePass.render();
co_await depthPrepass.render();
co_await lightCullingPass.render();
co_await basePass.render();
depthPrepass.endFrame();
lightCullingPass.endFrame();
basePass.endFrame();
co_await depthPrepass.endFrame();
co_await lightCullingPass.endFrame();
co_await basePass.endFrame();
renderFinishedEvent.raise();
}
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier)
+1 -1
View File
@@ -18,7 +18,7 @@ public:
virtual void commitUpdate() override;
virtual void prepareRender() override;
virtual void render() override;
virtual Job render() override;
PScene getScene() const { return scene; }
private:
+4 -1
View File
@@ -1,5 +1,6 @@
#pragma once
#include "Graphics/RenderPass/RenderGraph.h"
#include "ThreadPool.h"
namespace Seele
{
@@ -20,15 +21,17 @@ public:
// These are called from the render thread
// prepare render is also locked, so reading from shared memory is also safe
virtual void prepareRender() {}
virtual void render() {}
virtual Job render() { co_return; }
void applyArea(URect area);
void setFocused();
Event renderFinished() { return renderFinishedEvent; }
protected:
Gfx::PGraphics graphics;
Gfx::PViewport viewport;
PWindow owner;
std::string name;
Event renderFinishedEvent;
virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) = 0;
virtual void mouseMoveCallback(double xPos, double yPos) = 0;
+4
View File
@@ -37,6 +37,10 @@ MainJob Window::render()
}
windowView->view->render();
}
for(auto& windowView : views)
{
co_await windowView->view->renderFinished();
}
gfxHandle->endFrame();
//Enqueue a new render main job
render();