2015-07-04 15:22:28 +02:00
|
|
|
#include "renderer.h"
|
|
|
|
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/array.h"
|
2016-06-03 02:17:47 +02:00
|
|
|
#include "engine/command_line_parser.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/crc32.h"
|
2019-06-13 17:26:52 +02:00
|
|
|
#include "engine/debug.h"
|
2017-01-26 09:28:23 +01:00
|
|
|
#include "engine/engine.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/log.h"
|
2018-07-11 23:35:34 +02:00
|
|
|
#include "engine/job_system.h"
|
|
|
|
#include "engine/mt/atomic.h"
|
2018-07-08 18:16:16 +02:00
|
|
|
#include "engine/mt/sync.h"
|
|
|
|
#include "engine/mt/task.h"
|
2018-12-24 17:21:50 +01:00
|
|
|
#include "engine/os.h"
|
2016-05-10 08:24:31 +02:00
|
|
|
#include "engine/profiler.h"
|
2017-11-19 14:04:10 +01:00
|
|
|
#include "engine/reflection.h"
|
2017-01-26 09:28:23 +01:00
|
|
|
#include "engine/resource_manager.h"
|
|
|
|
#include "engine/string.h"
|
2017-05-23 21:51:10 +02:00
|
|
|
#include "engine/universe/component.h"
|
2017-01-26 09:28:23 +01:00
|
|
|
#include "engine/universe/universe.h"
|
2019-06-26 18:52:52 +02:00
|
|
|
#include "renderer/font.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/material.h"
|
|
|
|
#include "renderer/model.h"
|
2018-07-01 18:13:44 +02:00
|
|
|
#include "renderer/pipeline.h"
|
2018-08-22 19:52:08 +02:00
|
|
|
#include "renderer/particle_system.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/render_scene.h"
|
|
|
|
#include "renderer/shader.h"
|
2017-01-26 09:28:23 +01:00
|
|
|
#include "renderer/terrain.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/texture.h"
|
2019-06-26 18:52:52 +02:00
|
|
|
|
2018-06-24 17:50:33 +02:00
|
|
|
|
|
|
|
#include <Windows.h>
|
2019-06-13 17:26:52 +02:00
|
|
|
#undef near
|
|
|
|
#undef far
|
2018-06-24 17:50:33 +02:00
|
|
|
#include "gl/GL.h"
|
|
|
|
#include "ffr/ffr.h"
|
2019-07-29 18:03:08 +02:00
|
|
|
#include <stdio.h>
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2018-07-08 18:16:16 +02:00
|
|
|
#define FFR_GL_IMPORT(prototype, name) static prototype name;
|
|
|
|
#define FFR_GL_IMPORT_TYPEDEFS
|
|
|
|
|
|
|
|
#include "ffr/gl_ext.h"
|
|
|
|
|
|
|
|
#define CHECK_GL(gl) \
|
|
|
|
do { \
|
|
|
|
gl; \
|
|
|
|
GLenum err = glGetError(); \
|
|
|
|
if (err != GL_NO_ERROR) { \
|
2019-06-21 17:14:06 +02:00
|
|
|
logError("Renderer") << "OpenGL error " << err; \
|
2018-07-08 18:16:16 +02:00
|
|
|
} \
|
|
|
|
} while(0)
|
2014-06-16 21:18:15 +02:00
|
|
|
|
2015-07-04 15:22:28 +02:00
|
|
|
namespace Lumix
|
|
|
|
{
|
2015-02-16 00:34:18 +01:00
|
|
|
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2018-07-29 10:53:13 +02:00
|
|
|
static const ComponentType MODEL_INSTANCE_TYPE = Reflection::getComponentType("model_instance");
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2019-08-07 21:21:31 +02:00
|
|
|
enum {
|
2019-10-05 14:26:26 +02:00
|
|
|
TRANSIENT_BUFFER_INIT_SIZE = 16 * 1024 * 1024,
|
|
|
|
MATERIAL_BUFFER_SIZE = 16 * 1024 * 1024
|
2019-08-07 21:21:31 +02:00
|
|
|
};
|
2018-07-22 15:22:36 +02:00
|
|
|
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
struct FrameData {
|
|
|
|
FrameData(struct RendererImpl& renderer, IAllocator& allocator)
|
|
|
|
: jobs(allocator)
|
|
|
|
, renderer(renderer)
|
|
|
|
{}
|
|
|
|
|
|
|
|
ffr::BufferHandle transient_buffer = ffr::INVALID_BUFFER;
|
|
|
|
i32 transient_offset = 0;
|
|
|
|
u32 transient_size = 0;
|
|
|
|
u8* transient_ptr = nullptr;
|
|
|
|
JobSystem::SignalHandle transient_mapped = JobSystem::INVALID_HANDLE;
|
|
|
|
JobSystem::SignalHandle setup_done = JobSystem::INVALID_HANDLE;
|
|
|
|
JobSystem::SignalHandle rendering_done = JobSystem::INVALID_HANDLE;
|
|
|
|
Array<Renderer::RenderJob*> jobs;
|
|
|
|
OS::Point window_size;
|
|
|
|
RendererImpl& renderer;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-06-12 23:38:06 +02:00
|
|
|
template <typename T>
|
|
|
|
struct RenderResourceManager : public ResourceManager
|
|
|
|
{
|
|
|
|
RenderResourceManager(Renderer& renderer, IAllocator& allocator)
|
|
|
|
: ResourceManager(allocator)
|
|
|
|
, m_renderer(renderer)
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
Resource* createResource(const Path& path) override
|
|
|
|
{
|
|
|
|
return LUMIX_NEW(m_allocator, T)(path, *this, m_renderer, m_allocator);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroyResource(Resource& resource) override
|
|
|
|
{
|
|
|
|
LUMIX_DELETE(m_allocator, &resource);
|
|
|
|
}
|
|
|
|
|
|
|
|
Renderer& m_renderer;
|
|
|
|
};
|
2019-06-02 01:57:10 +02:00
|
|
|
|
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
struct GPUProfiler
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2019-06-02 01:57:10 +02:00
|
|
|
struct Query
|
|
|
|
{
|
|
|
|
StaticString<32> name;
|
|
|
|
ffr::QueryHandle handle;
|
|
|
|
u64 result;
|
2019-06-09 23:53:38 +02:00
|
|
|
i64 profiler_link;
|
2019-06-02 01:57:10 +02:00
|
|
|
bool is_end;
|
|
|
|
bool is_frame;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
GPUProfiler(IAllocator& allocator)
|
2018-07-14 17:52:06 +02:00
|
|
|
: m_queries(allocator)
|
2018-07-14 10:03:38 +02:00
|
|
|
, m_pool(allocator)
|
2019-06-02 01:57:10 +02:00
|
|
|
, m_gpu_to_cpu_offset(0)
|
2018-07-14 10:03:38 +02:00
|
|
|
{
|
|
|
|
}
|
2018-07-08 18:16:16 +02:00
|
|
|
|
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
~GPUProfiler()
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2018-07-14 17:52:06 +02:00
|
|
|
ASSERT(m_pool.empty());
|
|
|
|
ASSERT(m_queries.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-02 01:57:10 +02:00
|
|
|
u64 toCPUTimestamp(u64 gpu_timestamp) const
|
|
|
|
{
|
2019-08-25 13:39:05 +02:00
|
|
|
return u64(gpu_timestamp * (OS::Timer::getFrequency() / double(ffr::getQueryFrequency()))) + m_gpu_to_cpu_offset;
|
2019-06-02 01:57:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void init()
|
|
|
|
{
|
2019-06-17 21:15:04 +02:00
|
|
|
ffr::QueryHandle q = ffr::createQuery();
|
|
|
|
ffr::queryTimestamp(q);
|
2019-06-21 12:32:07 +02:00
|
|
|
const u64 cpu_timestamp = OS::Timer::getRawTimestamp();
|
2019-08-25 13:39:05 +02:00
|
|
|
u32 try_num = 0;
|
|
|
|
while (!ffr::isQueryReady(q) && try_num < 1000) {
|
|
|
|
Sleep(1);
|
|
|
|
++try_num;
|
|
|
|
}
|
|
|
|
if (try_num == 1000) {
|
|
|
|
logError("Renderer") << "Failed to get GPU timestamp, timing are unreliable.";
|
|
|
|
m_gpu_to_cpu_offset = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const u64 gpu_timestamp = ffr::getQueryResult(q);
|
|
|
|
m_gpu_to_cpu_offset = cpu_timestamp - u64(gpu_timestamp * (OS::Timer::getFrequency() / double(ffr::getQueryFrequency())));
|
|
|
|
ffr::destroy(q);
|
|
|
|
}
|
2019-06-02 01:57:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-14 17:52:06 +02:00
|
|
|
void clear()
|
|
|
|
{
|
2019-06-23 14:22:33 +02:00
|
|
|
m_queries.clear();
|
|
|
|
|
2018-07-14 17:52:06 +02:00
|
|
|
for(const ffr::QueryHandle h : m_pool) {
|
|
|
|
ffr::destroy(h);
|
|
|
|
}
|
|
|
|
m_pool.clear();
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-14 10:03:38 +02:00
|
|
|
ffr::QueryHandle allocQuery()
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2018-07-14 10:03:38 +02:00
|
|
|
if(!m_pool.empty()) {
|
|
|
|
const ffr::QueryHandle res = m_pool.back();
|
|
|
|
m_pool.pop();
|
|
|
|
return res;
|
2018-07-11 23:35:34 +02:00
|
|
|
}
|
2018-07-14 10:03:38 +02:00
|
|
|
return ffr::createQuery();
|
|
|
|
}
|
2018-07-08 18:16:16 +02:00
|
|
|
|
|
|
|
|
2019-06-09 23:53:38 +02:00
|
|
|
void beginQuery(const char* name, i64 profiler_link)
|
2018-07-14 10:03:38 +02:00
|
|
|
{
|
2019-06-02 01:57:10 +02:00
|
|
|
MT::CriticalSectionLock lock(m_mutex);
|
2018-07-14 10:03:38 +02:00
|
|
|
Query& q = m_queries.emplace();
|
2019-06-09 23:53:38 +02:00
|
|
|
q.profiler_link = profiler_link;
|
2018-07-14 10:03:38 +02:00
|
|
|
q.name = name;
|
|
|
|
q.is_end = false;
|
2019-06-02 01:57:10 +02:00
|
|
|
q.is_frame = false;
|
2018-07-14 10:03:38 +02:00
|
|
|
q.handle = allocQuery();
|
|
|
|
ffr::queryTimestamp(q.handle);
|
|
|
|
}
|
2018-07-08 18:16:16 +02:00
|
|
|
|
|
|
|
|
2018-07-14 10:03:38 +02:00
|
|
|
void endQuery()
|
|
|
|
{
|
2019-06-02 01:57:10 +02:00
|
|
|
MT::CriticalSectionLock lock(m_mutex);
|
2018-07-14 10:03:38 +02:00
|
|
|
Query& q = m_queries.emplace();
|
|
|
|
q.is_end = true;
|
2019-06-02 01:57:10 +02:00
|
|
|
q.is_frame = false;
|
2018-07-14 10:03:38 +02:00
|
|
|
q.handle = allocQuery();
|
|
|
|
ffr::queryTimestamp(q.handle);
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
2014-09-28 02:12:41 +02:00
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
void frame()
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2019-05-04 23:37:59 +02:00
|
|
|
PROFILE_FUNCTION();
|
2019-06-02 01:57:10 +02:00
|
|
|
MT::CriticalSectionLock lock(m_mutex);
|
|
|
|
Query frame_query;
|
|
|
|
frame_query.is_frame = true;
|
|
|
|
m_queries.push(frame_query);
|
|
|
|
while (!m_queries.empty()) {
|
|
|
|
Query q = m_queries[0];
|
|
|
|
if (q.is_frame) {
|
|
|
|
Profiler::gpuFrame();
|
|
|
|
m_queries.erase(0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ffr::isQueryReady(q.handle)) break;
|
|
|
|
|
|
|
|
if (q.is_end) {
|
|
|
|
const u64 timestamp = toCPUTimestamp(ffr::getQueryResult(q.handle));
|
|
|
|
Profiler::endGPUBlock(timestamp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const u64 timestamp = toCPUTimestamp(ffr::getQueryResult(q.handle));
|
2019-06-09 23:53:38 +02:00
|
|
|
Profiler::beginGPUBlock(q.name, timestamp, q.profiler_link);
|
2019-06-02 01:57:10 +02:00
|
|
|
}
|
2018-07-14 10:03:38 +02:00
|
|
|
m_pool.push(q.handle);
|
2019-06-02 01:57:10 +02:00
|
|
|
m_queries.erase(0);
|
2018-07-14 10:03:38 +02:00
|
|
|
}
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
Array<Query> m_queries;
|
2018-07-14 10:03:38 +02:00
|
|
|
Array<ffr::QueryHandle> m_pool;
|
2019-06-02 01:57:10 +02:00
|
|
|
MT::CriticalSection m_mutex;
|
|
|
|
i64 m_gpu_to_cpu_offset;
|
2018-07-08 18:16:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-11-19 14:04:10 +01:00
|
|
|
struct BoneProperty : Reflection::IEnumProperty
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2018-01-28 21:04:50 +01:00
|
|
|
BoneProperty()
|
|
|
|
{
|
|
|
|
name = "Bone";
|
|
|
|
}
|
2017-10-18 23:43:02 +02:00
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
|
2019-06-11 22:39:39 +02:00
|
|
|
void getValue(ComponentUID cmp, int index, OutputMemoryStream& stream) const override
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-10-18 23:43:02 +02:00
|
|
|
RenderScene* scene = static_cast<RenderScene*>(cmp.scene);
|
2018-08-19 17:35:37 +02:00
|
|
|
int value = scene->getBoneAttachmentBone((EntityRef)cmp.entity);
|
2017-10-18 23:43:02 +02:00
|
|
|
stream.write(value);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-11 22:39:39 +02:00
|
|
|
void setValue(ComponentUID cmp, int index, InputMemoryStream& stream) const override
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-10-18 23:43:02 +02:00
|
|
|
RenderScene* scene = static_cast<RenderScene*>(cmp.scene);
|
|
|
|
int value = stream.read<int>();
|
2018-08-19 17:35:37 +02:00
|
|
|
scene->setBoneAttachmentBone((EntityRef)cmp.entity, value);
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-19 17:35:37 +02:00
|
|
|
EntityPtr getModelInstance(RenderScene* render_scene, EntityRef bone_attachment) const
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2018-08-19 17:35:37 +02:00
|
|
|
EntityPtr parent_entity = render_scene->getBoneAttachmentParent(bone_attachment);
|
|
|
|
if (!parent_entity.isValid()) return INVALID_ENTITY;
|
|
|
|
return render_scene->getUniverse().hasComponent((EntityRef)parent_entity, MODEL_INSTANCE_TYPE) ? parent_entity : INVALID_ENTITY;
|
2016-05-02 21:41:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-12 17:02:10 +01:00
|
|
|
int getEnumValueIndex(ComponentUID cmp, int value) const override { return value; }
|
|
|
|
int getEnumValue(ComponentUID cmp, int index) const override { return index; }
|
2018-01-26 01:21:31 +01:00
|
|
|
|
|
|
|
|
2017-10-18 23:43:02 +02:00
|
|
|
int getEnumCount(ComponentUID cmp) const override
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-10-18 23:43:02 +02:00
|
|
|
RenderScene* render_scene = static_cast<RenderScene*>(cmp.scene);
|
2018-08-19 17:35:37 +02:00
|
|
|
EntityPtr model_instance = getModelInstance(render_scene, (EntityRef)cmp.entity);
|
2018-01-12 17:01:26 +01:00
|
|
|
if (!model_instance.isValid()) return 0;
|
|
|
|
|
2018-08-19 17:35:37 +02:00
|
|
|
auto* model = render_scene->getModelInstanceModel((EntityRef)model_instance);
|
2016-05-02 21:41:18 +02:00
|
|
|
if (!model || !model->isReady()) return 0;
|
2018-01-12 17:01:26 +01:00
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
return model->getBoneCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-18 23:43:02 +02:00
|
|
|
const char* getEnumName(ComponentUID cmp, int index) const override
|
2016-05-02 21:41:18 +02:00
|
|
|
{
|
2017-10-18 23:43:02 +02:00
|
|
|
RenderScene* render_scene = static_cast<RenderScene*>(cmp.scene);
|
2018-08-19 17:35:37 +02:00
|
|
|
EntityPtr model_instance = getModelInstance(render_scene, (EntityRef)cmp.entity);
|
2018-01-12 17:01:26 +01:00
|
|
|
if (!model_instance.isValid()) return "";
|
|
|
|
|
2018-08-19 17:35:37 +02:00
|
|
|
auto* model = render_scene->getModelInstanceModel((EntityRef)model_instance);
|
2016-05-02 21:41:18 +02:00
|
|
|
if (!model) return "";
|
2018-01-12 17:01:26 +01:00
|
|
|
|
2016-05-02 21:41:18 +02:00
|
|
|
return model->getBone(index).name.c_str();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-01-20 16:32:37 +01:00
|
|
|
static void registerProperties(IAllocator& allocator)
|
|
|
|
{
|
2017-11-19 14:04:10 +01:00
|
|
|
using namespace Reflection;
|
2017-10-18 23:43:02 +02:00
|
|
|
|
2018-01-26 01:21:31 +01:00
|
|
|
static auto rotationModeDesc = enumDesciptor<Terrain::GrassType::RotationMode>(
|
|
|
|
LUMIX_ENUM_VALUE(Terrain::GrassType::RotationMode::ALL_RANDOM),
|
|
|
|
LUMIX_ENUM_VALUE(Terrain::GrassType::RotationMode::Y_UP),
|
|
|
|
LUMIX_ENUM_VALUE(Terrain::GrassType::RotationMode::ALIGN_WITH_NORMAL)
|
|
|
|
);
|
|
|
|
registerEnum(rotationModeDesc);
|
2018-01-11 14:03:16 +01:00
|
|
|
|
2017-10-18 23:43:02 +02:00
|
|
|
static auto render_scene = scene("renderer",
|
|
|
|
component("bone_attachment",
|
2018-01-11 14:03:16 +01:00
|
|
|
property("Parent", LUMIX_PROP(RenderScene, BoneAttachmentParent)),
|
|
|
|
property("Relative position", LUMIX_PROP(RenderScene, BoneAttachmentPosition)),
|
|
|
|
property("Relative rotation", LUMIX_PROP(RenderScene, BoneAttachmentRotation),
|
2017-10-18 23:43:02 +02:00
|
|
|
RadiansAttribute()),
|
|
|
|
BoneProperty()
|
|
|
|
),
|
2018-01-28 23:19:25 +01:00
|
|
|
component("environment_probe",
|
2019-06-13 17:26:52 +02:00
|
|
|
property("Enabled", &RenderScene::isEnvironmentProbeEnabled, &RenderScene::enableEnvironmentProbe),
|
2018-09-05 20:45:06 +02:00
|
|
|
property("Radius", LUMIX_PROP(RenderScene, EnvironmentProbeRadius)),
|
2019-06-13 17:26:52 +02:00
|
|
|
property("Enabled reflection", &RenderScene::isEnvironmentProbeReflectionEnabled, &RenderScene::enableEnvironmentProbeReflection),
|
|
|
|
property("Override global size", &RenderScene::isEnvironmentProbeCustomSize, &RenderScene::enableEnvironmentProbeCustomSize),
|
|
|
|
var_property("Radiance size", &RenderScene::getEnvironmentProbe, &EnvironmentProbe::radiance_size),
|
|
|
|
var_property("Irradiance size", &RenderScene::getEnvironmentProbe, &EnvironmentProbe::irradiance_size)
|
2018-01-28 23:19:25 +01:00
|
|
|
),
|
2018-08-22 19:52:08 +02:00
|
|
|
component("particle_emitter",
|
|
|
|
property("Resource", LUMIX_PROP(RenderScene, ParticleEmitterPath),
|
|
|
|
ResourceAttribute("Particle emitter (*.par)", ParticleEmitterResource::TYPE))
|
2017-10-24 17:18:53 +02:00
|
|
|
),
|
2017-10-18 23:43:02 +02:00
|
|
|
component("camera",
|
2019-06-13 17:26:52 +02:00
|
|
|
var_property("FOV", &RenderScene::getCamera, &Camera::fov, RadiansAttribute()),
|
|
|
|
var_property("Near", &RenderScene::getCamera, &Camera::near, MinAttribute(0)),
|
|
|
|
var_property("Far", &RenderScene::getCamera, &Camera::far, MinAttribute(0)),
|
|
|
|
var_property("Orthographic", &RenderScene::getCamera, &Camera::is_ortho),
|
|
|
|
var_property("Orthographic size", &RenderScene::getCamera, &Camera::ortho_size, MinAttribute(0))
|
2017-10-18 23:43:02 +02:00
|
|
|
),
|
2018-07-29 10:53:13 +02:00
|
|
|
component("model_instance",
|
2019-06-13 17:26:52 +02:00
|
|
|
property("Enabled", &RenderScene::isModelInstanceEnabled, &RenderScene::enableModelInstance),
|
2018-01-11 14:03:16 +01:00
|
|
|
property("Source", LUMIX_PROP(RenderScene, ModelInstancePath),
|
2019-06-23 17:54:05 +02:00
|
|
|
ResourceAttribute("Mesh (*.msh)", Model::TYPE))
|
2017-10-18 23:43:02 +02:00
|
|
|
),
|
2019-06-23 19:29:07 +02:00
|
|
|
component("environment",
|
|
|
|
var_property("Color", &RenderScene::getEnvironment, &Environment::m_diffuse_color, ColorAttribute()),
|
|
|
|
var_property("Intensity", &RenderScene::getEnvironment, &Environment::m_diffuse_intensity, MinAttribute(0)),
|
|
|
|
var_property("Indirect intensity", &RenderScene::getEnvironment, &Environment::m_indirect_intensity, MinAttribute(0)),
|
|
|
|
var_property("Fog density", &RenderScene::getEnvironment, &Environment::m_fog_density, ClampAttribute(0, 1)),
|
|
|
|
var_property("Fog bottom", &RenderScene::getEnvironment, &Environment::m_fog_bottom),
|
|
|
|
var_property("Fog height", &RenderScene::getEnvironment, &Environment::m_fog_height, MinAttribute(0)),
|
|
|
|
var_property("Fog color", &RenderScene::getEnvironment, &Environment::m_fog_color, ColorAttribute()),
|
2019-07-13 21:13:21 +02:00
|
|
|
property("Shadow cascades", LUMIX_PROP(RenderScene, ShadowmapCascades)),
|
2019-09-25 01:28:36 +02:00
|
|
|
property("Cast shadows", LUMIX_PROP(RenderScene, EnvironmentCastShadows)),
|
|
|
|
property("Fast filtering", LUMIX_PROP(RenderScene, EnvironmentFastFiltering))
|
2017-10-18 23:43:02 +02:00
|
|
|
),
|
|
|
|
component("point_light",
|
2019-06-13 17:26:52 +02:00
|
|
|
var_property("Cast shadows", &RenderScene::getPointLight, &PointLight::cast_shadows),
|
|
|
|
var_property("Intensity", &RenderScene::getPointLight, &PointLight::intensity, MinAttribute(0)),
|
|
|
|
var_property("FOV", &RenderScene::getPointLight, &PointLight::fov, ClampAttribute(0, 360), RadiansAttribute()),
|
|
|
|
var_property("Attenuation", &RenderScene::getPointLight, &PointLight::attenuation_param, ClampAttribute(0, 100)),
|
|
|
|
var_property("Color", &RenderScene::getPointLight, &PointLight::color, ColorAttribute()),
|
|
|
|
property("Range", LUMIX_PROP(RenderScene, LightRange), MinAttribute(0))
|
2017-10-18 23:43:02 +02:00
|
|
|
),
|
2018-01-30 21:39:21 +01:00
|
|
|
component("text_mesh",
|
|
|
|
property("Text", LUMIX_PROP(RenderScene, TextMeshText)),
|
|
|
|
property("Font", LUMIX_PROP(RenderScene, TextMeshFontPath),
|
|
|
|
ResourceAttribute("Font (*.ttf)", FontResource::TYPE)),
|
|
|
|
property("Font Size", LUMIX_PROP(RenderScene, TextMeshFontSize)),
|
|
|
|
property("Color", LUMIX_PROP(RenderScene, TextMeshColorRGBA),
|
2018-03-08 15:48:23 +01:00
|
|
|
ColorAttribute()),
|
2019-06-13 17:26:52 +02:00
|
|
|
property("Camera-oriented", &RenderScene::isTextMeshCameraOriented, &RenderScene::setTextMeshCameraOriented)
|
2018-01-30 21:39:21 +01:00
|
|
|
),
|
2017-10-18 23:43:02 +02:00
|
|
|
component("decal",
|
2018-01-11 14:03:16 +01:00
|
|
|
property("Material", LUMIX_PROP(RenderScene, DecalMaterialPath),
|
2018-01-11 21:13:59 +01:00
|
|
|
ResourceAttribute("Material (*.mat)", Material::TYPE)),
|
2018-10-10 23:41:26 +02:00
|
|
|
property("Half extents", LUMIX_PROP(RenderScene, DecalHalfExtents),
|
2017-10-18 23:43:02 +02:00
|
|
|
MinAttribute(0))
|
|
|
|
),
|
|
|
|
component("terrain",
|
2018-01-11 14:03:16 +01:00
|
|
|
property("Material", LUMIX_PROP(RenderScene, TerrainMaterialPath),
|
2018-01-11 21:13:59 +01:00
|
|
|
ResourceAttribute("Material (*.mat)", Material::TYPE)),
|
2018-01-11 14:03:16 +01:00
|
|
|
property("XZ scale", LUMIX_PROP(RenderScene, TerrainXZScale),
|
2017-10-18 23:43:02 +02:00
|
|
|
MinAttribute(0)),
|
2018-01-11 14:03:16 +01:00
|
|
|
property("Height scale", LUMIX_PROP(RenderScene, TerrainYScale),
|
2017-10-18 23:43:02 +02:00
|
|
|
MinAttribute(0)),
|
|
|
|
array("grass", &RenderScene::getGrassCount, &RenderScene::addGrass, &RenderScene::removeGrass,
|
2018-01-11 14:03:16 +01:00
|
|
|
property("Mesh", LUMIX_PROP(RenderScene, GrassPath),
|
2019-06-23 17:54:05 +02:00
|
|
|
ResourceAttribute("Mesh (*.msh)", Model::TYPE)),
|
2018-01-11 14:03:16 +01:00
|
|
|
property("Distance", LUMIX_PROP(RenderScene, GrassDistance),
|
2017-10-18 23:43:02 +02:00
|
|
|
MinAttribute(1)),
|
2018-01-11 14:03:16 +01:00
|
|
|
property("Density", LUMIX_PROP(RenderScene, GrassDensity)),
|
2018-01-26 01:21:31 +01:00
|
|
|
enum_property("Mode", LUMIX_PROP(RenderScene, GrassRotationMode), rotationModeDesc)
|
2017-10-18 23:43:02 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
2017-11-20 17:25:04 +01:00
|
|
|
registerScene(render_scene);
|
2016-01-20 16:32:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-19 17:35:37 +02:00
|
|
|
struct RendererImpl final : public Renderer
|
2015-07-25 02:22:51 +02:00
|
|
|
{
|
2016-03-01 16:48:04 +01:00
|
|
|
explicit RendererImpl(Engine& engine)
|
2015-07-25 02:22:51 +02:00
|
|
|
: m_engine(engine)
|
|
|
|
, m_allocator(engine.getAllocator())
|
2018-07-08 18:16:16 +02:00
|
|
|
, m_texture_manager(*this, m_allocator)
|
2019-06-13 17:26:52 +02:00
|
|
|
, m_pipeline_manager(*this, m_allocator)
|
2017-11-07 16:49:18 +01:00
|
|
|
, m_model_manager(*this, m_allocator)
|
2019-06-13 17:26:52 +02:00
|
|
|
, m_particle_emitter_manager(*this, m_allocator)
|
2015-10-07 18:40:17 +02:00
|
|
|
, m_material_manager(*this, m_allocator)
|
2015-07-25 02:22:51 +02:00
|
|
|
, m_shader_manager(*this, m_allocator)
|
2018-01-08 13:08:11 +01:00
|
|
|
, m_font_manager(nullptr)
|
2015-09-05 13:08:47 +02:00
|
|
|
, m_shader_defines(m_allocator)
|
2017-10-02 16:35:21 +02:00
|
|
|
, m_vsync(true)
|
2019-05-23 23:28:50 +02:00
|
|
|
, m_profiler(m_allocator)
|
2018-10-13 15:08:58 +02:00
|
|
|
, m_layers(m_allocator)
|
2019-10-16 22:36:33 +02:00
|
|
|
, m_frame_data(m_allocator)
|
2019-08-07 21:21:31 +02:00
|
|
|
, m_material_buffer(m_allocator)
|
2015-07-25 02:22:51 +02:00
|
|
|
{
|
2019-08-21 21:11:51 +02:00
|
|
|
m_shader_defines.reserve(32);
|
2019-03-23 13:34:03 +01:00
|
|
|
ffr::preinit(m_allocator);
|
2019-10-16 22:36:33 +02:00
|
|
|
m_frame_data.emplace(*this, m_allocator);
|
|
|
|
m_frame_data.emplace(*this, m_allocator);
|
2019-03-23 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
~RendererImpl()
|
|
|
|
{
|
|
|
|
m_particle_emitter_manager.destroy();
|
|
|
|
m_pipeline_manager.destroy();
|
|
|
|
m_texture_manager.destroy();
|
|
|
|
m_model_manager.destroy();
|
|
|
|
m_material_manager.destroy();
|
|
|
|
m_shader_manager.destroy();
|
|
|
|
m_font_manager->destroy();
|
|
|
|
LUMIX_DELETE(m_allocator, m_font_manager);
|
|
|
|
|
2019-07-09 02:28:08 +02:00
|
|
|
frame();
|
|
|
|
|
2019-05-23 23:28:50 +02:00
|
|
|
JobSystem::SignalHandle signal = JobSystem::INVALID_HANDLE;
|
2019-05-25 13:03:00 +02:00
|
|
|
JobSystem::runEx(this, [](void* data) {
|
2019-05-23 23:28:50 +02:00
|
|
|
RendererImpl* renderer = (RendererImpl*)data;
|
2019-10-16 22:36:33 +02:00
|
|
|
for (FrameData& frame : renderer->m_frame_data) {
|
|
|
|
ffr::destroy(frame.transient_buffer);
|
|
|
|
}
|
2019-08-07 21:21:31 +02:00
|
|
|
ffr::destroy(renderer->m_material_buffer.buffer);
|
2019-05-23 23:28:50 +02:00
|
|
|
renderer->m_profiler.clear();
|
|
|
|
ffr::shutdown();
|
2019-10-16 22:36:33 +02:00
|
|
|
}, &signal, m_gpu_frame->rendering_done, 1);
|
2019-05-23 23:28:50 +02:00
|
|
|
JobSystem::wait(signal);
|
2019-03-23 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void init() override
|
|
|
|
{
|
|
|
|
registerProperties(m_engine.getAllocator());
|
2016-06-03 02:17:47 +02:00
|
|
|
char cmd_line[4096];
|
2019-07-25 19:14:12 +02:00
|
|
|
OS::getCommandLine(Span(cmd_line));
|
2017-05-23 19:57:11 +02:00
|
|
|
CommandLineParser cmd_line_parser(cmd_line);
|
2017-10-02 16:35:21 +02:00
|
|
|
m_vsync = true;
|
2019-07-30 21:58:31 +02:00
|
|
|
m_debug_opengl = false;
|
|
|
|
while (cmd_line_parser.next()) {
|
|
|
|
if (cmd_line_parser.currentEquals("-no_vsync")) {
|
2017-10-02 16:35:21 +02:00
|
|
|
m_vsync = false;
|
2019-07-30 21:58:31 +02:00
|
|
|
}
|
|
|
|
else if (cmd_line_parser.currentEquals("-debug_opengl")) {
|
|
|
|
m_debug_opengl = true;
|
2017-10-02 16:35:21 +02:00
|
|
|
}
|
2016-06-03 02:17:47 +02:00
|
|
|
}
|
|
|
|
|
2019-05-23 23:28:50 +02:00
|
|
|
JobSystem::SignalHandle signal = JobSystem::INVALID_HANDLE;
|
2019-05-25 13:03:00 +02:00
|
|
|
JobSystem::runEx(this, [](void* data) {
|
2019-05-23 23:28:50 +02:00
|
|
|
PROFILE_BLOCK("init_render");
|
|
|
|
RendererImpl& renderer = *(RendererImpl*)data;
|
|
|
|
Engine& engine = renderer.getEngine();
|
|
|
|
void* window_handle = engine.getPlatformData().window_handle;
|
2019-07-30 21:58:31 +02:00
|
|
|
ffr::init(window_handle, renderer.m_debug_opengl);
|
2019-10-16 22:36:33 +02:00
|
|
|
|
|
|
|
for (FrameData& frame : renderer.m_frame_data) {
|
|
|
|
frame.transient_buffer = ffr::allocBufferHandle();
|
|
|
|
frame.transient_offset = 0;
|
|
|
|
ffr::createBuffer(frame.transient_buffer, 0, TRANSIENT_BUFFER_INIT_SIZE, nullptr);
|
|
|
|
frame.transient_size = TRANSIENT_BUFFER_INIT_SIZE;
|
2019-10-16 22:52:16 +02:00
|
|
|
frame.transient_ptr = (u8*)ffr::map(frame.transient_buffer, TRANSIENT_BUFFER_INIT_SIZE);
|
2019-10-16 22:36:33 +02:00
|
|
|
}
|
|
|
|
renderer.m_cpu_frame = &renderer.m_frame_data[0];
|
|
|
|
renderer.m_gpu_frame = &renderer.m_frame_data[1];
|
|
|
|
|
2019-06-02 01:57:10 +02:00
|
|
|
renderer.m_profiler.init();
|
2019-08-07 21:21:31 +02:00
|
|
|
|
|
|
|
renderer.m_material_buffer.buffer = ffr::allocBufferHandle();
|
2019-08-23 13:33:43 +02:00
|
|
|
renderer.m_material_buffer.data.resize(400);
|
|
|
|
renderer.m_material_buffer.map.insert(0, 0);
|
|
|
|
ffr::createBuffer(renderer.m_material_buffer.buffer, (u32)ffr::BufferFlags::UNIFORM_BUFFER, renderer.m_material_buffer.data.byte_size(), nullptr);
|
2019-08-07 21:21:31 +02:00
|
|
|
|
2019-08-23 13:33:43 +02:00
|
|
|
const u32 max_mat_count = renderer.m_material_buffer.data.size();
|
|
|
|
for (u32 i = 0; i < max_mat_count; ++i) {
|
2019-08-07 21:21:31 +02:00
|
|
|
*(u32*)&renderer.m_material_buffer.data[i] = i + 1;
|
|
|
|
}
|
2019-08-23 13:33:43 +02:00
|
|
|
*(u32*)&renderer.m_material_buffer.data[max_mat_count - 1] = 0xffFFffFF;
|
|
|
|
renderer.m_material_buffer.data[0].color = Vec4(1, 0, 1, 1);
|
2019-05-23 23:28:50 +02:00
|
|
|
}, &signal, JobSystem::INVALID_HANDLE, 1);
|
|
|
|
JobSystem::wait(signal);
|
|
|
|
|
2019-03-23 13:34:03 +01:00
|
|
|
ResourceManagerHub& manager = m_engine.getResourceManager();
|
2018-09-09 17:58:25 +02:00
|
|
|
m_pipeline_manager.create(PipelineResource::TYPE, manager);
|
2018-01-11 21:13:59 +01:00
|
|
|
m_texture_manager.create(Texture::TYPE, manager);
|
|
|
|
m_model_manager.create(Model::TYPE, manager);
|
|
|
|
m_material_manager.create(Material::TYPE, manager);
|
2018-08-22 19:52:08 +02:00
|
|
|
m_particle_emitter_manager.create(ParticleEmitterResource::TYPE, manager);
|
2018-01-11 21:13:59 +01:00
|
|
|
m_shader_manager.create(Shader::TYPE, manager);
|
2018-01-08 13:08:11 +01:00
|
|
|
m_font_manager = LUMIX_NEW(m_allocator, FontManager)(*this, m_allocator);
|
2018-01-11 21:13:59 +01:00
|
|
|
m_font_manager->create(FontResource::TYPE, manager);
|
2015-07-25 02:22:51 +02:00
|
|
|
|
2016-04-02 15:35:08 +02:00
|
|
|
RenderScene::registerLuaAPI(m_engine.getState());
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2018-10-27 21:05:52 +02:00
|
|
|
m_layers.emplace("default");
|
2015-07-25 02:22:51 +02:00
|
|
|
}
|
2014-09-07 14:24:52 +02:00
|
|
|
|
2017-10-11 17:13:47 +02:00
|
|
|
|
2019-07-25 18:50:31 +02:00
|
|
|
MemRef copy(const void* data, u32 size) override
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
|
|
|
MemRef mem = allocate(size);
|
|
|
|
copyMemory(mem.data, data, size);
|
|
|
|
return mem;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IAllocator& getAllocator() override
|
|
|
|
{
|
|
|
|
return m_allocator;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
void free(const MemRef& memory) override
|
|
|
|
{
|
|
|
|
ASSERT(memory.own);
|
|
|
|
m_allocator.deallocate(memory.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-25 18:50:31 +02:00
|
|
|
MemRef allocate(u32 size) override
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
|
|
|
MemRef ret;
|
|
|
|
ret.size = size;
|
|
|
|
ret.own = true;
|
|
|
|
ret.data = m_allocator.allocate(size);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-09 23:53:38 +02:00
|
|
|
void beginProfileBlock(const char* name, i64 link) override
|
2018-07-14 10:03:38 +02:00
|
|
|
{
|
2019-06-09 23:53:38 +02:00
|
|
|
m_profiler.beginQuery(name, link);
|
2018-07-14 10:03:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void endProfileBlock() override
|
|
|
|
{
|
2019-05-23 23:28:50 +02:00
|
|
|
m_profiler.endQuery();
|
2018-07-14 10:03:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-05 20:45:06 +02:00
|
|
|
void getTextureImage(ffr::TextureHandle texture, int size, void* data) override
|
|
|
|
{
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-09-05 20:45:06 +02:00
|
|
|
void setup() override {}
|
|
|
|
void execute() override {
|
2019-06-07 01:26:09 +02:00
|
|
|
PROFILE_FUNCTION();
|
2018-09-05 20:45:06 +02:00
|
|
|
ffr::pushDebugGroup("get image data");
|
|
|
|
ffr::getTextureImage(handle, size, buf);
|
|
|
|
ffr::popDebugGroup();
|
|
|
|
}
|
|
|
|
|
|
|
|
ffr::TextureHandle handle;
|
2019-07-25 18:50:31 +02:00
|
|
|
u32 size;
|
2018-09-05 20:45:06 +02:00
|
|
|
void* buf;
|
|
|
|
};
|
|
|
|
|
2019-05-23 23:28:50 +02:00
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
2018-09-05 20:45:06 +02:00
|
|
|
cmd->handle = texture;
|
|
|
|
cmd->size = size;
|
|
|
|
cmd->buf = data;
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-09-05 20:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-25 18:50:31 +02:00
|
|
|
void updateTexture(ffr::TextureHandle handle, u32 x, u32 y, u32 w, u32 h, ffr::TextureFormat format, const MemRef& mem) override
|
2019-05-12 00:18:35 +02:00
|
|
|
{
|
|
|
|
ASSERT(mem.size > 0);
|
|
|
|
ASSERT(handle.isValid());
|
|
|
|
|
|
|
|
struct Cmd : RenderJob {
|
|
|
|
void setup() override {}
|
|
|
|
void execute() override {
|
2019-06-07 01:26:09 +02:00
|
|
|
PROFILE_FUNCTION();
|
2019-05-12 00:18:35 +02:00
|
|
|
ffr::update(handle, 0, x, y, w, h, format, mem.data);
|
|
|
|
if (mem.own) {
|
|
|
|
renderer->free(mem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ffr::TextureHandle handle;
|
2019-07-25 18:50:31 +02:00
|
|
|
u32 x, y, w, h;
|
2019-05-12 00:18:35 +02:00
|
|
|
ffr::TextureFormat format;
|
|
|
|
MemRef mem;
|
|
|
|
RendererImpl* renderer;
|
|
|
|
};
|
|
|
|
|
2019-05-23 23:28:50 +02:00
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
2019-05-12 00:18:35 +02:00
|
|
|
cmd->handle = handle;
|
|
|
|
cmd->x = x;
|
|
|
|
cmd->y = y;
|
|
|
|
cmd->w = w;
|
|
|
|
cmd->h = h;
|
|
|
|
cmd->format = format;
|
|
|
|
cmd->mem = mem;
|
|
|
|
cmd->renderer = this;
|
|
|
|
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2019-05-12 00:18:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-28 17:38:15 +01:00
|
|
|
ffr::TextureHandle loadTexture(const MemRef& memory, u32 flags, ffr::TextureInfo* info, const char* debug_name) override
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2018-07-11 23:35:34 +02:00
|
|
|
ASSERT(memory.size > 0);
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
const ffr::TextureHandle handle = ffr::allocTextureHandle();
|
|
|
|
if (!handle.isValid()) return handle;
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
if(info) {
|
2019-08-11 20:32:21 +02:00
|
|
|
*info = ffr::getTextureInfo(memory.data);
|
2018-07-11 23:35:34 +02:00
|
|
|
}
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-07-14 10:03:38 +02:00
|
|
|
void setup() override {}
|
|
|
|
void execute() override {
|
2019-06-07 01:26:09 +02:00
|
|
|
PROFILE_FUNCTION();
|
2018-10-28 17:38:15 +01:00
|
|
|
ffr::loadTexture(handle, memory.data, memory.size, flags, debug_name);
|
2018-07-14 17:52:06 +02:00
|
|
|
if(memory.own) {
|
|
|
|
renderer->free(memory);
|
|
|
|
}
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
2018-10-28 17:38:15 +01:00
|
|
|
StaticString<MAX_PATH_LENGTH> debug_name;
|
2018-07-11 23:35:34 +02:00
|
|
|
ffr::TextureHandle handle;
|
2018-07-08 18:16:16 +02:00
|
|
|
MemRef memory;
|
2018-07-11 23:35:34 +02:00
|
|
|
u32 flags;
|
2018-07-14 17:52:06 +02:00
|
|
|
RendererImpl* renderer;
|
2018-07-08 18:16:16 +02:00
|
|
|
};
|
|
|
|
|
2019-05-23 23:28:50 +02:00
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
2018-10-28 17:38:15 +01:00
|
|
|
cmd->debug_name = debug_name;
|
2018-07-11 23:35:34 +02:00
|
|
|
cmd->handle = handle;
|
2018-07-08 18:16:16 +02:00
|
|
|
cmd->memory = memory;
|
2018-07-11 23:35:34 +02:00
|
|
|
cmd->flags = flags;
|
2018-07-14 17:52:06 +02:00
|
|
|
cmd->renderer = this;
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
return handle;
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-25 18:50:31 +02:00
|
|
|
TransientSlice allocTransient(u32 size) override
|
2018-07-17 01:13:58 +02:00
|
|
|
{
|
2018-07-22 15:22:36 +02:00
|
|
|
TransientSlice slice;
|
2019-08-11 20:32:21 +02:00
|
|
|
size = (size + 15) & ~15;
|
2019-10-16 22:36:33 +02:00
|
|
|
slice.buffer = m_cpu_frame->transient_buffer;
|
|
|
|
slice.offset = MT::atomicAdd(&m_cpu_frame->transient_offset, size);
|
|
|
|
if (slice.offset + size > m_cpu_frame->transient_size) {
|
2019-06-21 17:14:06 +02:00
|
|
|
logError("Renderer") << "Out of transient memory";
|
2019-05-25 13:03:00 +02:00
|
|
|
slice.size = 0;
|
|
|
|
slice.ptr = nullptr;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
slice.size = size;
|
2019-10-16 22:36:33 +02:00
|
|
|
slice.ptr = m_cpu_frame->transient_ptr + slice.offset;
|
2019-05-25 13:03:00 +02:00
|
|
|
}
|
2018-07-22 15:22:36 +02:00
|
|
|
return slice;
|
2018-07-17 01:13:58 +02:00
|
|
|
}
|
2019-07-07 11:13:33 +02:00
|
|
|
|
2019-08-07 21:21:31 +02:00
|
|
|
ffr::BufferHandle getMaterialUniformBuffer() override {
|
|
|
|
return m_material_buffer.buffer;
|
|
|
|
}
|
|
|
|
|
2019-08-12 18:10:01 +02:00
|
|
|
u32 createMaterialConstants(const MaterialConsts& data) override {
|
|
|
|
const u32 hash = crc32(&data, sizeof(data));
|
2019-08-07 21:21:31 +02:00
|
|
|
auto iter = m_material_buffer.map.find(hash);
|
|
|
|
u32 idx;
|
|
|
|
if(iter.isValid()) {
|
|
|
|
idx = iter.value();
|
|
|
|
}
|
|
|
|
else {
|
2019-08-07 21:42:25 +02:00
|
|
|
idx = m_material_buffer.first_free;
|
2019-08-23 13:33:43 +02:00
|
|
|
if (idx == 0xffFFffFF) {
|
|
|
|
++m_material_buffer.data[0].ref_count;
|
|
|
|
return 0;
|
|
|
|
}
|
2019-08-07 21:21:31 +02:00
|
|
|
const u32 next_free = *(u32*)&m_material_buffer.data[m_material_buffer.first_free];
|
|
|
|
memcpy(&m_material_buffer.data[m_material_buffer.first_free], &data, sizeof(data));
|
|
|
|
m_material_buffer.data[m_material_buffer.first_free].ref_count = 0;
|
|
|
|
m_material_buffer.first_free = next_free;
|
|
|
|
ASSERT(next_free != 0xffFFffFF);
|
|
|
|
m_material_buffer.dirty = true;
|
|
|
|
m_material_buffer.map.insert(hash, idx);
|
|
|
|
}
|
|
|
|
++m_material_buffer.data[idx].ref_count;
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
void destroyMaterialConstants(u32 idx) override {
|
|
|
|
--m_material_buffer.data[idx].ref_count;
|
|
|
|
if(m_material_buffer.data[idx].ref_count == 0) {
|
2019-08-23 13:33:43 +02:00
|
|
|
const u32 hash = crc32(&m_material_buffer.data[idx], sizeof(m_material_buffer.data[idx]));
|
2019-08-07 21:21:31 +02:00
|
|
|
*(u32*)&m_material_buffer.data[idx] = m_material_buffer.first_free;
|
|
|
|
m_material_buffer.first_free = idx;
|
|
|
|
m_material_buffer.map.erase(hash);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-17 01:13:58 +02:00
|
|
|
|
2019-08-09 17:12:39 +02:00
|
|
|
ffr::BufferHandle createBuffer(const MemRef& memory, u32 flags) override
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2018-07-11 23:35:34 +02:00
|
|
|
ffr::BufferHandle handle = ffr::allocBufferHandle();
|
|
|
|
if(!handle.isValid()) return handle;
|
|
|
|
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-07-14 10:03:38 +02:00
|
|
|
void setup() override {}
|
|
|
|
void execute() override {
|
2019-06-07 01:26:09 +02:00
|
|
|
PROFILE_FUNCTION();
|
2019-08-09 17:12:39 +02:00
|
|
|
ffr::createBuffer(handle, flags, memory.size, memory.data);
|
2018-07-14 17:52:06 +02:00
|
|
|
if (memory.own) {
|
|
|
|
renderer->free(memory);
|
|
|
|
}
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
ffr::BufferHandle handle;
|
2018-07-08 18:16:16 +02:00
|
|
|
MemRef memory;
|
2019-08-09 17:12:39 +02:00
|
|
|
u32 flags;
|
2018-07-08 18:16:16 +02:00
|
|
|
ffr::TextureFormat format;
|
2018-07-14 17:52:06 +02:00
|
|
|
Renderer* renderer;
|
2018-07-08 18:16:16 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
2018-07-11 23:35:34 +02:00
|
|
|
cmd->handle = handle;
|
2018-07-08 18:16:16 +02:00
|
|
|
cmd->memory = memory;
|
2018-07-14 17:52:06 +02:00
|
|
|
cmd->renderer = this;
|
2019-08-09 17:12:39 +02:00
|
|
|
cmd->flags = flags;
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
return handle;
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
2018-10-27 21:05:52 +02:00
|
|
|
|
|
|
|
u8 getLayersCount() const override
|
|
|
|
{
|
|
|
|
return (u8)m_layers.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char* getLayerName(u8 layer) const override
|
|
|
|
{
|
|
|
|
return m_layers[layer];
|
|
|
|
}
|
|
|
|
|
2018-07-08 18:16:16 +02:00
|
|
|
|
2018-10-13 15:08:58 +02:00
|
|
|
u8 getLayerIdx(const char* name) override
|
|
|
|
{
|
|
|
|
for(int i = 0; i < m_layers.size(); ++i) {
|
|
|
|
if(m_layers[i] == name) return i;
|
|
|
|
}
|
|
|
|
m_layers.emplace(name);
|
|
|
|
return m_layers.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-25 18:33:38 +02:00
|
|
|
void runInRenderThread(void* user_ptr, void (*fnc)(Renderer& renderer, void*)) override
|
2018-08-09 22:35:00 +02:00
|
|
|
{
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-08-09 22:35:00 +02:00
|
|
|
void setup() override {}
|
2019-06-07 01:26:09 +02:00
|
|
|
void execute() override {
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
fnc(*renderer, ptr);
|
|
|
|
}
|
2018-08-09 22:35:00 +02:00
|
|
|
|
|
|
|
void* ptr;
|
2018-09-25 18:33:38 +02:00
|
|
|
void (*fnc)(Renderer&, void*);
|
|
|
|
Renderer* renderer;
|
|
|
|
|
2018-08-09 22:35:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
|
|
|
cmd->fnc = fnc;
|
|
|
|
cmd->ptr = user_ptr;
|
2018-09-25 18:33:38 +02:00
|
|
|
cmd->renderer = this;
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-08-09 22:35:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void destroy(ffr::ProgramHandle program) override
|
|
|
|
{
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-08-09 22:35:00 +02:00
|
|
|
void setup() override {}
|
2019-06-07 01:26:09 +02:00
|
|
|
void execute() override {
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
ffr::destroy(program);
|
|
|
|
}
|
2018-08-09 22:35:00 +02:00
|
|
|
|
|
|
|
ffr::ProgramHandle program;
|
|
|
|
RendererImpl* renderer;
|
|
|
|
};
|
|
|
|
|
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
|
|
|
cmd->program = program;
|
|
|
|
cmd->renderer = this;
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-08-09 22:35:00 +02:00
|
|
|
}
|
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
void destroy(ffr::BufferHandle buffer) override
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-07-14 10:03:38 +02:00
|
|
|
void setup() override {}
|
2019-06-07 01:26:09 +02:00
|
|
|
void execute() override {
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
ffr::destroy(buffer);
|
|
|
|
}
|
2018-07-11 23:35:34 +02:00
|
|
|
|
|
|
|
ffr::BufferHandle buffer;
|
|
|
|
RendererImpl* renderer;
|
|
|
|
};
|
|
|
|
|
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
|
|
|
cmd->buffer = buffer;
|
|
|
|
cmd->renderer = this;
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-25 18:50:31 +02:00
|
|
|
ffr::TextureHandle createTexture(u32 w, u32 h, u32 depth, ffr::TextureFormat format, u32 flags, const MemRef& memory, const char* debug_name) override
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2018-07-11 23:35:34 +02:00
|
|
|
ffr::TextureHandle handle = ffr::allocTextureHandle();
|
|
|
|
if(!handle.isValid()) return handle;
|
|
|
|
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-07-14 10:03:38 +02:00
|
|
|
void setup() override {}
|
2018-07-14 17:52:06 +02:00
|
|
|
void execute() override
|
|
|
|
{
|
2019-06-07 01:26:09 +02:00
|
|
|
PROFILE_FUNCTION();
|
2018-10-28 17:38:15 +01:00
|
|
|
ffr::createTexture(handle, w, h, depth, format, flags, memory.data, debug_name);
|
2018-10-21 18:05:43 +02:00
|
|
|
if (memory.own) renderer->free(memory);
|
2018-07-14 17:52:06 +02:00
|
|
|
}
|
2018-07-11 23:35:34 +02:00
|
|
|
|
2018-10-28 17:38:15 +01:00
|
|
|
StaticString<MAX_PATH_LENGTH> debug_name;
|
2018-07-11 23:35:34 +02:00
|
|
|
ffr::TextureHandle handle;
|
|
|
|
MemRef memory;
|
2019-07-25 18:50:31 +02:00
|
|
|
u32 w;
|
|
|
|
u32 h;
|
|
|
|
u32 depth;
|
2018-07-11 23:35:34 +02:00
|
|
|
ffr::TextureFormat format;
|
2018-07-14 17:52:06 +02:00
|
|
|
Renderer* renderer;
|
2018-10-09 00:55:56 +02:00
|
|
|
u32 flags;
|
2018-07-11 23:35:34 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
2018-10-28 17:38:15 +01:00
|
|
|
cmd->debug_name = debug_name;
|
2018-07-11 23:35:34 +02:00
|
|
|
cmd->handle = handle;
|
|
|
|
cmd->memory = memory;
|
|
|
|
cmd->format = format;
|
2018-10-09 00:55:56 +02:00
|
|
|
cmd->flags = flags;
|
2018-07-11 23:35:34 +02:00
|
|
|
cmd->w = w;
|
|
|
|
cmd->h = h;
|
2018-10-21 18:05:43 +02:00
|
|
|
cmd->depth = depth;
|
2018-07-14 17:52:06 +02:00
|
|
|
cmd->renderer = this;
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-07-11 23:35:34 +02:00
|
|
|
|
|
|
|
return handle;
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-11 23:35:34 +02:00
|
|
|
void destroy(ffr::TextureHandle tex)
|
|
|
|
{
|
2019-06-27 18:19:24 +02:00
|
|
|
ASSERT(tex.isValid());
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-07-14 10:03:38 +02:00
|
|
|
void setup() override {}
|
2019-06-07 01:26:09 +02:00
|
|
|
void execute() override {
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
ffr::destroy(texture);
|
|
|
|
}
|
2018-07-11 23:35:34 +02:00
|
|
|
|
|
|
|
ffr::TextureHandle texture;
|
|
|
|
RendererImpl* renderer;
|
|
|
|
};
|
|
|
|
|
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
|
|
|
cmd->texture = tex;
|
|
|
|
cmd->renderer = this;
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-07-11 23:35:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-04 13:31:48 +02:00
|
|
|
void queue(RenderJob* cmd, i64 profiler_link) override
|
2018-07-08 18:16:16 +02:00
|
|
|
{
|
2019-06-09 23:53:38 +02:00
|
|
|
cmd->profiler_link = profiler_link;
|
2019-05-23 23:28:50 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
m_cpu_frame->jobs.push(cmd);
|
2019-07-04 13:31:48 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
JobSystem::runEx(cmd, [](void* data){
|
2019-05-23 23:28:50 +02:00
|
|
|
RenderJob* cmd = (RenderJob*)data;
|
|
|
|
PROFILE_BLOCK("setup_render_job");
|
2018-07-14 10:03:38 +02:00
|
|
|
cmd->setup();
|
2019-10-16 22:36:33 +02:00
|
|
|
}, &m_cpu_frame->setup_done, m_cpu_frame->transient_mapped, JobSystem::ANY_WORKER);
|
2018-07-08 18:16:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-26 18:52:52 +02:00
|
|
|
ResourceManager& getTextureManager() override { return m_texture_manager; }
|
2018-01-08 13:08:11 +01:00
|
|
|
FontManager& getFontManager() override { return *m_font_manager; }
|
2015-12-09 17:12:59 +01:00
|
|
|
|
2016-11-09 09:51:03 +01:00
|
|
|
void createScenes(Universe& ctx) override
|
2015-07-25 02:22:51 +02:00
|
|
|
{
|
2016-11-09 09:51:03 +01:00
|
|
|
auto* scene = RenderScene::createInstance(*this, m_engine, ctx, m_allocator);
|
|
|
|
ctx.addScene(scene);
|
2015-07-25 02:22:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-22 15:12:36 +01:00
|
|
|
void destroyScene(IScene* scene) override { RenderScene::destroyInstance(static_cast<RenderScene*>(scene)); }
|
2015-11-22 00:31:23 +01:00
|
|
|
const char* getName() const override { return "renderer"; }
|
2015-11-20 16:58:10 +01:00
|
|
|
Engine& getEngine() override { return m_engine; }
|
2017-02-22 15:12:36 +01:00
|
|
|
int getShaderDefinesCount() const override { return m_shader_defines.size(); }
|
2018-07-01 18:13:44 +02:00
|
|
|
const char* getShaderDefine(int define_idx) const override { return m_shader_defines[define_idx]; }
|
2019-06-13 17:26:52 +02:00
|
|
|
|
2018-06-24 17:50:33 +02:00
|
|
|
void makeScreenshot(const Path& filename) override { }
|
|
|
|
void resize(int w, int h) override { }
|
2015-09-05 21:36:34 +02:00
|
|
|
|
|
|
|
|
2016-11-20 17:27:41 +01:00
|
|
|
u8 getShaderDefineIdx(const char* define) override
|
2015-09-05 13:08:47 +02:00
|
|
|
{
|
2019-08-21 21:11:51 +02:00
|
|
|
MT::CriticalSectionLock lock(m_shader_defines_mutex);
|
2015-09-05 13:08:47 +02:00
|
|
|
for (int i = 0; i < m_shader_defines.size(); ++i)
|
|
|
|
{
|
2016-04-28 10:14:47 +02:00
|
|
|
if (m_shader_defines[i] == define)
|
2015-09-05 13:08:47 +02:00
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-16 19:16:01 +02:00
|
|
|
if (m_shader_defines.size() >= MAX_SHADER_DEFINES) {
|
|
|
|
ASSERT(false);
|
2019-06-21 17:14:06 +02:00
|
|
|
logError("Renderer") << "Too many shader defines.";
|
2018-06-16 19:16:01 +02:00
|
|
|
}
|
|
|
|
|
2016-04-28 10:14:47 +02:00
|
|
|
m_shader_defines.emplace(define);
|
2019-08-21 21:11:51 +02:00
|
|
|
ASSERT(m_shader_defines.size() <= 32); // m_shader_defines are reserved in renderer constructor, so getShaderDefine() is MT safe
|
2015-09-05 13:08:47 +02:00
|
|
|
return m_shader_defines.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-05 20:45:06 +02:00
|
|
|
void startCapture() override
|
|
|
|
{
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-09-05 20:45:06 +02:00
|
|
|
void setup() override {}
|
|
|
|
void execute() override {
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
ffr::startCapture();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-09-05 20:45:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void stopCapture() override
|
|
|
|
{
|
2018-10-12 00:12:44 +02:00
|
|
|
struct Cmd : RenderJob {
|
2018-09-05 20:45:06 +02:00
|
|
|
void setup() override {}
|
|
|
|
void execute() override {
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
ffr::stopCapture();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Cmd* cmd = LUMIX_NEW(m_allocator, Cmd);
|
2019-07-04 13:31:48 +02:00
|
|
|
queue(cmd, 0);
|
2018-09-05 20:45:06 +02:00
|
|
|
}
|
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
void render(FrameData& frame) {
|
|
|
|
ffr::unmap(frame.transient_buffer);
|
|
|
|
frame.transient_ptr = nullptr;
|
2019-07-04 13:31:48 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
if (m_material_buffer.dirty) {
|
|
|
|
ffr::update(m_material_buffer.buffer, m_material_buffer.data.begin(), m_material_buffer.data.byte_size());
|
|
|
|
m_material_buffer.dirty = false;
|
|
|
|
}
|
2019-08-22 19:25:15 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
ffr::bindVertexBuffer(0, ffr::INVALID_BUFFER, 0, 0);
|
|
|
|
ffr::bindVertexBuffer(1, ffr::INVALID_BUFFER, 0, 0);
|
|
|
|
for (RenderJob* job : frame.jobs) {
|
|
|
|
PROFILE_BLOCK("execute_render_job");
|
|
|
|
Profiler::blockColor(0xaa, 0xff, 0xaa);
|
|
|
|
Profiler::link(job->profiler_link);
|
|
|
|
job->execute();
|
|
|
|
LUMIX_DELETE(m_allocator, job);
|
|
|
|
}
|
|
|
|
frame.jobs.clear();
|
2019-07-04 13:31:48 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
PROFILE_BLOCK("swap buffers");
|
|
|
|
JobSystem::enableBackupWorker(true);
|
2019-08-09 09:55:19 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
ffr::swapBuffers(frame.window_size.x, frame.window_size.y);
|
2019-07-04 13:31:48 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
JobSystem::enableBackupWorker(false);
|
|
|
|
m_profiler.frame();
|
|
|
|
|
|
|
|
if ((u32)frame.transient_offset > frame.transient_size) {
|
|
|
|
frame.transient_size = nextPow2(frame.transient_offset);
|
|
|
|
ffr::destroy(frame.transient_buffer);
|
|
|
|
frame.transient_buffer = ffr::allocBufferHandle();
|
|
|
|
ffr::createBuffer(frame.transient_buffer, 0, frame.transient_size, nullptr);
|
2019-07-04 13:31:48 +02:00
|
|
|
}
|
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
ASSERT(!frame.transient_ptr);
|
|
|
|
frame.transient_ptr = (u8*)ffr::map(frame.transient_buffer, frame.transient_size);
|
|
|
|
frame.transient_offset = 0;
|
|
|
|
JobSystem::decSignal(frame.transient_mapped);
|
|
|
|
}
|
2018-09-05 20:45:06 +02:00
|
|
|
|
2019-09-29 15:02:27 +02:00
|
|
|
void waitForCommandSetup() override
|
|
|
|
{
|
2019-10-16 22:36:33 +02:00
|
|
|
JobSystem::wait(m_cpu_frame->setup_done);
|
|
|
|
m_cpu_frame->setup_done = JobSystem::INVALID_HANDLE;
|
2019-09-29 15:02:27 +02:00
|
|
|
}
|
|
|
|
|
2019-05-25 13:03:00 +02:00
|
|
|
void frame() override
|
2018-07-11 23:35:34 +02:00
|
|
|
{
|
2019-05-25 13:03:00 +02:00
|
|
|
PROFILE_FUNCTION();
|
2019-07-04 13:31:48 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
JobSystem::wait(m_cpu_frame->setup_done);
|
|
|
|
m_cpu_frame->setup_done = JobSystem::INVALID_HANDLE;
|
|
|
|
JobSystem::wait(m_gpu_frame->rendering_done);
|
|
|
|
m_gpu_frame->rendering_done = JobSystem::INVALID_HANDLE;
|
|
|
|
|
2019-08-09 09:55:19 +02:00
|
|
|
const void* window_handle = m_engine.getPlatformData().window_handle;
|
2019-10-16 22:36:33 +02:00
|
|
|
m_cpu_frame->window_size = OS::getWindowClientSize((OS::WindowHandle)window_handle);
|
|
|
|
JobSystem::incSignal(&m_cpu_frame->transient_mapped);
|
2019-08-22 19:25:15 +02:00
|
|
|
|
2019-10-16 22:36:33 +02:00
|
|
|
JobSystem::runEx(m_cpu_frame, [](void* ptr){
|
|
|
|
auto* data = (FrameData*)ptr;
|
|
|
|
data->renderer.render(*data);
|
|
|
|
}, &m_cpu_frame->rendering_done, JobSystem::INVALID_HANDLE, 1);
|
|
|
|
|
|
|
|
swap(m_gpu_frame, m_cpu_frame);
|
2015-07-31 22:22:37 +02:00
|
|
|
}
|
|
|
|
|
2015-07-25 02:22:51 +02:00
|
|
|
Engine& m_engine;
|
2016-02-04 16:20:01 +01:00
|
|
|
IAllocator& m_allocator;
|
2019-07-04 13:56:05 +02:00
|
|
|
Array<StaticString<32>> m_shader_defines;
|
2019-08-21 21:11:51 +02:00
|
|
|
MT::CriticalSection m_shader_defines_mutex;
|
2018-10-13 15:08:58 +02:00
|
|
|
Array<StaticString<32>> m_layers;
|
2018-01-08 13:08:11 +01:00
|
|
|
FontManager* m_font_manager;
|
2019-08-23 13:33:43 +02:00
|
|
|
MaterialManager m_material_manager;
|
2019-06-12 23:38:06 +02:00
|
|
|
RenderResourceManager<Model> m_model_manager;
|
2019-06-13 17:26:52 +02:00
|
|
|
RenderResourceManager<ParticleEmitterResource> m_particle_emitter_manager;
|
|
|
|
RenderResourceManager<PipelineResource> m_pipeline_manager;
|
2019-06-12 23:38:06 +02:00
|
|
|
RenderResourceManager<Shader> m_shader_manager;
|
2019-06-26 18:52:52 +02:00
|
|
|
RenderResourceManager<Texture> m_texture_manager;
|
2017-10-02 16:35:21 +02:00
|
|
|
bool m_vsync;
|
2019-07-30 21:58:31 +02:00
|
|
|
bool m_debug_opengl = false;
|
2019-10-16 22:36:33 +02:00
|
|
|
|
|
|
|
Array<FrameData> m_frame_data;
|
|
|
|
FrameData* m_cpu_frame = nullptr;
|
|
|
|
FrameData* m_gpu_frame = nullptr;
|
|
|
|
|
2019-05-23 23:28:50 +02:00
|
|
|
GPUProfiler m_profiler;
|
2019-08-07 21:21:31 +02:00
|
|
|
|
|
|
|
struct MaterialBuffer {
|
2019-08-23 13:33:43 +02:00
|
|
|
MaterialBuffer(IAllocator& alloc) : map(alloc), data(alloc) {}
|
2019-08-07 21:21:31 +02:00
|
|
|
ffr::BufferHandle buffer = ffr::INVALID_BUFFER;
|
2019-08-23 13:33:43 +02:00
|
|
|
Array<MaterialConsts> data;
|
2019-08-07 21:21:31 +02:00
|
|
|
HashMap<u32, u32> map;
|
2019-08-23 13:33:43 +02:00
|
|
|
u32 first_free = 1;
|
2019-08-07 21:21:31 +02:00
|
|
|
// TODO this is not MT safe
|
|
|
|
bool dirty = false;
|
|
|
|
} m_material_buffer;
|
2019-05-23 23:28:50 +02:00
|
|
|
};
|
2018-07-11 23:35:34 +02:00
|
|
|
|
|
|
|
|
2015-08-17 23:45:26 +02:00
|
|
|
extern "C"
|
2015-07-25 02:22:51 +02:00
|
|
|
{
|
2016-02-14 11:28:08 +01:00
|
|
|
LUMIX_PLUGIN_ENTRY(renderer)
|
2015-08-17 23:45:26 +02:00
|
|
|
{
|
2016-07-11 19:41:28 +02:00
|
|
|
return LUMIX_NEW(engine.getAllocator(), RendererImpl)(engine);
|
2015-08-17 23:45:26 +02:00
|
|
|
}
|
2015-07-25 02:22:51 +02:00
|
|
|
}
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2015-02-27 23:56:06 +01:00
|
|
|
|
2016-02-14 21:02:09 +01:00
|
|
|
} // namespace Lumix
|
2015-08-17 23:45:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
|