ffr WIP
This commit is contained in:
parent
54b735ed87
commit
25c5721822
10 changed files with 158 additions and 28 deletions
|
@ -162,6 +162,20 @@ namespace Lumix
|
|||
}
|
||||
|
||||
|
||||
void* OutputBlob::skip(int size)
|
||||
{
|
||||
ASSERT(size > 0);
|
||||
|
||||
if (m_pos + size > m_size)
|
||||
{
|
||||
reserve((m_pos + size) << 1);
|
||||
}
|
||||
void* ret = (u8*)m_data + m_pos;
|
||||
m_pos += size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void OutputBlob::write(const void* data, int size)
|
||||
{
|
||||
if (!size) return;
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace Lumix
|
|||
void writeString(const char* string);
|
||||
template <class T> void write(const T& value);
|
||||
void clear();
|
||||
void* skip(int size);
|
||||
|
||||
OutputBlob& operator << (const char* str);
|
||||
OutputBlob& operator << (u64 value);
|
||||
|
|
|
@ -84,8 +84,7 @@ void Resource::fileLoaded(FS::IFile& file, bool success)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!load(file))
|
||||
{
|
||||
if (!load(file)) {
|
||||
++m_failed_dep_count;
|
||||
}
|
||||
|
||||
|
|
|
@ -1093,6 +1093,12 @@ void drawTriangles(uint indices_count)
|
|||
}
|
||||
|
||||
|
||||
void drawTriangleStripArraysInstanced(uint offset, uint indices_count, uint instances_count)
|
||||
{
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, offset, indices_count, instances_count);
|
||||
}
|
||||
|
||||
|
||||
void drawArrays(uint offset, uint count, PrimitiveType type)
|
||||
{
|
||||
checkThread();
|
||||
|
|
|
@ -198,6 +198,7 @@ void drawTriangles(uint indices_count);
|
|||
void drawTrianglesInstanced(uint indices_offset_bytes, uint indices_count, uint instances_count);
|
||||
void drawElements(uint offset, uint count, PrimitiveType type);
|
||||
void drawArrays(uint offset, uint count, PrimitiveType type);
|
||||
void drawTriangleStripArraysInstanced(uint offset, uint indices_count, uint instances_count);
|
||||
|
||||
void pushDebugGroup(const char* msg);
|
||||
void popDebugGroup();
|
||||
|
|
|
@ -43,6 +43,7 @@ FFR_GL_IMPORT(PFNGLDELETEPROGRAMPROC, glDeleteProgram);
|
|||
FFR_GL_IMPORT(PFNGLDELETEQUERIESPROC, glDeleteQueries);
|
||||
FFR_GL_IMPORT(PFNGLDELETESHADERPROC, glDeleteShader);
|
||||
FFR_GL_IMPORT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray);
|
||||
FFR_GL_IMPORT(PFNGLDRAWARRAYSINSTANCEDARBPROC, glDrawArraysInstanced);
|
||||
FFR_GL_IMPORT(PFNGLDRAWBUFFERSPROC, glDrawBuffers);
|
||||
FFR_GL_IMPORT(PFNGLDRAWELEMENTSINSTANCEDPROC, glDrawElementsInstanced);
|
||||
FFR_GL_IMPORT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray);
|
||||
|
|
|
@ -101,6 +101,12 @@ struct Compiler
|
|||
{
|
||||
m_streams[0].type = DataStream::CONST;
|
||||
m_streams[0].index = 0;
|
||||
m_streams[1].type = DataStream::CONST;
|
||||
m_streams[1].index = 1;
|
||||
m_streams[2].type = DataStream::CONST;
|
||||
m_streams[2].index = 2;
|
||||
m_streams[3].type = DataStream::CONST;
|
||||
m_streams[3].index = 3;
|
||||
++m_streams_count;
|
||||
++m_constants_count;
|
||||
}
|
||||
|
@ -248,6 +254,13 @@ struct Compiler
|
|||
}
|
||||
|
||||
|
||||
static int sub(lua_State* L)
|
||||
{
|
||||
writeBinaryInstruction(Instructions::SUB, L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int out(lua_State* L)
|
||||
{
|
||||
Compiler* c = getCompiler(L);
|
||||
|
@ -313,6 +326,7 @@ bool ParticleEmitterResource::load(FS::IFile& file)
|
|||
DEFINE_LUA_FUNC(mov);
|
||||
|
||||
DEFINE_LUA_FUNC(add);
|
||||
DEFINE_LUA_FUNC(sub);
|
||||
DEFINE_LUA_FUNC(mul);
|
||||
DEFINE_LUA_FUNC(cos);
|
||||
DEFINE_LUA_FUNC(sin);
|
||||
|
@ -350,6 +364,22 @@ bool ParticleEmitterResource::load(FS::IFile& file)
|
|||
m_emit_byte_offset = compiler.m_bytecode.getPos();
|
||||
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "emit");
|
||||
if(lua_isfunction(L, -1)) {
|
||||
lua_pushinteger(L, 1);
|
||||
lua_pushinteger(L, 2);
|
||||
lua_pushinteger(L, 3);
|
||||
if(lua_pcall(L, 3, 0, 0) != 0) {
|
||||
g_log_error.log("Renderer") << lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
lua_close(L);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
compiler.m_bytecode.write(Instructions::END);
|
||||
|
||||
m_output_byte_offset = compiler.m_bytecode.getPos();
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "output");
|
||||
if(lua_isfunction(L, -1)) {
|
||||
if(lua_pcall(L, 0, 0, 0) != 0) {
|
||||
g_log_error.log("Renderer") << lua_tostring(L, -1);
|
||||
|
@ -360,6 +390,7 @@ bool ParticleEmitterResource::load(FS::IFile& file)
|
|||
}
|
||||
lua_pop(L, 1);
|
||||
compiler.m_bytecode.write(Instructions::END);
|
||||
|
||||
m_channels_count = compiler.m_channels_count;
|
||||
m_registers_count = compiler.m_registers_count;
|
||||
m_outputs_count = compiler.m_outputs_count;
|
||||
|
@ -374,7 +405,10 @@ bool ParticleEmitterResource::load(FS::IFile& file)
|
|||
|
||||
lua_close(L);
|
||||
|
||||
if (!m_material) return false;
|
||||
if (!m_material) {
|
||||
g_log_error.log("Renderer") << getPath() << " has no material.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -384,7 +418,6 @@ ParticleEmitter::ParticleEmitter(EntityPtr entity, IAllocator& allocator)
|
|||
: m_allocator(allocator)
|
||||
, m_entity(entity)
|
||||
, m_emit_buffer(allocator)
|
||||
, m_instance_data(allocator)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -540,7 +573,7 @@ void ParticleEmitter::execute(InputBlob& blob, int particle_index)
|
|||
}
|
||||
|
||||
|
||||
static float4* getStream(ParticleEmitter& emitter
|
||||
static float4* getStream(const ParticleEmitter& emitter
|
||||
, Compiler::DataStream::Type type
|
||||
, int idx
|
||||
, int particles_count
|
||||
|
@ -572,7 +605,6 @@ void ParticleEmitter::update(float dt)
|
|||
Array<float4> reg_mem(m_allocator);
|
||||
reg_mem.resize(m_resource->getRegistersCount() * ((m_particles_count + 3) >> 2));
|
||||
m_instances_count = m_particles_count;
|
||||
m_instance_data.resize(m_particles_count * m_resource->getOutputsCount() * 4);
|
||||
int output_idx = 0;
|
||||
|
||||
for (;;)
|
||||
|
@ -657,7 +689,7 @@ void ParticleEmitter::update(float dt)
|
|||
break;
|
||||
}
|
||||
case Instructions::OUTPUT: {
|
||||
const auto arg_type = blob.read<Compiler::DataStream::Type>();
|
||||
/* const auto arg_type = blob.read<Compiler::DataStream::Type>();
|
||||
const u8 arg_idx = blob.read<u8>();
|
||||
const float* arg = (float*)getStream(*this, arg_type, arg_idx, m_particles_count, reg_mem.begin());
|
||||
float* dst = m_instance_data.begin() + output_idx;
|
||||
|
@ -665,7 +697,7 @@ void ParticleEmitter::update(float dt)
|
|||
const int stride = m_resource->getOutputsCount();
|
||||
for (int i = 0; i < m_particles_count; ++i) {
|
||||
dst[i * stride] = arg[i];
|
||||
}
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -686,6 +718,68 @@ void ParticleEmitter::update(float dt)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int ParticleEmitter::getInstanceDataSizeBytes() const
|
||||
{
|
||||
return ((m_particles_count + 3) & ~3) * m_resource->getOutputsCount() * sizeof(float);
|
||||
}
|
||||
|
||||
|
||||
void ParticleEmitter::fillInstanceData(const Vec3& cam_pos, float* data)
|
||||
{
|
||||
const OutputBlob& bytecode = m_resource->getBytecode();
|
||||
const int offset = m_resource->getOutputByteOffset();
|
||||
InputBlob blob((u8*)bytecode.getData() + offset, bytecode.getPos());
|
||||
|
||||
// TODO
|
||||
m_constants[1].value = cam_pos.x;
|
||||
m_constants[2].value = cam_pos.y;
|
||||
m_constants[3].value = cam_pos.z;
|
||||
// TODO
|
||||
Array<float4> reg_mem(m_allocator);
|
||||
reg_mem.resize(m_resource->getRegistersCount() * ((m_particles_count + 3) >> 2));
|
||||
int output_idx = 0;
|
||||
for (;;)
|
||||
{
|
||||
u8 instruction = blob.read<u8>();
|
||||
switch ((Instructions)instruction)
|
||||
{
|
||||
case Instructions::END:
|
||||
return;
|
||||
case Instructions::SIN: {
|
||||
const auto dst_type = blob.read<Compiler::DataStream::Type>();
|
||||
const u8 dst_idx = blob.read<u8>();
|
||||
const auto arg_type = blob.read<Compiler::DataStream::Type>();
|
||||
const u8 arg_idx = blob.read<u8>();
|
||||
|
||||
const float* arg = (float*)getStream(*this, arg_type, arg_idx, m_particles_count, reg_mem.begin());
|
||||
float* result = (float*)getStream(*this, dst_type, dst_idx, m_particles_count, reg_mem.begin());
|
||||
const float* const end = result + ((m_particles_count + 3) & ~3);
|
||||
|
||||
for (; result != end; ++result, ++arg) {
|
||||
*result = sinf(*arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Instructions::OUTPUT: {
|
||||
const auto arg_type = blob.read<Compiler::DataStream::Type>();
|
||||
const u8 arg_idx = blob.read<u8>();
|
||||
const float* arg = (float*)getStream(*this, arg_type, arg_idx, m_particles_count, reg_mem.begin());
|
||||
float* dst = data + output_idx;
|
||||
++output_idx;
|
||||
const int stride = m_resource->getOutputsCount();
|
||||
for (int i = 0; i < m_particles_count; ++i) {
|
||||
dst[i * stride] = arg[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*
|
||||
bgfx::InstanceDataBuffer ParticleEmitter::generateInstanceBuffer() const
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
bool load(FS::IFile& file) override;
|
||||
const OutputBlob& getBytecode() const { return m_bytecode; }
|
||||
int getEmitByteOffset() const { return m_emit_byte_offset; }
|
||||
int getOutputByteOffset() const { return m_output_byte_offset; }
|
||||
int getChannelsCount() const { return m_channels_count; }
|
||||
int getRegistersCount() const { return m_registers_count; }
|
||||
int getOutputsCount() const { return m_outputs_count; }
|
||||
|
@ -53,6 +54,7 @@ private:
|
|||
OutputBlob m_bytecode;
|
||||
float m_literals[16];
|
||||
int m_emit_byte_offset;
|
||||
int m_output_byte_offset;
|
||||
int m_channels_count;
|
||||
int m_registers_count;
|
||||
int m_outputs_count;
|
||||
|
@ -75,8 +77,8 @@ public:
|
|||
void deserialize(InputBlob& blob, ResourceManagerHub& manager);
|
||||
void update(float dt);
|
||||
void emit(const float* args);
|
||||
const float* getInstanceData() const { return m_instance_data.begin(); }
|
||||
int getInstanceDataSizeBytes() const { return m_instance_data.byte_size(); }
|
||||
void fillInstanceData(const Vec3& cam_pos, float* data);
|
||||
int getInstanceDataSizeBytes() const;
|
||||
ParticleEmitterResource* getResource() const { return m_resource; }
|
||||
void setResource(ParticleEmitterResource* res);
|
||||
int getInstancesCount() const { return m_instances_count; }
|
||||
|
@ -110,7 +112,6 @@ private:
|
|||
int m_particles_count = 0;
|
||||
int m_instances_count = 0;
|
||||
ParticleEmitterResource* m_resource = nullptr;
|
||||
Array<float> m_instance_data;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -719,6 +719,7 @@ struct PipelineImpl final : Pipeline
|
|||
if (lua_type(L, pipeline_idx) != LUA_TLIGHTUSERDATA) {
|
||||
LuaWrapper::argError<PipelineImpl*>(L, pipeline_idx);
|
||||
}
|
||||
const CameraParams cp = checkCameraParams(L ,3);
|
||||
PipelineImpl* pipeline = LuaWrapper::toType<PipelineImpl*>(L, pipeline_idx);
|
||||
|
||||
struct Cmd : Renderer::RenderCommandBase
|
||||
|
@ -740,47 +741,57 @@ struct PipelineImpl final : Pipeline
|
|||
|
||||
for (ParticleEmitter* emitter : emitters) {
|
||||
if (!emitter->getResource() || !emitter->getResource()->isReady()) continue;
|
||||
const int instances_count = emitter->getInstancesCount();
|
||||
if (instances_count == 0) continue;
|
||||
|
||||
const Material* material = emitter->getResource()->getMaterial();
|
||||
m_data.write(material->getShader()->m_render_data);
|
||||
m_data.write(emitter->getInstanceDataSizeBytes());
|
||||
m_data.write(emitter->getInstancesCount());
|
||||
m_data.write(emitter->getInstanceData(), emitter->getInstanceDataSizeBytes());
|
||||
m_data.write(instances_count);
|
||||
const int size = emitter->getInstanceDataSizeBytes();
|
||||
float* instance_data = (float*)m_data.skip(size);
|
||||
emitter->fillInstanceData(m_camera_params.pos, instance_data);
|
||||
}
|
||||
}
|
||||
|
||||
void execute() override
|
||||
{
|
||||
ffr::pushDebugGroup("particles");
|
||||
InputBlob blob(m_data);
|
||||
ffr::VertexDecl instance_decl;
|
||||
instance_decl.addAttribute(2, ffr::AttributeType::FLOAT, false, false);
|
||||
instance_decl.addAttribute(3, ffr::AttributeType::FLOAT, false, false);
|
||||
|
||||
while(blob.getPosition() < blob.getSize()) {
|
||||
Shader::RenderData* shader_data = blob.read<Shader::RenderData*>();
|
||||
const int byte_size = blob.read<int>();
|
||||
const int instances_count = blob.read<int>();
|
||||
const Renderer::TransientSlice transient = m_pipeline->m_renderer.allocTransient(byte_size);
|
||||
if ((int)transient.size < byte_size) break;
|
||||
if ((int)transient.size < byte_size) {
|
||||
g_log_warning.log("Renderer") << "Not enough memory reserved to render all particles.";
|
||||
break;
|
||||
}
|
||||
|
||||
const void* mem = blob.skip(byte_size);
|
||||
ffr::update(transient.buffer, mem, transient.offset, byte_size);
|
||||
|
||||
const Shader::Program& prog = Shader::getProgram(shader_data, 0);
|
||||
|
||||
ffr::blending(0);
|
||||
ffr::useProgram(prog.handle);
|
||||
ffr::setInstanceBuffer(instance_decl, transient.buffer, transient.offset, 0);
|
||||
#error todo
|
||||
// TODO
|
||||
// ffr::setIndexBuffer(m_pipeline->getParticlesIndexBuffer());
|
||||
ffr::drawTrianglesInstanced(0, 6, instances_count);
|
||||
ffr::drawTriangleStripArraysInstanced(0, 4, instances_count);
|
||||
}
|
||||
ffr::popDebugGroup();
|
||||
}
|
||||
|
||||
OutputBlob m_data;
|
||||
PipelineImpl* m_pipeline;
|
||||
CameraParams m_camera_params;
|
||||
};
|
||||
|
||||
Cmd* cmd = LUMIX_NEW(pipeline->m_allocator, Cmd)(pipeline->m_allocator);
|
||||
cmd->m_pipeline = pipeline;
|
||||
cmd->m_camera_params = cp;
|
||||
|
||||
pipeline->m_renderer.push(cmd);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -441,14 +441,16 @@ bool Shader::load(FS::IFile& file)
|
|||
|
||||
void Shader::unload()
|
||||
{
|
||||
m_renderer.runInRenderThread(m_render_data, [](void* ptr){
|
||||
RenderData* rd = (RenderData*)ptr;
|
||||
for(const Program& prg : rd->programs) {
|
||||
ffr::destroy(prg.handle);
|
||||
}
|
||||
LUMIX_DELETE(rd->allocator, rd);
|
||||
});
|
||||
m_render_data = nullptr;
|
||||
if (m_render_data) {
|
||||
m_renderer.runInRenderThread(m_render_data, [](void* ptr){
|
||||
RenderData* rd = (RenderData*)ptr;
|
||||
for(const Program& prg : rd->programs) {
|
||||
if (prg.handle.isValid()) ffr::destroy(prg.handle);
|
||||
}
|
||||
LUMIX_DELETE(rd->allocator, rd);
|
||||
});
|
||||
m_render_data = nullptr;
|
||||
}
|
||||
// TODO
|
||||
/*
|
||||
for (auto& uniform : m_uniforms)
|
||||
|
|
Loading…
Reference in a new issue