more opengl related fixes (like proper instancing), disabled signaling a command buffer rebuild on graphic.updateMesh (to-do: properly handle this strictly for immediate-mode debug draw, or just do some lambda memery)

This commit is contained in:
ecker 2026-07-02 19:22:07 -05:00
parent 65a08839f9
commit fa5f421140
10 changed files with 214 additions and 113 deletions

View File

@ -274,7 +274,7 @@
"rebuild on tick begin": false "rebuild on tick begin": false
}, },
"pipelines": { "pipelines": {
"culling": true "culling": false
}, },
"experimental": { "experimental": {
"rebuild on tick begin": false, "rebuild on tick begin": false,
@ -353,11 +353,11 @@
"max": 0.1 // 0.2 "max": 0.1 // 0.2
}, },
"debug draw": { "debug draw": {
"static": true, "static": false,
"dynamic": true, "dynamic": false,
"trigger": false, "trigger": false,
"contacts": false, "contacts": false,
"constraints": true, "constraints": false,
"rays": false, "rays": false,
"depthTest": true "depthTest": true
}, },

View File

@ -1,8 +1,8 @@
{ {
// "import": "./rp_downtown_v2.json" // "import": "./rp_downtown_v2.json"
// "import": "./ss2_medsci1.json" // "import": "./ss2_medsci1.json"
// "import": "./mds_mcdonalds.json" "import": "./mds_mcdonalds.json"
"import": "./cs_office.json" // "import": "./cs_office.json"
// "import": "./de_dust2.json" // "import": "./de_dust2.json"
// "import": "./gm_construct.json" // "import": "./gm_construct.json"
} }

View File

@ -40,6 +40,7 @@ namespace ext {
struct { struct {
uf::stl::vector<Buffer> buffers; uf::stl::vector<Buffer> buffers;
uf::stl::vector<Texture> textures;
} transient; } transient;
void initialize(); void initialize();

View File

@ -86,6 +86,7 @@ namespace ext {
// extern UF_API RenderMode* currentRenderMode; // extern UF_API RenderMode* currentRenderMode;
extern UF_API uf::stl::vector<RenderMode*> renderModes; extern UF_API uf::stl::vector<RenderMode*> renderModes;
extern UF_API uf::ThreadUnique<RenderMode*> currentRenderMode; extern UF_API uf::ThreadUnique<RenderMode*> currentRenderMode;
extern UF_API uf::stl::unordered_map<uf::stl::string, ext::opengl::RenderMode*> renderModesMap;
bool UF_API hasRenderMode( const uf::stl::string&, bool = true ); bool UF_API hasRenderMode( const uf::stl::string&, bool = true );
RenderMode& UF_API addRenderMode( RenderMode*, const uf::stl::string& = "" ); RenderMode& UF_API addRenderMode( RenderMode*, const uf::stl::string& = "" );

View File

@ -11,6 +11,7 @@ namespace ext {
bool execute = false; bool execute = false;
bool executed = false; bool executed = false;
bool rebuild = false; bool rebuild = false;
bool rerecord = false;
bool resized = false; bool resized = false;
uint32_t width = 0; uint32_t width = 0;

View File

@ -748,11 +748,9 @@ void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity, uf::M
if ( material.modeCull == pod::Material::CullMode::NONE ) { if ( material.modeCull == pod::Material::CullMode::NONE ) {
tag["renderer"]["cull mode"] = "none"; tag["renderer"]["cull mode"] = "none";
} }
#if UF_USE_VULKAN
if ( material.modeAlpha == pod::Material::AlphaMode::BLEND ) { if ( material.modeAlpha == pod::Material::AlphaMode::BLEND ) {
graphic.descriptor.renderTarget = 1; graphic.descriptor.renderTarget = 1;
} }
#endif
} }
} }
} }

View File

@ -252,7 +252,7 @@ void ext::opengl::CommandBuffer::drawIndexed( const ext::opengl::CommandBuffer::
GL_ERROR_CHECK(glMatrixMode(GL_PROJECTION)); GL_ERROR_CHECK(glMatrixMode(GL_PROJECTION));
GL_ERROR_CHECK(glLoadMatrixf( &projection[0] )); GL_ERROR_CHECK(glLoadMatrixf( &projection[0] ));
#if UF_ENV_DREAMCAST #if 0 && UF_ENV_DREAMCAST
// washingtondc has a regression where non-alpha-tested polys do not render // washingtondc has a regression where non-alpha-tested polys do not render
// more convenient to just work around the regression since later builds have working opengl backends // more convenient to just work around the regression since later builds have working opengl backends
GL_ERROR_CHECK(glEnable(GL_ALPHA_TEST)); GL_ERROR_CHECK(glEnable(GL_ALPHA_TEST));

View File

@ -297,8 +297,9 @@ bool ext::opengl::Graphic::updateMesh( uf::Mesh& mesh ) {
}\ }\
} }
bool rebuild = true; // to-do: deduce if the "buffer" would resize to trigger a command buffer invalidation
ext::opengl::states::rebuild = true; bool rebuild = false;
//ext::opengl::states::rebuild = true;
// we actually don't buffer anything directly at the moment so this will always fail // we actually don't buffer anything directly at the moment so this will always fail
// as vertex data is directly read from the mesh object // as vertex data is directly read from the mesh object
/* /*
@ -409,8 +410,9 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
} }
if ( uniformBufferSize == sizeof(pod::Camera::Viewports) ) { if ( uniformBufferSize == sizeof(pod::Camera::Viewports) ) {
drawCommandInfoBase.matrices.view = &viewports->matrices[0].view; auto viewIndex = descriptor.aux * 2;
drawCommandInfoBase.matrices.projection = &viewports->matrices[0].projection; drawCommandInfoBase.matrices.view = &viewports->matrices[viewIndex].view;
drawCommandInfoBase.matrices.projection = &viewports->matrices[viewIndex].projection;
} else if ( uniformBufferSize == sizeof(pod::Uniform) ) { } else if ( uniformBufferSize == sizeof(pod::Uniform) ) {
drawCommandInfoBase.matrices.model = &uniforms->modelView; drawCommandInfoBase.matrices.model = &uniforms->modelView;
drawCommandInfoBase.matrices.projection = &uniforms->projection; drawCommandInfoBase.matrices.projection = &uniforms->projection;
@ -461,73 +463,68 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
// const bool optimize = false; // const bool optimize = false;
uf::stl::unordered_map<size_t, uf::stl::vector<CommandBuffer::InfoDraw>> pool; uf::stl::unordered_map<size_t, uf::stl::vector<CommandBuffer::InfoDraw>> pool;
for ( auto i = 0; i < descriptor.inputs.indirect.count; ++i ) { for ( auto drawID = 0; drawID < descriptor.inputs.indirect.count; ++drawID ) {
auto& drawCommand = drawCommands[i]; auto& drawCommand = drawCommands[drawID];
auto instanceID = drawCommand.instanceID; for ( auto instanceOffset = 0; instanceOffset < drawCommand.instances; ++instanceOffset ) {
auto instanceID = drawCommand.instanceID + instanceOffset;
auto& instance = instances[instanceID]; auto& instance = instances[instanceID];
auto objectID = instance.objectID; auto objectID = instance.objectID;
auto materialID = instance.materialID; auto materialID = instance.materialID;
auto lightmapID = instance.lightmapID; auto lightmapID = instance.lightmapID;
auto& object = objects[objectID]; auto& object = objects[objectID];
auto& material = materials[materialID]; auto& material = materials[materialID];
auto textureID = material.indexAlbedo; auto textureID = material.indexAlbedo;
auto& infos = pool[textureID]; auto& infos = pool[textureID];
CommandBuffer::InfoDraw& drawCommandInfo = infos.emplace_back( drawCommandInfoBase ); CommandBuffer::InfoDraw& drawCommandInfo = infos.emplace_back( drawCommandInfoBase );
// CommandBuffer::InfoDraw drawCommandInfo = drawCommandInfoBase; // CommandBuffer::InfoDraw drawCommandInfo = drawCommandInfoBase;
drawCommandInfo.descriptor.inputs.index.first = drawCommand.indexID; drawCommandInfo.descriptor.inputs.index.first = drawCommand.indexID;
drawCommandInfo.descriptor.inputs.index.count = drawCommand.indices; drawCommandInfo.descriptor.inputs.index.count = drawCommand.indices;
drawCommandInfo.descriptor.inputs.vertex.first = drawCommand.vertexID; drawCommandInfo.descriptor.inputs.vertex.first = drawCommand.vertexID;
drawCommandInfo.descriptor.inputs.vertex.count = drawCommand.vertices; drawCommandInfo.descriptor.inputs.vertex.count = drawCommand.vertices;
drawCommandInfo.attributes.instance.pointer = (uint8_t*) (void*) &instance; drawCommandInfo.attributes.instance.pointer = (uint8_t*) (void*) &instance;
drawCommandInfo.attributes.instance.length = sizeof(instance); drawCommandInfo.attributes.instance.length = sizeof(instance);
drawCommandInfo.attributes.indirect.pointer = (uint8_t*) (void*) &drawCommand; drawCommandInfo.attributes.indirect.pointer = (uint8_t*) (void*) &drawCommand;
drawCommandInfo.attributes.indirect.length = sizeof(drawCommand); drawCommandInfo.attributes.indirect.length = sizeof(drawCommand);
drawCommandInfo.matrices.model = &object.model; drawCommandInfo.matrices.model = &object.model;
drawCommandInfo.blend.modeAlpha = material.modeAlpha; drawCommandInfo.blend.modeAlpha = material.modeAlpha;
drawCommandInfo.blend.alphaCutoff = material.factorAlphaCutoff; drawCommandInfo.blend.alphaCutoff = material.factorAlphaCutoff;
drawCommandInfo.color.value = object.color * material.colorBase; // to-do: blend properly drawCommandInfo.color.value = object.color * material.colorBase; // to-do: blend properly
drawCommandInfo.color.enabled = drawCommandInfo.color.value != pod::Vector4f{1.0f, 1.0f, 1.0f, 1.0f}; drawCommandInfo.color.enabled = drawCommandInfo.color.value != pod::Vector4f{1.0f, 1.0f, 1.0f, 1.0f};
if ( drawCommandInfo.color.value.w == 0.0f ) { if ( drawCommandInfo.color.value.w == 0.0f ) {
continue; continue;
} }
if ( 0 <= textureID ) { if ( 0 <= textureID ) {
auto texture2DID = textures[textureID].index; auto texture2DID = textures[textureID].index;
drawCommandInfo.textures.primary = this->material.textures.at(texture2DID).descriptor; drawCommandInfo.textures.primary = this->material.textures.at(texture2DID).descriptor;
} }
if ( 0 <= lightmapID ) { if ( 0 <= lightmapID ) {
auto textureID = lightmapID; auto textureID = lightmapID;
auto texture2DID = textures[lightmapID].index; auto texture2DID = textures[lightmapID].index;
drawCommandInfo.textures.secondary = this->material.textures.at(texture2DID).descriptor; drawCommandInfo.textures.secondary = this->material.textures.at(texture2DID).descriptor;
} }
switch ( drawCommandInfo.blend.modeAlpha ) { if ( drawCommandInfo.blend.modeAlpha == pod::Material::AlphaMode::BLEND ) {
case pod::Material::AlphaMode::BLEND: drawCommandInfos.translucents.emplace_back(drawCommandInfo); break; drawCommandInfo.descriptor.renderTarget = 1;
default: drawCommandInfos.opaques.emplace_back(drawCommandInfo); break; }
commandBuffer.record( drawCommandInfo );
} }
} }
} else { } else {
CommandBuffer::InfoDraw drawCommandInfo = drawCommandInfoBase; CommandBuffer::InfoDraw drawCommandInfo = drawCommandInfoBase;
// ???
/*
drawCommandInfoBase.matrices.model = NULL;
drawCommandInfoBase.matrices.view = NULL;
drawCommandInfoBase.matrices.projection = NULL;
*/
if ( !material.textures.empty() ) { if ( !material.textures.empty() ) {
auto& texture = material.textures.front(); auto& texture = material.textures.front();
drawCommandInfo.textures.primary = texture.descriptor; drawCommandInfo.textures.primary = texture.descriptor;
@ -543,13 +540,17 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
break; break;
} }
} }
commandBuffer.record( drawCommandInfo );
/*
switch ( drawCommandInfo.blend.modeAlpha ) { switch ( drawCommandInfo.blend.modeAlpha ) {
case 0: drawCommandInfos.opaques.emplace_back(drawCommandInfo); break; case 0: drawCommandInfos.opaques.emplace_back(drawCommandInfo); break;
default: drawCommandInfos.translucents.emplace_back(drawCommandInfo); break; default: drawCommandInfos.translucents.emplace_back(drawCommandInfo); break;
} }
*/
} }
/*
if ( uf::matrix::reverseInfiniteProjection ) { if ( uf::matrix::reverseInfiniteProjection ) {
for ( auto it = drawCommandInfos.opaques.rbegin(); it != drawCommandInfos.opaques.rend(); ++it ) { for ( auto it = drawCommandInfos.opaques.rbegin(); it != drawCommandInfos.opaques.rend(); ++it ) {
auto& drawCommandInfo = (*it); auto& drawCommandInfo = (*it);
@ -563,6 +564,7 @@ void ext::opengl::Graphic::record( CommandBuffer& commandBuffer, const GraphicDe
for ( auto& drawCommandInfo : drawCommandInfos.opaques ) commandBuffer.record(drawCommandInfo); for ( auto& drawCommandInfo : drawCommandInfos.opaques ) commandBuffer.record(drawCommandInfo);
for ( auto& drawCommandInfo : drawCommandInfos.translucents ) commandBuffer.record(drawCommandInfo); for ( auto& drawCommandInfo : drawCommandInfos.translucents ) commandBuffer.record(drawCommandInfo);
} }
*/
// UF_MSG_DEBUG("END") // UF_MSG_DEBUG("END")
} }
void ext::opengl::Graphic::destroy() { void ext::opengl::Graphic::destroy() {

View File

@ -87,13 +87,67 @@ uint32_t ext::opengl::states::currentBuffer = 0;
uint32_t ext::opengl::states::frameAccumulate = 0; uint32_t ext::opengl::states::frameAccumulate = 0;
bool ext::opengl::states::frameAccumulateReset = false; bool ext::opengl::states::frameAccumulateReset = false;
uf::ThreadUnique<ext::opengl::RenderMode*> ext::opengl::currentRenderMode; namespace {
uf::stl::vector<ext::opengl::RenderMode*> fetchRenderModes( bool initGraphics = false ) {
auto& scene = uf::scene::getCurrentScene();
auto/*&*/ graph = scene.getGraph();
uf::stl::vector<uf::renderer::RenderMode*> renderModes = ext::opengl::renderModes;
for ( auto entity : graph ) {
if ( entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
if ( std::find( renderModes.begin(), renderModes.end(), &renderMode ) == renderModes.end() )
renderModes.emplace_back(&renderMode);
}
if ( entity->hasComponent<uf::renderer::DeferredRenderMode>() ) {
auto& renderMode = entity->getComponent<uf::renderer::DeferredRenderMode>();
if ( std::find( renderModes.begin(), renderModes.end(), &renderMode ) == renderModes.end() )
renderModes.emplace_back(&renderMode);
}
}
// group by category
uf::stl::unordered_map<uf::stl::string, uf::stl::vector<uf::renderer::RenderMode*>> renderModesMap;
for ( auto* renderMode : renderModes ) {
renderModesMap[renderMode->getName()].emplace_back( renderMode );
}
// empty
renderModes = {};
// order the end rendermodes in a specific way: Gui -> Deferred -> Swapchain
uf::stl::vector<uf::renderer::RenderMode*> end;
if ( renderModesMap.count("Gui") > 0 ) {
end.insert( end.end(), renderModesMap["Gui"].begin(), renderModesMap["Gui"].end() );
renderModesMap.erase("Gui");
}
if ( renderModesMap.count("") > 0 ) {
end.insert( end.end(), renderModesMap[""].begin(), renderModesMap[""].end() );
renderModesMap.erase("");
}
if ( renderModesMap.count("Swapchain") > 0 ) {
end.insert( end.end(), renderModesMap["Swapchain"].begin(), renderModesMap["Swapchain"].end() );
renderModesMap.erase("Swapchain");
}
for ( auto& pair : renderModesMap ) {
renderModes.insert( renderModes.end(), pair.second.begin(), pair.second.end() );
}
renderModes.insert( renderModes.end(), end.begin(), end.end() );
return renderModes;
}
}
uf::ThreadUnique<ext::opengl::RenderMode*> ext::opengl::currentRenderMode;
uf::stl::vector<ext::opengl::RenderMode*> ext::opengl::renderModes = { uf::stl::vector<ext::opengl::RenderMode*> ext::opengl::renderModes = {
new ext::opengl::BaseRenderMode, new ext::opengl::BaseRenderMode,
}; };
uf::stl::unordered_map<uf::stl::string, ext::opengl::RenderMode*> ext::opengl::renderModesMap;
uf::stl::string ext::opengl::errorString() { uf::stl::string ext::opengl::errorString() {
return ext::opengl::errorString(glGetError()); return ext::opengl::errorString(glGetError());
} }
@ -110,37 +164,25 @@ uf::stl::string ext::opengl::errorString( GLenum error ) {
///// /////
bool ext::opengl::hasRenderMode( const uf::stl::string& name, bool isName ) { bool ext::opengl::hasRenderMode( const uf::stl::string& name, bool isName ) {
for ( auto& renderMode: ext::opengl::renderModes ) { if ( isName && ext::opengl::renderModesMap.count(name) > 0 ) return true;
if ( isName ) { if ( renderMode->getName() == name ) return true; auto renderModes = ::fetchRenderModes();
} else if ( renderMode->getType() == name ) return true; for ( auto& renderMode: renderModes ) {
if ( isName && renderMode->getName() == name ) return true;
else if ( renderMode->getType() == name ) return true;
} }
return false; return false;
} }
ext::opengl::RenderMode& ext::opengl::addRenderMode( ext::opengl::RenderMode* mode, const uf::stl::string& name ) { ext::opengl::RenderMode& ext::opengl::addRenderMode( ext::opengl::RenderMode* mode, const uf::stl::string& name ) {
mode->metadata.name = name; mode->metadata.name = name;
renderModes.push_back(mode); renderModesMap[name] = renderModes.emplace_back(mode);
if ( ext::opengl::settings::validation::enabled ) UF_MSG_DEBUG("Adding RenderMode: {}: {}", name, mode->getType());
// reorder
if ( hasRenderMode("", true) ) {
RenderMode& primary = getRenderMode("", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
} else {
RenderMode& primary = getRenderMode("Swapchain", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
if ( hasRenderMode("Gui", true) ) {
RenderMode& primary = getRenderMode("Gui", true);
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
if ( it + 1 != renderModes.end() ) std::rotate( it, it + 1, renderModes.end() );
}
ext::opengl::states::rebuild = true; ext::opengl::states::rebuild = true;
return *mode; return *mode;
} }
ext::opengl::RenderMode& ext::opengl::getRenderMode( const uf::stl::string& name, bool isName ) { ext::opengl::RenderMode& ext::opengl::getRenderMode( const uf::stl::string& name, bool isName ) {
if ( isName && renderModesMap.count(name) > 0 ) return *renderModesMap[name];
auto renderModes = ::fetchRenderModes();
RenderMode* target = renderModes[0]; RenderMode* target = renderModes[0];
for ( auto& renderMode: renderModes ) { for ( auto& renderMode: renderModes ) {
if ( isName ) { if ( isName ) {
@ -156,23 +198,39 @@ ext::opengl::RenderMode& ext::opengl::getRenderMode( const uf::stl::string& name
} }
} }
} }
// VK_VALIDATION_MESSAGE("Requesting RenderMode `" << name << "`, got `" << target->getName() << "` (" << target->getType() << ")");
return *target; return *target;
} }
uf::stl::vector<ext::opengl::RenderMode*> ext::opengl::getRenderModes( const uf::stl::string& name, bool isName ) { uf::stl::vector<ext::opengl::RenderMode*> ext::opengl::getRenderModes( const uf::stl::string& name, bool isName ) {
if ( isName && renderModesMap.count(name) > 0 ) return { renderModesMap[name] };
return ext::opengl::getRenderModes(uf::stl::vector<uf::stl::string>{name}, isName); return ext::opengl::getRenderModes(uf::stl::vector<uf::stl::string>{name}, isName);
} }
uf::stl::vector<ext::opengl::RenderMode*> ext::opengl::getRenderModes( const uf::stl::vector<uf::stl::string>& names, bool isName ) { uf::stl::vector<ext::opengl::RenderMode*> ext::opengl::getRenderModes( const uf::stl::vector<uf::stl::string>& names, bool isName ) {
uf::stl::vector<RenderMode*> targets; uf::stl::vector<RenderMode*> targets;
auto renderModes = ::fetchRenderModes();
#if 1
// this way keeps the render mode ordered as requested
for ( auto& name : names ) {
for ( auto& renderMode: renderModes ) {
if ( (isName && renderMode->getName() == name) || (!isName && renderMode->getType() == name) ) {
targets.emplace_back( renderMode );
}
}
}
#else
for ( auto& renderMode: renderModes ) { for ( auto& renderMode: renderModes ) {
if ( ( isName && std::find(names.begin(), names.end(), renderMode->getName()) != names.end() ) || std::find(names.begin(), names.end(), renderMode->getType()) != names.end() ) { if ( ( isName && std::find(names.begin(), names.end(), renderMode->getName()) != names.end() ) || std::find(names.begin(), names.end(), renderMode->getType()) != names.end() ) {
targets.push_back(renderMode); targets.push_back(renderMode);
} }
} }
#endif
return targets; return targets;
} }
void ext::opengl::removeRenderMode( ext::opengl::RenderMode* mode, bool free ) { void ext::opengl::removeRenderMode( ext::opengl::RenderMode* mode, bool free ) {
if ( !mode ) return; if ( !mode ) return;
uf::stl::string name = mode->getName();
renderModes.erase( std::remove( renderModes.begin(), renderModes.end(), mode ), renderModes.end() ); renderModes.erase( std::remove( renderModes.begin(), renderModes.end(), mode ), renderModes.end() );
renderModesMap.erase( name );
mode->destroy(); mode->destroy();
if ( free ) delete mode; if ( free ) delete mode;
ext::opengl::states::rebuild = true; ext::opengl::states::rebuild = true;
@ -181,6 +239,9 @@ ext::opengl::RenderMode* ext::opengl::getCurrentRenderMode() {
return getCurrentRenderMode( std::this_thread::get_id() ); return getCurrentRenderMode( std::this_thread::get_id() );
} }
ext::opengl::RenderMode* ext::opengl::getCurrentRenderMode( std::thread::id id ) { ext::opengl::RenderMode* ext::opengl::getCurrentRenderMode( std::thread::id id ) {
// bool exists = ext::opengl::currentRenderMode.has(id);
// auto& currentRenderMode = ext::opengl::currentRenderMode.get(id);
// return currentRenderMode;
return ext::opengl::currentRenderMode.get(id); return ext::opengl::currentRenderMode.get(id);
} }
void ext::opengl::setCurrentRenderMode( ext::opengl::RenderMode* renderMode ) { void ext::opengl::setCurrentRenderMode( ext::opengl::RenderMode* renderMode ) {
@ -224,7 +285,7 @@ void ext::opengl::initialize() {
auto tasks = uf::thread::schedule(settings::invariant::multithreadedRecording); auto tasks = uf::thread::schedule(settings::invariant::multithreadedRecording);
for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue;
tasks.queue([&]{ tasks.queue([renderMode]{
if ( settings::invariant::individualPipelines ) renderMode->bindPipelines(); if ( settings::invariant::individualPipelines ) renderMode->bindPipelines();
renderMode->createCommandBuffers(); renderMode->createCommandBuffers();
}); });
@ -371,11 +432,29 @@ void ext::opengl::initialize() {
} }
void ext::opengl::tick(){ void ext::opengl::tick(){
ext::opengl::mutex.lock(); ext::opengl::mutex.lock();
if ( ext::opengl::states::resized || ext::opengl::settings::experimental::rebuildOnTickBegin ) {
if ( ext::opengl::states::resized ) {
synchronize(0b11);
ext::opengl::states::rebuild = true;
// ::skip = true;
}
if ( ext::opengl::settings::experimental::rebuildOnTickBegin ) {
ext::opengl::states::rebuild = true; ext::opengl::states::rebuild = true;
} }
auto& scene = uf::scene::getCurrentScene();
auto& graph = scene.getGraph(); auto renderModes = ::fetchRenderModes();
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( renderMode->executed && !renderMode->execute ) continue;
if ( !renderMode->device ) {
renderMode->initialize(ext::opengl::device);
ext::opengl::states::rebuild = true;
}
renderMode->tick();
}
auto& scene = uf::scene::getCurrentScene();
auto/*&*/ graph = scene.getGraph();
for ( auto entity : graph ) { for ( auto entity : graph ) {
if ( entity->hasComponent<ext::opengl::Graphics>() ) { if ( entity->hasComponent<ext::opengl::Graphics>() ) {
auto& graphics = entity->getComponent<ext::opengl::Graphics>(); auto& graphics = entity->getComponent<ext::opengl::Graphics>();
@ -392,27 +471,25 @@ void ext::opengl::tick(){
ext::opengl::states::rebuild = true; ext::opengl::states::rebuild = true;
} }
} }
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
if ( !renderMode->device ) {
renderMode->initialize(ext::opengl::device);
ext::opengl::states::rebuild = true;
}
renderMode->tick();
}
auto tasks = uf::thread::schedule(settings::invariant::multithreadedRecording); auto tasks = uf::thread::schedule( settings::invariant::multithreadedRecording );
for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; for ( auto& renderMode : renderModes ) { if ( !renderMode || (renderMode->executed && !renderMode->execute) ) continue;
if ( ext::opengl::states::rebuild || renderMode->rebuild ) tasks.queue([&]{ if ( ext::opengl::states::rebuild || renderMode->rebuild ) tasks.queue([renderMode]{
if ( settings::invariant::individualPipelines ) renderMode->bindPipelines(); renderMode->bindPipelines();
renderMode->createCommandBuffers(); renderMode->createCommandBuffers();
}); });
} else if ( renderMode->rerecord ) tasks.queue([renderMode]{
renderMode->createCommandBuffers();
});
}
uf::thread::execute( tasks ); uf::thread::execute( tasks );
// if ( ext::opengl::states::rebuild && ext::opengl::settings::experimental::skipRenderOnRebuild ) ::skip = true;
ext::opengl::states::rebuild = false; ext::opengl::states::rebuild = false;
ext::opengl::states::resized = false; ext::opengl::states::resized = false;
ext::opengl::mutex.unlock(); ext::opengl::mutex.unlock();
} }
void ext::opengl::render(){ void ext::opengl::render(){
@ -486,6 +563,9 @@ void ext::opengl::render(){
for ( auto& buffer : transient.buffers ) buffer.destroy(false); for ( auto& buffer : transient.buffers ) buffer.destroy(false);
transient.buffers.clear(); transient.buffers.clear();
for ( auto& texture : transient.textures ) texture.destroy(false);
transient.textures.clear();
ext::opengl::mutex.unlock(); ext::opengl::mutex.unlock();
} }
void ext::opengl::destroy() { void ext::opengl::destroy() {
@ -520,7 +600,7 @@ void ext::opengl::synchronize( uint8_t flag ) {
} }
} }
if ( flag & 0b10 ) { if ( flag & 0b10 ) {
// vkDeviceWaitIdle( device ); glFlush();
} }
} }
uf::stl::string ext::opengl::allocatorStats(){ uf::stl::string ext::opengl::allocatorStats(){

View File

@ -34,17 +34,9 @@ void ext::opengl::DeferredRenderMode::destroy() {
void ext::opengl::DeferredRenderMode::createCommandBuffers( const uf::stl::vector<ext::opengl::Graphic*>& graphics ) { void ext::opengl::DeferredRenderMode::createCommandBuffers( const uf::stl::vector<ext::opengl::Graphic*>& graphics ) {
float width = this->width > 0 ? this->width : ext::opengl::settings::width; float width = this->width > 0 ? this->width : ext::opengl::settings::width;
float height = this->height > 0 ? this->height : ext::opengl::settings::height; float height = this->height > 0 ? this->height : ext::opengl::settings::height;
auto& commands = getCommands(); auto& commands = getCommands();
commands.start(); { commands.start(); {
#if 0
CommandBuffer::InfoClear clearCommandInfo = {};
clearCommandInfo.type = enums::Command::CLEAR;
clearCommandInfo.color = {0.0f, 0.0f, 0.0f, 0.0f};
clearCommandInfo.depth = uf::Camera::USE_REVERSE_INFINITE_PROJECTION ? 0.0f : 1.0f;
clearCommandInfo.bits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
commands.record(clearCommandInfo);
#endif
CommandBuffer::InfoViewport viewportCommandInfo = {}; CommandBuffer::InfoViewport viewportCommandInfo = {};
viewportCommandInfo.type = enums::Command::VIEWPORT; viewportCommandInfo.type = enums::Command::VIEWPORT;
viewportCommandInfo.corner = pod::Vector2ui{0, 0}; viewportCommandInfo.corner = pod::Vector2ui{0, 0};
@ -54,8 +46,34 @@ void ext::opengl::DeferredRenderMode::createCommandBuffers( const uf::stl::vecto
size_t currentSubpass = 0; size_t currentSubpass = 0;
size_t currentPass = 0; size_t currentPass = 0;
size_t currentDraw = 0; size_t currentDraw = 0;
// draw skybox'd geometry
for ( auto graphic : graphics ) { for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->getName() ) continue; if ( graphic->descriptor.renderMode != this->getName() ) continue;
if ( graphic->descriptor.aux != 1 ) continue;
GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
graphic->record( commands, descriptor, currentPass, currentDraw++ );
}
// clear depth
if ( currentDraw > 0 ) {
CommandBuffer::InfoClear clearCommandInfo = {};
clearCommandInfo.type = enums::Command::CLEAR;
clearCommandInfo.bits = GL_DEPTH_BUFFER_BIT;
clearCommandInfo.depth = uf::matrix::reverseInfiniteProjection ? 0.0f : 1.0f;
commands.record(clearCommandInfo);
}
// draw normal geometry
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->getName() ) continue;
if ( graphic->descriptor.aux != 0 ) continue;
if ( graphic->descriptor.renderTarget != 0 ) continue;
GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
graphic->record( commands, descriptor, currentPass, currentDraw++ );
}
// draw transparency
for ( auto graphic : graphics ) {
if ( graphic->descriptor.renderMode != this->getName() ) continue;
if ( graphic->descriptor.aux != 0 ) continue;
if ( graphic->descriptor.renderTarget != 1 ) continue;
GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass); GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass);
graphic->record( commands, descriptor, currentPass, currentDraw++ ); graphic->record( commands, descriptor, currentPass, currentDraw++ );
} }