From 768d3209198c0136a49d02270a0c26a47d1ac24b Mon Sep 17 00:00:00 2001 From: Neil Forbes-Richardson Date: Sun, 28 Jan 2018 11:58:23 +1100 Subject: [PATCH] Resource load settings added. Model data includes CRC32 to verify data. Model waits on materials to load. --- res/settings.json | 7 ++++ .../converters/converter_material.cpp | 2 +- src/graphics/converters/converter_model.cpp | 26 +++++++++++-- src/graphics/converters/converter_shader.cpp | 2 +- src/graphics/converters/converter_texture.cpp | 2 +- src/graphics/private/material.cpp | 3 ++ src/graphics/private/model.cpp | 14 +++++++ src/graphics/private/model_impl.h | 2 + src/graphics/private/shader.cpp | 2 + src/graphics/private/texture.cpp | 37 ++++++++++++++++++- src/resource/factory.h | 12 ++++++ src/resource/private/manager.cpp | 15 +++++++- src/resource/tests/manager_tests.cpp | 2 + 13 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 res/settings.json diff --git a/res/settings.json b/res/settings.json new file mode 100644 index 0000000..abd773e --- /dev/null +++ b/res/settings.json @@ -0,0 +1,7 @@ +{ + "resources" : { + "texture" : { + "skipMips" : 0 + } + } +} diff --git a/src/graphics/converters/converter_material.cpp b/src/graphics/converters/converter_material.cpp index eb8f540..cb973e2 100644 --- a/src/graphics/converters/converter_material.cpp +++ b/src/graphics/converters/converter_material.cpp @@ -55,7 +55,7 @@ namespace strcat_s(outFilename, sizeof(outFilename), destPath); Core::FileNormalizePath(outFilename, sizeof(outFilename), true); - auto materialFile = Core::File(sourceFile, Core::FileFlags::READ, context.GetPathResolver()); + auto materialFile = Core::File(sourceFile, Core::FileFlags::DEFAULT_READ, context.GetPathResolver()); auto materialSer = Serialization::Serializer(materialFile, Serialization::Flags::TEXT); Graphics::ImportMaterial material; diff --git a/src/graphics/converters/converter_model.cpp b/src/graphics/converters/converter_model.cpp index ba03113..c681749 100644 --- a/src/graphics/converters/converter_model.cpp +++ b/src/graphics/converters/converter_model.cpp @@ -333,6 +333,13 @@ namespace meshData.endVertexElements_ = numVertexElements + mesh.elements_.size(); meshData.startDraws_ = numDraws; meshData.endDraws_ = numDraws + mesh.draws_.size(); + + for(const auto& stream : mesh.vertexData_) + meshData.vertexDataCrc32_ = + Core::HashCRC32(meshData.vertexDataCrc32_, stream.Data(), stream.Size()); + meshData.indexDataCrc32_ = + Core::HashCRC32(meshData.indexDataCrc32_, mesh.indexData_.Data(), mesh.indexData_.Size()); + outFile.Write(&meshData, sizeof(meshData)); numVertexElements += mesh.elements_.size(); @@ -902,13 +909,24 @@ namespace // If file exists, load and serialize. Otherwise, use template. Graphics::ImportMaterial importMaterial; + bool useTemplate = true; if(Core::FileExists(materialPath.data())) { - auto materialFile = Core::File(materialPath.data(), Core::FileFlags::READ); - auto materialSer = Serialization::Serializer(materialFile, Serialization::Flags::TEXT); - importMaterial.Serialize(materialSer); + auto materialFile = Core::File(materialPath.data(), Core::FileFlags::DEFAULT_READ); + if(auto materialSer = Serialization::Serializer(materialFile, Serialization::Flags::TEXT)) + { + importMaterial.Serialize(materialSer); + + if(importMaterial.shader_.size() == 0) + useTemplate = false; + } + else + { + importMaterial = materialEntry.template_; + } } - else + + if(useTemplate) { importMaterial = materialEntry.template_; } diff --git a/src/graphics/converters/converter_shader.cpp b/src/graphics/converters/converter_shader.cpp index 10313f1..b7a7ad3 100644 --- a/src/graphics/converters/converter_shader.cpp +++ b/src/graphics/converters/converter_shader.cpp @@ -70,7 +70,7 @@ namespace bool retVal = false; // - Core::File shaderFile(sourceFile, Core::FileFlags::READ, pathResolver); + Core::File shaderFile(sourceFile, Core::FileFlags::DEFAULT_READ, pathResolver); if(shaderFile) { Core::Vector shaderSource; diff --git a/src/graphics/converters/converter_texture.cpp b/src/graphics/converters/converter_texture.cpp index fc7f477..2339c01 100644 --- a/src/graphics/converters/converter_texture.cpp +++ b/src/graphics/converters/converter_texture.cpp @@ -158,7 +158,7 @@ namespace { char fileExt[8] = {0}; Core::FileSplitPath(sourceFile, nullptr, 0, nullptr, 0, fileExt, sizeof(fileExt)); - Core::File imageFile(sourceFile, Core::FileFlags::READ, context.GetPathResolver()); + Core::File imageFile(sourceFile, Core::FileFlags::DEFAULT_READ, context.GetPathResolver()); return Image::Load( imageFile, [&context](const char* errorMsg) { context.AddError(__FILE__, __LINE__, errorMsg); }); diff --git a/src/graphics/private/material.cpp b/src/graphics/private/material.cpp index 95a667c..169a369 100644 --- a/src/graphics/private/material.cpp +++ b/src/graphics/private/material.cpp @@ -135,6 +135,9 @@ namespace Graphics return true; } + bool SerializeSettings(Serialization::Serializer& ser) override { return true; } + + GPU::Handle defaultTex_; }; diff --git a/src/graphics/private/model.cpp b/src/graphics/private/model.cpp index 181943c..c7ea61f 100644 --- a/src/graphics/private/model.cpp +++ b/src/graphics/private/model.cpp @@ -134,10 +134,14 @@ namespace Graphics } // Create materials for mesh nodes. + // Only load them one by one. + // TODO: We need a better heuristic to control + // the wait policy for certain resource types. impl->materials_.reserve(impl->meshNodes_.size()); for(const auto& meshNode : impl->meshNodes_) { impl->materials_.emplace_back(meshNode.material_); + impl->materials_.back().WaitUntilReady(); DBG_ASSERT(impl->materials_.back()); } @@ -167,6 +171,10 @@ namespace Graphics desc.bindFlags_ = GPU::BindFlags::VERTEX_BUFFER; GPU::Handle vb = GPU::Manager::CreateBuffer(desc, data, "%s/vb_%d", name, vbIdx++); impl->vbs_.push_back(vb); + + u32 dataCrc32 = Core::HashCRC32(0, data, desc.size_); + DBG_ASSERT(mesh.vertexDataCrc32_ == dataCrc32); + data += desc.size_; } @@ -178,6 +186,10 @@ namespace Graphics desc.bindFlags_ = GPU::BindFlags::INDEX_BUFFER; GPU::Handle ib = GPU::Manager::CreateBuffer(desc, data, "%s/ib_%d", name, ibIdx++); impl->ibs_.push_back(ib); + + u32 dataCrc32 = Core::HashCRC32(0, data, desc.size_); + DBG_ASSERT(mesh.indexDataCrc32_ == dataCrc32); + data += desc.size_; } } @@ -232,6 +244,8 @@ namespace Graphics return true; } + + bool SerializeSettings(Serialization::Serializer& ser) override { return true; } }; DEFINE_RESOURCE(Model); diff --git a/src/graphics/private/model_impl.h b/src/graphics/private/model_impl.h index d58f8a9..ec40c1f 100644 --- a/src/graphics/private/model_impl.h +++ b/src/graphics/private/model_impl.h @@ -89,6 +89,8 @@ namespace Graphics i32 endVertexElements_ = 0; i32 startDraws_ = 0; i32 endDraws_ = 0; + u32 vertexDataCrc32_ = 0; + u32 indexDataCrc32_ = 0; }; struct ModelImpl diff --git a/src/graphics/private/shader.cpp b/src/graphics/private/shader.cpp index 51d82d7..cd91484 100644 --- a/src/graphics/private/shader.cpp +++ b/src/graphics/private/shader.cpp @@ -321,6 +321,8 @@ namespace Graphics return true; } + bool SerializeSettings(Serialization::Serializer& ser) override { return true; } + i32 FindBindingSetIdx(const char* name) { for(i32 idx = 0; idx < bindingSetHeaders_.size(); ++idx) diff --git a/src/graphics/private/texture.cpp b/src/graphics/private/texture.cpp index 418255a..6428145 100644 --- a/src/graphics/private/texture.cpp +++ b/src/graphics/private/texture.cpp @@ -11,6 +11,7 @@ #include "gpu/manager.h" #include "gpu/resources.h" #include "gpu/utils.h" +#include "serialization/serializer.h" namespace Graphics { @@ -59,6 +60,15 @@ namespace Graphics Core::Vector subRscs; subRscs.reserve(numSubRsc); + // Should we skip loading mip levels? + i16 skipMips = skipMips_; + if(desc.levels_ < skipMips) + { + skipMips = desc.levels_ - 1; + } + + auto formatInfo = GPU::GetFormatInfo(desc.format_); + i64 texDataOffset = 0; for(i32 element = 0; element < desc.elements_; ++element) { @@ -77,10 +87,19 @@ namespace Graphics subRsc.slicePitch_ = texLayoutInfo.slicePitch_; texDataOffset += subRscSize; - subRscs.push_back(subRsc); + + if(level >= skipMips) + { + subRscs.push_back(subRsc); + } } } + desc.width_ = Core::Max(1, desc.width_ >> (i32)skipMips); + desc.height_ = Core::Max(1, desc.height_ >> (i32)skipMips); + desc.depth_ = Core::Max((i16)1, desc.depth_ >> skipMips); + desc.levels_ -= skipMips_; + // Create GPU texture if initialized. if(GPU::Manager::IsInitialized()) { @@ -119,6 +138,22 @@ namespace Graphics return true; } + + bool SerializeSettings(Serialization::Serializer& ser) override + { + bool retVal = true; + if(auto object = ser.Object("texture")) + { + retVal &= ser.Serialize("skipMips", skipMips_); + } + return retVal; + } + + + /** + * Settings. + */ + i16 skipMips_ = 0; }; DEFINE_RESOURCE(Texture); diff --git a/src/resource/factory.h b/src/resource/factory.h index 0430c72..29061c3 100644 --- a/src/resource/factory.h +++ b/src/resource/factory.h @@ -9,6 +9,11 @@ namespace Core class UUID; } // namespace Core +namespace Serialization +{ + class Serializer; +} + namespace Resource { /** @@ -61,6 +66,13 @@ namespace Resource * @param type Type UUID. */ virtual bool DestroyResource(IFactoryContext& context, void** inResource, const Core::UUID& type) = 0; + + /** + * Serialize settings. + * Used to load/save resource loading settings. + * @param ser Serializer to use. + */ + virtual bool SerializeSettings(Serialization::Serializer& ser) = 0; }; } // namespace Resource diff --git a/src/resource/private/manager.cpp b/src/resource/private/manager.cpp index 4fc78b5..b6e6d59 100644 --- a/src/resource/private/manager.cpp +++ b/src/resource/private/manager.cpp @@ -294,7 +294,7 @@ namespace Resource { char uuidStr[38]; type.AsString(uuidStr); - DBG_LOG("Fsctory does not exist for type %s\n", uuidStr); + DBG_LOG("Factory does not exist for type %s\n", uuidStr); return nullptr; } return it->second; @@ -820,6 +820,19 @@ namespace Resource return false; impl_->factories_.insert(type, factory); + + // Load settings. + if(auto file = Core::File("settings.json", Core::FileFlags::DEFAULT_READ, &impl_->pathResolver_)) + { + if(auto ser = Serialization::Serializer(file, Serialization::Flags::TEXT)) + { + if(auto object = ser.Object("resources")) + { + factory->SerializeSettings(ser); + } + } + } + return true; } diff --git a/src/resource/tests/manager_tests.cpp b/src/resource/tests/manager_tests.cpp index 6713b3c..1aba37d 100644 --- a/src/resource/tests/manager_tests.cpp +++ b/src/resource/tests/manager_tests.cpp @@ -105,6 +105,8 @@ namespace *inResource = nullptr; return true; } + + bool SerializeSettings(Serialization::Serializer& ser) { return true; } }; DEFINE_RESOURCE(TestResource);