diff --git a/code/Modules/Assets/Assets.cc b/code/Modules/Assets/Assets.cc index 9e5da1615..7e3da11fc 100644 --- a/code/Modules/Assets/Assets.cc +++ b/code/Modules/Assets/Assets.cc @@ -34,8 +34,42 @@ Assets::IsValid() { return nullptr != state; } +//------------------------------------------------------------------------------ +const class AssetsSetup& +Assets::AssetsSetup() { + o_assert_dbg(IsValid()); + return state->setup; +} + +//------------------------------------------------------------------------------ +void +Assets::AttachLoader(const Ptr& loader) { + o_assert_dbg(IsValid()); + state->loaderRegistry.AttachLoader(loader); +} + +//------------------------------------------------------------------------------ +void +Assets::DetachLoader(const Ptr& loader) { + o_assert_dbg(IsValid()); + state->loaderRegistry.DetachLoader(loader); +} + +//------------------------------------------------------------------------------ +AssetId +Assets::Lookup(const Locator& loc) { + o_assert_dbg(IsValid()); + return AssetId(state->registry.Lookup(loc)); +} -FIXME: -- Load must first check the registry, then call assetLoaderRegistry +//------------------------------------------------------------------------------ +AssetId +Assets::Register(const Locator& loc, Id resId, DiscardFunc discardFunc) { + o_assert_dbg(IsValid()); + o_assert_dbg(!state->registry.Contains(id)); + o_assert_dbg(!state->registry.Lookup(loc).IsValid()); + state->registry.Add(loc, resId, discardFunc); + return AssetId(resId); +} } // namespace Oryol \ No newline at end of file diff --git a/code/Modules/Assets/Assets.h b/code/Modules/Assets/Assets.h index 2dfbf274f..94b9d2580 100644 --- a/code/Modules/Assets/Assets.h +++ b/code/Modules/Assets/Assets.h @@ -11,16 +11,19 @@ #include #include "Core/Types.h" #include "IO/Stream/Stream.h" +#include "Resource/ResourceState.h" #include "Assets/AssetId.h" #include "Assets/AssetsSetup.h" #include "Assets/Core/assetRegistry.h" +#include "Assets/Core/assetLoaderRegistry.h" +#include "Assets/Core/assetCreator.h" #include "Assets/Core/AssetLoader.h" namespace Oryol { class Assets { public: /// asset discard function - typedef std::function DiscardFunc; + typedef _priv::assetRegistry::DiscardFunc DiscardFunc; /// setup the Asset module static void Setup(const AssetsSetup& setup = AssetsSetup()); @@ -35,9 +38,19 @@ class Assets { static void AttachLoader(const Ptr& loader); /// detach an asset loader static void DetachLoader(const Ptr& loader); - + + /// push a new asset creation label + void PushAssetLabel(uint8 label); + /// pop top most asset creation label + uint8 PopAssetLabel(); + /// discard all assets matching label + void DiscardAssets(uint8 label); /// async load shared asset (or return existing shared asset) template static AssetId Load(const SETUP& setup); + /// directly create a shared, use-counted asset + template static AssetId Create(const SETUP& setup); + /// directly create a shared, use-count asset with data + template static AssetId Create(const SETUP& setup, const Ptr& data); /// lookup a shared asset by locator (bumps use-count) static AssetId Lookup(const Locator& loc); /// register an existing resource as shared asset @@ -54,10 +67,46 @@ class Assets { struct _state { class AssetsSetup setup; _priv::assetRegistry registry; + _priv::assetLoaderRegistry loaderRegistry; }; static _state* state; }; +//------------------------------------------------------------------------------ +template AssetId +Assets::Create(const SETUP& setup) { + o_assert_dbg(IsValid()); + Id resId = state->registry.Lookup(setup.Locator); + if (!resId.IsValid()) { + resId = _priv::assetCreator::Create(setup, state->registry); + } + return AssetId(resId); +} + +//------------------------------------------------------------------------------ +template AssetId +Assets::Create(const SETUP& setup, const Ptr& data) { + o_assert_dbg(IsValid()); + Id resId = state->registry.Lookup(setup.Locator); + if (!resId.IsValid()) { + resId = _priv::assetCreator::Create(setup, state->registry); + } + return AssetId(resId); +} + +//------------------------------------------------------------------------------ +template AssetId +Assets::Load(const SETUP& setup) { + o_assert_dbg(IsValid()); + + // first check whether the asset already exists + Id resId = state->registry.Lookup(setup.Locator); + if (!resId.IsValid()) { + resId = state->loaderRegistry.Load(setup); + } + return AssetId(resId); +} + //------------------------------------------------------------------------------ inline void Assets::releaseAsset(const Id& resId) { diff --git a/code/Modules/Assets/CMakeLists.txt b/code/Modules/Assets/CMakeLists.txt index f37f450b2..d37b1e299 100644 --- a/code/Modules/Assets/CMakeLists.txt +++ b/code/Modules/Assets/CMakeLists.txt @@ -7,7 +7,10 @@ fips_begin_module(Assets) fips_dir(Core) fips_files( assetRegistry.cc assetRegistry.h - AssetLoader.h + assetLoaderRegistry.cc assetLoaderRegistry.h + assetCreator.h + assetCreator_Gfx.cc + AssetLoader.cc AssetLoader.h ) fips_dir(Util) fips_files( diff --git a/code/Modules/Assets/Core/AssetLoader.cc b/code/Modules/Assets/Core/AssetLoader.cc new file mode 100644 index 000000000..c62abf8e1 --- /dev/null +++ b/code/Modules/Assets/Core/AssetLoader.cc @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------ +// AssetLoader.cc +//------------------------------------------------------------------------------ +#include "Pre.h" +#include "AssetLoader.h" + +namespace Oryol { + +OryolClassImpl(AssetLoader); + +//------------------------------------------------------------------------------ +void +AssetLoader::Attached() { + // empty +} + +//------------------------------------------------------------------------------ +void +AssetLoader::Detached() { + // empty +} + +//------------------------------------------------------------------------------ +bool +AssetLoader::TryLoad(const Id& /*id*/, const Ptr& /*data*/) { + return false; +} + +} // namespace Oryol \ No newline at end of file diff --git a/code/Modules/Assets/Core/AssetLoader.h b/code/Modules/Assets/Core/AssetLoader.h index 772b27bb4..e8edb7602 100644 --- a/code/Modules/Assets/Core/AssetLoader.h +++ b/code/Modules/Assets/Core/AssetLoader.h @@ -5,15 +5,18 @@ @ingroup Assets @brief base class for asset loaders */ -#include "Assets/AssetFormat.h" +#include "Core/RefCounted.h" +#include "Resource/Id.h" +#include "IO/Stream/Stream.h" namespace Oryol { -class AssetLoader { +class AssetLoader : public RefCounted { + OryolClassDecl(AssetLoader); public: /// called when attached to Assets module - virtual void Attached() = 0; + virtual void Attached(); /// called when detached from Assets module - virtual void Detached() = 0; + virtual void Detached(); /// try loading/creating the resource, return false if not possible virtual bool TryLoad(const Id& id, const Ptr& data); }; diff --git a/code/Modules/Assets/Core/assetCreator.h b/code/Modules/Assets/Core/assetCreator.h new file mode 100644 index 000000000..0dbef8dab --- /dev/null +++ b/code/Modules/Assets/Core/assetCreator.h @@ -0,0 +1,42 @@ +#pragma once +//------------------------------------------------------------------------------ +/** + @class Oryol::assetCreator + @ingroup Assets + @brief wrapper class for directly creating assets + + This class contains entirely of specialized template methods + to forward a resource creation request to a specific Module + and return the resulting resource id as AssetId. Each set of + specialization methods should live in its own source code + (compilation unit) to make sure that unused Modules are not + linked in. +*/ +#include "IO/Stream/Stream.h" +#include "Assets/Core/assetRegistry.h" + +namespace Oryol { +namespace _priv { + +class assetCreator { +public: + /// setup the asset creator + void Setup(assetRegistry* registry); + /// discard the asset creator + void Discard(); + + /// directly create a shared, use-counted asset + template Id Create(const SETUP& setup, assetRegistry* registry); + /// directly create a shared, use-count asset with data + template Id Create(const SETUP& setup, const Ptr& data, assetRegistry* registry); + /// allocate a resource (for async resource loading) + template Id Alloc(const SETUP& setup, Id placeholder, assetRegistry* registry); + /// setup a previously allocated resource from data (for async resource loading) + template void Init(const Id& id, const SETUP& setup, const Ptr& data); + + /// one-time register a push-label function + void regFuncsOnce(void(*push)(uint8), uint8(*pop)(), void(*discard)(uint8)); +}; + +} // namespace _priv +} // namespace Oryol \ No newline at end of file diff --git a/code/Modules/Assets/Core/assetCreator_Gfx.cc b/code/Modules/Assets/Core/assetCreator_Gfx.cc new file mode 100644 index 000000000..b599880b2 --- /dev/null +++ b/code/Modules/Assets/Core/assetCreator_Gfx.cc @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +// assetCreator_Gfx.cc +//------------------------------------------------------------------------------ +#include "Pre.h" +#include "assetCreator.h" +#include "Gfx/Gfx.h" + +namespace Oryol { +namespace _priv { + +//------------------------------------------------------------------------------ +template Id +assetCreator::Create(const SETUP& setup, assetRegistry* registry) { + this->regFuncsOnce(Gfx::PushResourceLabel, Gfx::PopResourceLabel, Gfx::DiscardResources); + Id resId = Gfx::CreateResource(setup); + registry->Add(setup.Locator, resId); + return resId; +} + +//------------------------------------------------------------------------------ +template Id +assetCreator::Create(const SETUP& setup, const Ptr& data, assetRegistry* registry) { + this->regFuncsOnce(Gfx::PushResourceLabel, Gfx::PopResourceLabel, Gfx::DiscardResources); + Id resId = Gfx::CreateResource(setup, data); + registry->Add(setup.Locator, resId); + return resId; +} + +//------------------------------------------------------------------------------ +template Id +assetCreator::Alloc(const SETUP& setup, Id placeholder, assetRegistry* registry) { + this->regFuncsOnce(Gfx::PushResourceLabel, Gfx::PopResourceLabel, Gfx::DiscardResources); + Id resId = Gfx::AllocResource(setup, placeholder); + registry->Add(setup.Locator, resId); + return resId; +} + +//------------------------------------------------------------------------------ +template void +assetCreator::Init(const Id& id, const SETUP& setup, const Ptr& data) { + Gfx::InitResource(id, setup, data); +} + +} // namespace _priv +} // namespace Oryol diff --git a/code/Modules/Assets/Core/assetLoaderRegistry.cc b/code/Modules/Assets/Core/assetLoaderRegistry.cc index 7d8ea68f7..0faee58c3 100644 --- a/code/Modules/Assets/Core/assetLoaderRegistry.cc +++ b/code/Modules/Assets/Core/assetLoaderRegistry.cc @@ -3,8 +3,10 @@ //------------------------------------------------------------------------------ #include "Pre.h" #include "assetLoaderRegistry.h" +#include "Core/Core.h" namespace Oryol { +namespace _priv { //------------------------------------------------------------------------------ assetLoaderRegistry::assetLoaderRegistry() : @@ -69,14 +71,5 @@ assetLoaderRegistry::DetachLoader(Ptr loader) { this->loaders.Erase(loaderIndex); } -//------------------------------------------------------------------------------ -FIXME: Load method: - -- specialized for asset type by SETUP template param -- get resource Id from Gfx via Gfx::AllocResource -- create IO request -- append to pendingRequests -- then in update: check requests for finished, and call Gfx::SetupResource - - +} // namespace _priv } // namespace Oryol diff --git a/code/Modules/Assets/Core/assetLoaderRegistry.h b/code/Modules/Assets/Core/assetLoaderRegistry.h index 455b999b6..935fa926c 100644 --- a/code/Modules/Assets/Core/assetLoaderRegistry.h +++ b/code/Modules/Assets/Core/assetLoaderRegistry.h @@ -41,7 +41,7 @@ class assetLoaderRegistry { Array> loaders; struct request { Id id; - Ptr ioRequest; + Ptr ioRequest; }; Array pendingRequests; RunLoop::Id runLoopId; diff --git a/code/Modules/Assets/Core/assetRegistry.cc b/code/Modules/Assets/Core/assetRegistry.cc index 5c9b7ad28..5091a84d8 100644 --- a/code/Modules/Assets/Core/assetRegistry.cc +++ b/code/Modules/Assets/Core/assetRegistry.cc @@ -88,7 +88,7 @@ assetRegistry::findEntryById(const Id& id) const { //------------------------------------------------------------------------------ bool -assetRegistry::Exists(const Id& id) const { +assetRegistry::Contains(const Id& id) const { o_assert(this->isValid); o_assert(id.IsValid()); return this->idIndexMap.Contains(id); @@ -109,27 +109,18 @@ assetRegistry::Lookup(const Locator& loc) { //------------------------------------------------------------------------------ void -assetRegistry::Use(const Id& id) { - this->incrUseCount(id); -} - -//------------------------------------------------------------------------------ -bool -assetRegistry::Release(const Id& id) { +assetRegistry::Remove(uint8 label) { o_assert(this->isValid); - o_assert(id.IsValid()); - if (this->decrUseCount(id)) { - const int32 mapIndex = this->idIndexMap.FindIndex(id); - if (InvalidIndex != mapIndex) { - const int32 entryIndex = this->idIndexMap.ValueAtIndex(mapIndex); - o_assert(this->entries[entryIndex].useCount == 0); - o_assert(this->entries[entryIndex].id == id); + // for each entry where id.label matches label (from behind + // because matching entries will be removed) + // FIXME: this can be slow if many resource are live! + int32 entryIndex = this->entries.Size() - 1; + for (; entryIndex >= 0; entryIndex--) { + if (this->entries[entryIndex].id.Label() == label) { + Id id = this->entries[entryIndex].id; Locator loc = this->entries[entryIndex].locator; - // call the discard function to release the resource - this->entries[entryIndex].discardFunc(id); - // remove entries this->entries.EraseSwapBack(entryIndex); this->idIndexMap.Erase(id); @@ -159,42 +150,7 @@ assetRegistry::Release(const Id& id) { o_assert(this->checkIntegrity()); #endif } - return true; } - else { - return false; - } -} - -//------------------------------------------------------------------------------ -void -assetRegistry::incrUseCount(const Id& id) { - o_assert_dbg(id.IsValid()); - Entry* entry = (Entry*) this->findEntryById(id); - o_assert_dbg(nullptr != entry); - entry->useCount++; -} - -//------------------------------------------------------------------------------ -bool -assetRegistry::decrUseCount(const Id& id) { - o_assert_dbg(id.IsValid()); - Entry* entry = (Entry*) this->findEntryById(id); - o_assert_dbg(nullptr != entry); - o_assert_dbg(entry->useCount > 0); - entry->useCount--; - return 0 == entry->useCount; -} - -//------------------------------------------------------------------------------ -int32 -assetRegistry::GetUseCount(const Id& id) const { - o_assert(this->isValid); - o_assert(id.IsValid()); - - const Entry* entry = this->findEntryById(id); - o_assert(nullptr != entry); - return entry->useCount; } //------------------------------------------------------------------------------ diff --git a/code/Modules/Assets/Core/assetRegistry.h b/code/Modules/Assets/Core/assetRegistry.h index e32ed7659..bc16dbed7 100644 --- a/code/Modules/Assets/Core/assetRegistry.h +++ b/code/Modules/Assets/Core/assetRegistry.h @@ -19,9 +19,6 @@ namespace _priv { class assetRegistry { public: - /// discard function definition - typedef std::function DiscardFunc; - /// constructor assetRegistry(); /// destructor @@ -35,18 +32,14 @@ class assetRegistry { bool IsValid() const; /// add a new asset to the registry - void Add(const Locator& loc, const Id& id, DiscardFunc discardFunc); + void Add(const Locator& loc, const Id& id); /// lookup asset by locator Id Lookup(const Locator& loc); - /// increment the use-count of the asset - void Use(const Id& id); - /// decreases use-count, return true if resource must be destroyed - bool Release(const Id& id); + /// remove all resource matching label from registry (does not discard!) + void Remove(uint8 label); /// check if asset is registered by AssetId - bool Exists(const Id& id) const; - /// (debug) get the current use-count of an asset (fail hard if resource doesn't exist) - int32 GetUseCount(const Id& id) const; + bool Contains(const Id& id) const; /// (debug) get the locator of an asset (fail hard if asset doesn't exist) const Locator& GetLocator(const Id& id) const; @@ -66,20 +59,12 @@ class assetRegistry { #endif struct Entry { - Entry() : - useCount(0) { - }; - Entry(const Locator& loc_, const Id& id_, DiscardFunc discardFunc_) : - useCount(0), + Entry(const Locator& loc_, const Id& id_) : locator(loc_), - id(id_), - discardFunc(discardFunc_) { - }; + id(id_) { }; - int32 useCount; Locator locator; Id id; - DiscardFunc discardFunc; }; /// find an entry by locator diff --git a/code/Modules/Gfx/Core/drawStateFactory.cc b/code/Modules/Gfx/Core/drawStateFactory.cc index d6d5cd70a..cd879eb19 100644 --- a/code/Modules/Gfx/Core/drawStateFactory.cc +++ b/code/Modules/Gfx/Core/drawStateFactory.cc @@ -50,8 +50,8 @@ void drawStateFactory::SetupResource(drawState& ds) { o_assert(ds.GetState() == ResourceState::Setup); const DrawStateSetup& setup = ds.GetSetup(); - ds.mesh = this->meshPool->Lookup(setup.Mesh.Id()); - ds.programBundle = this->programBundlePool->Lookup(setup.Program.Id()); + ds.mesh = this->meshPool->Lookup(setup.Mesh); + ds.programBundle = this->programBundlePool->Lookup(setup.Program); ds.setState(ResourceState::Valid); } diff --git a/code/Modules/Gfx/Core/resourceMgr.cc b/code/Modules/Gfx/Core/resourceMgr.cc index 393c472c8..805f64db7 100644 --- a/code/Modules/Gfx/Core/resourceMgr.cc +++ b/code/Modules/Gfx/Core/resourceMgr.cc @@ -133,7 +133,6 @@ resourceMgr::CreateResource(const TextureSetup& setup) { Id resId = this->texturePool.AllocId(); this->texturePool.Assign(resId, setup); return resId; - } } //------------------------------------------------------------------------------ @@ -200,7 +199,6 @@ resourceMgr::DiscardResource(const Id& resId) { o_assert(false); break; } - } } //------------------------------------------------------------------------------ diff --git a/code/Modules/Gfx/Core/resourceMgr.h b/code/Modules/Gfx/Core/resourceMgr.h index acd0f4e96..c720c314a 100644 --- a/code/Modules/Gfx/Core/resourceMgr.h +++ b/code/Modules/Gfx/Core/resourceMgr.h @@ -15,7 +15,6 @@ #include "Gfx/Core/programBundlePool.h" #include "Gfx/Core/texturePool.h" #include "Gfx/Core/drawStatePool.h" -#include "Resource/Core/ResourceRegistry.h" namespace Oryol { namespace _priv { diff --git a/code/Modules/Gfx/Gfx.h b/code/Modules/Gfx/Gfx.h index 2fbb6bedf..5c43be1a3 100644 --- a/code/Modules/Gfx/Gfx.h +++ b/code/Modules/Gfx/Gfx.h @@ -48,7 +48,13 @@ class Gfx { static const struct DisplayAttrs& RenderTargetAttrs(); /// test if an optional feature is supported static bool Supports(GfxFeature::Code feat); - + + /// push a new resource label, all resources after this get this label + static void PushResourceLabel(uint8 label); + /// pop current top level resource label + static uint8 PopResourceLabel(); + /// discard all resource matching label + static void DiscardResources(uint8 label); /// create a gfx resource template static Id CreateResource(const SETUP& setup); /// create a gfx resource with data in stream object @@ -56,9 +62,7 @@ class Gfx { /// allocate a resource (for async resource loading) template static Id AllocResource(const SETUP& setup, Id placeholder=Id::InvalidId()); /// setup a previously allocated resource from data (for async resource loading) - static void SetupResource(const Id& id, const Ptr& data); - /// discard a gfx resource - static void DiscardResource(const Id& id); + template static void InitResource(const Id& id, const SETUP& setup, const Ptr& data); /// get the loading state of a resource static ResourceState::Code QueryResourceState(const Id& id); /// query the resource setup object for an id @@ -139,16 +143,17 @@ Gfx::CreateResource(const SETUP& setup, const Ptr& data) { //------------------------------------------------------------------------------ inline void -Gfx::DiscardResource(const Id& id) { +Gfx::DiscardResources(uint8 label) { o_assert_dbg(IsValid()); - state->resourceManager.DiscardResource(id); + +o_error("FIXME FIXM FIXME"); } //------------------------------------------------------------------------------ template<> inline void Gfx::ApplyVariable(int32 index, const Id& texResId) { o_assert_dbg(IsValid()); - _priv::texture* tex = state->resourceManager.LookupTexture(texResId.Id()); + _priv::texture* tex = state->resourceManager.LookupTexture(texResId); state->renderer.applyTexture(index, tex); } @@ -194,20 +199,4 @@ Gfx::ApplyBlendColor(const glm::vec4& blendColor) { state->renderer.applyBlendColor(blendColor); } -//------------------------------------------------------------------------------ -inline void -Gfx::releaseResource(const Id& resId) { - if (IsValid()) { - state->resourceManager.ReleaseResource(resId); - } -} - -//------------------------------------------------------------------------------ -inline void -Gfx::useResource(const Id& resId) { - if (IsValid()) { - state->resourceManager.UseResource(resId); - } -} - } // namespace Oryol diff --git a/code/Modules/Gfx/Setup/DrawStateSetup.cc b/code/Modules/Gfx/Setup/DrawStateSetup.cc index ec94e159c..8e3680f23 100644 --- a/code/Modules/Gfx/Setup/DrawStateSetup.cc +++ b/code/Modules/Gfx/Setup/DrawStateSetup.cc @@ -16,7 +16,7 @@ ProgramSelectionMask(0) { //------------------------------------------------------------------------------ DrawStateSetup -DrawStateSetup::FromMeshAndProg(const GfxId& msh, const GfxId& prg, uint32 selMask) { +DrawStateSetup::FromMeshAndProg(const Id& msh, const Id& prg, uint32 selMask) { DrawStateSetup setup; setup.Mesh = msh; setup.Program = prg; diff --git a/code/Modules/Gfx/Setup/DrawStateSetup.h b/code/Modules/Gfx/Setup/DrawStateSetup.h index f13c7a3ab..d16e0d722 100644 --- a/code/Modules/Gfx/Setup/DrawStateSetup.h +++ b/code/Modules/Gfx/Setup/DrawStateSetup.h @@ -10,14 +10,13 @@ #include "Gfx/Core/BlendState.h" #include "Gfx/Core/DepthStencilState.h" #include "Gfx/Core/RasterizerState.h" -#include "Gfx/Core/GfxId.h" namespace Oryol { class DrawStateSetup { public: /// construct from mesh and prog - static DrawStateSetup FromMeshAndProg(const GfxId& mesh, const GfxId& prog, uint32 progSelMask=0); + static DrawStateSetup FromMeshAndProg(const Id& mesh, const Id& prog, uint32 progSelMask=0); /// default constructor DrawStateSetup(); @@ -31,9 +30,9 @@ class DrawStateSetup { /// rasterizer state class RasterizerState RasterizerState; /// mesh - GfxId Mesh; + Id Mesh; /// program bundle - GfxId Program; + Id Program; /// program bundle selection mask uint32 ProgramSelectionMask; }; diff --git a/code/Modules/Gfx/Setup/MeshSetup.cc b/code/Modules/Gfx/Setup/MeshSetup.cc index a75cfd6a1..ae286e8d4 100644 --- a/code/Modules/Gfx/Setup/MeshSetup.cc +++ b/code/Modules/Gfx/Setup/MeshSetup.cc @@ -13,16 +13,17 @@ IndexUsage(Usage::InvalidUsage), NumVertices(0), NumIndices(0), IndicesType(IndexType::None), +Locator(Locator::NonShared()), numPrimGroups(0), setupLoadAsync(false), setupFromStream(false), setupEmpty(false), -setupFullScreenQuad(false), -Locator(Locator::NonShared()) { +setupFullScreenQuad(false) { // empty } //------------------------------------------------------------------------------ +MeshSetup MeshSetup::FromFileAsync(const class Locator& loc, Id placeholder) { MeshSetup setup; setup.Locator = loc; diff --git a/code/Modules/Gfx/Setup/ProgramBundleSetup.cc b/code/Modules/Gfx/Setup/ProgramBundleSetup.cc index 5c97f8908..789d34545 100644 --- a/code/Modules/Gfx/Setup/ProgramBundleSetup.cc +++ b/code/Modules/Gfx/Setup/ProgramBundleSetup.cc @@ -40,10 +40,10 @@ ProgramBundleSetup::obtainEntry(uint32 mask) { //------------------------------------------------------------------------------ void -ProgramBundleSetup::AddProgram(uint32 mask, const GfxId& vs, const GfxId& fs) { +ProgramBundleSetup::AddProgram(uint32 mask, const Id& vs, const Id& fs) { o_assert(this->numProgramEntries < MaxNumProgramEntries); - o_assert(vs.IsValid() && vs.Id().Type() == ResourceType::Shader); - o_assert(fs.IsValid() && fs.Id().Type() == ResourceType::Shader); + o_assert(vs.IsValid() && vs.Type() == ResourceType::Shader); + o_assert(fs.IsValid() && fs.Type() == ResourceType::Shader); programEntry& entry = this->obtainEntry(mask); entry.vertexShader = vs; @@ -100,14 +100,14 @@ ProgramBundleSetup::Mask(int32 progIndex) const { } //------------------------------------------------------------------------------ -const GfxId& +const Id& ProgramBundleSetup::VertexShader(int32 progIndex) const { o_assert_range(progIndex, this->numProgramEntries); return this->programEntries[progIndex].vertexShader; } //------------------------------------------------------------------------------ -const GfxId& +const Id& ProgramBundleSetup::FragmentShader(int32 progIndex) const { o_assert_range(progIndex, this->numProgramEntries); return this->programEntries[progIndex].fragmentShader; diff --git a/code/Modules/Gfx/Setup/ProgramBundleSetup.h b/code/Modules/Gfx/Setup/ProgramBundleSetup.h index 046f06ebb..e5dc8daa0 100644 --- a/code/Modules/Gfx/Setup/ProgramBundleSetup.h +++ b/code/Modules/Gfx/Setup/ProgramBundleSetup.h @@ -10,7 +10,6 @@ #include "Resource/Locator.h" #include "Resource/Id.h" #include "Gfx/Core/Enums.h" -#include "Gfx/Core/GfxId.h" namespace Oryol { @@ -25,7 +24,7 @@ class ProgramBundleSetup { class Locator Locator; /// add a program consisting of precompiled vertex and fragment shader - void AddProgram(uint32 mask, const GfxId& vertexShader, const GfxId& fragmentShader); + void AddProgram(uint32 mask, const Id& vertexShader, const Id& fragmentShader); /// add a program from vertex- and fragment-shader sources void AddProgramFromSources(uint32 mask, ShaderLang::Code slang, const String& vsSource, const String& fsSource); /// bind a shader uniform name to a variable slot @@ -38,9 +37,9 @@ class ProgramBundleSetup { /// get program mask by index uint32 Mask(int32 progIndex) const; /// get program vertex shader (only valid if setup from precompiled shaders) - const GfxId& VertexShader(int32 progIndex) const; + const Id& VertexShader(int32 progIndex) const; /// get program fragment shader (only valid if setup from precompiled shaders) - const GfxId& FragmentShader(int32 progIndex) const; + const Id& FragmentShader(int32 progIndex) const; /// get program vertex shader source (only valid if setup from sources) const String& VertexShaderSource(int32 progIndex, ShaderLang::Code slang) const; /// get program fragment shader source (only valid if setup from sources) @@ -62,8 +61,8 @@ class ProgramBundleSetup { struct programEntry { programEntry() : mask(0) {}; uint32 mask; - GfxId vertexShader; - GfxId fragmentShader; + Id vertexShader; + Id fragmentShader; String vsSources[ShaderLang::NumShaderLangs]; String fsSources[ShaderLang::NumShaderLangs]; }; diff --git a/code/Modules/Gfx/Setup/TextureSetup.cc b/code/Modules/Gfx/Setup/TextureSetup.cc index 77abf9d35..689daab31 100644 --- a/code/Modules/Gfx/Setup/TextureSetup.cc +++ b/code/Modules/Gfx/Setup/TextureSetup.cc @@ -8,7 +8,6 @@ namespace Oryol { //------------------------------------------------------------------------------ TextureSetup::TextureSetup() : -IOLane(0), Width(0), Height(0), RelWidth(0.0f), @@ -20,14 +19,14 @@ WrapV(TextureWrapMode::Repeat), WrapW(TextureWrapMode::Repeat), MagFilter(TextureFilterMode::Nearest), MinFilter(TextureFilterMode::Nearest), +Locator(Locator::NonShared()), shouldSetupLoadAsync(false), shouldSetupFromImageFileData(false), shouldSetupFromPixelData(false), shouldSetupAsRenderTarget(false), isRelSizeRenderTarget(false), hasSharedDepth(false), -hasMipMaps(false), -Locator(Locator::NonShared()) { +hasMipMaps(false) { // empty } @@ -101,8 +100,8 @@ TextureSetup::RelSizeRenderTarget(float32 relWidth, float32 relHeight) { //------------------------------------------------------------------------------ TextureSetup -TextureSetup::SharedDepthRenderTarget(const GfxId& depthRenderTarget) { - o_assert(depthRenderTarget.IsValid() && depthRenderTarget.Id().Type() == ResourceType::Texture); +TextureSetup::SharedDepthRenderTarget(const Id& depthRenderTarget) { + o_assert(depthRenderTarget.IsValid() && depthRenderTarget.Type() == ResourceType::Texture); TextureSetup setup; setup.shouldSetupAsRenderTarget = true; diff --git a/code/Modules/Gfx/gl/glMeshFactory.cc b/code/Modules/Gfx/gl/glMeshFactory.cc index 65106a98f..28317889a 100644 --- a/code/Modules/Gfx/gl/glMeshFactory.cc +++ b/code/Modules/Gfx/gl/glMeshFactory.cc @@ -154,7 +154,7 @@ glMeshFactory::createIndexBuffer(const void* indexData, uint32 indexDataSize, Us //------------------------------------------------------------------------------ void glMeshFactory::attachInstanceBuffer(mesh& msh) { - const Id& instMeshId = msh.GetSetup().InstanceMesh.Id(); + const Id& instMeshId = msh.GetSetup().InstanceMesh; if (instMeshId.IsValid()) { o_assert(this->meshPool->QueryState(instMeshId) == ResourceState::Valid); const mesh* instMesh = this->meshPool->Lookup(instMeshId); diff --git a/code/Modules/Gfx/gl/glProgramBundleFactory.cc b/code/Modules/Gfx/gl/glProgramBundleFactory.cc index 7e2b9a624..af3e7046d 100644 --- a/code/Modules/Gfx/gl/glProgramBundleFactory.cc +++ b/code/Modules/Gfx/gl/glProgramBundleFactory.cc @@ -88,7 +88,7 @@ glProgramBundleFactory::SetupResource(programBundle& progBundle) { } else { // vertex shader is precompiled - const shader* vertexShader = this->shdPool->Lookup(setup.VertexShader(progIndex).Id()); + const shader* vertexShader = this->shdPool->Lookup(setup.VertexShader(progIndex)); o_assert(nullptr != vertexShader); glVertexShader = vertexShader->glShd; } @@ -104,7 +104,7 @@ glProgramBundleFactory::SetupResource(programBundle& progBundle) { } else { // fragment shader is precompiled - const shader* fragmentShader = this->shdPool->Lookup(setup.FragmentShader(progIndex).Id()); + const shader* fragmentShader = this->shdPool->Lookup(setup.FragmentShader(progIndex)); o_assert(nullptr != fragmentShader); glFragmentShader = fragmentShader->glShd; } diff --git a/code/Modules/Gfx/gl/glTextureFactory.cc b/code/Modules/Gfx/gl/glTextureFactory.cc index 731262364..606c951ea 100644 --- a/code/Modules/Gfx/gl/glTextureFactory.cc +++ b/code/Modules/Gfx/gl/glTextureFactory.cc @@ -71,8 +71,7 @@ glTextureFactory::SetupResource(texture& tex) { } else { // let a loader take over, parent class will take care of this - o_assert(tex.GetSetup().ShouldSetupFromFile()); - loaderFactory::SetupResource(tex); + o_error("FIXME FIXME FIXME"); } } @@ -82,7 +81,7 @@ glTextureFactory::SetupResource(texture& tex, const Ptr& data) { o_assert(this->isValid); o_assert(tex.GetState() == ResourceState::Setup); o_assert(!tex.GetSetup().ShouldSetupAsRenderTarget()); - o_assert(!tex.GetSetup().ShouldSetupFromFile()); + o_assert(!tex.GetSetup().ShouldSetupFromFileAsync()); if (tex.GetSetup().ShouldSetupFromPixelData()) { this->createFromPixelData(tex, data); @@ -159,7 +158,7 @@ glTextureFactory::createRenderTarget(texture& tex) { else if (setup.HasSharedDepth()) { // a shared-depth-buffer render target, obtain width and height // from the original render target - texture* sharedDepthProvider = this->texPool->Lookup(setup.DepthRenderTarget.Id()); + texture* sharedDepthProvider = this->texPool->Lookup(setup.DepthRenderTarget); o_assert(nullptr != sharedDepthProvider); width = sharedDepthProvider->textureAttrs.Width; height = sharedDepthProvider->textureAttrs.Height; diff --git a/code/Modules/Gfx/gl/glTextureLoader.cc b/code/Modules/Gfx/gl/glTextureLoader.cc index ed78306d8..b9a5a9f7b 100644 --- a/code/Modules/Gfx/gl/glTextureLoader.cc +++ b/code/Modules/Gfx/gl/glTextureLoader.cc @@ -64,6 +64,8 @@ glTextureLoader::Accepts(const texture& tex, const Ptr& data) const { //------------------------------------------------------------------------------ void glTextureLoader::Load(texture& tex) const { +o_error("FIXME FIXME FIXME"); +/* const TextureSetup& setup = tex.GetSetup(); const ResourceState::Code state = tex.GetState(); o_assert((state == ResourceState::Setup) || (state == ResourceState::Pending)); @@ -90,6 +92,7 @@ glTextureLoader::Load(texture& tex) const { tex.setIORequest(nullptr); } } +*/ } //------------------------------------------------------------------------------ diff --git a/code/Modules/Resource/Core/ResourcePool.h b/code/Modules/Resource/Core/ResourcePool.h index 46ea8a882..8923e9a45 100644 --- a/code/Modules/Resource/Core/ResourcePool.h +++ b/code/Modules/Resource/Core/ResourcePool.h @@ -150,8 +150,11 @@ ResourcePool::IsValid() const { //------------------------------------------------------------------------------ template Id ResourcePool::AllocId() { +o_error("FIXE FIXME FIXME"); +/* o_assert(this->isValid); return Id(this->uniqueCounter++, this->freeSlots.Dequeue(), this->resourceType); +*/ } //------------------------------------------------------------------------------ diff --git a/code/Modules/Resource/Core/resourceBase.h b/code/Modules/Resource/Core/resourceBase.h index 2bc6b8279..3cba7b972 100644 --- a/code/Modules/Resource/Core/resourceBase.h +++ b/code/Modules/Resource/Core/resourceBase.h @@ -15,6 +15,7 @@ setup object is stored in the resource object, so that the resource can be destroyed and re-created if needed. */ +#include "Core/Assertion.h" #include "Resource/Id.h" #include "Resource/ResourceState.h" diff --git a/code/Modules/Resource/Id.h b/code/Modules/Resource/Id.h index fe7763a1c..70bb4fce3 100644 --- a/code/Modules/Resource/Id.h +++ b/code/Modules/Resource/Id.h @@ -18,7 +18,9 @@ class Id { /// invalid slot index constant static const uint16 InvalidSlotIndex = 0xFFFF; /// invalid type constant - static const uint16 InvalidType = 0xFFFF; + static const uint8 InvalidType = 0xFF; + /// invalid label constant + static const uint8 InvalidLabel = 0xFF; /// returns an invalid resource id static Id InvalidId(); @@ -26,7 +28,7 @@ class Id { /// default constructor, constructs invalid id Id(); /// create with uniqueStamp, slotIndex and type - Id(uint32 uniqueStamp, uint16 slotIndex, uint16 type); + Id(uint32 uniqueStamp, uint16 slotIndex, uint8 type, uint8 label); /// copy constructor Id(const Id& rhs); @@ -47,15 +49,25 @@ class Id { /// get the slot index uint16 SlotIndex() const; /// get the type - uint16 Type() const; + uint8 Type() const; + /// get the label + uint8 Label() const; /// get the unique-stamp uint32 UniqueStamp() const; private: - /// make id from uniqueStamp, slotIndex and type - uint64 makeId(uint32 uniqueStamp, uint16 slotIndex, uint16 type); - - uint64 id; + /// invalid id value + static const uint64 invalidId = 0xFFFFFFFFFFFFFFFF; + + union { + struct { + uint16 slotIndex; + uint8 type; + uint8 label; + uint32 uniqueStamp; + }; + uint64 id; + }; }; //------------------------------------------------------------------------------ @@ -64,28 +76,21 @@ Id::InvalidId() { return Id(); } -//------------------------------------------------------------------------------ -inline uint64 -Id::makeId(uint32 uniqueStamp, uint16 slotIndex, uint16 type) { - // type must be most-signifant, then uniqueStamp, then slotIndex - uint64 result = type; - result <<= 32; - result |= uniqueStamp; - result <<= 16; - result |= slotIndex; - return result; -} - //------------------------------------------------------------------------------ inline -Id::Id() { - this->id = this->makeId(InvalidUniqueStamp, InvalidSlotIndex, InvalidType); +Id::Id() : +id(invalidId) { + // empty } //------------------------------------------------------------------------------ inline -Id::Id(uint32 uniqueStamp, uint16 slotIndex, uint16 type) { - this->id = this->makeId(uniqueStamp, slotIndex, type); +Id::Id(uint32 uniqueStamp_, uint16 slotIndex_, uint8 type_, uint8 label_) : +slotIndex(slotIndex_), +type(type_), +label(label_), +uniqueStamp(uniqueStamp_) { + // empty } //------------------------------------------------------------------------------ @@ -124,31 +129,37 @@ Id::operator<(const Id& rhs) const { //------------------------------------------------------------------------------ inline uint16 Id::SlotIndex() const { - return this->id & 0xFFFF; + return this->slotIndex; } //------------------------------------------------------------------------------ -inline uint16 +inline uint8 Id::Type() const { - return (this->id >> 48) & 0xFFFF; + return this->type; +} + +//------------------------------------------------------------------------------ +inline uint8 +Id::Label() const { + return this->label; } //------------------------------------------------------------------------------ inline uint32 Id::UniqueStamp() const { - return (this->id >> 16) & 0xFFFFFFFF; + return this->uniqueStamp; } //------------------------------------------------------------------------------ inline bool Id::IsValid() const { - return InvalidUniqueStamp != this->UniqueStamp(); + return InvalidUniqueStamp != this->uniqueStamp; } //------------------------------------------------------------------------------ inline void Id::Invalidate() { - this->id = this->makeId(InvalidUniqueStamp, InvalidSlotIndex, InvalidType); + this->id = invalidId; } } // namespace Oryol diff --git a/doc/planning/asset_planning.md b/doc/planning/asset_planning.md index fa7cb953c..18308cc35 100644 --- a/doc/planning/asset_planning.md +++ b/doc/planning/asset_planning.md @@ -16,7 +16,7 @@ The following Gfx features should be moved out of Gfx: - asynchronous resource loading - custom resource loaders -- resource sharing and use-count +- resource sharing - resource placeholders Where to move this to? It would make sense to move this into the @@ -25,6 +25,17 @@ Gfx would depend on Resource, Resource would depend on Gfx. Current plan: +NO USE COUNTS ANYMORE. + +Use counts are too complicated for dependent resources (e.g. +when a Shader is a dependent resource of a ProgramBundle, +or an instance mesh is a dependent resource of an instanced mesh. + +Instead use resource labels and batch deletion. Each created +resource gets a label slapped on which can be set by +the caller before creating resources. Then there's a DiscardResource(label) +method which deletes all resource matching that label. + - make Resource module even lower level, and introduce a new higher level 'Asset' module - Resource module keeps: