Commit for 2022.06.13 01-15-08.7z

This commit is contained in:
mrq 2022-06-13 01:15:00 -05:00
parent e38c08ff85
commit 4b7a9d5714
34 changed files with 520 additions and 261 deletions

View File

@ -1,7 +1,7 @@
{
"engine": {
"scenes": {
"start": "SS2",
"start": "McDonalds",
"meshes": { "interleaved": false },
"matrix": { "reverseInfinite": true },
"lights": { "enabled": true,
@ -12,13 +12,12 @@
"enabled": true,
"update": 2,
"max": 8,
"samples": 1,
"experimental mode": 1
"samples": 1
},
"textures": {
"max": {
"2D": 256,
"cube": 32,
"2D": 1024,
"cube": 256,
"3D": 1
}
},
@ -31,6 +30,7 @@
"granularity": 12,
"voxelizeScale": 1,
"occlusionFalloff": 2,
"traceStartOffsetFactor": 2,
"shadows": 0,
"extents": {
"min": [ -8, -1, -8 ],
@ -76,7 +76,7 @@
},
"gpu": "auto",
"experimental": {
"batch queue submissions": true,
"batch queue submissions": false,
"dedicated thread": false
},
"invariant": {},
@ -198,15 +198,15 @@
"streams by default": true
},
"memory pool": {
"enabled": true,
"enabled": false,
"subPools": true,
"alignment": 64,
"override": false,
"size": "1024 MiB",
"size": "512 MiB",
"pools": {
"entity": "256 MiB",
"userdata": "256 MiB",
"component": "256 MiB"
"entity": "128 MiB",
"userdata": "128 MiB",
"component": "128 MiB"
}
},
"render modes": { "gui": true, "deferred": true },

View File

@ -25,7 +25,9 @@
"combined": false,
"encode buffers": true,
"unwrap": true,
// "unwrap": "tagged",
"optimize": "tagged",
// "optimize": true,
"quit": true,
"mesh": {
// "print": true
@ -41,7 +43,7 @@
"output": "./lightmap.%i.png",
"settings": {
"useInputMeshUvs": true,
"maxIterations": 8,
"maxIterations": 16,
// "maxChartSize": 0,
"padding": 4,
// "texelsPerUnit": 0,
@ -49,7 +51,7 @@
"blockAlign": true,
"bruteForce": true,
// "rotateChartsToAxis": false,
"rotateChartsToAxis": false,
"rotateCharts": true
}
},

View File

@ -23,7 +23,8 @@
"/^worldspawn/": {
"physics": { "type": "mesh", "static": true },
"grid": { "size": [4,1,4], "epsilon": 1.0, "cleanup": true, "print": true },
"optimize mesh": { "simplify": 0 }
"optimize mesh": { "simplify": 0 },
"unwrap mesh": true
},
"info_player_spawn": { "action": "attach", "filename": "./player.json", "preserve orientation": true },

View File

@ -34,15 +34,16 @@
"exposure": 1.0,
"gamma": 1.0,
"brightnessThreshold": 1.2,
"ambient": [ 0, 0, 0 ],
// "ambient": [ 0, 0, 0 ],
"ambient": [ 0.025, 0.025, 0.025 ],
// "ambient": [ 0.1, 0.1, 0.1 ],
// "ambient": [ 0.4, 0.4, 0.4 ],
"fog-": {
"fog": {
"color": [ 0.5, 0.5, 0.5 ],
"range": [ 16, 32 ],
"step scale": 2,
"absorbtion": 0.07,
"absorbtion": 0.01,
"density": {
"threshold": 0.35,
"multiplier": 5.0,
@ -68,7 +69,8 @@
"shadows": 0,
*/
"occlusionFalloff": 2,
"granularity": 4,
"traceStartOffsetFactor": 1,
"granularity": 2,
"extents": {
"min": [ -1.5, -1.5, -1.5 ],
"max": [ 1.5, 1.5, 1.5 ]

View File

@ -26,8 +26,9 @@
"tags": {
"/^worldspawn/": {
"physics": { "type": "mesh", "static": true },
"grid": { "size": [5,1,5], "epsilon": 1.0, "cleanup": true, "print": true },
"optimize mesh": { "simplify": 0 }
"grid": { "size": [3,1,3], "epsilon": 0.0001, "cleanup": true, "print": true },
"optimize mesh": { "simplify": 0 },
"unwrap mesh": true
},
"info_player_spawn": {
"action": "attach",

View File

@ -71,6 +71,7 @@ float omniShadowMap( const Light light, float def ) {
float sampled = 0;
const int samples = int(SHADOW_SAMPLES);
// cubemap point light
if ( light.typeMap == 1 ) {
if ( samples < 1 ) {
sampled = texture(samplerCubemaps[nonuniformEXT(light.indexMap)], D).r * sampledDepthScale;
@ -84,6 +85,7 @@ float omniShadowMap( const Light light, float def ) {
}
return factor;
}
// separated point lights
} else if ( light.typeMap == 2 ) {
const vec2 uv = positionClip.xy * 0.5 + 0.5;
if ( samples < 1 ) {
@ -102,6 +104,7 @@ float omniShadowMap( const Light light, float def ) {
#endif
float shadowFactor( const Light light, float def ) {
if ( light.typeMap != 0 ) return omniShadowMap( light, def );
if ( !validTextureIndex(light.indexMap) )
#if VXGI
return voxelShadowFactor( light, def );

View File

@ -180,8 +180,8 @@ struct Vxgi {
float voxelizeScale;
float occlusionFalloff;
float traceStartOffsetFactor;
uint shadows;
uint padding1;
uint padding2;
uint padding3;
};

View File

@ -28,9 +28,9 @@ vec4 voxelTrace( inout Ray ray, float aperture, float maxDistance ) {
const float tStart = rayBoxInfoA.x;
const float tEnd = maxDistance > 0 ? min(maxDistance, rayBoxInfoB.y) : rayBoxInfoB.y;
const float tDelta = voxelInfo.radianceSizeRecip * granularityRecip * 1.5;
const float tDelta = voxelInfo.radianceSizeRecip * granularityRecip;
// marcher
ray.distance = tStart;
ray.distance = tStart + tDelta * ubo.vxgi.traceStartOffsetFactor;
ray.position = vec3(0);
vec4 radiance = vec4(0);

View File

@ -6,14 +6,13 @@
"matrix": { "reverseInfinite": false },
"lights": { "enabled": false,
"useLightmaps": true,
"max": 0
"max": 1
},
"shadows": {
"enabled": false,
"update": 2,
"max": 8,
"samples": 2,
"experimental mode": 1
"samples": 1
},
"textures": {
"max": {
@ -54,7 +53,7 @@
"compression": "gz"
},
"reactphysics": {
"timescale": 0.03333333333,
"timescale": 0.06666666666,
"interpolate": false,
"debug draw": {
"enabled": false,
@ -77,11 +76,11 @@
"streams by default": true
},
"memory pool": {
"enabled": false,
"enabled": true,
"subPools": true,
"alignment": 32,
"override": true,
"size": "8 MiB",
"override": false,
"size": "512 KiB",
"pools": {
"entity": "96 KiB",
"userdata": "96 KiB",

View File

@ -50,8 +50,7 @@ namespace ext {
virtual ext::opengl::Graphic* getBlitter(size_t = 0);
virtual uf::stl::vector<ext::opengl::Graphic*> getBlitters();
virtual CommandBuffer& getCommands();
virtual CommandBuffer& getCommands( std::thread::id );
virtual CommandBuffer& getCommands( std::thread::id = std::this_thread::get_id() );
virtual GraphicDescriptor bindGraphicDescriptor( const GraphicDescriptor&, size_t = 0 );
virtual void bindGraphicPushConstants( ext::opengl::Graphic*, size_t = 0 );

View File

@ -60,12 +60,11 @@ namespace ext {
uf::Image screenshot(size_t = 0, size_t = 0);
commands_container_t& getCommands();
commands_container_t& getCommands( std::thread::id );
void lockMutex();
void lockMutex( std::thread::id );
void unlockMutex();
void unlockMutex( std::thread::id );
commands_container_t& getCommands( std::thread::id = std::this_thread::get_id() );
void lockMutex( std::thread::id = std::this_thread::get_id() );
bool tryMutex( std::thread::id = std::this_thread::get_id() );
void unlockMutex( std::thread::id = std::this_thread::get_id() );
std::lock_guard<std::mutex> guardMutex( std::thread::id = std::this_thread::get_id() );
virtual ~RenderMode();
// RAII

View File

@ -5,7 +5,10 @@
#if UF_USE_XATLAS
namespace ext {
namespace xatlas {
size_t UF_API unwrap( pod::Graph&, bool = false );
size_t UF_API unwrap( pod::Graph& );
size_t UF_API unwrapLazy( pod::Graph& );
size_t UF_API unwrapExperimental( pod::Graph& );
}
}
#endif

View File

@ -96,7 +96,7 @@
#define UF_TIMER_MULTITRACE(X) {\
TIMER_TRACE_CUR = TIMER_TRACE.elapsed().asMicroseconds();\
UF_MSG_DEBUG(std::setfill(' ') << std::setw(4) << TIMER_TRACE_CUR << " ns\t" << std::setfill(' ') << std::setw(4) << (TIMER_TRACE_CUR - TIMER_TRACE_PREV) << " ns\t" << X);\
UF_MSG_DEBUG(std::setfill(' ') << std::setw(4) << TIMER_TRACE_CUR << " us\t" << std::setfill(' ') << std::setw(4) << (TIMER_TRACE_CUR - TIMER_TRACE_PREV) << " us\t" << X);\
TIMER_TRACE_PREV = TIMER_TRACE_CUR;\
}

View File

@ -20,12 +20,12 @@ namespace uf {
bool has( id_t id = std::this_thread::get_id() ) const;
T& get( id_t id = std::this_thread::get_id() );
void lock( id_t id = std::this_thread::get_id() );
void unlock( id_t id = std::this_thread::get_id() );
std::lock_guard<std::mutex> guard( id_t id = std::this_thread::get_id() );
container_t& container();
void lockMutex( id_t id = std::this_thread::get_id() );
bool tryMutex( id_t id = std::this_thread::get_id() );
void unlockMutex( id_t id = std::this_thread::get_id() );
std::lock_guard<std::mutex> guardMutex( id_t id = std::this_thread::get_id() );
};
}

View File

@ -16,17 +16,22 @@ T& uf::ThreadUnique<T>::get( id_t id ) {
return m_container[id];
}
template<typename T>
void uf::ThreadUnique<T>::lock( id_t id ) {
void uf::ThreadUnique<T>::lockMutex( id_t id ) {
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
m_mutex_container[id]->lock();
}
template<typename T>
void uf::ThreadUnique<T>::unlock( id_t id ) {
bool uf::ThreadUnique<T>::tryMutex( id_t id ) {
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
return m_mutex_container[id]->try_lock();
}
template<typename T>
void uf::ThreadUnique<T>::unlockMutex( id_t id ) {
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
m_mutex_container[id]->unlock();
}
template<typename T>
std::lock_guard<std::mutex> uf::ThreadUnique<T>::guard( id_t id ) {
std::lock_guard<std::mutex> uf::ThreadUnique<T>::guardMutex( id_t id ) {
if ( m_mutex_container.count(id) == 0 ) m_mutex_container[id] = new std::mutex;
return std::lock_guard<std::mutex>(*m_mutex_container[id]);
}

View File

@ -89,6 +89,7 @@ void uf::Behaviors::tick() {
if ( m_graph.tick.empty() ) return;
#if UF_GRAPH_PRINT_TRACE
UF_TIMER_MULTITRACE_START("Starting tick " << self.getName() << ": " << self.getUid());
// for ( auto& behavior : m_behaviors ) if ( behavior.traits.ticks ) UF_MSG_DEBUG( behavior.type.name() );
for ( auto& fun : m_graph.tick ) {
fun(self);
UF_TIMER_MULTITRACE("");

View File

@ -131,6 +131,13 @@ uf::Entity* uf::Entity::globalFindByUid( size_t uid ) {
uf::Entity* entity = (uf::Entity*) (allocation.pointer);
if ( entity->getUid() == uid ) return entity;
}
{
auto& scene = uf::scene::getCurrentScene();
auto& graph = scene.getGraph();
for ( uf::Entity* entity : graph ) {
if ( entity->getUid() == uid ) return entity;
}
}
return NULL;
}
uf::Entity* uf::Entity::globalFindByName( const uf::stl::string& name ) {
@ -139,5 +146,12 @@ uf::Entity* uf::Entity::globalFindByName( const uf::stl::string& name ) {
if ( !entity->isValid() ) continue;
if ( entity->getName() == name ) return entity;
}
{
auto& scene = uf::scene::getCurrentScene();
auto& graph = scene.getGraph();
for ( uf::Entity* entity : graph ) {
if ( entity->getName() == name ) return entity;
}
}
return NULL;
}

View File

@ -760,6 +760,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
if ( key == "transform" ) return;
metadataLight[key] = value;
});
#if !UF_USE_OPENGL
if ( !(graph.metadata["lightmapped"].as<bool>() && !(metadataLight["shadows"].as<bool>() || metadataLight["dynamic"].as<bool>())) ) {
// {
auto& metadataJson = entity.getComponent<uf::Serializer>();
@ -769,6 +770,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
metadataJson["light"][key] = value;
});
}
#endif
}
}
@ -806,7 +808,8 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
}
size_t objectID = uf::graph::storage.entities.keys.size();
uf::graph::storage.entities[std::to_string(objectID)] = &entity;
auto objectKeyName = std::to_string(objectID);
uf::graph::storage.entities[objectKeyName] = &entity;
if ( 0 <= node.mesh && node.mesh < graph.meshes.size() ) {
auto model = uf::transform::model( transform );
@ -819,7 +822,9 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
auto& primitive = primitives[i];
size_t instanceID = uf::graph::storage.instances.keys.size();
auto& instance = uf::graph::storage.instances[graph.instances.emplace_back(std::to_string(instanceID))];
auto instanceKeyName = graph.instances.emplace_back(std::to_string(instanceID));
auto& instance = uf::graph::storage.instances[instanceKeyName];
instance = primitive.instance;
instance.model = model;
@ -973,15 +978,30 @@ void uf::graph::update( pod::Graph& graph ) {
}
void uf::graph::update( pod::Graph& graph, float delta ) {
// update our instances
#if !UF_ENV_DREAMCAST
// UF_TIMER_MULTITRACE_START("Tick Start");
uf::stl::unordered_map<size_t, pod::Matrix4f> instanceCache;
for ( auto& name : uf::graph::storage.instances.keys ) {
auto& instance = uf::graph::storage.instances[name];
if ( instanceCache.count( instance.objectID ) > 0 ) {
instance.model = instanceCache[instance.objectID];
continue;
}
auto& entity = *uf::graph::storage.entities[std::to_string(instance.objectID)];
auto& metadata = entity.getComponent<uf::ObjectBehavior::Metadata>();
if ( metadata.system.ignoreGraph ) continue;
auto& transform = entity.getComponent<pod::Transform<>>();
instance.model = uf::transform::model( transform );
instance.model = (instanceCache[instance.objectID] = uf::transform::model( transform ));
}
// UF_TIMER_MULTITRACE_END("Tick End");
#endif
// no skins
if ( !(graph.metadata["flags"]["SKINNED"].as<bool>()) ) return;
if ( !(graph.metadata["flags"]["SKINNED"].as<bool>()) ) {
return;
}
if ( graph.sequence.empty() ) goto UPDATE;
if ( graph.settings.animations.override.a >= 0 ) goto OVERRIDE;
@ -1053,15 +1073,6 @@ void uf::graph::update( pod::Graph& graph, pod::Node& node ) {
joints[i] = inverseTransform * (uf::graph::matrix(graph, skin.joints[i]) * skin.inverseBindMatrices[i]);
}
}
/*
if ( node.entity && node.entity->hasComponent<uf::Graphic>() ) {
auto& graphic = node.entity->getComponent<uf::Graphic>();
if ( node.buffers.joint < graphic.buffers.size() ) {
auto& buffer = graphic.buffers.at(node.buffers.joint);
shader.updateBuffer( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f), buffer );
}
}
*/
}
}
void uf::graph::destroy( pod::Graph& graph ) {
@ -1099,18 +1110,16 @@ void uf::graph::initialize() {
}
void uf::graph::tick() {
uf::stl::vector<pod::Instance> instances; instances.reserve(uf::graph::storage.instances.map.size());
uf::stl::vector<pod::Matrix4f> joints; joints.reserve(uf::graph::storage.joints.map.size());
for ( auto key : uf::graph::storage.instances.keys ) instances.emplace_back( uf::graph::storage.instances.map[key] );
if ( !instances.empty() ) uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) );
uf::stl::vector<pod::Matrix4f> joints; joints.reserve(uf::graph::storage.joints.map.size());
for ( auto key : uf::graph::storage.joints.keys ) {
auto& matrices = uf::graph::storage.joints[key];
joints.reserve( joints.size() + matrices.size() );
for ( auto& mat : matrices ) joints.emplace_back( mat );
}
uf::graph::storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) );
uf::graph::storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) );
if ( !joints.empty() ) uf::graph::storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) );
if ( ::newGraphAdded ) {
uf::stl::vector<pod::DrawCommand> drawCommands; drawCommands.reserve(uf::graph::storage.drawCommands.map.size());

View File

@ -239,6 +239,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
}
// load meshes
{
size_t masterAuxID = 0;
graph.meshes.reserve(model.meshes.size());
/*graph.storage*/uf::graph::storage.meshes.reserve(model.meshes.size());
@ -466,7 +467,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
}
#if UF_USE_XATLAS
// generate STs
if ( graph.metadata["exporter"]["unwrap"].as<bool>(true) ) {
if ( graph.metadata["exporter"]["unwrap"].as<bool>(true) || graph.metadata["exporter"]["unwrap"].as<uf::stl::string>() == "tagged" ) {
UF_MSG_DEBUG( "Generating ST's..." );
size_t atlases = ext::xatlas::unwrap( graph );
UF_MSG_DEBUG( "Generated ST's for " << atlases << " lightmaps" );

View File

@ -16,7 +16,7 @@
uint32_t ext::opengl::settings::width = 640;
uint32_t ext::opengl::settings::height = 480;
uint8_t ext::opengl::settings::msaa = 1;
bool ext::opengl::settings::validation = true;
bool ext::opengl::settings::validation = false;
// constexpr size_t ext::opengl::settings::maxViews = 6;
size_t ext::opengl::settings::viewCount = 1;
@ -28,24 +28,29 @@ uf::stl::vector<uf::stl::string> ext::opengl::settings::requestedInstanceExtensi
ext::opengl::enums::Filter::type_t ext::opengl::settings::swapchainUpscaleFilter = ext::opengl::enums::Filter::LINEAR;
// these go hand in hand for the above
#if UF_ENV_DREAMCAST
bool ext::opengl::settings::experimental::dedicatedThread = false;
#else
bool ext::opengl::settings::experimental::dedicatedThread = true;
#endif
bool ext::opengl::settings::experimental::rebuildOnTickBegin = false;
// not so experimental
bool ext::opengl::settings::invariant::waitOnRenderEnd = false;
bool ext::opengl::settings::invariant::individualPipelines = true;
bool ext::opengl::settings::invariant::multithreadedRecording = true;
uf::stl::string ext::opengl::settings::invariant::deferredMode = "";
bool ext::opengl::settings::invariant::deferredReconstructPosition = false;
bool ext::opengl::settings::invariant::deferredAliasOutputToSwapchain = true;
bool ext::opengl::settings::invariant::deferredSampling = true;
bool ext::opengl::settings::invariant::deferredAliasOutputToSwapchain = false;
bool ext::opengl::settings::invariant::deferredSampling = false;
bool ext::opengl::settings::invariant::multiview = true;
bool ext::opengl::settings::invariant::multiview = false;
// pipelines
bool ext::opengl::settings::pipelines::vsync = true;
bool ext::opengl::settings::pipelines::hdr = true;
bool ext::opengl::settings::pipelines::vxgi = true;
bool ext::opengl::settings::pipelines::hdr = false;
bool ext::opengl::settings::pipelines::vxgi = false;
bool ext::opengl::settings::pipelines::culling = false;
bool ext::opengl::settings::pipelines::bloom = false;
@ -97,7 +102,22 @@ ext::opengl::RenderMode& ext::opengl::addRenderMode( ext::opengl::RenderMode* mo
renderModes.push_back(mode);
if ( ext::opengl::settings::validation ) UF_MSG_DEBUG("Adding RenderMode: " << name << ": " << mode->getType());
// reorder
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() );
}
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() );
}
ext::opengl::states::rebuild = true;
return *mode;
}
ext::opengl::RenderMode& ext::opengl::getRenderMode( const uf::stl::string& name, bool isName ) {
@ -366,13 +386,7 @@ void UF_API ext::opengl::tick(){
}
uf::thread::execute( tasks );
/*
ext::opengl::device.activateContext();
ext::opengl::device.commandBuffer.end();
ext::opengl::device.commandBuffer.submit();
ext::opengl::device.commandBuffer.flush();
ext::opengl::device.commandBuffer.start();
*/
ext::opengl::states::rebuild = false;
ext::opengl::states::resized = false;
ext::opengl::mutex.unlock();
@ -380,22 +394,6 @@ void UF_API ext::opengl::tick(){
void UF_API ext::opengl::render(){
ext::opengl::mutex.lock();
#if !UF_ENV_DREAMCAST
#if 1
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() );
}
#endif
ext::opengl::device.activateContext();
#endif
@ -460,6 +458,7 @@ void UF_API ext::opengl::destroy() {
synchronize();
Texture2D::empty.destroy();
/*
auto& scene = uf::scene::getCurrentScene();
auto& graph = scene.getGraph();
for ( auto entity : graph ) {
@ -467,6 +466,7 @@ void UF_API ext::opengl::destroy() {
uf::Graphic& graphic = entity->getComponent<uf::Graphic>();
graphic.destroy();
}
*/
for ( auto& renderMode : renderModes ) {
if ( !renderMode ) continue;
renderMode->destroy();

View File

@ -73,9 +73,6 @@ void ext::opengl::RenderMode::createCommandBuffers() {
this->mostRecentCommandPoolId = std::this_thread::get_id();
this->rebuild = false;
}
ext::opengl::CommandBuffer& ext::opengl::RenderMode::getCommands() {
return getCommands( std::this_thread::get_id() );
}
ext::opengl::CommandBuffer& ext::opengl::RenderMode::getCommands( std::thread::id id ) {
bool exists = this->commands.has(id); //this->commands.count(id) > 0;
auto& commands = this->commands.get(id); //this->commands[id];

View File

@ -13,6 +13,7 @@ const uf::stl::string ext::opengl::BaseRenderMode::getType() const {
return "Swapchain";
}
void ext::opengl::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ext::opengl::Graphic*>& graphics ) {
#if 0
float width = this->width > 0 ? this->width : ext::opengl::settings::width;
float height = this->height > 0 ? this->height : ext::opengl::settings::height;
@ -53,6 +54,7 @@ void ext::opengl::BaseRenderMode::createCommandBuffers( const uf::stl::vector<ex
graphic->record( commands, descriptor, currentPass, currentDraw++ );
}
} commands.end();
#endif
}
void ext::opengl::BaseRenderMode::initialize( Device& device ) {
@ -72,11 +74,12 @@ void ext::opengl::BaseRenderMode::initialize( Device& device ) {
GL_ERROR_CHECK(glEnable(GL_DEPTH_TEST));
GL_ERROR_CHECK(glEnable(GL_TEXTURE_2D));
#if 0 && !UF_ENV_DREAMCAST
GL_ERROR_CHECK(glEnable(GL_ALPHA_TEST));
GL_ERROR_CHECK(glAlphaFunc(GL_GREATER, 0.1f));
GL_ERROR_CHECK(glEnable(GL_BLEND));
GL_ERROR_CHECK(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
#endif
// GL_ERROR_CHECK(glEnable(GL_LIGHTING));
// GL_ERROR_CHECK(glEnable(GL_NORMALIZE));
@ -106,7 +109,9 @@ void ext::opengl::BaseRenderMode::tick() {
ext::opengl::RenderMode::tick();
}
void ext::opengl::BaseRenderMode::render() {
#if 0
ext::opengl::RenderMode::render();
#endif
}
void ext::opengl::BaseRenderMode::destroy() {

View File

@ -35,7 +35,7 @@ void ext::vulkan::Buffer::aliasBuffer( const ext::vulkan::Buffer& buffer ) {
}
void* ext::vulkan::Buffer::map( VkDeviceSize size, VkDeviceSize offset ) {
VK_CHECK_RESULT(vmaMapMemory( allocator, allocation, &mapped ));
if ( !mapped ) VK_CHECK_RESULT(vmaMapMemory( allocator, allocation, &mapped ));
return mapped;
}
void ext::vulkan::Buffer::unmap() {

View File

@ -631,15 +631,12 @@ void ext::vulkan::Pipeline::update( const Graphic& graphic, const GraphicDescrip
}
}
renderMode.rebuild = true;
vkUpdateDescriptorSets(
*device,
writeDescriptorSets.size(),
writeDescriptorSets.data(),
0,
NULL
);
{
// bool locked = renderMode.tryMutex();
renderMode.rebuild = true;
vkUpdateDescriptorSets( *device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL );
// if ( locked ) renderMode.unlockMutex();
}
return;
PIPELINE_UPDATE_INVALID:

View File

@ -204,9 +204,6 @@ void ext::vulkan::RenderMode::createCommandBuffers() {
this->mostRecentCommandPoolId = std::this_thread::get_id();
this->rebuild = false;
}
ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands() {
return getCommands( std::this_thread::get_id() );
}
ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands( std::thread::id id ) {
bool exists = this->commands.has(id); //this->commands.count(id) > 0;
auto& commands = this->commands.get(id); //this->commands[id];
@ -223,17 +220,17 @@ ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getComma
}
return commands;
}
void ext::vulkan::RenderMode::lockMutex() {
return lockMutex( std::this_thread::get_id() );
}
void ext::vulkan::RenderMode::lockMutex( std::thread::id id ) {
this->commands.lock( id );
this->commands.lockMutex( id );
}
void ext::vulkan::RenderMode::unlockMutex() {
return unlockMutex( std::this_thread::get_id() );
bool ext::vulkan::RenderMode::tryMutex( std::thread::id id ) {
this->commands.tryMutex( id );
}
void ext::vulkan::RenderMode::unlockMutex( std::thread::id id ) {
this->commands.unlock( id );
this->commands.unlockMutex( id );
}
std::lock_guard<std::mutex> ext::vulkan::RenderMode::guardMutex( std::thread::id id ) {
return this->commands.guardMutex( id );
}
void ext::vulkan::RenderMode::createCommandBuffers( const uf::stl::vector<ext::vulkan::Graphic*>& graphics ) {

View File

@ -316,10 +316,11 @@ void ext::vulkan::initialize() {
auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread ? "Aux" : "Main");
for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue;
tasks.queue([&]{
renderMode->lockMutex();
auto guard = renderMode->guardMutex();
// renderMode->lockMutex();
if ( settings::invariant::individualPipelines ) renderMode->bindPipelines();
renderMode->createCommandBuffers();
renderMode->unlockMutex();
// renderMode->unlockMutex();
});
}
uf::thread::execute( tasks );
@ -395,10 +396,11 @@ void ext::vulkan::tick() {
auto tasks = uf::thread::schedule(settings::experimental::dedicatedThread ? "Aux" : "Main");
for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue;
if ( ext::vulkan::states::rebuild || renderMode->rebuild ) tasks.queue([&]{
renderMode->lockMutex();
auto guard = renderMode->guardMutex();
// renderMode->lockMutex();
if ( settings::invariant::individualPipelines ) renderMode->bindPipelines();
renderMode->createCommandBuffers();
renderMode->unlockMutex();
// renderMode->unlockMutex();
});
}
uf::thread::execute( tasks );
@ -468,13 +470,14 @@ void ext::vulkan::render() {
for ( auto& renderMode : renderModes ) {
if ( !renderMode || !renderMode->execute || !renderMode->metadata.limiter.execute ) continue;
renderMode->lockMutex( renderMode->mostRecentCommandPoolId );
// renderMode->lockMutex( renderMode->mostRecentCommandPoolId );
auto guard = renderMode->guardMutex( renderMode->mostRecentCommandPoolId );
ext::vulkan::setCurrentRenderMode(renderMode);
uf::graph::render();
uf::scene::render();
renderMode->render();
ext::vulkan::setCurrentRenderMode(NULL);
renderMode->unlockMutex( renderMode->mostRecentCommandPoolId );
// renderMode->unlockMutex( renderMode->mostRecentCommandPoolId );
}
}

View File

@ -3,9 +3,12 @@
#include <xatlas/xatlas.h>
#define UF_XATLAS_UNWRAP_MULTITHREAD 1
#define UF_XATLAS_LAZY 1 // i do not understand why it needs to insert extra vertices for it to not even be used in the indices buffer, this flag avoids having to account for it
#define UF_XATLAS_LAZY 0 // i do not understand why it needs to insert extra vertices for it to not even be used in the indices buffer, this flag avoids having to account for it
size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
size_t UF_API ext::xatlas::unwrap( pod::Graph& graph ) {
return graph.metadata["exporter"]["unwrap lazy"].as<bool>(false) ? unwrapLazy( graph ) : unwrapExperimental( graph );
}
size_t UF_API ext::xatlas::unwrapExperimental( pod::Graph& graph ) {
struct Entry {
size_t index = 0;
size_t commandID = 0;
@ -23,18 +26,35 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
uf::stl::unordered_map<size_t, Atlas> atlases;
atlases.reserve(graph.meshes.size());
uf::stl::vector<size_t> sizes( graph.meshes.size(), 0 );
uf::stl::unordered_map<size_t, size_t> sizesVertex;
uf::stl::unordered_map<size_t, size_t> sizesIndex;
// copy source meshes
// create mesh decls for passing to xatlas
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
auto& name = graph.meshes[index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
sources.emplace_back(mesh).updateDescriptor();
if ( mesh.isInterleaved() ) {
UF_EXCEPTION("unwrapping interleaved mesh is not supported");
}
sources.emplace_back(mesh).updateDescriptor();
bool should = false;
if ( graph.metadata["exporter"]["unwrap"].is<bool>() && graph.metadata["exporter"]["unwrap"].as<bool>() ) {
should = true;
} else {
ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) {
// if ( ext::json::isNull( value["unwrap mesh"] ) ) return;
if ( !value["unwrap mesh"].as<bool>(false) ) return;
if ( uf::string::isRegex( key ) ) {
if ( !uf::string::matched( name, key ) ) return;
} else if ( name != key ) return;
should = true;
});
}
if ( !should ) continue;
uf::Mesh::Input vertexInput = mesh.vertex;
@ -65,7 +85,7 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
size_t atlasID = combined ? 0 : drawCommands[i].auxID;
size_t atlasID = drawCommands[i].auxID;
vertexInput = mesh.remapVertexInput( i );
indexInput = mesh.remapIndexInput( i );
@ -152,27 +172,22 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
tasks.queue([&]{
auto& atlas = pair.second;
::xatlas::Generate(atlas.pointer, chartOptions, packOptions);
#if !UF_XATLAS_LAZY
// get vertices size ahead of time
for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) {
auto& xmesh = atlas.pointer->meshes[i];
auto& entry = atlas.entries[i];
// atlas.vertices += xmesh.vertexCount;
sizes[entry.index] += xmesh.vertexCount;
}
#endif
});
}
uf::thread::execute( tasks );
#if !UF_XATLAS_LAZY
for ( auto& pair : atlases ) {
auto& atlas = pair.second;
// get vertices size ahead of time
for ( auto i = 0; i < atlas.pointer->meshCount; ++i ) {
auto& xmesh = atlas.pointer->meshes[i];
auto& entry = atlas.entries[i];
sizes[entry.index] += xmesh.vertexCount;
if ( sizesVertex.count(entry.index) == 0 ) sizesVertex[entry.index] = 0;
if ( sizesIndex.count(entry.index) == 0 ) sizesIndex[entry.index] = 0;
sizesVertex[entry.index] += xmesh.vertexCount;
sizesIndex[entry.index] += xmesh.indexCount;
}
}
@ -180,12 +195,65 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
for ( auto i = 0; i < graph.meshes.size(); ++i ) {
auto& name = graph.meshes[i];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
if ( sizes[i] != mesh.vertex.count ) {
mesh.resizeVertices( sizes[i] );
mesh.updateDescriptor();
if ( sizesVertex[i] != mesh.vertex.count ) {
mesh.resizeVertices( sizesVertex[i] );
}
if ( sizesIndex[i] != mesh.index.count ) {
mesh.resizeIndices( sizesIndex[i] );
}
mesh.updateDescriptor();
}
// update vertices count
for ( auto& pair : atlases ) {
auto& atlas = pair.second;
for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) {
auto& xmesh = atlas.pointer->meshes[i];
auto& entry = atlas.entries[i];
auto& name = graph.meshes[entry.index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
auto& source = sources[entry.index];
source.updateDescriptor();
// draw commands
if ( !mesh.indirect.count ) continue;
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
auto& primitive = primitives[entry.commandID];
auto& drawCommand = drawCommands[entry.commandID];
drawCommand.vertices = xmesh.vertexCount;
drawCommand.indices = xmesh.indexCount;
}
}
// update vertexID offsets for indirect commands
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
auto& name = graph.meshes[index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
if ( !mesh.indirect.count ) continue;
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
size_t vertexID = 0;
size_t indexID = 0;
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
auto& primitive = primitives[i];
auto& drawCommand = drawCommands[i];
drawCommand.vertexID = vertexID;
drawCommand.indexID = indexID;
primitive.drawCommand = drawCommand;
vertexID += drawCommand.vertices;
indexID += drawCommand.indices;
}
}
#endif
// update vertices
for ( auto& pair : atlases ) {
@ -204,51 +272,44 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
auto srcInput = source.remapVertexInput( entry.commandID );
auto dstInput = mesh.remapVertexInput( entry.commandID );
#if UF_XATLAS_LAZY
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
for ( auto k = 0; k < srcInput.attributes.size(); ++k ) {
auto dstAttribute = dstInput.attributes[k];
if ( dstAttribute.descriptor.name != "st" ) continue;
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (ref + dstInput.first) );
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
}
}
#else
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
bool mismatched = xmesh.vertexCount != drawCommands[entry.commandID].vertices;
vertexIDOffset += xmesh.vertexCount - drawCommands[entry.commandID].vertices;
drawCommands[entry.commandID].vertices = xmesh.vertexCount;
primitives[entry.commandID].drawCommand.vertices = xmesh.vertexCount;
drawCommands[entry.commandID].vertexID += vertexIDOffset;
primitives[entry.commandID].drawCommand.vertexID += vertexIDOffset;
auto& drawCommand = drawCommands[entry.commandID];
auto& primitive = primitives[entry.commandID];
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
for ( auto k = 0; k < srcInput.attributes.size(); ++k ) {
auto srcAttribute = srcInput.attributes[k];
auto dstAttribute = dstInput.attributes[k];
for ( auto _ = 0; _ < srcInput.attributes.size(); ++_ ) {
auto srcAttribute = srcInput.attributes[_];
auto dstAttribute = dstInput.attributes[_];
if ( dstAttribute.descriptor.name == "st" ) {
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) );
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
} else {
memcpy( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first), static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first), srcAttribute.stride );
}
memcpy(
static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first),
static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * (ref + srcInput.first),
srcAttribute.stride
);
}
}
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
for ( auto _ = 0; _ < srcInput.attributes.size(); ++_ ) {
auto dstAttribute = dstInput.attributes[_];
if ( dstAttribute.descriptor.name != "st" ) continue;
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (j + dstInput.first) );
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
}
}
// indices
if ( mesh.index.count ) {
uf::Mesh::Input indexInput = mesh.remapIndexInput( entry.commandID );
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
// uf::Mesh::Attribute indexAttribute = mesh.remapIndexAttribute( mesh.index.attributes.front(), entry.commandID );
uf::Mesh::Attribute indexAttribute = indexInput.attributes.front();
uint8_t* pointer = (uint8_t*) static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * indexInput.first;
for ( auto index = 0; index < xmesh.indexCount; ++index ) {
switch ( mesh.index.size ) {
@ -258,29 +319,12 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
}
}
}
#endif
} else {
uf::Mesh::Attribute stAttribute;
for ( auto& attribute : mesh.vertex.attributes ) if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
UF_ASSERT( stAttribute.descriptor.name == "st" );
// vertices
#if UF_XATLAS_LAZY
auto srcInput = source.vertex;
auto dstInput = mesh.vertex;
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
for ( auto k = 0; k < srcInput.attributes.size(); ++k ) {
auto dstAttribute = dstInput.attributes[k];
if ( dstAttribute.descriptor.name != "st" ) continue;
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (ref + dstInput.first) );
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
}
}
#else
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
@ -290,33 +334,12 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
auto dstAttribute = mesh.vertex.attributes[k];
if ( dstAttribute.descriptor.name == "st" ) {
pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * j);
pod::Vector2f& st = *(pod::Vector2f*) ( ((uint8_t*) dstAttribute.pointer) + dstAttribute.stride * (mesh.vertex.first + j));
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
} else {
memcpy( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * j, static_cast<uint8_t*>(srcAttribute.pointer) + srcAttribute.stride * ref, srcAttribute.stride );
}
}
/*
if ( mesh.isInterleaved( mesh.vertex.interleaved ) ) {
uint8_t* srcAttribute = source.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size;
uint8_t* dstAttribute = mesh.buffers[mesh.vertex.interleaved].data() + j * mesh.vertex.size;
memcpy( dstAttribute, srcAttribute, mesh.vertex.size );
pod::Vector2f& st = *(pod::Vector2f*) (dstAttribute + stAttribute.descriptor.offset);
st = { vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
} else for ( auto& attribute : mesh.vertex.attributes ) {
uint8_t* srcAttribute = source.buffers[attribute.buffer].data() + j * attribute.descriptor.size;
uint8_t* dstAttribute = mesh.buffers[attribute.buffer].data() + j * attribute.descriptor.size;
if ( attribute.descriptor.name == "st" ) {
pod::Vector2f& st = *(pod::Vector2f*) dstAttribute;
st = { vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };
} else {
memcpy( dstAttribute, srcAttribute, attribute.descriptor.size );
}
}
*/
}
// indices
if ( mesh.index.count ) {
@ -330,37 +353,223 @@ size_t UF_API ext::xatlas::unwrap( pod::Graph& graph, bool combined ) {
}
}
}
#endif
}
mesh.updateDescriptor();
}
}
#if !UF_XATLAS_LAZY
// update vertexID offsets for indirect commands
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
auto& name = graph.meshes[index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
if ( !mesh.indirect.count ) continue;
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
size_t vertexID = 0;
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
auto& primitive = primitives[i];
auto& drawCommand = drawCommands[i];
drawCommand.vertexID = vertexID;
primitive.drawCommand.vertexID = vertexID;
vertexID += drawCommand.vertices;
}
}
#endif
// cleanup
size_t atlasCount = 0;
for ( auto& pair : atlases ) {
auto& atlas = pair.second;
::xatlas::Destroy(atlas.pointer);
++atlasCount;
}
return atlasCount;
}
size_t UF_API ext::xatlas::unwrapLazy( pod::Graph& graph ) {
struct Entry {
size_t index = 0;
size_t commandID = 0;
::xatlas::MeshDecl decl;
};
struct Atlas {
::xatlas::Atlas* pointer = NULL;
uf::stl::vector<Entry> entries;
size_t vertexOffset = 0;
};
uf::stl::unordered_map<size_t, Atlas> atlases;
atlases.reserve(graph.meshes.size());
// copy source meshes
// create mesh decls for passing to xatlas
for ( auto index = 0; index < graph.meshes.size(); ++index ) {
auto& name = graph.meshes[index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
if ( mesh.isInterleaved() ) {
UF_EXCEPTION("unwrapping interleaved mesh is not supported");
}
bool should = false;
if ( graph.metadata["exporter"]["unwrap"].is<bool>() && graph.metadata["exporter"]["unwrap"].as<bool>() ) {
should = true;
} else {
ext::json::forEach( graph.metadata["tags"], [&]( const uf::stl::string& key, ext::json::Value& value ) {
// if ( ext::json::isNull( value["unwrap mesh"] ) ) return;
if ( !value["unwrap mesh"].as<bool>(false) ) return;
if ( uf::string::isRegex( key ) ) {
if ( !uf::string::matched( name, key ) ) return;
} else if ( name != key ) return;
should = true;
});
}
if ( !should ) continue;
uf::Mesh::Input vertexInput = mesh.vertex;
uf::Mesh::Attribute positionAttribute;
uf::Mesh::Attribute uvAttribute;
uf::Mesh::Attribute stAttribute;
for ( auto& attribute : mesh.vertex.attributes ) {
if ( attribute.descriptor.name == "position" ) positionAttribute = attribute;
else if ( attribute.descriptor.name == "uv" ) uvAttribute = attribute;
else if ( attribute.descriptor.name == "st" ) stAttribute = attribute;
}
UF_ASSERT( positionAttribute.descriptor.name == "position" && uvAttribute.descriptor.name == "uv" && stAttribute.descriptor.name == "st" );
if ( mesh.index.count ) {
uf::Mesh::Input indexInput = mesh.index;
uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front();
::xatlas::IndexFormat indexType = ::xatlas::IndexFormat::UInt32;
switch ( mesh.index.size ) {
case sizeof(uint16_t): indexType = ::xatlas::IndexFormat::UInt16; break;
case sizeof(uint32_t): indexType = ::xatlas::IndexFormat::UInt32; break;
default: UF_EXCEPTION("unsupported index type"); break;
}
if ( mesh.indirect.count ) {
auto& primitives = /*graph.storage*/uf::graph::storage.primitives[name];
pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data();
for ( auto i = 0; i < mesh.indirect.count; ++i ) {
size_t atlasID = drawCommands[i].auxID;
vertexInput = mesh.remapVertexInput( i );
indexInput = mesh.remapIndexInput( i );
auto& atlas = atlases[atlasID];
auto& entry = atlas.entries.emplace_back();
entry.index = index;
entry.commandID = i;
auto& decl = entry.decl;
decl.vertexPositionData = static_cast<uint8_t*>(positionAttribute.pointer) + positionAttribute.stride * vertexInput.first;
decl.vertexPositionStride = positionAttribute.stride;
decl.vertexUvData = static_cast<uint8_t*>(uvAttribute.pointer) + uvAttribute.stride * vertexInput.first;
decl.vertexUvStride = uvAttribute.stride;
decl.vertexCount = vertexInput.count;
decl.indexCount = indexInput.count;
decl.indexData = static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * indexInput.first;
decl.indexFormat = indexType;
}
} else {
size_t atlasID = 0;
auto& atlas = atlases[atlasID];
auto& entry = atlas.entries.emplace_back();
entry.index = index;
auto& decl = entry.decl;
decl.vertexPositionData = static_cast<uint8_t*>(positionAttribute.pointer) + positionAttribute.stride * vertexInput.first;
decl.vertexPositionStride = positionAttribute.stride;
decl.vertexUvData = static_cast<uint8_t*>(uvAttribute.pointer) + uvAttribute.stride * vertexInput.first;
decl.vertexUvStride = uvAttribute.stride;
decl.vertexCount = vertexInput.count;
decl.indexCount = indexInput.count;
decl.indexData = static_cast<uint8_t*>(indexAttribute.pointer) + indexAttribute.stride * indexInput.first;
decl.indexFormat = indexType;
}
} else UF_EXCEPTION("to-do: not require indices for meshes");
}
// add mesh decls to mesh atlases
// done after the fact since we'll know the total amount of meshes added
for ( auto& pair : atlases ) {
auto& atlas = pair.second;
if ( !atlas.pointer ) atlas.pointer = ::xatlas::Create();
for ( auto& entry : atlas.entries ) {
::xatlas::AddMeshError error = ::xatlas::AddMesh(atlas.pointer, entry.decl, atlas.entries.size());
if (error != ::xatlas::AddMeshError::Success) {
::xatlas::Destroy(atlas.pointer);
UF_EXCEPTION(::xatlas::StringForEnum(error));
}
}
}
::xatlas::ChartOptions chartOptions{};
chartOptions.useInputMeshUvs = graph.metadata["baking"]["settings"]["useInputMeshUvs"].as(chartOptions.useInputMeshUvs);
chartOptions.maxIterations = graph.metadata["baking"]["settings"]["maxIterations"].as(chartOptions.maxIterations);
::xatlas::PackOptions packOptions{};
packOptions.maxChartSize = graph.metadata["baking"]["settings"]["maxChartSize"].as(packOptions.maxChartSize);
packOptions.padding = graph.metadata["baking"]["settings"]["padding"].as(packOptions.padding);
packOptions.texelsPerUnit = graph.metadata["baking"]["settings"]["texelsPerUnit"].as(packOptions.texelsPerUnit);
packOptions.bilinear = graph.metadata["baking"]["settings"]["bilinear"].as(packOptions.bilinear);
packOptions.blockAlign = graph.metadata["baking"]["settings"]["blockAlign"].as(packOptions.blockAlign);
packOptions.bruteForce = graph.metadata["baking"]["settings"]["bruteForce"].as(packOptions.bruteForce);
packOptions.createImage = graph.metadata["baking"]["settings"]["createImage"].as(packOptions.createImage);
packOptions.rotateChartsToAxis = graph.metadata["baking"]["settings"]["rotateChartsToAxis"].as(packOptions.rotateChartsToAxis);
packOptions.rotateCharts = graph.metadata["baking"]["settings"]["rotateCharts"].as(packOptions.rotateCharts);
packOptions.resolution = graph.metadata["baking"]["resolution"].as(packOptions.resolution);
// pack
#if UF_XATLAS_UNWRAP_MULTITHREAD
auto tasks = uf::thread::schedule("Async");
#else
auto tasks = uf::thread::schedule("Main");
#endif
for ( auto& pair : atlases ) {
tasks.queue([&]{
auto& atlas = pair.second;
::xatlas::Generate(atlas.pointer, chartOptions, packOptions);
});
}
uf::thread::execute( tasks );
// update vertices
for ( auto& pair : atlases ) {
auto& atlas = pair.second;
for ( auto i = 0; i < atlas.pointer->meshCount; i++ ) {
auto& xmesh = atlas.pointer->meshes[i];
auto& entry = atlas.entries[i];
auto& name = graph.meshes[entry.index];
auto& mesh = /*graph.storage*/uf::graph::storage.meshes[name];
// draw commands
if ( mesh.indirect.count ) {
auto vertexInput = mesh.remapVertexInput( entry.commandID );
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
for ( auto k = 0; k < vertexInput.attributes.size(); ++k ) {
auto dstAttribute = vertexInput.attributes[k];
if ( dstAttribute.descriptor.name != "st" ) continue;
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (ref + vertexInput.first) );
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
}
}
} else {
for ( auto j = 0; j < xmesh.vertexCount; ++j ) {
auto& vertex = xmesh.vertexArray[j];
auto ref = vertex.xref;
for ( auto k = 0; k < mesh.vertex.attributes.size(); ++k ) {
auto dstAttribute = mesh.vertex.attributes[k];
if ( dstAttribute.descriptor.name != "st" ) continue;
pod::Vector2f& st = *(pod::Vector2f*) ( static_cast<uint8_t*>(dstAttribute.pointer) + dstAttribute.stride * (ref + mesh.vertex.first) );
st = pod::Vector2f{ vertex.uv[0] / atlas.pointer->width, vertex.uv[1] / atlas.pointer->height };;
}
}
}
mesh.updateDescriptor();
}
}
// cleanup
size_t atlasCount = 0;
for ( auto& pair : atlases ) {

View File

@ -187,8 +187,8 @@ void uf::meshgrid::partition( uf::meshgrid::Grid& grid,
for ( auto& pair : grid.nodes ) { auto& node = pair.second;
auto& meshlet = node.meshlets[primitive.instance.primitiveID];
// if ( isInside( tri.vertices[0], node.extents.min, node.extents.max ) || isInside( tri.vertices[1], node.extents.min, node.extents.max ) || isInside( tri.vertices[2], node.extents.min, node.extents.max ) ) {
if ( isInside( tri.center, node.extents.min, node.extents.max ) ) {
if ( isInside( tri.vertices[0], node.extents.min, node.extents.max ) || isInside( tri.vertices[1], node.extents.min, node.extents.max ) || isInside( tri.vertices[2], node.extents.min, node.extents.max ) ) {
// if ( isInside( tri.center, node.extents.min, node.extents.max ) ) {
meshlet.indices.emplace_back( tri.indices[0] );
meshlet.indices.emplace_back( tri.indices[1] );
meshlet.indices.emplace_back( tri.indices[2] );
@ -202,8 +202,8 @@ void uf::meshgrid::partition( uf::meshgrid::Grid& grid,
found = true;
break;
}
if ( isInside( tri.vertices[0], node.extents.min, node.extents.max ) || isInside( tri.vertices[1], node.extents.min, node.extents.max ) || isInside( tri.vertices[2], node.extents.min, node.extents.max ) ) {
// if ( isInside( tri.center, node.extents.min, node.extents.max ) ) {
// if ( isInside( tri.vertices[0], node.extents.min, node.extents.max ) || isInside( tri.vertices[1], node.extents.min, node.extents.max ) || isInside( tri.vertices[2], node.extents.min, node.extents.max ) ) {
if ( isInside( tri.center, node.extents.min, node.extents.max ) ) {
meshlet.indices.emplace_back( tri.indices[0] );
meshlet.indices.emplace_back( tri.indices[1] );
meshlet.indices.emplace_back( tri.indices[2] );

View File

@ -56,7 +56,7 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
renderMode.execute = false;
renderMode.metadata.type = "single";
renderMode.metadata.type = "depth"; // "single";
renderMode.metadata.pipeline = "baking";
renderMode.metadata.samples = 1;
// renderMode.metadata.views = metadata.max.layers; // gl_Layer doesn't work
@ -88,10 +88,10 @@ void ext::BakingBehavior::initialize( uf::Object& self ) {
shader.textures.emplace_back().aliasTexture( metadata.buffers.baked );
});
UF_MSG_DEBUG("Finished initialiation.");
uf::thread::queue([&]{
// uf::thread::queue([&]{
uf::renderer::addRenderMode( &renderMode, metadata.renderModeName );
});
// });
UF_MSG_DEBUG("Finished initialiation.");
});
this->queueHook( "entity:PostInitialization.%UID%", ext::json::null(), 1 );
@ -132,7 +132,7 @@ SAVE: {
auto tasks = uf::thread::schedule("Main");
#endif
// 0 is always broken, do not save it
for ( size_t i = 1; i < metadata.max.layers; ++i ) {
for ( size_t i = 0; i < metadata.max.layers; ++i ) {
tasks.queue([&, i]{
// auto image = renderMode.screenshot(0, i);
auto image = metadata.buffers.baked.screenshot(i);

View File

@ -481,11 +481,14 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
renderMode.execute = true;
renderMode.metadata.limiter.execute = true;
}
constexpr uint32_t MODE_SPLIT = 0;
constexpr uint32_t MODE_CUBEMAP = 1;
constexpr uint32_t MODE_SEPARATE_2DS = 2;
// if point light, and combining is requested
if ( metadata.shadow.experimentalMode > 0 && renderMode.renderTarget.views == 6 ) {
if ( metadata.shadow.typeMap > MODE_SPLIT && renderMode.renderTarget.views == 6 ) {
int32_t index = -1;
// separated texture2Ds
if ( metadata.shadow.experimentalMode == 2 ) {
if ( metadata.shadow.typeMap == MODE_SEPARATE_2DS ) {
index = uf::graph::storage.shadow2Ds.size();
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
@ -495,7 +498,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
break;
}
// cubemapped
} else {
} else if ( metadata.shadow.typeMap == MODE_CUBEMAP ) {
index = uf::graph::storage.shadowCubes.size();
for ( auto& attachment : renderMode.renderTarget.attachments ) {
if ( !(attachment.descriptor.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
@ -511,7 +514,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
.color = info.color,
.intensity = info.intensity,
.type = info.type,
.typeMap = metadata.shadow.experimentalMode,
.typeMap = metadata.shadow.typeMap,
.indexMap = index,
.depthBias = info.bias,
});
@ -604,7 +607,7 @@ void ext::ExtSceneBehavior::Metadata::deserialize( uf::Object& self, uf::Seriali
/*this->*/shadow.samples = ext::config["engine"]["scenes"]["shadows"]["samples"].as<uint32_t>();
/*this->*/shadow.max = ext::config["engine"]["scenes"]["shadows"]["max"].as<uint32_t>();
/*this->*/shadow.update = ext::config["engine"]["scenes"]["shadows"]["update"].as<uint32_t>();
/*this->*/shadow.experimentalMode = ext::config["engine"]["scenes"]["shadows"]["experimental mode"].as<uint32_t>(0);
/*this->*/shadow.typeMap = ext::config["engine"]["scenes"]["shadows"]["map type"].as<uint32_t>(1);
/*this->*/light.enabled = ext::config["engine"]["scenes"]["lights"]["enabled"].as<bool>(true) && serializer["light"]["should"].as<bool>(true);
/*this->*/light.max = ext::config["engine"]["scenes"]["lights"]["max"].as<uint32_t>(/*this->*/light.max);
@ -737,8 +740,8 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
alignas(4) float voxelizeScale;
alignas(4) float occlusionFalloff;
alignas(4) float traceStartOffsetFactor;
alignas(4) uint32_t shadows;
alignas(4) uint32_t padding1;
alignas(4) uint32_t padding2;
alignas(4) uint32_t padding3;
} vxgi;
@ -842,6 +845,7 @@ void ext::ExtSceneBehavior::bindBuffers( uf::Object& self, const uf::stl::string
.voxelizeScale = 1.0f / (metadataVxgi.voxelizeScale * std::max<uint32_t>( metadataVxgi.voxelSize.x, std::max<uint32_t>(metadataVxgi.voxelSize.y, metadataVxgi.voxelSize.z))),
.occlusionFalloff = metadataVxgi.occlusionFalloff,
.traceStartOffsetFactor = metadataVxgi.traceStartOffsetFactor,
.shadows = metadataVxgi.shadows,
};

View File

@ -38,8 +38,7 @@ namespace ext {
int samples = 4;
int max = 8;
uint32_t update = 4;
uint32_t experimentalMode = 0;
uint32_t typeMap = 1;
} shadow;
struct {
uint32_t mode;

View File

@ -397,8 +397,8 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
/*alignas(4)*/ float voxelizeScale;
/*alignas(4)*/ float occlusionFalloff;
/*alignas(4)*/ float traceStartOffsetFactor;
/*alignas(4)*/ uint32_t shadows;
/*alignas(4)*/ uint32_t padding1;
/*alignas(4)*/ uint32_t padding2;
/*alignas(4)*/ uint32_t padding3;
};
@ -415,6 +415,7 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
.voxelizeScale = 1.0f / (metadata.voxelizeScale * std::max<uint32_t>( metadata.voxelSize.x, std::max<uint32_t>(metadata.voxelSize.y, metadata.voxelSize.z))),
.occlusionFalloff = metadata.occlusionFalloff,
.traceStartOffsetFactor = metadata.traceStartOffsetFactor,
.shadows = metadata.shadows,
};
shader.updateUniform( "UBO", uniform );
@ -426,6 +427,7 @@ void ext::VoxelizerBehavior::tick( uf::Object& self ) {
.voxelizeScale = 1.0f / (metadata.voxelizeScale * std::max<uint32_t>( metadata.voxelSize.x, std::max<uint32_t>(metadata.voxelSize.y, metadata.voxelSize.z))),
.occlusionFalloff = metadata.occlusionFalloff,
.traceStartOffsetFactor = metadata.traceStartOffsetFactor,
.shadows = metadata.shadows,
};
shader.updateBuffer( uniforms, shader.getUniformBuffer("UBO") );
@ -459,6 +461,7 @@ void ext::VoxelizerBehavior::Metadata::serialize( uf::Object& self, uf::Serializ
serializer["vxgi"]["granularity"] = /*this->*/granularity;
serializer["vxgi"]["voxelizeScale"] = /*this->*/voxelizeScale;
serializer["vxgi"]["occlusionFalloff"] = /*this->*/occlusionFalloff;
serializer["vxgi"]["traceStartOffsetFactor"] = /*this->*/traceStartOffsetFactor;
serializer["vxgi"]["shadows"] = /*this->*/shadows;
serializer["vxgi"]["extents"]["min"] = uf::vector::encode(/*this->*/extents.min);
@ -480,6 +483,7 @@ void ext::VoxelizerBehavior::Metadata::deserialize( uf::Object& self, uf::Serial
/*this->*/granularity = serializer["vxgi"]["granularity"].as<float>(4);
/*this->*/voxelizeScale = serializer["vxgi"]["voxelizeScale"].as<float>(1);
/*this->*/occlusionFalloff = serializer["vxgi"]["occlusionFalloff"].as<float>(128);
/*this->*/traceStartOffsetFactor = serializer["vxgi"]["traceStartOffsetFactor"].as<float>(1.0f);
/*this->*/shadows = serializer["vxgi"]["shadows"].as<size_t>(0);
/*this->*/extents.min = uf::vector::decode( serializer["vxgi"]["extents"]["min"], pod::Vector3f{-32, -32, -32} );

View File

@ -23,6 +23,7 @@ namespace ext {
float granularity = 0;
float voxelizeScale = 0;
float occlusionFalloff = 0;
float traceStartOffsetFactor = 1.0f;
uint32_t shadows = 0;
struct {

View File

@ -210,7 +210,11 @@ void EXT_API ext::initialize() {
}
{
uf::Mesh::defaultInterleaved = ::json["engine"]["scenes"]["meshes"]["interleaved"].as( uf::Mesh::defaultInterleaved );
#if UF_USE_OPENGL
uf::matrix::reverseInfiniteProjection = false;
#else
uf::matrix::reverseInfiniteProjection = ::json["engine"]["scenes"]["matrix"]["reverseInfinite"].as( uf::matrix::reverseInfiniteProjection );
#endif
}
/* Create initial scene (kludge) */ {