This commit is contained in:
Mikulas Florek 2018-08-26 18:19:50 +02:00
parent 54b735ed87
commit 25c5721822
10 changed files with 158 additions and 28 deletions

View file

@ -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;

View file

@ -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);

View file

@ -84,8 +84,7 @@ void Resource::fileLoaded(FS::IFile& file, bool success)
return;
}
if (!load(file))
{
if (!load(file)) {
++m_failed_dep_count;
}

View file

@ -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();

View file

@ -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();

View file

@ -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);

View file

@ -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

View file

@ -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;
};

View file

@ -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;

View file

@ -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)