diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d858edc506..d1e55b5fe2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,19 +9,21 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - vulkan-version: [1.3.268.0] + # os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest] + vulkan-version: [1.4.341.1] build-shared: [OFF] - include: - - build-shared: ON - os: windows-latest - vulkan-version: 1.3.268.0 + # include: + # - build-shared: ON + # os: windows-latest + # vulkan-version: 1.4.341.1 + continue-on-error: ${{ matrix.vulkan-version == 'latest' }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup cmake - uses: jwlawson/actions-setup-cmake@v1.12 + uses: jwlawson/actions-setup-cmake@v2.2.0 with: cmake-version: ${{ env.CMakeVersion }} - name: Install Vulkan SDK @@ -30,7 +32,7 @@ jobs: version: ${{ matrix.vulkan-version }} cache: true - name: Add MSBuild to PATH - uses: microsoft/setup-msbuild@v2 + uses: microsoft/setup-msbuild@v3 if: startsWith(matrix.os, 'windows') - name: Build and Install VSG shell: bash diff --git a/.gitignore b/.gitignore index 5b075e1993..d6cec6ae34 100644 --- a/.gitignore +++ b/.gitignore @@ -84,4 +84,5 @@ DerivedData/ include/glslang src/vsg/CHANGES.md src/vsg/vsgTargets.cmake - +*.txt.user +*.txt.user.* diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c15ccf73c..02a3e047f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,11 @@ cmake_minimum_required(VERSION 3.10) project(vsg - VERSION 1.1.14 + VERSION 1.1.15 DESCRIPTION "VulkanSceneGraph library" LANGUAGES CXX ) -set(VSG_SOVERSION 16) +set(VSG_SOVERSION 17) SET(VSG_RELEASE_CANDIDATE 0) set(Vulkan_MIN_VERSION 1.1.70.0) diff --git a/cmake/cppcheck-suppression-list.txt b/cmake/cppcheck-suppression-list.txt index 6cb1322f6e..1e866116d2 100644 --- a/cmake/cppcheck-suppression-list.txt +++ b/cmake/cppcheck-suppression-list.txt @@ -9,7 +9,6 @@ invalidPointerCast:*/include/vsg/core/Data.h invalidPointerCast:*/include/vsg/core/Array.h invalidPointerCast:*/include/vsg/core/Array2D.h invalidPointerCast:*/include/vsg/core/Array3D.h -invalidPointerCast:*/include/vsg/core/Array3D.h invalidPointerCast:*/src/vsg/commands/CopyAndReleaseImage.cpp // suppress inappropriate stl algorithm suggestions @@ -153,6 +152,7 @@ arrayIndexOutOfBounds:*/include/vsg/vk/State.h // suppress warnings about intentional code usage or where cppcheck just hasn't got a clue about how templates are used... knownConditionTrueFalse:*/src/vsg/utils/Builder.cpp knownConditionTrueFalse:*/include/vsg/utils/CommandLine.h +knownConditionTrueFalse:*/include/vsg/core/Inherit.h // suppress warning about initializtion. useInitializationList:*/include/vsg/core/ScratchMemory.h @@ -224,6 +224,11 @@ cstyleCast:*/src/vsg/io/mem_stream.cpp // suppress unhelpful warnings of override that make inform programmers what is being done uselessOverride:*/include/vsg/utils/TracyInstrumentation.h +uselessOverride:*/include/vsg/ui/WindowEvent.h +uselessOverride:*/include/vsg/utils/ShaderSet.h +uselessOverride:*/include/vsg/nodes/Transform.h +uselessOverride:*/include/vsg/raytracing/DescriptorAccelerationStructure.h +uselessOverride:*/include/vsg/raytracing/RayTracingShaderGroup.h // suppress inappropriate warning constParameterReference:*/include/vsg/vk/Device.h @@ -243,3 +248,25 @@ constVariablePointer:*/src/vsg/app/SecondaryCommandGraph.cpp // suppress inappropriate warning passedByValue:*/src/vsg/vk/Device.cpp passedByValue:*/src/vsg/vk/Instance.cpp + +// suppress inappropriate warnings +functionStatic:*/include/vsg/io/Output.h +functionStatic:*/include/vsg/io/Input.h +functionStatic:*/include/vsg/app/CompileManager.h +functionStatic:*/include/vsg/app/CompileManager.cpp +functionStatic:*/include/vsg/app/RecordTraversal.h +functionStatic:*/src/vsg/app/RecordTraversal.cpp +functionStatic:*/include/vsg/io/VSG.h +functionStatic:*/src/vsg/io/VSG.cpp +functionStatic:*/include/vsg/io/json.h +functionStatic:*/include/vsg/io/txt.h +functionStatic:*/include/vsg/io/tile.h +functionStatic:*/include/vsg/state/QueryPool.h +functionStatic:*/include/vsg/state/ArrayState.h +functionStatic:*/include/vsg/text/StandardLayout.h +functionStatic:*/include/vsg/utils/Builder.h +functionStatic:*/include/vsg/utils/ShaderCompiler.h + + +// suppress inappropriate warnings +suspiciousFloatingPointCast:*/src/vsg/maths/maths_transform.cpp diff --git a/include/vsg/animation/AnimationGroup.h b/include/vsg/animation/AnimationGroup.h index 32db782862..6d4ce7d56f 100644 --- a/include/vsg/animation/AnimationGroup.h +++ b/include/vsg/animation/AnimationGroup.h @@ -50,7 +50,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~AnimationGroup(); + ~AnimationGroup() override; }; VSG_type_name(vsg::AnimationGroup); diff --git a/include/vsg/animation/Joint.h b/include/vsg/animation/Joint.h index 2350e248ea..608f4fec9c 100644 --- a/include/vsg/animation/Joint.h +++ b/include/vsg/animation/Joint.h @@ -54,7 +54,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~Joint(); + ~Joint() override; }; VSG_type_name(vsg::Joint); diff --git a/include/vsg/app/CommandGraph.h b/include/vsg/app/CommandGraph.h index d7cccddc38..f16e400bc2 100644 --- a/include/vsg/app/CommandGraph.h +++ b/include/vsg/app/CommandGraph.h @@ -54,7 +54,7 @@ namespace vsg ref_ptr instrumentation; protected: - virtual ~CommandGraph(); + ~CommandGraph() override; CommandBuffers _commandBuffers; // assign one per index? Or just use round robin, each has a CommandPool }; diff --git a/include/vsg/app/CompileManager.h b/include/vsg/app/CompileManager.h index dff3c9f905..fefdd3e25e 100644 --- a/include/vsg/app/CompileManager.h +++ b/include/vsg/app/CompileManager.h @@ -20,6 +20,7 @@ namespace vsg // forward declare class RecordAndSubmitTask; + class Viewer; /// CompileResult struct encapsulates the results of compile traversal. /// Used to help guide further operations done with the compiled subgraph. @@ -36,7 +37,19 @@ namespace vsg void reset(); void add(const CompileResult& cr); - bool requiresViewerUpdate() const; + bool requiresViewerUpdate(const Viewer* viewer = nullptr) const; + }; + + /// ResourceScavenger provides a mechanism for releasing and reusing unused resources when allocation of required GPU memory fails. + class VSG_DECLSPEC ResourceScavenger : public Inherit + { + public: + explicit ResourceScavenger(ref_ptr in_databasePager); + + virtual bool scavenge(ResourceRequirements& resourceRequirements); + + uint64_t sleepDuration = 16 * 5; /// milliseconds sleep to make after adjusting load targets to allow other threads to free up space, default to 5 frames at 60fps + observer_ptr databasePager; }; /// CompileManager is a helper class that compiles subgraphs for the windows/framebuffers associated with the CompileManager. @@ -71,7 +84,15 @@ namespace vsg /// compile all the command graphs in a task CompileResult compileTask(ref_ptr task, const ResourceRequirements& resourceRequirements = {}); + /// mechanism for releasing and reusing used resources + ref_ptr resourceScavenger; + + std::atomic_uint successfulCompileCount{0}; + std::atomic_uint failedCompileCount{0}; + protected: + ~CompileManager() override; + using CompileTraversals = ThreadSafeQueue>; size_t numCompileTraversals = 0; ref_ptr compileTraversals; diff --git a/include/vsg/app/CompileTraversal.h b/include/vsg/app/CompileTraversal.h index fa9fdf1809..04db232b90 100644 --- a/include/vsg/app/CompileTraversal.h +++ b/include/vsg/app/CompileTraversal.h @@ -103,7 +103,7 @@ namespace vsg void apply(View& view) override; protected: - ~CompileTraversal(); + ~CompileTraversal() override; void add(ref_ptr context, Framebuffer& framebuffer, ref_ptr transferTask, ref_ptr view, const ResourceRequirements& resourceRequirements); void addViewDependentState(ViewDependentState& viewDependentState, ref_ptr device, ref_ptr transferTask, const ResourceRequirements& resourceRequirements); diff --git a/include/vsg/app/RecordTraversal.h b/include/vsg/app/RecordTraversal.h index 42527d4f55..ccd15bd1eb 100644 --- a/include/vsg/app/RecordTraversal.h +++ b/include/vsg/app/RecordTraversal.h @@ -185,7 +185,7 @@ namespace vsg ref_ptr viewDependentState; protected: - virtual ~RecordTraversal(); + ~RecordTraversal() override; }; } // namespace vsg diff --git a/include/vsg/app/SecondaryCommandGraph.h b/include/vsg/app/SecondaryCommandGraph.h index 7e03f35f1e..ace2168cfc 100644 --- a/include/vsg/app/SecondaryCommandGraph.h +++ b/include/vsg/app/SecondaryCommandGraph.h @@ -43,7 +43,7 @@ namespace vsg void record(ref_ptr recordedCommandBuffers, ref_ptr frameStamp = {}, ref_ptr databasePager = {}) override; protected: - virtual ~SecondaryCommandGraph(); + ~SecondaryCommandGraph() override; friend ExecuteCommands; diff --git a/include/vsg/app/UpdateOperations.h b/include/vsg/app/UpdateOperations.h index e2530ee44f..0ad12f7fa2 100644 --- a/include/vsg/app/UpdateOperations.h +++ b/include/vsg/app/UpdateOperations.h @@ -55,7 +55,7 @@ namespace vsg virtual void run(); protected: - virtual ~UpdateOperations(); + ~UpdateOperations() override; mutable std::mutex _updateOperationMutex; std::list> _updateOperationsOneTime; diff --git a/include/vsg/app/View.h b/include/vsg/app/View.h index 94ea32d1be..b20ad41db3 100644 --- a/include/vsg/app/View.h +++ b/include/vsg/app/View.h @@ -90,7 +90,7 @@ namespace vsg GraphicsPipelineStates overridePipelineStates; protected: - virtual ~View(); + ~View() override; }; VSG_type_name(vsg::View); diff --git a/include/vsg/app/Viewer.h b/include/vsg/app/Viewer.h index a2603e0daa..8d0127a97f 100644 --- a/include/vsg/app/Viewer.h +++ b/include/vsg/app/Viewer.h @@ -149,7 +149,7 @@ namespace vsg void assignInstrumentation(ref_ptr in_instrumentation); protected: - virtual ~Viewer(); + ~Viewer() override; bool _close = false; diff --git a/include/vsg/app/Window.h b/include/vsg/app/Window.h index 8d84920c1a..736f5ec708 100644 --- a/include/vsg/app/Window.h +++ b/include/vsg/app/Window.h @@ -134,7 +134,7 @@ namespace vsg protected: Window(ref_ptr traits); - virtual ~Window(); + ~Window() override; virtual void _initSurface() = 0; void _initFormats(); diff --git a/include/vsg/app/WindowAdapter.h b/include/vsg/app/WindowAdapter.h index bb30230377..1c047f7927 100644 --- a/include/vsg/app/WindowAdapter.h +++ b/include/vsg/app/WindowAdapter.h @@ -41,7 +41,7 @@ namespace vsg bool windowValid = false; protected: - virtual ~WindowAdapter() {} + ~WindowAdapter() override {} void _initSurface() override {}; }; diff --git a/include/vsg/app/WindowResizeHandler.h b/include/vsg/app/WindowResizeHandler.h index 87be5b3efa..b579af1a04 100644 --- a/include/vsg/app/WindowResizeHandler.h +++ b/include/vsg/app/WindowResizeHandler.h @@ -53,7 +53,7 @@ namespace vsg WindowResizeHandler(); template - T scale_parameter(T original, R extentOriginal, R extentNew) + static T scale_parameter(T original, R extentOriginal, R extentNew) { if (original == static_cast(extentOriginal)) return static_cast(extentNew); return static_cast(static_cast(original) * static_cast(extentNew) / static_cast(extentOriginal) + 0.5f); diff --git a/include/vsg/app/WindowTraits.h b/include/vsg/app/WindowTraits.h index 155a3a41be..4efbe8e8c0 100644 --- a/include/vsg/app/WindowTraits.h +++ b/include/vsg/app/WindowTraits.h @@ -99,7 +99,7 @@ namespace vsg std::any systemConnection; protected: - virtual ~WindowTraits() {} + ~WindowTraits() override {} }; VSG_type_name(vsg::WindowTraits); diff --git a/include/vsg/commands/BindIndexBuffer.h b/include/vsg/commands/BindIndexBuffer.h index 42e94a44cd..400b238f2c 100644 --- a/include/vsg/commands/BindIndexBuffer.h +++ b/include/vsg/commands/BindIndexBuffer.h @@ -47,7 +47,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~BindIndexBuffer(); + ~BindIndexBuffer() override; }; VSG_type_name(vsg::BindIndexBuffer); diff --git a/include/vsg/commands/BindVertexBuffers.h b/include/vsg/commands/BindVertexBuffers.h index 69908920fb..a9cfd38967 100644 --- a/include/vsg/commands/BindVertexBuffers.h +++ b/include/vsg/commands/BindVertexBuffers.h @@ -42,7 +42,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~BindVertexBuffers(); + ~BindVertexBuffers() override; vk_buffer _vulkanData; }; diff --git a/include/vsg/commands/Commands.h b/include/vsg/commands/Commands.h index 9ecf037f41..d87eed3a0d 100644 --- a/include/vsg/commands/Commands.h +++ b/include/vsg/commands/Commands.h @@ -57,7 +57,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~Commands(); + ~Commands() override; }; VSG_type_name(vsg::Commands); diff --git a/include/vsg/commands/CopyAndReleaseBuffer.h b/include/vsg/commands/CopyAndReleaseBuffer.h index ddd020575f..5354eb0b7b 100644 --- a/include/vsg/commands/CopyAndReleaseBuffer.h +++ b/include/vsg/commands/CopyAndReleaseBuffer.h @@ -36,7 +36,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~CopyAndReleaseBuffer(); + ~CopyAndReleaseBuffer() override; struct CopyData { diff --git a/include/vsg/commands/CopyAndReleaseImage.h b/include/vsg/commands/CopyAndReleaseImage.h index a400aa7d99..c1b9a6e5f9 100644 --- a/include/vsg/commands/CopyAndReleaseImage.h +++ b/include/vsg/commands/CopyAndReleaseImage.h @@ -58,7 +58,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~CopyAndReleaseImage(); + ~CopyAndReleaseImage() override; void _copyDirectly(ref_ptr data, ref_ptr dest, uint32_t numMipMapLevels); diff --git a/include/vsg/commands/Event.h b/include/vsg/commands/Event.h index 92fe0ce9d6..d580a46cff 100644 --- a/include/vsg/commands/Event.h +++ b/include/vsg/commands/Event.h @@ -36,7 +36,7 @@ namespace vsg VkResult status(); protected: - virtual ~Event(); + ~Event() override; VkEvent _event; ref_ptr _device; @@ -57,7 +57,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~SetEvent(); + ~SetEvent() override; }; VSG_type_name(vsg::SetEvent); @@ -73,7 +73,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~ResetEvent(); + ~ResetEvent() override; }; VSG_type_name(vsg::ResetEvent); @@ -107,7 +107,7 @@ namespace vsg ImageMemoryBarriers imageMemoryBarriers; protected: - virtual ~WaitEvents(); + ~WaitEvents() override; }; VSG_type_name(vsg::WaitEvents); diff --git a/include/vsg/commands/ExecuteCommands.h b/include/vsg/commands/ExecuteCommands.h index 76ce6f34b7..81d1668e8f 100644 --- a/include/vsg/commands/ExecuteCommands.h +++ b/include/vsg/commands/ExecuteCommands.h @@ -37,7 +37,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~ExecuteCommands(); + ~ExecuteCommands() override; struct CommandGraphAndBuffer { diff --git a/include/vsg/commands/NextSubPass.h b/include/vsg/commands/NextSubPass.h index 5db9581a5b..5c032eadee 100644 --- a/include/vsg/commands/NextSubPass.h +++ b/include/vsg/commands/NextSubPass.h @@ -32,7 +32,7 @@ namespace vsg VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE; protected: - virtual ~NextSubPass(); + ~NextSubPass() override; }; VSG_type_name(vsg::NextSubPass); diff --git a/include/vsg/commands/PipelineBarrier.h b/include/vsg/commands/PipelineBarrier.h index 4631d3be71..d5a563203a 100644 --- a/include/vsg/commands/PipelineBarrier.h +++ b/include/vsg/commands/PipelineBarrier.h @@ -152,7 +152,7 @@ namespace vsg ImageMemoryBarriers imageMemoryBarriers; protected: - virtual ~PipelineBarrier(); + ~PipelineBarrier() override; }; VSG_type_name(vsg::PipelineBarrier); diff --git a/include/vsg/core/Allocator.h b/include/vsg/core/Allocator.h index 4bf93d9941..a93e2e16ce 100644 --- a/include/vsg/core/Allocator.h +++ b/include/vsg/core/Allocator.h @@ -105,12 +105,12 @@ namespace vsg using other = allocator_affinity_adapter; }; - value_type* allocate(std::size_t n) + static value_type* allocate(std::size_t n) { return static_cast(vsg::allocate(n * sizeof(value_type), A)); } - void deallocate(value_type* ptr, std::size_t n) + static void deallocate(value_type* ptr, std::size_t n) { vsg::deallocate(ptr, n * sizeof(value_type)); } diff --git a/include/vsg/core/Array.h b/include/vsg/core/Array.h index 6fcc98fbe2..ec70eb4280 100644 --- a/include/vsg/core/Array.h +++ b/include/vsg/core/Array.h @@ -57,12 +57,12 @@ namespace vsg dirty(); } - explicit Array(uint32_t numElements, Properties in_properties = {}) : + explicit Array(uint32_t numElements, const Properties& in_properties = {}) : Data(in_properties, sizeof(value_type)), _data(_allocate(numElements)), _size(numElements) { dirty(); } - Array(uint32_t numElements, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : + Array(uint32_t numElements, value_type* data, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : Data(in_properties, sizeof(value_type)), _data(data), _size(numElements) @@ -71,7 +71,7 @@ namespace vsg dirty(); } - Array(uint32_t numElements, const value_type& value, Properties in_properties = {}) : + Array(uint32_t numElements, const value_type& value, const Properties& in_properties = {}) : Data(in_properties, sizeof(value_type)), _data(_allocate(numElements)), _size(numElements) @@ -80,7 +80,7 @@ namespace vsg dirty(); } - Array(ref_ptr data, uint32_t offset, uint32_t stride, uint32_t numElements, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : + Array(ref_ptr data, uint32_t offset, uint32_t stride, uint32_t numElements, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : Data(), _data(nullptr), _size(0) @@ -247,7 +247,7 @@ namespace vsg return *this; } - void assign(uint32_t numElements, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) + void assign(uint32_t numElements, value_type* data, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) { _delete(); @@ -262,7 +262,7 @@ namespace vsg dirty(); } - void assign(ref_ptr storage, uint32_t offset, uint32_t stride, uint32_t numElements, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) + void assign(ref_ptr storage, uint32_t offset, uint32_t stride, uint32_t numElements, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) { _delete(); @@ -344,7 +344,7 @@ namespace vsg const_iterator end() const { return const_iterator{data(_size), properties.stride}; } protected: - virtual ~Array() + ~Array() override { _delete(); } diff --git a/include/vsg/core/Array2D.h b/include/vsg/core/Array2D.h index 203a800828..1460faff43 100644 --- a/include/vsg/core/Array2D.h +++ b/include/vsg/core/Array2D.h @@ -57,7 +57,7 @@ namespace vsg } } - Array2D(uint32_t width, uint32_t height, Properties in_properties = {}) : + Array2D(uint32_t width, uint32_t height, const Properties& in_properties = {}) : Data(in_properties, sizeof(value_type)), _data(nullptr), _width(width), @@ -67,7 +67,7 @@ namespace vsg dirty(); } - Array2D(uint32_t width, uint32_t height, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : + Array2D(uint32_t width, uint32_t height, value_type* data, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : Data(in_properties, sizeof(value_type)), _data(data), _width(width), @@ -77,7 +77,7 @@ namespace vsg dirty(); } - Array2D(uint32_t width, uint32_t height, const value_type& value, Properties in_properties = {}) : + Array2D(uint32_t width, uint32_t height, const value_type& value, const Properties& in_properties = {}) : Data(in_properties, sizeof(value_type)), _data(nullptr), _width(width), @@ -91,7 +91,7 @@ namespace vsg } } - Array2D(ref_ptr data, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : + Array2D(ref_ptr data, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : Data(), _data(nullptr), _width(0), @@ -231,7 +231,7 @@ namespace vsg return *this; } - void assign(uint32_t width, uint32_t height, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) + void assign(uint32_t width, uint32_t height, value_type* data, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) { _delete(); @@ -247,7 +247,7 @@ namespace vsg dirty(); } - void assign(ref_ptr storage, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) + void assign(ref_ptr storage, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) { _delete(); @@ -340,7 +340,7 @@ namespace vsg const_iterator end() const { return const_iterator{data(_width * _height), properties.stride}; } protected: - virtual ~Array2D() + ~Array2D() override { _delete(); } diff --git a/include/vsg/core/Array3D.h b/include/vsg/core/Array3D.h index 1e1c26befa..aa3c911c1b 100644 --- a/include/vsg/core/Array3D.h +++ b/include/vsg/core/Array3D.h @@ -59,7 +59,7 @@ namespace vsg } } - Array3D(uint32_t width, uint32_t height, uint32_t depth, Properties in_properties = {}) : + Array3D(uint32_t width, uint32_t height, uint32_t depth, const Properties& in_properties = {}) : Data(in_properties, sizeof(value_type)), _data(nullptr), _width(width), @@ -70,7 +70,7 @@ namespace vsg dirty(); } - Array3D(uint32_t width, uint32_t height, uint32_t depth, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : + Array3D(uint32_t width, uint32_t height, uint32_t depth, value_type* data, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : Data(in_properties, sizeof(value_type)), _data(data), _width(width), @@ -81,7 +81,7 @@ namespace vsg dirty(); } - Array3D(uint32_t width, uint32_t height, uint32_t depth, const value_type& value, Properties in_properties = {}) : + Array3D(uint32_t width, uint32_t height, uint32_t depth, const value_type& value, const Properties& in_properties = {}) : Data(in_properties, sizeof(value_type)), _data(nullptr), _width(width), @@ -96,7 +96,7 @@ namespace vsg } } - Array3D(ref_ptr data, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, uint32_t depth, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : + Array3D(ref_ptr data, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, uint32_t depth, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) : Data(), _data(nullptr), _width(0), @@ -242,7 +242,7 @@ namespace vsg return *this; } - void assign(uint32_t width, uint32_t height, uint32_t depth, value_type* data, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) + void assign(uint32_t width, uint32_t height, uint32_t depth, value_type* data, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) { _delete(); @@ -259,7 +259,7 @@ namespace vsg dirty(); } - void assign(ref_ptr storage, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, uint32_t depth, Properties in_properties = {}, MipmapLayout* mipmapLayout = nullptr) + void assign(ref_ptr storage, uint32_t offset, uint32_t stride, uint32_t width, uint32_t height, uint32_t depth, const Properties& in_properties = {}, MipmapLayout* mipmapLayout = nullptr) { _delete(); @@ -356,7 +356,7 @@ namespace vsg const_iterator end() const { return const_iterator{data(_width * _height * _depth), properties.stride}; } protected: - virtual ~Array3D() + ~Array3D() override { _delete(); } diff --git a/include/vsg/core/Data.h b/include/vsg/core/Data.h index 8777ba3e24..4fc60b05c2 100644 --- a/include/vsg/core/Data.h +++ b/include/vsg/core/Data.h @@ -144,10 +144,10 @@ namespace vsg Data(const Data& data, const CopyOp& copyop = {}) : Object(data, copyop), properties(data.properties) {} - explicit Data(Properties layout) : + explicit Data(const Properties& layout) : properties(layout) {} - Data(Properties layout, uint32_t min_stride) : + Data(const Properties& layout, uint32_t min_stride) : properties(layout) { if (properties.stride < min_stride) properties.stride = min_stride; @@ -227,32 +227,12 @@ namespace vsg const MipmapLayout* getMipmapLayout() const; protected: - virtual ~Data() {} + ~Data() override {} void _copy(const Data& rhs); void _clear(); ModifiedCount _modifiedCount; - -#if 1 - public: - /// deprecated: provided for backwards compatibility, use Properties instead. - using Layout = Properties; - - /// deprecated: use data->properties = properties instead. - void setLayout(Layout layout) - { - VkFormat previous_format = properties.format; // temporary hack to keep applications that call setFormat(..) before setLayout(..) working - uint32_t previous_stride = properties.stride; - properties = layout; - if (properties.format == 0 && previous_format != 0) properties.format = previous_format; // temporary hack to keep existing applications working - if (properties.stride == 0 && previous_stride != 0) properties.stride = previous_stride; // make sure the layout has a valid stride. - } - /// deprecated: use data->properties - Layout& getLayout() { return properties; } - /// deprecated: use data->properties - Layout getLayout() const { return properties; } -#endif }; VSG_type_name(vsg::Data); diff --git a/include/vsg/core/Exception.h b/include/vsg/core/Exception.h index 6e40a17cb4..dea3619d3e 100644 --- a/include/vsg/core/Exception.h +++ b/include/vsg/core/Exception.h @@ -12,6 +12,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ +#include + #include namespace vsg @@ -19,7 +21,7 @@ namespace vsg /// Exception object that can be thrown from VSG code, such as failed Vulkan calls where the result value will be the VkResult value /// returned from failed Vulkan call. - struct Exception + struct VSG_DECLSPEC Exception { std::string message; int result = 0; diff --git a/include/vsg/core/External.h b/include/vsg/core/External.h index 47a8aa6235..d015261eaa 100644 --- a/include/vsg/core/External.h +++ b/include/vsg/core/External.h @@ -59,7 +59,7 @@ namespace vsg void add(const Path& filename, ref_ptr object = {}) { entries[filename] = object; } protected: - virtual ~External(); + ~External() override; }; VSG_type_name(vsg::External); diff --git a/include/vsg/core/IntrusiveAllocator.h b/include/vsg/core/IntrusiveAllocator.h index 131a33a320..51c68cedf8 100644 --- a/include/vsg/core/IntrusiveAllocator.h +++ b/include/vsg/core/IntrusiveAllocator.h @@ -48,7 +48,7 @@ namespace vsg explicit IntrusiveAllocator(size_t in_defaultAlignment = 8); explicit IntrusiveAllocator(std::unique_ptr in_nestedAllocator, size_t in_defaultAlignment = 8); - ~IntrusiveAllocator(); + ~IntrusiveAllocator() override; void report(std::ostream& out) const override; @@ -104,9 +104,13 @@ namespace vsg next(static_cast(in_next)), status(in_status) {} - Element() = default; - Element(const Element&) = default; - Element& operator=(const Element&) = default; + Element() : index(0) {} + Element(const Element& rhs) : index(rhs.index) {} + Element& operator=(const Element& rhs) + { + index = rhs.index; + return *this; + } }; struct FreeList @@ -142,7 +146,7 @@ namespace vsg struct VSG_DECLSPEC SlotTester { SlotTester(Element* in_mem, size_t in_head) : - mem(in_mem), head(in_head){}; + mem(in_mem), head(in_head) {}; const Element* mem = nullptr; size_t head = 0; diff --git a/include/vsg/core/MemorySlots.h b/include/vsg/core/MemorySlots.h index 2680478702..59775f5011 100644 --- a/include/vsg/core/MemorySlots.h +++ b/include/vsg/core/MemorySlots.h @@ -31,6 +31,9 @@ namespace vsg MEMORY_TRACKING_DEFAULT = MEMORY_TRACKING_NO_CHECKS }; + // forward declare + struct LogOutput; + /** class used internally by vsg::Allocator, vsg::DeviceMemory and vsg::Buffer to manage suballocation within a block of CPU or GPU memory.*/ class VSG_DECLSPEC MemorySlots { @@ -52,7 +55,8 @@ namespace vsg size_t totalMemorySize() const { return _totalMemorySize; } // debug facilities - void report(std::ostream& out) const; + void report(LogOutput& log) const; + bool check() const; mutable int memoryTracking = MEMORY_TRACKING_DEFAULT; diff --git a/include/vsg/core/MipmapLayout.h b/include/vsg/core/MipmapLayout.h index 968114255f..51d91bae76 100644 --- a/include/vsg/core/MipmapLayout.h +++ b/include/vsg/core/MipmapLayout.h @@ -47,7 +47,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~MipmapLayout(); + ~MipmapLayout() override; }; VSG_type_name(vsg::MipmapLayout); diff --git a/include/vsg/core/Object.h b/include/vsg/core/Object.h index b29a643b36..02f678a4e7 100644 --- a/include/vsg/core/Object.h +++ b/include/vsg/core/Object.h @@ -260,7 +260,7 @@ namespace vsg C dest; dest.reserve(src.size()); - for (auto& ptr : src) + for (const auto& ptr : src) { dest.push_back(operator()(ptr)); } @@ -283,4 +283,15 @@ namespace vsg return new_object.template cast(); } + /// clone a named meta data object stored within an object's Auxliary object if available, others default construct object + template + ref_ptr clone(const std::string& key, C container) + { + if (container) + { + if (auto prototype = container->template getRefObject(key)) return vsg::clone(prototype); + } + return T::create(); + } + } // namespace vsg diff --git a/include/vsg/core/Objects.h b/include/vsg/core/Objects.h index 292a6c60ae..5618bd94fd 100644 --- a/include/vsg/core/Objects.h +++ b/include/vsg/core/Objects.h @@ -48,7 +48,7 @@ namespace vsg } protected: - virtual ~Objects(); + ~Objects() override; }; VSG_type_name(vsg::Objects); diff --git a/include/vsg/core/ScratchMemory.h b/include/vsg/core/ScratchMemory.h index 17a06bd5bb..25729da00d 100644 --- a/include/vsg/core/ScratchMemory.h +++ b/include/vsg/core/ScratchMemory.h @@ -37,12 +37,12 @@ namespace vsg ScratchMemory(const ScratchMemory&) = delete; ScratchMemory& operator=(const ScratchMemory&) = delete; - ~ScratchMemory() + ~ScratchMemory() override { delete[] buffer; } - uint8_t* align(uint8_t* p) const + static uint8_t* align(uint8_t* p) { auto alignment = sizeof(p); uint8_t* new_p = reinterpret_cast(((reinterpret_cast(p) + alignment - 1) / alignment) * alignment); diff --git a/include/vsg/core/Value.h b/include/vsg/core/Value.h index 0b60876db7..a5c02bd704 100644 --- a/include/vsg/core/Value.h +++ b/include/vsg/core/Value.h @@ -162,7 +162,7 @@ namespace vsg void set(const value_type& value) { _value = value; } protected: - virtual ~Value() {} + ~Value() override {} private: value_type _value; diff --git a/include/vsg/core/observer_ptr.h b/include/vsg/core/observer_ptr.h index c37633d46d..55850f3893 100644 --- a/include/vsg/core/observer_ptr.h +++ b/include/vsg/core/observer_ptr.h @@ -185,6 +185,9 @@ namespace vsg return {}; } + /// We strongly recommend access via ref_ptr<> rather than get(). Only use get() to get access to the raw C pointer when it's know that the object pointed to will remain in memory through use of that raw C pointer. + T* get() const noexcept { return _ptr; } + protected: template friend class observer_ptr; diff --git a/include/vsg/core/type_name.h b/include/vsg/core/type_name.h index 318a49baa1..4972050d23 100644 --- a/include/vsg/core/type_name.h +++ b/include/vsg/core/type_name.h @@ -49,7 +49,7 @@ namespace vsg template<> constexpr const char* vsg::type_name() noexcept { return #T; } \ template<> constexpr const char* vsg::type_name() noexcept { return "const "#T; } - /// convinience function for adding a space in front of the type_name string. + /// convenience function for adding a space in front of the type_name string. template std::string space_type_name(const T&) { return std::string(" ") + type_name(); } diff --git a/include/vsg/io/DatabasePager.h b/include/vsg/io/DatabasePager.h index 9b01c0649b..a0fa424117 100644 --- a/include/vsg/io/DatabasePager.h +++ b/include/vsg/io/DatabasePager.h @@ -104,12 +104,15 @@ namespace vsg void add(ref_ptr plod, const CompileResult& cr); - ref_ptr take_when_available(); + /// prune entries older than specified frameCount + uint32_t prune(uint64_t frameCount); + + ref_ptr take_when_available(uint64_t frameCount); Nodes take_all(CompileResult& result); protected: - virtual ~DatabaseQueue(); + ~DatabaseQueue() override; std::mutex _mutex; std::condition_variable _cv; @@ -138,13 +141,16 @@ namespace vsg ref_ptr compileManager; std::atomic_uint numActiveRequests{0}; - std::atomic_uint64_t frameCount; + std::atomic_uint64_t frameCount{0}; ref_ptr culledPagedLODs; /// for systems with smaller GPU memory limits you may need to reduce the targetMaxNumPagedLODWithHighResSubgraphs to keep memory usage within available limits. uint32_t targetMaxNumPagedLODWithHighResSubgraphs = 1500; + /// number of frames before a PagedLOD with a failed load/compile is attempted to be loaded/compiled again. + uint64_t delayBeforeNextLoadAttempt = 60; + std::mutex pendingPagedLODMutex; ref_ptr pagedLODContainer; @@ -158,16 +164,16 @@ namespace vsg /// read and delete threads created by start() std::list threads; + ref_ptr status; + ref_ptr deleteQueue; + protected: - virtual ~DatabasePager(); + ~DatabasePager() override; void requestDiscarded(PagedLOD* plod); - ref_ptr _status; - ref_ptr _requestQueue; ref_ptr _toMergeQueue; - ref_ptr _deleteQueue; }; VSG_type_name(vsg::DatabasePager); diff --git a/include/vsg/io/JSONParser.h b/include/vsg/io/JSONParser.h index 90c72d7bb3..024c86a55a 100644 --- a/include/vsg/io/JSONParser.h +++ b/include/vsg/io/JSONParser.h @@ -82,7 +82,7 @@ namespace vsg warnings.push_back(vsg::make_string("Parsing error at [", line, ":", column, "], pos = ", pos, " [ ", lineEnclosingPosition(pos), " ]. ", std::forward(args)...)); } - inline bool white_space(char c) const + static inline bool white_space(char c) { return (c == ' ' || c == '\t' || c == '\r' || c == '\n'); } diff --git a/include/vsg/io/Logger.h b/include/vsg/io/Logger.h index 8791f901ff..84f5231fed 100644 --- a/include/vsg/io/Logger.h +++ b/include/vsg/io/Logger.h @@ -232,7 +232,7 @@ namespace vsg void log_stream(Level msg_level, PrintToStreamFunction print); protected: - virtual ~Logger(); + ~Logger() override; std::mutex _mutex; std::ostringstream _stream; diff --git a/include/vsg/io/ObjectFactory.h b/include/vsg/io/ObjectFactory.h index ab8ec2dbf8..4ba6ce907a 100644 --- a/include/vsg/io/ObjectFactory.h +++ b/include/vsg/io/ObjectFactory.h @@ -46,7 +46,7 @@ namespace vsg static ref_ptr& instance(); protected: - virtual ~ObjectFactory(); + ~ObjectFactory() override; CreateMap _createMap; }; diff --git a/include/vsg/io/Options.h b/include/vsg/io/Options.h index 90bd9e3974..981304123a 100644 --- a/include/vsg/io/Options.h +++ b/include/vsg/io/Options.h @@ -122,7 +122,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~Options(); + ~Options() override; }; VSG_type_name(vsg::Options); diff --git a/include/vsg/io/stream.h b/include/vsg/io/stream.h index b1cf8c0251..66c7ef3e51 100644 --- a/include/vsg/io/stream.h +++ b/include/vsg/io/stream.h @@ -29,6 +29,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include +#include #include namespace vsg @@ -333,4 +334,29 @@ namespace vsg return output; } + template + std::ostream& operator<<(std::ostream& output, const std::set& values) + { + if (values.empty()) + output << "{}"; + else + { + output << "{ "; + + bool first = true; + for (const auto& v : values) + { + if (!first) + output << ", "; + else + first = false; + + output << v; + } + + output << " }"; + } + return output; + } + } // namespace vsg diff --git a/include/vsg/lighting/AmbientLight.h b/include/vsg/lighting/AmbientLight.h index 9417bda87e..61d418c2a3 100644 --- a/include/vsg/lighting/AmbientLight.h +++ b/include/vsg/lighting/AmbientLight.h @@ -29,11 +29,8 @@ namespace vsg public: ref_ptr clone(const CopyOp& copyop = {}) const override { return AmbientLight::create(*this, copyop); } - void read(Input& input) override; - void write(Output& output) const override; - protected: - virtual ~AmbientLight() {} + ~AmbientLight() override {} }; VSG_type_name(vsg::AmbientLight); diff --git a/include/vsg/lighting/DirectionalLight.h b/include/vsg/lighting/DirectionalLight.h index 890c69721a..4ff000e7e9 100644 --- a/include/vsg/lighting/DirectionalLight.h +++ b/include/vsg/lighting/DirectionalLight.h @@ -37,7 +37,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~DirectionalLight() {} + ~DirectionalLight() override {} }; VSG_type_name(vsg::DirectionalLight); diff --git a/include/vsg/lighting/HardShadows.h b/include/vsg/lighting/HardShadows.h index 1f868cb4c7..035351aa0c 100644 --- a/include/vsg/lighting/HardShadows.h +++ b/include/vsg/lighting/HardShadows.h @@ -25,10 +25,6 @@ namespace vsg public: ref_ptr clone(const CopyOp& copyop = {}) const override { return HardShadows::create(*this, copyop); } - int compare(const Object& rhs) const override; - - void read(Input& input) override; - void write(Output& output) const override; }; VSG_type_name(vsg::HardShadows); diff --git a/include/vsg/lighting/Light.h b/include/vsg/lighting/Light.h index bf6887be4a..cd2f44e7bf 100644 --- a/include/vsg/lighting/Light.h +++ b/include/vsg/lighting/Light.h @@ -41,7 +41,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~Light() {} + ~Light() override {} }; VSG_type_name(vsg::Light); diff --git a/include/vsg/lighting/PercentageCloserSoftShadows.h b/include/vsg/lighting/PercentageCloserSoftShadows.h index 40bd546ebd..8bda61a965 100644 --- a/include/vsg/lighting/PercentageCloserSoftShadows.h +++ b/include/vsg/lighting/PercentageCloserSoftShadows.h @@ -25,10 +25,6 @@ namespace vsg public: ref_ptr clone(const CopyOp& copyop = {}) const override { return PercentageCloserSoftShadows::create(*this, copyop); } - int compare(const Object& rhs) const override; - - void read(Input& input) override; - void write(Output& output) const override; }; VSG_type_name(vsg::PercentageCloserSoftShadows); diff --git a/include/vsg/lighting/PointLight.h b/include/vsg/lighting/PointLight.h index fd8fca3cef..7462d0f280 100644 --- a/include/vsg/lighting/PointLight.h +++ b/include/vsg/lighting/PointLight.h @@ -37,7 +37,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~PointLight() {} + ~PointLight() override {} }; VSG_type_name(vsg::PointLight); diff --git a/include/vsg/lighting/ShadowSettings.h b/include/vsg/lighting/ShadowSettings.h index 055e619297..2e36cc120e 100644 --- a/include/vsg/lighting/ShadowSettings.h +++ b/include/vsg/lighting/ShadowSettings.h @@ -33,7 +33,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~ShadowSettings() {} + ~ShadowSettings() override {} }; VSG_type_name(vsg::ShadowSettings); diff --git a/include/vsg/lighting/SpotLight.h b/include/vsg/lighting/SpotLight.h index 614d8de386..b8d8db3244 100644 --- a/include/vsg/lighting/SpotLight.h +++ b/include/vsg/lighting/SpotLight.h @@ -40,7 +40,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~SpotLight() {} + ~SpotLight() override {} }; VSG_type_name(vsg::SpotLight); diff --git a/include/vsg/maths/box.h b/include/vsg/maths/box.h index 80ab988d01..25fecafa54 100644 --- a/include/vsg/maths/box.h +++ b/include/vsg/maths/box.h @@ -42,7 +42,7 @@ namespace vsg constexpr t_box& operator=(const t_box&) = default; - constexpr std::size_t size() const { return 6; } + constexpr static std::size_t size() { return 6; } value_type& operator[](std::size_t i) { return data()[i]; } value_type operator[](std::size_t i) const { return data()[i]; } diff --git a/include/vsg/maths/mat2.h b/include/vsg/maths/mat2.h index dd011a9781..d9f8693e68 100644 --- a/include/vsg/maths/mat2.h +++ b/include/vsg/maths/mat2.h @@ -59,9 +59,9 @@ namespace vsg value[1] = rhs[1]; } - constexpr std::size_t size() const { return 4; } - constexpr std::size_t columns() const { return 2; } - constexpr std::size_t rows() const { return 2; } + constexpr static std::size_t size() { return 4; } + constexpr static std::size_t columns() { return 2; } + constexpr static std::size_t rows() { return 2; } column_type& operator[](std::size_t c) { return value[c]; } const column_type& operator[](std::size_t c) const { return value[c]; } diff --git a/include/vsg/maths/mat3.h b/include/vsg/maths/mat3.h index 95a9020513..510e1e2e4f 100644 --- a/include/vsg/maths/mat3.h +++ b/include/vsg/maths/mat3.h @@ -66,9 +66,9 @@ namespace vsg value[2] = rhs[2]; } - constexpr std::size_t size() const { return 9; } - constexpr std::size_t columns() const { return 3; } - constexpr std::size_t rows() const { return 3; } + constexpr static std::size_t size() { return 9; } + constexpr static std::size_t columns() { return 3; } + constexpr static std::size_t rows() { return 3; } column_type& operator[](std::size_t c) { return value[c]; } const column_type& operator[](std::size_t c) const { return value[c]; } diff --git a/include/vsg/maths/mat4.h b/include/vsg/maths/mat4.h index 8174d094b2..ad5ab16031 100644 --- a/include/vsg/maths/mat4.h +++ b/include/vsg/maths/mat4.h @@ -75,9 +75,9 @@ namespace vsg value[3] = rhs[3]; } - constexpr std::size_t size() const { return 16; } - constexpr std::size_t columns() const { return 4; } - constexpr std::size_t rows() const { return 4; } + constexpr static std::size_t size() { return 16; } + constexpr static std::size_t columns() { return 4; } + constexpr static std::size_t rows() { return 4; } column_type& operator[](std::size_t c) { return value[c]; } const column_type& operator[](std::size_t c) const { return value[c]; } @@ -236,9 +236,8 @@ namespace vsg t_vec3 operator*(const t_vec3& lhs, const t_mat4& rhs) { T inv = numbers::one() / (lhs[0] * rhs[3][0] + lhs[1] * rhs[3][1] + lhs[2] * rhs[3][2] + rhs[3][3]); - return t_vec3(lhs[0] * rhs[0][0] + lhs[1] * rhs[0][1] + lhs[2] * rhs[0][2] + rhs[0][3] * inv, - lhs[0] * rhs[1][0] + lhs[1] * rhs[1][1] + lhs[2] * rhs[1][2] + rhs[1][3] * inv, - lhs[0] * rhs[2][0] + lhs[1] * rhs[2][1] + lhs[2] * rhs[2][2] + rhs[2][3] * inv); + return t_vec3((lhs[0] * rhs[0][0] + lhs[1] * rhs[0][1] + lhs[2] * rhs[0][2] + rhs[0][3]) * inv, + (lhs[0] * rhs[1][0] + lhs[1] * rhs[1][1] + lhs[2] * rhs[1][2] + rhs[1][3]) * inv, + (lhs[0] * rhs[2][0] + lhs[1] * rhs[2][1] + lhs[2] * rhs[2][2] + rhs[2][3]) * inv); } - } // namespace vsg diff --git a/include/vsg/maths/plane.h b/include/vsg/maths/plane.h index 1c28ea47b7..5ce9d44675 100644 --- a/include/vsg/maths/plane.h +++ b/include/vsg/maths/plane.h @@ -77,7 +77,7 @@ namespace vsg constexpr explicit t_plane(const t_vec4& v) : value{v[0], v[1], v[2], v[3]} {} - constexpr std::size_t size() const { return 4; } + constexpr static std::size_t size() { return 4; } value_type& operator[](std::size_t i) { return value[i]; } value_type operator[](std::size_t i) const { return value[i]; } diff --git a/include/vsg/maths/quat.h b/include/vsg/maths/quat.h index a4a3aad531..ca42f8e47f 100644 --- a/include/vsg/maths/quat.h +++ b/include/vsg/maths/quat.h @@ -65,7 +65,7 @@ namespace vsg constexpr t_quat& operator=(const t_quat&) = default; - constexpr std::size_t size() const { return 4; } + constexpr static std::size_t size() { return 4; } value_type& operator[](std::size_t i) { return value[i]; } value_type operator[](std::size_t i) const { return value[i]; } diff --git a/include/vsg/maths/sphere.h b/include/vsg/maths/sphere.h index 7de13c45c3..9ec6604ee9 100644 --- a/include/vsg/maths/sphere.h +++ b/include/vsg/maths/sphere.h @@ -74,7 +74,7 @@ namespace vsg constexpr t_sphere(R sx, R sy, R sz, R sd) : value{sx, sy, sz, sd} {} - constexpr std::size_t size() const { return 4; } + constexpr static std::size_t size() { return 4; } value_type& operator[](std::size_t i) { return value[i]; } value_type operator[](std::size_t i) const { return value[i]; } diff --git a/include/vsg/maths/vec2.h b/include/vsg/maths/vec2.h index b39e5ff9fc..c83379a82a 100644 --- a/include/vsg/maths/vec2.h +++ b/include/vsg/maths/vec2.h @@ -68,7 +68,7 @@ namespace vsg constexpr explicit t_vec2(const t_vec2& v) : value{static_cast(v.x), static_cast(v.y)} {} - constexpr std::size_t size() const { return 2; } + constexpr static std::size_t size() { return 2; } value_type& operator[](std::size_t i) { return value[i]; } value_type operator[](std::size_t i) const { return value[i]; } diff --git a/include/vsg/maths/vec3.h b/include/vsg/maths/vec3.h index 0aa38a3c37..8599501879 100644 --- a/include/vsg/maths/vec3.h +++ b/include/vsg/maths/vec3.h @@ -67,7 +67,7 @@ namespace vsg constexpr explicit t_vec3(const t_vec3& v) : value{static_cast(v.x), static_cast(v.y), static_cast(v.z)} {} - constexpr std::size_t size() const { return 3; } + constexpr static std::size_t size() { return 3; } value_type& operator[](std::size_t i) { return value[i]; } value_type operator[](std::size_t i) const { return value[i]; } diff --git a/include/vsg/maths/vec4.h b/include/vsg/maths/vec4.h index f502896225..9ff9202f3c 100644 --- a/include/vsg/maths/vec4.h +++ b/include/vsg/maths/vec4.h @@ -78,7 +78,7 @@ namespace vsg constexpr t_vec4(const t_vec3& v, value_type in_w) : value{static_cast(v.x), static_cast(v.y), static_cast(v.z), in_w} {} - constexpr std::size_t size() const { return 4; } + constexpr static std::size_t size() { return 4; } value_type& operator[](std::size_t i) { return value[i]; } value_type operator[](std::size_t i) const { return value[i]; } diff --git a/include/vsg/nodes/Bin.h b/include/vsg/nodes/Bin.h index 8840237f40..4b8eca0f38 100644 --- a/include/vsg/nodes/Bin.h +++ b/include/vsg/nodes/Bin.h @@ -51,7 +51,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~Bin(); + ~Bin() override; std::vector _matrices; std::vector _stateCommands; diff --git a/include/vsg/nodes/CullGroup.h b/include/vsg/nodes/CullGroup.h index 3e8cb28fc4..ed344cd36e 100644 --- a/include/vsg/nodes/CullGroup.h +++ b/include/vsg/nodes/CullGroup.h @@ -36,7 +36,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~CullGroup(); + ~CullGroup() override; }; VSG_type_name(vsg::CullGroup); diff --git a/include/vsg/nodes/CullNode.h b/include/vsg/nodes/CullNode.h index 71ce22e3de..ff851f288b 100644 --- a/include/vsg/nodes/CullNode.h +++ b/include/vsg/nodes/CullNode.h @@ -43,7 +43,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~CullNode(); + ~CullNode() override; }; VSG_type_name(vsg::CullNode); diff --git a/include/vsg/nodes/DepthSorted.h b/include/vsg/nodes/DepthSorted.h index ca9a9f7bdd..8e50c93134 100644 --- a/include/vsg/nodes/DepthSorted.h +++ b/include/vsg/nodes/DepthSorted.h @@ -46,7 +46,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~DepthSorted(); + ~DepthSorted() override; }; VSG_type_name(vsg::DepthSorted); diff --git a/include/vsg/nodes/Geometry.h b/include/vsg/nodes/Geometry.h index 0483e16286..ce40c599b3 100644 --- a/include/vsg/nodes/Geometry.h +++ b/include/vsg/nodes/Geometry.h @@ -54,7 +54,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~Geometry(); + ~Geometry() override; vk_buffer _vulkanData; VkIndexType indexType = VK_INDEX_TYPE_UINT16; diff --git a/include/vsg/nodes/Group.h b/include/vsg/nodes/Group.h index 1cd46fef7d..ff1e625974 100644 --- a/include/vsg/nodes/Group.h +++ b/include/vsg/nodes/Group.h @@ -59,7 +59,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~Group(); + ~Group() override; }; VSG_type_name(vsg::Group); diff --git a/include/vsg/nodes/InstanceDraw.h b/include/vsg/nodes/InstanceDraw.h index 4c56c7ee98..c50fbb06a2 100644 --- a/include/vsg/nodes/InstanceDraw.h +++ b/include/vsg/nodes/InstanceDraw.h @@ -48,7 +48,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~InstanceDraw(); + ~InstanceDraw() override; }; VSG_type_name(vsg::InstanceDraw) diff --git a/include/vsg/nodes/InstanceDrawIndexed.h b/include/vsg/nodes/InstanceDrawIndexed.h index 88401443cc..07ee3aab1d 100644 --- a/include/vsg/nodes/InstanceDrawIndexed.h +++ b/include/vsg/nodes/InstanceDrawIndexed.h @@ -51,7 +51,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~InstanceDrawIndexed(); + ~InstanceDrawIndexed() override; VkIndexType indexType = VK_INDEX_TYPE_UINT16; }; diff --git a/include/vsg/nodes/InstanceNode.h b/include/vsg/nodes/InstanceNode.h index dea9962742..5399defda8 100644 --- a/include/vsg/nodes/InstanceNode.h +++ b/include/vsg/nodes/InstanceNode.h @@ -21,10 +21,10 @@ namespace vsg { /// InstanceNode provides a mechanism for specifying the translations, rotations and scales (transform arrays) of subgraph - /// that contains InstanceDraw leaf node(s) that utlize the InstanceNode's per instance transform arrays combined with the + /// that contains InstanceDraw leaf node(s) that utilize the InstanceNode's per instance transform arrays combined with the /// InstanceDraw nodes per vertex arrays. /// - /// InstanceNode only work correctly when the child subgraphs that obey these contraints: + /// InstanceNode only work correctly when the child subgraphs that obey these constraints: /// 1. Do not contain any Transform nodes /// 2. Do not contain any Culling nodes /// 3. Do not contain any InstanceNode nodes @@ -76,7 +76,7 @@ namespace vsg void compile(Context& context) override; protected: - virtual ~InstanceNode(); + ~InstanceNode() override; }; VSG_type_name(vsg::InstanceNode); diff --git a/include/vsg/nodes/InstrumentationNode.h b/include/vsg/nodes/InstrumentationNode.h index 9ea80e156e..f336637f7c 100644 --- a/include/vsg/nodes/InstrumentationNode.h +++ b/include/vsg/nodes/InstrumentationNode.h @@ -50,7 +50,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~InstrumentationNode(); + ~InstrumentationNode() override; uint32_t _level = 1; uint_color _color; diff --git a/include/vsg/nodes/LOD.h b/include/vsg/nodes/LOD.h index da3d25f7f6..c7274da216 100644 --- a/include/vsg/nodes/LOD.h +++ b/include/vsg/nodes/LOD.h @@ -66,7 +66,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~LOD(); + ~LOD() override; }; VSG_type_name(vsg::LOD); diff --git a/include/vsg/nodes/Layer.h b/include/vsg/nodes/Layer.h index 6f19c579ee..2de68f7885 100644 --- a/include/vsg/nodes/Layer.h +++ b/include/vsg/nodes/Layer.h @@ -52,7 +52,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~Layer(); + ~Layer() override; }; VSG_type_name(vsg::Layer); diff --git a/include/vsg/nodes/Node.h b/include/vsg/nodes/Node.h index b6d25b0936..ea1470f91c 100644 --- a/include/vsg/nodes/Node.h +++ b/include/vsg/nodes/Node.h @@ -33,7 +33,7 @@ namespace vsg static void operator delete(void* ptr); protected: - virtual ~Node(); + ~Node() override; }; VSG_type_name(vsg::Node); diff --git a/include/vsg/nodes/PagedLOD.h b/include/vsg/nodes/PagedLOD.h index 607761ffdf..5c929fe5eb 100644 --- a/include/vsg/nodes/PagedLOD.h +++ b/include/vsg/nodes/PagedLOD.h @@ -78,7 +78,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~PagedLOD(); + ~PagedLOD() override; public: ref_ptr options; @@ -89,6 +89,9 @@ namespace vsg mutable std::atomic_uint64_t frameHighResLastUsed{0}; mutable std::atomic_uint requestCount{0}; + mutable std::atomic_uint64_t frameNextLoadAttempt{0}; + mutable std::atomic_uint64_t loadAttempts{0}; + enum RequestStatus : unsigned int { NoRequest = 0, diff --git a/include/vsg/nodes/QuadGroup.h b/include/vsg/nodes/QuadGroup.h index 902008fd22..f4836c00d1 100644 --- a/include/vsg/nodes/QuadGroup.h +++ b/include/vsg/nodes/QuadGroup.h @@ -52,7 +52,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~QuadGroup(); + ~QuadGroup() override; }; VSG_type_name(vsg::QuadGroup); diff --git a/include/vsg/nodes/RegionOfInterest.h b/include/vsg/nodes/RegionOfInterest.h index 93d767d03c..2b54605d1c 100644 --- a/include/vsg/nodes/RegionOfInterest.h +++ b/include/vsg/nodes/RegionOfInterest.h @@ -50,7 +50,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~RegionOfInterest(); + ~RegionOfInterest() override; }; VSG_type_name(vsg::RegionOfInterest); diff --git a/include/vsg/nodes/StateGroup.h b/include/vsg/nodes/StateGroup.h index fb3dfd71aa..2f1f9044b4 100644 --- a/include/vsg/nodes/StateGroup.h +++ b/include/vsg/nodes/StateGroup.h @@ -81,7 +81,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~StateGroup(); + ~StateGroup() override; }; VSG_type_name(vsg::StateGroup); diff --git a/include/vsg/nodes/Switch.h b/include/vsg/nodes/Switch.h index 39264e7481..009f4c0743 100644 --- a/include/vsg/nodes/Switch.h +++ b/include/vsg/nodes/Switch.h @@ -69,7 +69,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~Switch(); + ~Switch() override; }; VSG_type_name(vsg::Switch); diff --git a/include/vsg/nodes/VertexDraw.h b/include/vsg/nodes/VertexDraw.h index 0a26df4a6d..6db79b5412 100644 --- a/include/vsg/nodes/VertexDraw.h +++ b/include/vsg/nodes/VertexDraw.h @@ -50,7 +50,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~VertexDraw(); + ~VertexDraw() override; vk_buffer _vulkanData; }; diff --git a/include/vsg/nodes/VertexIndexDraw.h b/include/vsg/nodes/VertexIndexDraw.h index f5b0ec9f70..b9e06be9ec 100644 --- a/include/vsg/nodes/VertexIndexDraw.h +++ b/include/vsg/nodes/VertexIndexDraw.h @@ -53,7 +53,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~VertexIndexDraw(); + ~VertexIndexDraw() override; vk_buffer _vulkanData; VkIndexType indexType = VK_INDEX_TYPE_UINT16; diff --git a/include/vsg/platform/macos/MacOS_Window.h b/include/vsg/platform/macos/MacOS_Window.h index 21b9331680..ddaeaaf0e9 100644 --- a/include/vsg/platform/macos/MacOS_Window.h +++ b/include/vsg/platform/macos/MacOS_Window.h @@ -57,7 +57,7 @@ namespace vsgMacOS const char* instanceExtensionSurfaceName() const override { return "VK_MVK_macos_surface"; } - bool valid() const override { return _window; } + bool valid() const override { return _window || _view; } bool pollEvents(vsg::UIEvents& events) override; diff --git a/include/vsg/platform/win32/Win32_Window.h b/include/vsg/platform/win32/Win32_Window.h index 54755cf159..62f8aa5ca4 100644 --- a/include/vsg/platform/win32/Win32_Window.h +++ b/include/vsg/platform/win32/Win32_Window.h @@ -40,86 +40,71 @@ namespace vsgWin32 { uint16_t modifierMask = 0; - // see https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input#keystroke-message-flags - WORD keyFlags = HIWORD(lParam); - WORD scanCode = LOBYTE(keyFlags); // scan code - BOOL isExtendedKey = (keyFlags & KF_EXTENDED) == KF_EXTENDED; // extended-key flag, 1 if scancode has 0xE0 prefix + // Get scancode + uint16_t keyFlags = HIWORD(lParam); + uint16_t scanCode = LOBYTE(lParam); + bool isExtendedKey = (keyFlags & KF_EXTENDED) == KF_EXTENDED; if (isExtendedKey) + { scanCode = MAKEWORD(scanCode, 0xE0); + } + + // Get virtual key code + uint32_t virtualKey = static_cast(wParam); + + // Left and right modifier detection + if (virtualKey == VK_SHIFT) + { + virtualKey = (scanCode == 0x2A) ? VK_RSHIFT : VK_LSHIFT; + } + else if (virtualKey == VK_CONTROL) + { + virtualKey = isExtendedKey ? VK_RCONTROL : VK_LCONTROL; + } + else if (virtualKey == VK_MENU) + { + virtualKey = isExtendedKey ? VK_RMENU : VK_LMENU; + } - uint32_t virtualKey = ::MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK_EX, ::GetKeyboardLayout(0)); auto itr = _vk2vsg.find(virtualKey); if (itr == _vk2vsg.end()) { - // What ever the code was in lParam should translate to a Virtual Key that we know of in _vk2vsg - // If we cannot find it, we simply return. return false; } - // This is the base-key that was pressed. (i.e., the VSG enum of the physical key pressed). keySymbol = itr->second; - // Look for any modifiers that may be active. + // Get keys state BYTE keyState[256]; - if (virtualKey == 0 || !::GetKeyboardState(keyState)) - { - // if virtualKey was undefined or we could not get the keyboard state, simply return. - return false; - } - // If any of the specific left/right modifier keys are active - // add the side-independent vsg modifier to the modifier Mask - switch (virtualKey) + if (!::GetKeyboardState(keyState)) { - case VK_LSHIFT: - case VK_RSHIFT: - modifierMask |= vsg::KeyModifier::MODKEY_Shift; - break; - - case VK_LCONTROL: - case VK_RCONTROL: - modifierMask |= vsg::KeyModifier::MODKEY_Control; - break; - - case VK_LMENU: - case VK_RMENU: - modifierMask |= vsg::KeyModifier::MODKEY_Alt; - break; - - default: - virtualKey = static_cast(wParam); - break; + return false; } - // Check if caps lock or numlock is toggled. + // Modifier's flags setting + if (keyState[VK_SHIFT] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Shift; + if (keyState[VK_CONTROL] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Control; + if (keyState[VK_MENU] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Alt; if (keyState[VK_CAPITAL] & 0x01) modifierMask |= vsg::KeyModifier::MODKEY_CapsLock; if (keyState[VK_NUMLOCK] & 0x01) modifierMask |= vsg::KeyModifier::MODKEY_NumLock; - // Check if the modifier keys are down (these are non-toggle keys, so the high-order bit is relevant!) - // again, vsg only has a side-independent modifier - if (keyState[VK_LSHIFT] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Shift; - if (keyState[VK_RSHIFT] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Shift; - if (keyState[VK_LCONTROL] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Control; - if (keyState[VK_RCONTROL] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Control; - if (keyState[VK_LMENU] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Alt; - if (keyState[VK_RMENU] & 0x80) modifierMask |= vsg::KeyModifier::MODKEY_Alt; - - // This is the final keyModifier keyModifier = static_cast(modifierMask); - // The actual keystroke is what we get after the ::ToAscii call - char asciiKey[2]; - int32_t numChars = ::ToAsciiEx(static_cast(wParam), scanCode, keyState, reinterpret_cast(asciiKey), 0, ::GetKeyboardLayout(0)); + // Get Unicode symbol + wchar_t unicodeChar[2] = {0}; + int numChars = ::ToUnicodeEx(virtualKey, scanCode, keyState, unicodeChar, 2, 0, ::GetKeyboardLayout(0)); + if (numChars == 1) { - // it is indeed an ascii character. 0-127 - modifiedKeySymbol = static_cast(asciiKey[0]); + wchar_t ch = unicodeChar[0]; + + modifiedKeySymbol = mapCharToKeySymbol(ch); } else { - // otherwise treat the modifiedKeySymbol as the same as the keySymbol. modifiedKeySymbol = keySymbol; } @@ -127,6 +112,19 @@ namespace vsgWin32 } protected: + + vsg::KeySymbol mapCharToKeySymbol(wchar_t ch) + { + // Special characters (with and without Shift) + switch (ch) + { + case L'\t': return vsg::KEY_Tab; + case L'\r': return vsg::KEY_Return; + } + + return static_cast(ch); + } + VirtualKeyToKeySymbolMap _vk2vsg; }; diff --git a/include/vsg/raytracing/AccelerationStructure.h b/include/vsg/raytracing/AccelerationStructure.h index 40773a32a7..f3cd750734 100644 --- a/include/vsg/raytracing/AccelerationStructure.h +++ b/include/vsg/raytracing/AccelerationStructure.h @@ -37,7 +37,7 @@ namespace vsg VkDeviceSize requiredScratchSize() const { return _requiredBuildScratchSize; } protected: - virtual ~AccelerationStructure(); + ~AccelerationStructure() override; VkAccelerationStructureKHR _accelerationStructure; VkAccelerationStructureCreateInfoKHR _accelerationStructureInfo; diff --git a/include/vsg/raytracing/RayTracingPipeline.h b/include/vsg/raytracing/RayTracingPipeline.h index 84fa32ef35..ec8910174c 100644 --- a/include/vsg/raytracing/RayTracingPipeline.h +++ b/include/vsg/raytracing/RayTracingPipeline.h @@ -56,12 +56,12 @@ namespace vsg VkPipeline vk(uint32_t deviceID) const { return _implementation[deviceID]->_pipeline; } protected: - virtual ~RayTracingPipeline(); + ~RayTracingPipeline() override; struct Implementation : public Inherit { Implementation(Context& context, RayTracingPipeline* rayTracingPipeline); - virtual ~Implementation(); + ~Implementation() override; VkPipeline _pipeline; @@ -103,7 +103,7 @@ namespace vsg virtual void release(); public: - virtual ~BindRayTracingPipeline(); + ~BindRayTracingPipeline() override; ref_ptr _pipeline; }; diff --git a/include/vsg/raytracing/RayTracingShaderGroup.h b/include/vsg/raytracing/RayTracingShaderGroup.h index 068c851660..0c3f5b50fb 100644 --- a/include/vsg/raytracing/RayTracingShaderGroup.h +++ b/include/vsg/raytracing/RayTracingShaderGroup.h @@ -38,7 +38,7 @@ namespace vsg ref_ptr bufferInfo; protected: - virtual ~RayTracingShaderGroup(); + ~RayTracingShaderGroup() override; }; VSG_type_name(vsg::RayTracingShaderGroup); diff --git a/include/vsg/state/ArrayState.h b/include/vsg/state/ArrayState.h index 4c4897495c..d2ff248632 100644 --- a/include/vsg/state/ArrayState.h +++ b/include/vsg/state/ArrayState.h @@ -92,7 +92,7 @@ namespace vsg virtual ref_ptr vertexArray(uint32_t instanceIndex); protected: - virtual ~ArrayState() {} + ~ArrayState() override {} }; VSG_type_name(vsg::ArrayState); diff --git a/include/vsg/state/BindDescriptorSet.h b/include/vsg/state/BindDescriptorSet.h index b38ea92b4c..9f975c1148 100644 --- a/include/vsg/state/BindDescriptorSet.h +++ b/include/vsg/state/BindDescriptorSet.h @@ -74,7 +74,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~BindDescriptorSets() {} + ~BindDescriptorSets() override {} struct VulkanData { @@ -151,7 +151,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~BindDescriptorSet() {} + ~BindDescriptorSet() override {} struct VulkanData { diff --git a/include/vsg/state/Buffer.h b/include/vsg/state/Buffer.h index f4c6530154..65a800ac21 100644 --- a/include/vsg/state/Buffer.h +++ b/include/vsg/state/Buffer.h @@ -60,7 +60,7 @@ namespace vsg virtual bool compile(Context& context); protected: - virtual ~Buffer(); + ~Buffer() override; struct VulkanData { diff --git a/include/vsg/state/BufferInfo.h b/include/vsg/state/BufferInfo.h index dc132c2e1f..f592ef608a 100644 --- a/include/vsg/state/BufferInfo.h +++ b/include/vsg/state/BufferInfo.h @@ -74,7 +74,7 @@ namespace vsg vk_buffer copiedModifiedCounts; protected: - virtual ~BufferInfo(); + ~BufferInfo() override; }; VSG_type_name(vsg::BufferInfo); diff --git a/include/vsg/state/BufferView.h b/include/vsg/state/BufferView.h index 862efeb653..3e11ff7ba4 100644 --- a/include/vsg/state/BufferView.h +++ b/include/vsg/state/BufferView.h @@ -42,7 +42,7 @@ namespace vsg virtual void compile(Context& context); protected: - virtual ~BufferView(); + ~BufferView() override; struct VulkanData { diff --git a/include/vsg/state/ColorBlendState.h b/include/vsg/state/ColorBlendState.h index 8f4d6558e0..0c9ac2a0a2 100644 --- a/include/vsg/state/ColorBlendState.h +++ b/include/vsg/state/ColorBlendState.h @@ -44,7 +44,7 @@ namespace vsg void apply(Context& context, VkGraphicsPipelineCreateInfo& pipelineInfo) const override; protected: - virtual ~ColorBlendState(); + ~ColorBlendState() override; }; VSG_type_name(vsg::ColorBlendState); diff --git a/include/vsg/state/ComputePipeline.h b/include/vsg/state/ComputePipeline.h index a832fa0f63..049977cce2 100644 --- a/include/vsg/state/ComputePipeline.h +++ b/include/vsg/state/ComputePipeline.h @@ -45,12 +45,12 @@ namespace vsg VkPipeline vk(uint32_t deviceID) const { return _implementation[deviceID]->_pipeline; } protected: - virtual ~ComputePipeline(); + ~ComputePipeline() override; struct Implementation : public Inherit { Implementation(Context& context, Device* device, const PipelineLayout* pipelineLayout, const ShaderStage* shaderStage); - virtual ~Implementation(); + ~Implementation() override; VkPipeline _pipeline; ref_ptr _device; @@ -80,7 +80,7 @@ namespace vsg void compile(Context& context) override; public: - virtual ~BindComputePipeline(); + ~BindComputePipeline() override; }; VSG_type_name(vsg::BindComputePipeline); diff --git a/include/vsg/state/DepthStencilState.h b/include/vsg/state/DepthStencilState.h index aa0f25299b..5085f19462 100644 --- a/include/vsg/state/DepthStencilState.h +++ b/include/vsg/state/DepthStencilState.h @@ -43,7 +43,7 @@ namespace vsg void apply(Context& context, VkGraphicsPipelineCreateInfo& pipelineInfo) const override; protected: - virtual ~DepthStencilState(); + ~DepthStencilState() override; }; VSG_type_name(vsg::DepthStencilState); diff --git a/include/vsg/state/DescriptorBuffer.h b/include/vsg/state/DescriptorBuffer.h index 013c824498..d259aae85d 100644 --- a/include/vsg/state/DescriptorBuffer.h +++ b/include/vsg/state/DescriptorBuffer.h @@ -46,7 +46,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~DescriptorBuffer(); + ~DescriptorBuffer() override; }; VSG_type_name(vsg::DescriptorBuffer) diff --git a/include/vsg/state/DescriptorSet.h b/include/vsg/state/DescriptorSet.h index b6e6ee424b..7ea4c69c2a 100644 --- a/include/vsg/state/DescriptorSet.h +++ b/include/vsg/state/DescriptorSet.h @@ -76,7 +76,7 @@ namespace vsg static void recycle(ref_ptr& dsi); protected: - virtual ~Implementation(); + ~Implementation() override; friend DescriptorPool; @@ -85,7 +85,7 @@ namespace vsg }; protected: - virtual ~DescriptorSet(); + ~DescriptorSet() override; vk_buffer> _implementation; }; diff --git a/include/vsg/state/DescriptorSetLayout.h b/include/vsg/state/DescriptorSetLayout.h index 9479114083..068c257f0f 100644 --- a/include/vsg/state/DescriptorSetLayout.h +++ b/include/vsg/state/DescriptorSetLayout.h @@ -64,13 +64,13 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~DescriptorSetLayout(); + ~DescriptorSetLayout() override; struct Implementation : public Inherit { Implementation(Device* device, VkDescriptorSetLayoutCreateFlags createFlags, const DescriptorSetLayoutBindings& descriptorSetLayoutBindings, const DescriptorSetLayoutBindingFlags& descriptorSetLayoutBindingFlags); - virtual ~Implementation(); + ~Implementation() override; ref_ptr _device; VkDescriptorSetLayout _descriptorSetLayout; diff --git a/include/vsg/state/DynamicState.h b/include/vsg/state/DynamicState.h index 420025129b..b316449f88 100644 --- a/include/vsg/state/DynamicState.h +++ b/include/vsg/state/DynamicState.h @@ -46,7 +46,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~DynamicState(); + ~DynamicState() override; }; VSG_type_name(vsg::DynamicState); diff --git a/include/vsg/state/GraphicsPipeline.h b/include/vsg/state/GraphicsPipeline.h index 81fd7f79be..0d276b4897 100644 --- a/include/vsg/state/GraphicsPipeline.h +++ b/include/vsg/state/GraphicsPipeline.h @@ -44,7 +44,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~GraphicsPipelineState() {} + ~GraphicsPipelineState() override {} }; VSG_type_name(vsg::GraphicsPipelineState); @@ -88,13 +88,13 @@ namespace vsg void release() { _implementation.clear(); } protected: - virtual ~GraphicsPipeline(); + ~GraphicsPipeline() override; struct Implementation : public Inherit { Implementation(Context& context, Device* device, const RenderPass* renderPass, const PipelineLayout* pipelineLayout, const ShaderStages& shaderStages, const GraphicsPipelineStates& pipelineStates, uint32_t subpass); - virtual ~Implementation(); + ~Implementation() override; GraphicsPipelineStates _pipelineStates; VkPipeline _pipeline; @@ -128,7 +128,7 @@ namespace vsg virtual void release(); public: - virtual ~BindGraphicsPipeline(); + ~BindGraphicsPipeline() override; }; VSG_type_name(vsg::BindGraphicsPipeline); diff --git a/include/vsg/state/Image.h b/include/vsg/state/Image.h index 9a802e1a7d..55f4b7da69 100644 --- a/include/vsg/state/Image.h +++ b/include/vsg/state/Image.h @@ -72,7 +72,7 @@ namespace vsg virtual VkResult compile(MemoryBufferPools& memoryBufferPools); protected: - virtual ~Image(); + ~Image() override; struct VulkanData { diff --git a/include/vsg/state/ImageInfo.h b/include/vsg/state/ImageInfo.h index 7d26450186..e8c5d9ebd7 100644 --- a/include/vsg/state/ImageInfo.h +++ b/include/vsg/state/ImageInfo.h @@ -69,7 +69,7 @@ namespace vsg vk_buffer copiedModifiedCounts; protected: - virtual ~ImageInfo(); + ~ImageInfo() override; }; VSG_type_name(vsg::ImageInfo); diff --git a/include/vsg/state/ImageView.h b/include/vsg/state/ImageView.h index 9de4bcbc0c..828e239a3e 100644 --- a/include/vsg/state/ImageView.h +++ b/include/vsg/state/ImageView.h @@ -44,7 +44,7 @@ namespace vsg virtual void compile(Context& context); protected: - virtual ~ImageView(); + ~ImageView() override; struct VulkanData { diff --git a/include/vsg/state/InputAssemblyState.h b/include/vsg/state/InputAssemblyState.h index 428d50ed67..a82031066e 100644 --- a/include/vsg/state/InputAssemblyState.h +++ b/include/vsg/state/InputAssemblyState.h @@ -35,7 +35,7 @@ namespace vsg void apply(Context& context, VkGraphicsPipelineCreateInfo& pipelineInfo) const override; protected: - virtual ~InputAssemblyState(); + ~InputAssemblyState() override; }; VSG_type_name(vsg::InputAssemblyState); diff --git a/include/vsg/state/MultisampleState.h b/include/vsg/state/MultisampleState.h index 5da05e09fd..826e10c789 100644 --- a/include/vsg/state/MultisampleState.h +++ b/include/vsg/state/MultisampleState.h @@ -38,7 +38,7 @@ namespace vsg void apply(Context& context, VkGraphicsPipelineCreateInfo& pipelineInfo) const override; protected: - virtual ~MultisampleState(); + ~MultisampleState() override; }; VSG_type_name(vsg::MultisampleState); diff --git a/include/vsg/state/PipelineLayout.h b/include/vsg/state/PipelineLayout.h index 2d5554f993..d6567489d7 100644 --- a/include/vsg/state/PipelineLayout.h +++ b/include/vsg/state/PipelineLayout.h @@ -54,13 +54,13 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~PipelineLayout(); + ~PipelineLayout() override; struct Implementation : public Inherit { Implementation(Device* device, const DescriptorSetLayouts& descriptorSetLayouts, const PushConstantRanges& pushConstantRanges, VkPipelineLayoutCreateFlags flags = 0); - virtual ~Implementation(); + ~Implementation() override; VkPipelineLayout _pipelineLayout; diff --git a/include/vsg/state/PushConstants.h b/include/vsg/state/PushConstants.h index bab577ff2b..e12735aea7 100644 --- a/include/vsg/state/PushConstants.h +++ b/include/vsg/state/PushConstants.h @@ -37,7 +37,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~PushConstants(); + ~PushConstants() override; }; VSG_type_name(vsg::PushConstants); diff --git a/include/vsg/state/QueryPool.h b/include/vsg/state/QueryPool.h index 7527fd3aa5..54ba71a71c 100644 --- a/include/vsg/state/QueryPool.h +++ b/include/vsg/state/QueryPool.h @@ -51,7 +51,7 @@ namespace vsg void compile(Context& context); protected: - ~QueryPool(); + ~QueryPool() override; VkQueryPool _queryPool{}; ref_ptr _device{}; diff --git a/include/vsg/state/RasterizationState.h b/include/vsg/state/RasterizationState.h index 6487b3f019..33e1c0802a 100644 --- a/include/vsg/state/RasterizationState.h +++ b/include/vsg/state/RasterizationState.h @@ -45,7 +45,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~RasterizationState(); + ~RasterizationState() override; }; VSG_type_name(vsg::RasterizationState); diff --git a/include/vsg/state/ResourceHints.h b/include/vsg/state/ResourceHints.h index 91fc704372..dc23b1c4ae 100644 --- a/include/vsg/state/ResourceHints.h +++ b/include/vsg/state/ResourceHints.h @@ -92,7 +92,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~ResourceHints(); + ~ResourceHints() override; }; VSG_type_name(vsg::ResourceHints); diff --git a/include/vsg/state/Sampler.h b/include/vsg/state/Sampler.h index 239e8366ff..0706afb4ca 100644 --- a/include/vsg/state/Sampler.h +++ b/include/vsg/state/Sampler.h @@ -59,13 +59,13 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~Sampler(); + ~Sampler() override; struct Implementation : public Inherit { Implementation(Device* device, const VkSamplerCreateInfo& createSamplerInfo); - virtual ~Implementation(); + ~Implementation() override; VkSampler _sampler; ref_ptr _device; diff --git a/include/vsg/state/ShaderModule.h b/include/vsg/state/ShaderModule.h index a57ff2e295..4cc75d7ee6 100644 --- a/include/vsg/state/ShaderModule.h +++ b/include/vsg/state/ShaderModule.h @@ -59,6 +59,8 @@ namespace vsg public: ref_ptr clone(const CopyOp& copyop = {}) const override { return ShaderCompileSettings::create(*this, copyop); } + + virtual int compare_except_defines(const Object& rhs_object) const; int compare(const Object& rhs_object) const override; void read(Input& input) override; @@ -103,13 +105,13 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~ShaderModule(); + ~ShaderModule() override; struct Implementation : public Inherit { Implementation(Device* device, ShaderModule* shader); - virtual ~Implementation(); + ~Implementation() override; VkShaderModule _shaderModule; ref_ptr _device; diff --git a/include/vsg/state/ShaderStage.h b/include/vsg/state/ShaderStage.h index 404e34f146..1b6ec3fe25 100644 --- a/include/vsg/state/ShaderStage.h +++ b/include/vsg/state/ShaderStage.h @@ -58,7 +58,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~ShaderStage(); + ~ShaderStage() override; }; VSG_type_name(vsg::ShaderStage); diff --git a/include/vsg/state/StateCommand.h b/include/vsg/state/StateCommand.h index 01e393b489..7e3f65ff99 100644 --- a/include/vsg/state/StateCommand.h +++ b/include/vsg/state/StateCommand.h @@ -36,7 +36,7 @@ namespace vsg uint32_t slot = 0; protected: - virtual ~StateCommand() {} + ~StateCommand() override {} }; VSG_type_name(vsg::StateCommand); diff --git a/include/vsg/state/TessellationState.h b/include/vsg/state/TessellationState.h index 430a3dbfd2..27998b1298 100644 --- a/include/vsg/state/TessellationState.h +++ b/include/vsg/state/TessellationState.h @@ -36,7 +36,7 @@ namespace vsg void apply(Context& context, VkGraphicsPipelineCreateInfo& pipelineInfo) const override; protected: - virtual ~TessellationState(); + ~TessellationState() override; }; VSG_type_name(vsg::TessellationState); diff --git a/include/vsg/state/VertexInputState.h b/include/vsg/state/VertexInputState.h index ff74e2f253..50221af206 100644 --- a/include/vsg/state/VertexInputState.h +++ b/include/vsg/state/VertexInputState.h @@ -40,7 +40,7 @@ namespace vsg void apply(Context& context, VkGraphicsPipelineCreateInfo& pipelineInfo) const override; protected: - virtual ~VertexInputState(); + ~VertexInputState() override; }; VSG_type_name(vsg::VertexInputState); diff --git a/include/vsg/state/ViewDependentState.h b/include/vsg/state/ViewDependentState.h index a502fdcb4e..ded1e84ca7 100644 --- a/include/vsg/state/ViewDependentState.h +++ b/include/vsg/state/ViewDependentState.h @@ -88,7 +88,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~BindViewDescriptorSets() {} + ~BindViewDescriptorSets() override {} }; VSG_type_name(vsg::BindViewDescriptorSets); @@ -175,7 +175,7 @@ namespace vsg mutable std::vector shadowMaps; protected: - ~ViewDependentState(); + ~ViewDependentState() override; }; VSG_type_name(vsg::ViewDependentState); diff --git a/include/vsg/state/ViewportState.h b/include/vsg/state/ViewportState.h index 89ac086340..0cf3ddb3b8 100644 --- a/include/vsg/state/ViewportState.h +++ b/include/vsg/state/ViewportState.h @@ -55,7 +55,7 @@ namespace vsg void record(CommandBuffer& commandBuffer) const override; protected: - virtual ~ViewportState(); + ~ViewportState() override; }; VSG_type_name(vsg::ViewportState); diff --git a/include/vsg/threading/ActivityStatus.h b/include/vsg/threading/ActivityStatus.h index bbcc18214f..c063b33c86 100644 --- a/include/vsg/threading/ActivityStatus.h +++ b/include/vsg/threading/ActivityStatus.h @@ -33,7 +33,7 @@ namespace vsg bool cancel() const noexcept { return !_active; } protected: - virtual ~ActivityStatus() {} + ~ActivityStatus() override {} std::atomic_bool _active; }; diff --git a/include/vsg/threading/Barrier.h b/include/vsg/threading/Barrier.h index 10f655e798..bdc1c03500 100644 --- a/include/vsg/threading/Barrier.h +++ b/include/vsg/threading/Barrier.h @@ -57,7 +57,7 @@ namespace vsg } protected: - virtual ~Barrier() {} + ~Barrier() override {} void _release() { diff --git a/include/vsg/threading/DeleteQueue.h b/include/vsg/threading/DeleteQueue.h index c87e74e462..511ddb72c1 100644 --- a/include/vsg/threading/DeleteQueue.h +++ b/include/vsg/threading/DeleteQueue.h @@ -37,6 +37,7 @@ namespace vsg std::atomic_uint64_t frameCount = 0; uint64_t retainForFrameCount = 3; + std::atomic_uint64_t deletedCount = 0; ActivityStatus* getStatus() { return _status; } const ActivityStatus* getStatus() const { return _status; } @@ -112,12 +113,16 @@ namespace vsg _cv.notify_one(); } - void wait_then_clear(); + /// wait till there are items to delete then delete objects scheduled for deletion more than retainForFrameCount, + /// return number of objects assigned directly to DeleteQeue that have been deleted (doesn't count children deleted.) + size_t wait_then_clear(); - void clear(); + /// immediately delete objects scheduled for deletion for more than retainForFrameCount, + /// return number of objects assigned directly to DeleteQeue that have been deleted (doesn't count children deleted.) + size_t clear(); protected: - virtual ~DeleteQueue(); + ~DeleteQueue() override; std::mutex _mutex; std::condition_variable _cv; diff --git a/include/vsg/threading/FrameBlock.h b/include/vsg/threading/FrameBlock.h index 6d7d8f10be..ad38da2620 100644 --- a/include/vsg/threading/FrameBlock.h +++ b/include/vsg/threading/FrameBlock.h @@ -67,7 +67,7 @@ namespace vsg } protected: - virtual ~FrameBlock() {} + ~FrameBlock() override {} std::mutex _mutex; std::condition_variable _cv; diff --git a/include/vsg/threading/Latch.h b/include/vsg/threading/Latch.h index 328d36d48c..0fdc6eb082 100644 --- a/include/vsg/threading/Latch.h +++ b/include/vsg/threading/Latch.h @@ -84,7 +84,7 @@ namespace vsg int count() const { return _count.load(); } protected: - virtual ~Latch() {} + ~Latch() override {} std::atomic_int _count; std::mutex _mutex; diff --git a/include/vsg/threading/OperationThreads.h b/include/vsg/threading/OperationThreads.h index 7a6ecd9528..265ef515a5 100644 --- a/include/vsg/threading/OperationThreads.h +++ b/include/vsg/threading/OperationThreads.h @@ -53,7 +53,7 @@ namespace vsg ref_ptr status; protected: - virtual ~OperationThreads(); + ~OperationThreads() override; }; VSG_type_name(vsg::OperationThreads) diff --git a/include/vsg/utils/Builder.h b/include/vsg/utils/Builder.h index 99b9eccf18..5004515750 100644 --- a/include/vsg/utils/Builder.h +++ b/include/vsg/utils/Builder.h @@ -113,7 +113,7 @@ namespace vsg Builder(const Builder& rhs) = delete; Builder& operator=(const Builder& rhs) = delete; - ~Builder(); + ~Builder() override; bool verbose = false; ref_ptr options; diff --git a/include/vsg/utils/CommandLine.h b/include/vsg/utils/CommandLine.h index 7f24c00f46..4594e65af7 100644 --- a/include/vsg/utils/CommandLine.h +++ b/include/vsg/utils/CommandLine.h @@ -155,7 +155,7 @@ namespace vsg bool read(std::initializer_list matches, Args&... args) { bool result = false; - for (auto str : matches) result = read(str, args...) | result; + for (auto str : matches) result = read(str, args...) || result; return result; } diff --git a/include/vsg/utils/GpuAnnotation.h b/include/vsg/utils/GpuAnnotation.h index 8c4d08c486..6d85e3c7ba 100644 --- a/include/vsg/utils/GpuAnnotation.h +++ b/include/vsg/utils/GpuAnnotation.h @@ -40,7 +40,7 @@ namespace vsg void leave(const vsg::SourceLocation* sl, uint64_t& reference, CommandBuffer& commandBuffer, const Object* object) const override; protected: - virtual ~GpuAnnotation(); + ~GpuAnnotation() override; }; VSG_type_name(vsg::GpuAnnotation); diff --git a/include/vsg/utils/Instrumentation.h b/include/vsg/utils/Instrumentation.h index ffaebae847..36d1e013c9 100644 --- a/include/vsg/utils/Instrumentation.h +++ b/include/vsg/utils/Instrumentation.h @@ -54,24 +54,24 @@ namespace vsg virtual ref_ptr shareOrDuplicateForThreadSafety() { return ref_ptr(this); } - virtual void setThreadName(const std::string& /*name*/) const {}; + virtual void setThreadName(const std::string& /*name*/) const {} - virtual void enterFrame(const SourceLocation* /*sl*/, uint64_t& /*reference*/, FrameStamp& /*frameStamp*/) const {}; - virtual void leaveFrame(const SourceLocation* /*sl*/, uint64_t& /*reference*/, FrameStamp& /*frameStamp*/) const {}; + virtual void enterFrame(const SourceLocation* /*sl*/, uint64_t& /*reference*/, FrameStamp& /*frameStamp*/) const {} + virtual void leaveFrame(const SourceLocation* /*sl*/, uint64_t& /*reference*/, FrameStamp& /*frameStamp*/) const {} - virtual void enter(const SourceLocation* /*sl*/, uint64_t& /*reference*/, const Object* /*object*/ = nullptr) const {}; - virtual void leave(const SourceLocation* /*sl*/, uint64_t& /*reference*/, const Object* /*object*/ = nullptr) const {}; + virtual void enter(const SourceLocation* /*sl*/, uint64_t& /*reference*/, const Object* /*object*/ = nullptr) const {} + virtual void leave(const SourceLocation* /*sl*/, uint64_t& /*reference*/, const Object* /*object*/ = nullptr) const {} - virtual void enterCommandBuffer(const SourceLocation* /*sl*/, uint64_t& /*reference*/, CommandBuffer& /*commandBuffer*/) const {}; - virtual void leaveCommandBuffer(const SourceLocation* /*sl*/, uint64_t& /*reference*/, CommandBuffer& /*commandBuffer*/) const {}; + virtual void enterCommandBuffer(const SourceLocation* /*sl*/, uint64_t& /*reference*/, CommandBuffer& /*commandBuffer*/) const {} + virtual void leaveCommandBuffer(const SourceLocation* /*sl*/, uint64_t& /*reference*/, CommandBuffer& /*commandBuffer*/) const {} - virtual void enter(const SourceLocation* /*sl*/, uint64_t& /*reference*/, CommandBuffer& /*commandBuffer*/, const Object* /*object*/ = nullptr) const {}; - virtual void leave(const SourceLocation* /*sl*/, uint64_t& /*reference*/, CommandBuffer& /*commandBuffer*/, const Object* /*object*/ = nullptr) const {}; + virtual void enter(const SourceLocation* /*sl*/, uint64_t& /*reference*/, CommandBuffer& /*commandBuffer*/, const Object* /*object*/ = nullptr) const {} + virtual void leave(const SourceLocation* /*sl*/, uint64_t& /*reference*/, CommandBuffer& /*commandBuffer*/, const Object* /*object*/ = nullptr) const {} - virtual void finish() const {}; + virtual void finish() const {} protected: - virtual ~Instrumentation(); + ~Instrumentation() override; }; VSG_type_name(vsg::Instrumentation); diff --git a/include/vsg/utils/ShaderCompiler.h b/include/vsg/utils/ShaderCompiler.h index d418011c8f..62ac2ca362 100644 --- a/include/vsg/utils/ShaderCompiler.h +++ b/include/vsg/utils/ShaderCompiler.h @@ -16,7 +16,7 @@ namespace vsg { public: ShaderCompiler(); - virtual ~ShaderCompiler(); + ~ShaderCompiler() override; /// return true if shader compilation is supported by this build of VulkanSceneGraph /// you can also use the VSG_SUPPORTS_ShaderCompiler define provided by include/vsg/core/Version.h diff --git a/include/vsg/utils/ShaderSet.h b/include/vsg/utils/ShaderSet.h index e3bf15ac4d..fe4c74f0ed 100644 --- a/include/vsg/utils/ShaderSet.h +++ b/include/vsg/utils/ShaderSet.h @@ -196,7 +196,7 @@ namespace vsg void write(Output& output) const override; protected: - virtual ~ShaderSet(); + ~ShaderSet() override; AttributeBinding _nullAttributeBinding; DescriptorBinding _nullDescriptorBinding; diff --git a/include/vsg/utils/SharedObjects.h b/include/vsg/utils/SharedObjects.h index dbf4a1c52b..23f3dd76d6 100644 --- a/include/vsg/utils/SharedObjects.h +++ b/include/vsg/utils/SharedObjects.h @@ -73,7 +73,7 @@ namespace vsg void report(vsg::LogOutput& output); protected: - virtual ~SharedObjects(); + ~SharedObjects() override; mutable std::recursive_mutex _mutex; std::map> _defaults; diff --git a/include/vsg/utils/TracyInstrumentation.h b/include/vsg/utils/TracyInstrumentation.h index 3f9d8aff74..f552cdebd8 100644 --- a/include/vsg/utils/TracyInstrumentation.h +++ b/include/vsg/utils/TracyInstrumentation.h @@ -17,8 +17,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include -using namespace tracy; - namespace vsg { @@ -35,7 +33,7 @@ namespace vsg class TracyContexts : public Inherit { public: - VkCtx* getOrCreateContext(CommandBuffer& commandBuffer) const + tracy::VkCtx* getOrCreateContext(CommandBuffer& commandBuffer) const { std::scoped_lock lock(mutex); @@ -79,10 +77,10 @@ namespace vsg } mutable std::mutex mutex; - mutable std::map, std::pair> ctxMap; + mutable std::map, std::pair> ctxMap; protected: - ~TracyContexts() + ~TracyContexts() override { for (auto itr = ctxMap.begin(); itr != ctxMap.end(); ++itr) { @@ -111,7 +109,7 @@ namespace vsg ref_ptr settings; ref_ptr contexts; - mutable VkCtx* ctx = nullptr; + mutable tracy::VkCtx* ctx = nullptr; bool requiresCollection = false; ref_ptr shareOrDuplicateForThreadSafety() override @@ -151,9 +149,9 @@ namespace vsg reference = 1; # endif - TracyQueuePrepare(QueueType::ZoneBegin); - MemWrite(&item->zoneBegin.time, tracy::Profiler::GetTime()); - MemWrite(&item->zoneBegin.srcloc, (uint64_t)slcloc); + TracyQueuePrepare(tracy::QueueType::ZoneBegin); + tracy::MemWrite(&item->zoneBegin.time, tracy::Profiler::GetTime()); + tracy::MemWrite(&item->zoneBegin.srcloc, (uint64_t)slcloc); TracyQueueCommit(zoneBeginThread); } @@ -165,8 +163,8 @@ namespace vsg if (reference == 0) return; # endif - TracyQueuePrepare(QueueType::ZoneEnd); - MemWrite(&item->zoneEnd.time, tracy::Profiler::GetTime()); + TracyQueuePrepare(tracy::QueueType::ZoneEnd); + tracy::MemWrite(&item->zoneEnd.time, tracy::Profiler::GetTime()); TracyQueueCommit(zoneEndThread); } @@ -210,12 +208,12 @@ namespace vsg CONTEXT_VK_FUNCTION_WRAPPER(vkCmdWriteTimestamp(cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->GetQueryPool(), queryId)); auto item = tracy::Profiler::QueueSerial(); - MemWrite(&item->hdr.type, QueueType::GpuZoneBeginSerial); - MemWrite(&item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime()); - MemWrite(&item->gpuZoneBegin.srcloc, (uint64_t)slcloc); - MemWrite(&item->gpuZoneBegin.thread, GetThreadHandle()); - MemWrite(&item->gpuZoneBegin.queryId, uint16_t(queryId)); - MemWrite(&item->gpuZoneBegin.context, ctx->GetId()); + tracy::MemWrite(&item->hdr.type, tracy::QueueType::GpuZoneBeginSerial); + tracy::MemWrite(&item->gpuZoneBegin.cpuTime, tracy::Profiler::GetTime()); + tracy::MemWrite(&item->gpuZoneBegin.srcloc, (uint64_t)slcloc); + tracy::MemWrite(&item->gpuZoneBegin.thread, tracy::GetThreadHandle()); + tracy::MemWrite(&item->gpuZoneBegin.queryId, uint16_t(queryId)); + tracy::MemWrite(&item->gpuZoneBegin.context, ctx->GetId()); tracy::Profiler::QueueSerialFinish(); } @@ -231,11 +229,11 @@ namespace vsg CONTEXT_VK_FUNCTION_WRAPPER(vkCmdWriteTimestamp(cmdbuf, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, ctx->GetQueryPool(), queryId)); auto item = tracy::Profiler::QueueSerial(); - MemWrite(&item->hdr.type, QueueType::GpuZoneEndSerial); - MemWrite(&item->gpuZoneEnd.cpuTime, tracy::Profiler::GetTime()); - MemWrite(&item->gpuZoneEnd.thread, GetThreadHandle()); - MemWrite(&item->gpuZoneEnd.queryId, uint16_t(queryId)); - MemWrite(&item->gpuZoneEnd.context, ctx->GetId()); + tracy::MemWrite(&item->hdr.type, tracy::QueueType::GpuZoneEndSerial); + tracy::MemWrite(&item->gpuZoneEnd.cpuTime, tracy::Profiler::GetTime()); + tracy::MemWrite(&item->gpuZoneEnd.thread, tracy::GetThreadHandle()); + tracy::MemWrite(&item->gpuZoneEnd.queryId, uint16_t(queryId)); + tracy::MemWrite(&item->gpuZoneEnd.context, ctx->GetId()); tracy::Profiler::QueueSerialFinish(); } }; diff --git a/include/vsg/vk/AllocationCallbacks.h b/include/vsg/vk/AllocationCallbacks.h index 7bc308400e..0730cba5c7 100644 --- a/include/vsg/vk/AllocationCallbacks.h +++ b/include/vsg/vk/AllocationCallbacks.h @@ -27,7 +27,7 @@ namespace vsg VkAllocationCallbacks{} {} protected: - virtual ~AllocationCallbacks() {} + ~AllocationCallbacks() override {} }; /* diff --git a/include/vsg/vk/CommandBuffer.h b/include/vsg/vk/CommandBuffer.h index a9f5cb929b..a4091d81d0 100644 --- a/include/vsg/vk/CommandBuffer.h +++ b/include/vsg/vk/CommandBuffer.h @@ -66,7 +66,7 @@ namespace vsg friend CommandPool; CommandBuffer(CommandPool* commandPool, VkCommandBuffer commandBuffer, VkCommandBufferLevel level); - virtual ~CommandBuffer(); + ~CommandBuffer() override; VkCommandBuffer _commandBuffer; VkCommandBufferLevel _level; @@ -94,7 +94,7 @@ namespace vsg CommandBuffers buffers() const; protected: - virtual ~RecordedCommandBuffers(); + ~RecordedCommandBuffers() override; mutable std::mutex _mutex; std::map> _orderedCommandBuffers; CommandBuffers _commandBuffers; diff --git a/include/vsg/vk/CommandPool.h b/include/vsg/vk/CommandPool.h index c287499827..b6cd69f789 100644 --- a/include/vsg/vk/CommandPool.h +++ b/include/vsg/vk/CommandPool.h @@ -41,7 +41,7 @@ namespace vsg const Device* getDevice() const { return _device; } protected: - virtual ~CommandPool(); + ~CommandPool() override; friend CommandBuffer; diff --git a/include/vsg/vk/Context.h b/include/vsg/vk/Context.h index daa5bb1ede..02d0e51446 100644 --- a/include/vsg/vk/Context.h +++ b/include/vsg/vk/Context.h @@ -70,7 +70,7 @@ namespace vsg Context(const Context& context); - virtual ~Context(); + ~Context() override; const uint32_t deviceID = 0; ref_ptr device; diff --git a/include/vsg/vk/DescriptorPool.h b/include/vsg/vk/DescriptorPool.h index 8bbaca55ee..e4324a06ba 100644 --- a/include/vsg/vk/DescriptorPool.h +++ b/include/vsg/vk/DescriptorPool.h @@ -54,7 +54,7 @@ namespace vsg mutable std::mutex mutex; protected: - virtual ~DescriptorPool(); + ~DescriptorPool() override; VkDescriptorPool _descriptorPool; ref_ptr _device; diff --git a/include/vsg/vk/DescriptorPools.h b/include/vsg/vk/DescriptorPools.h index 1ded89cae6..443f3f94c4 100644 --- a/include/vsg/vk/DescriptorPools.h +++ b/include/vsg/vk/DescriptorPools.h @@ -56,7 +56,7 @@ namespace vsg bool allocated(uint32_t& numSets, DescriptorPoolSizes& descriptorPoolSizes) const; protected: - virtual ~DescriptorPools(); + ~DescriptorPools() override; /// get the maxSets and descriptorPoolSizes to use void getDescriptorPoolSizesToUse(uint32_t& maxSets, DescriptorPoolSizes& descriptorPoolSizes); diff --git a/include/vsg/vk/Device.h b/include/vsg/vk/Device.h index f4f77ed176..92b97bfcef 100644 --- a/include/vsg/vk/Device.h +++ b/include/vsg/vk/Device.h @@ -85,8 +85,8 @@ namespace vsg /// return true if Device was created with specified extension bool supportsDeviceExtension(const char* extensionName) const; - /// return the amount of memory available in deviceMemoryBufferPools and allocatable on device - VkDeviceSize availableMemory(bool includeMemoryPools = true) const; + /// return the amount of remaining memory, compatible with specified flags, available that can be allocated. + VkDeviceSize availableMemory(VkMemoryPropertyFlags memoryPropertiesFlags, double allocatedMemoryLimit = 1.0) const; // provide observer_ptr to memory buffer, descriptor pools and transferTask so that these can be accessed when required observer_ptr deviceMemoryBufferPools; @@ -95,7 +95,7 @@ namespace vsg observer_ptr transferTask; protected: - virtual ~Device(); + ~Device() override; VkDevice _device; diff --git a/include/vsg/vk/DeviceExtensions.h b/include/vsg/vk/DeviceExtensions.h index 08641831fd..e65157208e 100644 --- a/include/vsg/vk/DeviceExtensions.h +++ b/include/vsg/vk/DeviceExtensions.h @@ -61,6 +61,9 @@ namespace vsg PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnable = nullptr; PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnable = nullptr; PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOp = nullptr; + + // cache whether extension is supported + bool memory_budget = false; // VK_EXT_memory_budget }; VSG_type_name(vsg::DeviceExtensions); diff --git a/include/vsg/vk/DeviceFeatures.h b/include/vsg/vk/DeviceFeatures.h index 54b61b9637..c9aa381fc0 100644 --- a/include/vsg/vk/DeviceFeatures.h +++ b/include/vsg/vk/DeviceFeatures.h @@ -64,7 +64,7 @@ namespace vsg void* data() const; protected: - ~DeviceFeatures(); + ~DeviceFeatures() override; struct FeatureHeader { diff --git a/include/vsg/vk/DeviceMemory.h b/include/vsg/vk/DeviceMemory.h index ebd86590c3..b7912d3562 100644 --- a/include/vsg/vk/DeviceMemory.h +++ b/include/vsg/vk/DeviceMemory.h @@ -44,6 +44,7 @@ namespace vsg const VkMemoryPropertyFlags& getMemoryPropertyFlags() const { return _properties; } MemorySlots::OptionalOffset reserve(VkDeviceSize size); + MemorySlots::OptionalOffset reserve(VkDeviceSize size, VkDeviceSize alignment); void release(VkDeviceSize offset, VkDeviceSize size); bool full() const; @@ -55,8 +56,10 @@ namespace vsg Device* getDevice() { return _device; } const Device* getDevice() const { return _device; } + void report(LogOutput& out) const; + protected: - virtual ~DeviceMemory(); + ~DeviceMemory() override; VkDeviceMemory _deviceMemory; VkMemoryRequirements _memoryRequirements; @@ -95,14 +98,14 @@ namespace vsg } template - static ref_ptr create(DeviceMemory* deviceMemory, VkDeviceSize offset, VkMemoryMapFlags flags, Data::Properties properties, Args... args) + static ref_ptr create(DeviceMemory* deviceMemory, VkDeviceSize offset, VkMemoryMapFlags flags, const Data::Properties& properties, Args... args) { auto data = ref_ptr(new MappedData(deviceMemory, offset, flags, args...)); data->properties = properties; return data; } - virtual ~MappedData() + ~MappedData() override { T::dataRelease(); // make sure that the Array doesn't delete this memory _deviceMemory->unmap(); diff --git a/include/vsg/vk/Fence.h b/include/vsg/vk/Fence.h index ebf90e80b5..b5ce2900dd 100644 --- a/include/vsg/vk/Fence.h +++ b/include/vsg/vk/Fence.h @@ -44,7 +44,7 @@ namespace vsg const Device* getDevice() const { return _device; } protected: - virtual ~Fence(); + ~Fence() override; VkFence _vkFence; Semaphores _dependentSemaphores; diff --git a/include/vsg/vk/Framebuffer.h b/include/vsg/vk/Framebuffer.h index f9daca0283..e09db28f48 100644 --- a/include/vsg/vk/Framebuffer.h +++ b/include/vsg/vk/Framebuffer.h @@ -43,7 +43,7 @@ namespace vsg VkExtent2D extent2D() const { return VkExtent2D{_width, _height}; } protected: - virtual ~Framebuffer(); + ~Framebuffer() override; VkFramebuffer _framebuffer; ref_ptr _device; diff --git a/include/vsg/vk/Instance.h b/include/vsg/vk/Instance.h index c863a99923..965df75c8d 100644 --- a/include/vsg/vk/Instance.h +++ b/include/vsg/vk/Instance.h @@ -90,7 +90,7 @@ namespace vsg } protected: - virtual ~Instance(); + ~Instance() override; VkInstance _instance; ref_ptr _allocator; diff --git a/include/vsg/vk/MemoryBufferPools.h b/include/vsg/vk/MemoryBufferPools.h index 765b2315ac..d6c27ebfa7 100644 --- a/include/vsg/vk/MemoryBufferPools.h +++ b/include/vsg/vk/MemoryBufferPools.h @@ -57,6 +57,8 @@ namespace vsg VkResult reserve(ResourceRequirements& requirements); + void report(LogOutput& out) const; + protected: mutable std::mutex _mutex; diff --git a/include/vsg/vk/PhysicalDevice.h b/include/vsg/vk/PhysicalDevice.h index b5f27f805e..6ecf2566e6 100644 --- a/include/vsg/vk/PhysicalDevice.h +++ b/include/vsg/vk/PhysicalDevice.h @@ -81,8 +81,7 @@ namespace vsg protected: // use Instance::getDevice(..) to create PhysicalDevice PhysicalDevice(Instance* instance, VkPhysicalDevice device); - - virtual ~PhysicalDevice(); + ~PhysicalDevice() override; friend class Instance; diff --git a/include/vsg/vk/Queue.h b/include/vsg/vk/Queue.h index 8f53140ae2..be4d04cf8b 100644 --- a/include/vsg/vk/Queue.h +++ b/include/vsg/vk/Queue.h @@ -44,7 +44,7 @@ namespace vsg protected: Queue(VkQueue queue, VkQueueFlags queueFlags, uint32_t queueFamilyIndex, uint32_t queueIndex); - virtual ~Queue(); + ~Queue() override; Queue() = delete; Queue(const Queue&) = delete; diff --git a/include/vsg/vk/RenderPass.h b/include/vsg/vk/RenderPass.h index dd9af0cbb0..02d988048b 100644 --- a/include/vsg/vk/RenderPass.h +++ b/include/vsg/vk/RenderPass.h @@ -107,7 +107,7 @@ namespace vsg const VkSampleCountFlagBits maxSamples; protected: - virtual ~RenderPass(); + ~RenderPass() override; /// Vulkan renderPass handle, created in RenderPass constructor. VkRenderPass _renderPass; diff --git a/include/vsg/vk/Semaphore.h b/include/vsg/vk/Semaphore.h index 14ce5438cc..6be180dcd0 100644 --- a/include/vsg/vk/Semaphore.h +++ b/include/vsg/vk/Semaphore.h @@ -36,7 +36,7 @@ namespace vsg const Device* getDevice() const { return _device; } protected: - virtual ~Semaphore(); + ~Semaphore() override; VkSemaphore _semaphore; VkPipelineStageFlags _pipelineStageFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; diff --git a/include/vsg/vk/Slots.h b/include/vsg/vk/Slots.h index 410cfaedb9..9f9e5a8f09 100644 --- a/include/vsg/vk/Slots.h +++ b/include/vsg/vk/Slots.h @@ -29,11 +29,18 @@ namespace vsg return view > state ? view : state; } - void merge(const Slots& rhs) + /// update this Slots object to hold the maximum state and view value of this and rhs Slots objects. + void update(const Slots& rhs) { if (rhs.state > state) state = rhs.state; if (rhs.view > view) view = rhs.view; } + + /// return true if this Slots object is less that rhs Slots object and needs to be updated by calling this Slots::merge(rhs). + bool requiresUpdate(const Slots& rhs) const + { + return rhs.state > state || rhs.view > view; + } }; } // namespace vsg diff --git a/include/vsg/vk/Surface.h b/include/vsg/vk/Surface.h index 61455b58b9..7e2000e035 100644 --- a/include/vsg/vk/Surface.h +++ b/include/vsg/vk/Surface.h @@ -39,7 +39,7 @@ namespace vsg } protected: - virtual ~Surface(); + ~Surface() override; VkSurfaceKHR _surface; ref_ptr _instance; diff --git a/include/vsg/vk/Swapchain.h b/include/vsg/vk/Swapchain.h index 97d3f4c821..6f5114f879 100644 --- a/include/vsg/vk/Swapchain.h +++ b/include/vsg/vk/Swapchain.h @@ -60,7 +60,7 @@ namespace vsg VkResult acquireNextImage(uint64_t timeout, ref_ptr semaphore, ref_ptr fence, uint32_t& imageIndex); protected: - virtual ~Swapchain(); + ~Swapchain() override; vsg::ref_ptr _device; vsg::ref_ptr _surface; diff --git a/include/vsg/vk/vk_buffer.h b/include/vsg/vk/vk_buffer.h index eb4833022c..4a2b9418b0 100644 --- a/include/vsg/vk/vk_buffer.h +++ b/include/vsg/vk/vk_buffer.h @@ -32,7 +32,7 @@ namespace vsg T& operator[](uint32_t) { return value; } const T& operator[](uint32_t) const { return value; } - uint32_t size() const { return 1; } + constexpr static uint32_t size() { return 1; } void clear() { value = {}; } diff --git a/include/vsg/vk/vulkan.h b/include/vsg/vk/vulkan.h index 2c25d49214..1afa8e30ce 100644 --- a/include/vsg/vk/vulkan.h +++ b/include/vsg/vk/vulkan.h @@ -149,6 +149,12 @@ typedef struct VkMemoryPriorityAllocateInfoEXT { float priority; } VkMemoryPriorityAllocateInfoEXT; + +#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_EXT VkStructureType(1000202000) +#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT VkStructureType(1000202001) +#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT VkStructureType(1000237000) +#define VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT VkStructureType(1000247000) + #endif //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -287,6 +293,49 @@ typedef struct VkPhysicalDeviceFloatControlsPropertiesKHR VkBool32 shaderRoundingModeRTZFloat64; } VkPhysicalDeviceFloatControlsPropertiesKHR; +#endif + +#ifndef VK_EXT_validation_features + +#define VK_EXT_validation_features 1 +#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 4 +#define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" + +typedef enum VkValidationFeatureEnableEXT { + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, + VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, + VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, + VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4, + VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureEnableEXT; + +typedef enum VkValidationFeatureDisableEXT { + VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0, + VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1, + VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2, + VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3, + VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4, + VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5, + VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6, + VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF +} VkValidationFeatureDisableEXT; +typedef struct VkValidationFeaturesEXT { + VkStructureType sType; + const void* pNext; + uint32_t enabledValidationFeatureCount; + const VkValidationFeatureEnableEXT* pEnabledValidationFeatures; + uint32_t disabledValidationFeatureCount; + const VkValidationFeatureDisableEXT* pDisabledValidationFeatures; +} VkValidationFeaturesEXT; + +#else + +#if (VK_EXT_VALIDATION_FEATURES_SPEC_VERSION < 4) +#define VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT static_cast(4) +#endif + + #endif //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -306,13 +355,6 @@ typedef struct VkPhysicalDeviceBufferDeviceAddressFeaturesEXT VkBool32 bufferDeviceAddressCaptureReplay; VkBool32 bufferDeviceAddressMultiDevice; } VkPhysicalDeviceBufferDeviceAddressFeaturesEXT; -#endif - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Definitions not provided prior to 1.1.106 -// -#if VK_HEADER_VERSION < 105 #define VK_EXT_host_query_reset 1 #define VK_EXT_HOST_QUERY_RESET_SPEC_VERSION 1 @@ -325,9 +367,6 @@ typedef struct VkPhysicalDeviceHostQueryResetFeaturesEXT { typedef void (VKAPI_PTR *PFN_vkResetQueryPoolEXT)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount); - - - #endif //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -382,10 +421,6 @@ typedef enum VkDescriptorBindingFlagBits { VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002, VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004, VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008, - VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, - VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, - VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, - VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT, VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VkDescriptorBindingFlagBits; typedef VkFlags VkDescriptorBindingFlags; @@ -573,47 +608,6 @@ typedef enum VkRayTracingShaderGroupTypeKHR #endif - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Definitions not provided prior to 1.2.150 -// -#if VK_HEADER_VERSION < 150 - -#define VK_EXT_validation_features 1 -#define VK_EXT_VALIDATION_FEATURES_SPEC_VERSION 4 -#define VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME "VK_EXT_validation_features" - -typedef enum VkValidationFeatureEnableEXT { - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT = 0, - VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT = 1, - VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT = 2, - VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT = 3, - VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT = 4, - VK_VALIDATION_FEATURE_ENABLE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkValidationFeatureEnableEXT; - -typedef enum VkValidationFeatureDisableEXT { - VK_VALIDATION_FEATURE_DISABLE_ALL_EXT = 0, - VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT = 1, - VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT = 2, - VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT = 3, - VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT = 4, - VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT = 5, - VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT = 6, - VK_VALIDATION_FEATURE_DISABLE_MAX_ENUM_EXT = 0x7FFFFFFF -} VkValidationFeatureDisableEXT; -typedef struct VkValidationFeaturesEXT { - VkStructureType sType; - const void* pNext; - uint32_t enabledValidationFeatureCount; - const VkValidationFeatureEnableEXT* pEnabledValidationFeatures; - uint32_t disabledValidationFeatureCount; - const VkValidationFeatureDisableEXT* pDisabledValidationFeatures; -} VkValidationFeaturesEXT; - -#endif - //////////////////////////////////////////////////////////////////////////////////////////////////// // // Definitions not provided prior to 1.2.162 @@ -903,7 +897,7 @@ typedef VkResult(VKAPI_PTR* PFN_vkCreateRenderPass2KHR_Compatibility)(VkDevice d typedef VkDeviceAddress(VKAPI_PTR* PFN_vkGetBufferDeviceAddressKHR_Compatibility)(VkDevice device, const VkBufferDeviceAddressInfo* pInfo); // -// Definitions not provided prior to 1.3.211 +// Definitions not provided prior to 1.3.204 // #if VK_HEADER_VERSION < 204 #define VK_API_VERSION_1_3 VK_MAKE_VERSION(1, 3, 0) diff --git a/src/vsg/animation/CameraSampler.cpp b/src/vsg/animation/CameraSampler.cpp index 1aaa146e58..1a222a8b55 100644 --- a/src/vsg/animation/CameraSampler.cpp +++ b/src/vsg/animation/CameraSampler.cpp @@ -45,6 +45,19 @@ void CameraKeyframes::read(Input& input) input.readObjects("path", track.value); } + if (input.version_greater_equal(1, 1, 15)) + { + // read origin key frames + uint32_t num_origins = input.readValue("origins"); + origins.resize(num_origins); + for (auto& origin : origins) + { + input.matchPropertyName("origin"); + input.read(1, &origin.time); + input.read(1, &origin.value); + } + } + // read position key frames uint32_t num_positions = input.readValue("positions"); positions.resize(num_positions); @@ -103,6 +116,19 @@ void CameraKeyframes::write(Output& output) const output.writeObjects("path", track.value); } + if (output.version_greater_equal(1, 1, 15)) + { + // write origin key frames + output.writeValue("origins", origins.size()); + for (const auto& origin : origins) + { + output.writePropertyName("origin"); + output.write(1, &origin.time); + output.write(1, &origin.value); + output.writeEndOfLine(); + } + } + // write position key frames output.writeValue("positions", positions.size()); for (const auto& position : positions) @@ -123,15 +149,6 @@ void CameraKeyframes::write(Output& output) const output.writeEndOfLine(); } - // write scale key frames - for (const auto& scale : fieldOfViews) - { - output.writePropertyName("fov"); - output.write(1, &scale.time); - output.write(1, &scale.value); - output.writeEndOfLine(); - } - // write field of view key frames output.writeValue("fieldOfViews", fieldOfViews.size()); for (const auto& fov : fieldOfViews) diff --git a/src/vsg/app/CompileManager.cpp b/src/vsg/app/CompileManager.cpp index cdd28de2ad..0db9a10a58 100644 --- a/src/vsg/app/CompileManager.cpp +++ b/src/vsg/app/CompileManager.cpp @@ -21,6 +21,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI using namespace vsg; +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// CompileResult +// void CompileResult::reset() { result = VK_INCOMPLETE; @@ -37,7 +41,7 @@ void CompileResult::add(const CompileResult& cr) result = cr.result; } - maxSlots.merge(cr.maxSlots); + maxSlots.update(cr.maxSlots); if (!containsPagedLOD) containsPagedLOD = cr.containsPagedLOD; @@ -50,10 +54,10 @@ void CompileResult::add(const CompileResult& cr) binDetails.bins.insert(src_binDetails.bins.begin(), src_binDetails.bins.end()); } - dynamicData.add(dynamicData); + dynamicData.add(cr.dynamicData); } -bool CompileResult::requiresViewerUpdate() const +bool CompileResult::requiresViewerUpdate(const Viewer* viewer) const { if (result == VK_INCOMPLETE) return false; @@ -63,9 +67,66 @@ bool CompileResult::requiresViewerUpdate() const { if (!binDetails.indices.empty() || !binDetails.bins.empty()) return true; } + + if (viewer) + { + for (const auto& task : viewer->recordAndSubmitTasks) + { + for (const auto& commandGraph : task->commandGraphs) + { + if (commandGraph->maxSlots.requiresUpdate(maxSlots)) return true; + } + } + } + return false; } +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// CompileManager +// + +ResourceScavenger::ResourceScavenger(ref_ptr in_databasePager) : + databasePager(in_databasePager) +{ +} + +bool ResourceScavenger::scavenge(ResourceRequirements& /*resourceRequirements*/) +{ + bool scavenged = false; + + // get raw C pointer to avoid a database pager thread invoking scavenger and keeping the database pager alive and pausing destruction + if (auto ref_databasePager = databasePager.get()) + { + if (!ref_databasePager->status->active()) return false; + + uint32_t targetPagedLOD = ref_databasePager->pagedLODContainer->activeList.count; + if (ref_databasePager->pagedLODContainer->inactiveList.count > ref_databasePager->numActiveRequests) targetPagedLOD += ref_databasePager->pagedLODContainer->inactiveList.count - ref_databasePager->numActiveRequests; + + if (targetPagedLOD < ref_databasePager->targetMaxNumPagedLODWithHighResSubgraphs) + { + debug("ResourceScavenger::scavenge(..) resetting databasePager->targetMaxNumPagedLODWithHighResSubgraphs to ", targetPagedLOD); + + ref_databasePager->targetMaxNumPagedLODWithHighResSubgraphs = targetPagedLOD; + } + + auto before_deletedCount = ref_databasePager->deleteQueue->deletedCount.load(); + + if (sleepDuration > 0) std::this_thread::sleep_for(std::chrono::milliseconds(sleepDuration)); + + auto after_deletedCount = ref_databasePager->deleteQueue->deletedCount.load(); + + scavenged = (after_deletedCount > before_deletedCount); + } + + return scavenged; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// CompileManager +// CompileManager::CompileManager(Viewer& viewer, ref_ptr hints) { compileTraversals = CompileTraversals::create(viewer.status); @@ -84,6 +145,11 @@ CompileManager::CompileManager(Viewer& viewer, ref_ptr hints) #endif } +CompileManager::~CompileManager() +{ + vsg::debug("CompileManager::~CompileManager() successfulCompileCount= ", successfulCompileCount, ", failedCompileCount = ", failedCompileCount); +} + CompileManager::CompileTraversals::container_type CompileManager::takeCompileTraversals(size_t count) { CompileTraversals::container_type cts; @@ -167,16 +233,22 @@ CompileResult CompileManager::compile(ref_ptr object, ContextSelectionFu auto& requirements = collectRequirements.requirements; auto& viewDetailsStack = requirements.viewDetailsStack; + VkResult reserve_result = VK_INCOMPLETE; CompileResult result; result.maxSlots = requirements.maxSlots; result.containsPagedLOD = requirements.containsPagedLOD; result.views = requirements.views; result.dynamicData = requirements.dynamicData; + result.message = "Nothing assigned yet."; auto compileTraversal = compileTraversals->take_when_available(); // if no CompileTraversals are available abort compile - if (!compileTraversal) return result; + if (!compileTraversal) + { + debug("Unable to aquire compileTraversal."); + return result; + } auto run_compile_traversal = [&]() -> void { try @@ -199,9 +271,24 @@ CompileResult CompileManager::compile(ref_ptr object, ContextSelectionFu } } } + } + + for (auto& context : compileTraversal->contexts) + { + reserve_result = context->reserve(requirements); + + // vsg::info(" done reserve context->reserve() ", reserve_result); + if (reserve_result != VK_SUCCESS && resourceScavenger && resourceScavenger->scavenge(requirements)) + { + reserve_result = context->reserve(requirements); + } - auto reserveResult = context->reserve(requirements); - if (reserveResult != VK_SUCCESS) throw vsg::Exception{"Context::reserve() failed", reserveResult}; + if (reserve_result != VK_SUCCESS) + { + result.message = vsg::make_string("Context::reserve() failed", reserve_result); + result.result = reserve_result; + return; + } } object->accept(*compileTraversal); @@ -251,6 +338,15 @@ CompileResult CompileManager::compile(ref_ptr object, ContextSelectionFu compileTraversals->add(compileTraversal); + if (result.result == VK_SUCCESS) + { + ++successfulCompileCount; + } + else + { + ++failedCompileCount; + } + return result; } diff --git a/src/vsg/app/CompileTraversal.cpp b/src/vsg/app/CompileTraversal.cpp index 9eecb70761..9694c36f2a 100644 --- a/src/vsg/app/CompileTraversal.cpp +++ b/src/vsg/app/CompileTraversal.cpp @@ -189,7 +189,7 @@ void CompileTraversal::add(const Viewer& viewer, const ResourceRequirements& res ref_ptr transferTask; AddViews(CompileTraversal* in_ct, const ResourceRequirements& in_rr) : - ct(in_ct), resourceRequirements(in_rr){}; + ct(in_ct), resourceRequirements(in_rr) {}; const char* className() const noexcept override { return "vsg::CompileTraversal::AddViews"; } @@ -325,7 +325,7 @@ void CompileTraversal::apply(CommandGraph& commandGraph) for (const auto& context : contexts) { - commandGraph.maxSlots.merge(context->resourceRequirements.maxSlots); + commandGraph.maxSlots.update(context->resourceRequirements.maxSlots); } commandGraph.traverse(*this); @@ -339,7 +339,7 @@ void CompileTraversal::apply(SecondaryCommandGraph& secondaryCommandGraph) for (auto& context : contexts) { - secondaryCommandGraph.maxSlots.merge(context->resourceRequirements.maxSlots); + secondaryCommandGraph.maxSlots.update(context->resourceRequirements.maxSlots); // save previous states to be restored after traversal auto previousRenderPass = context->renderPass; diff --git a/src/vsg/app/RecordAndSubmitTask.cpp b/src/vsg/app/RecordAndSubmitTask.cpp index 8aa2a30531..d61d9685e6 100644 --- a/src/vsg/app/RecordAndSubmitTask.cpp +++ b/src/vsg/app/RecordAndSubmitTask.cpp @@ -306,7 +306,7 @@ void vsg::updateTasks(RecordAndSubmitTasks& tasks, ref_ptr compi { for (const auto& commandGraph : task->commandGraphs) { - commandGraph->maxSlots.merge(compileResult.maxSlots); + commandGraph->maxSlots.update(compileResult.maxSlots); } } diff --git a/src/vsg/app/Viewer.cpp b/src/vsg/app/Viewer.cpp index 07a599860f..3c186b14a3 100644 --- a/src/vsg/app/Viewer.cpp +++ b/src/vsg/app/Viewer.cpp @@ -92,7 +92,7 @@ void Viewer::removeWindow(ref_ptr window) CommandGraphs commandGraphs; for (const auto& task : recordAndSubmitTasks) { - for (auto& cg : task->commandGraphs) + for (const auto& cg : task->commandGraphs) { if (cg->window != window) commandGraphs.push_back(cg); } @@ -383,6 +383,7 @@ CompileResult Viewer::compile(ref_ptr hints) if (databasePager && !databasePager->compileManager) { databasePager->compileManager = compileManager; + compileManager->resourceScavenger = ResourceScavenger::create(databasePager); } for (auto& task : recordAndSubmitTasks) @@ -581,7 +582,7 @@ void Viewer::addRecordAndSubmitTaskAndPresentation(CommandGraphs commandGraphs) CommandGraphs combinedCommandGraphs; for (const auto& task : recordAndSubmitTasks) { - for (auto& cg : task->commandGraphs) + for (const auto& cg : task->commandGraphs) { combinedCommandGraphs.push_back(cg); } @@ -793,17 +794,22 @@ void Viewer::update() { CPU_INSTRUMENTATION_L1_NC(instrumentation, "Viewer update", COLOR_UPDATE); + CompileResult cr; + // merge any updates from the DatabasePager for (const auto& task : recordAndSubmitTasks) { if (task->databasePager) { - CompileResult cr; task->databasePager->updateSceneGraph(_frameStamp, cr); - if (cr.requiresViewerUpdate()) updateViewer(*this, cr); } } + if (cr.requiresViewerUpdate(this)) + { + updateViewer(*this, cr); + } + // run update operations updateOperations->run(); diff --git a/src/vsg/commands/ExecuteCommands.cpp b/src/vsg/commands/ExecuteCommands.cpp index 5aa2821563..cb17b008b0 100644 --- a/src/vsg/commands/ExecuteCommands.cpp +++ b/src/vsg/commands/ExecuteCommands.cpp @@ -71,7 +71,7 @@ void ExecuteCommands::record(CommandBuffer& commandBuffer) const std::scoped_lock lock(_mutex); std::vector vk_commandBuffers; - for (auto& entry : _commandGraphsAndBuffers) + for (const auto& entry : _commandGraphsAndBuffers) { if (entry.cb) vk_commandBuffers.push_back(*entry.cb); } diff --git a/src/vsg/core/IntrusiveAllocator.cpp b/src/vsg/core/IntrusiveAllocator.cpp index f28124898a..aac14a35bd 100644 --- a/src/vsg/core/IntrusiveAllocator.cpp +++ b/src/vsg/core/IntrusiveAllocator.cpp @@ -431,7 +431,7 @@ bool IntrusiveAllocator::MemoryBlock::deallocate(void* ptr, std::size_t /*size*/ memory[P].next += memory[C].next; if (N != 0) memory[N].previous = memory[P].next; - // freeList linked list entries will not need updating. + // freeList linked list entries will not need updating. #if DEBUG_ALLOCATOR if (!validate()) diff --git a/src/vsg/core/MemorySlots.cpp b/src/vsg/core/MemorySlots.cpp index 366801dab1..46c2d5e7e0 100644 --- a/src/vsg/core/MemorySlots.cpp +++ b/src/vsg/core/MemorySlots.cpp @@ -46,7 +46,8 @@ MemorySlots::~MemorySlots() else { info("MemorySlots::~MemorySlots() ", this, ", not all slots restored correctly."); - info_stream([&](auto& fout) { report(fout); }); + LogOutput output; + report(output); } } if (memoryTracking & MEMORY_TRACKING_CHECK_ACTIONS) @@ -98,7 +99,9 @@ bool MemorySlots::check() const if (computedSize != _totalMemorySize) { warn("MemorySlots::check() ", this, " failed, computedSize (", computedSize, ") != _totalMemorySize (", _totalMemorySize, ")"); - warn_stream([&](auto& fout) { report(fout); }); + + LogOutput output; + report(output); return false; } @@ -106,18 +109,20 @@ bool MemorySlots::check() const return true; } -void MemorySlots::report(std::ostream& out) const +void MemorySlots::report(LogOutput& out) const { - out << "MemorySlots::report() " << this << std::endl; + out.enter("MemorySlots::report(...)"); + out("MemorySlots::report() ", this); for (auto& [offset, size] : _offsetSizes) { - out << " available " << offset << ", " << size << std::endl; + out(" available ", offset, ", ", size); } for (auto& [offset, size] : _reservedMemory) { - out << " reserved " << std::dec << offset << ", " << size << std::endl; + out(" reserved ", std::dec, offset, ", ", size); } + out.leave(); } void MemorySlots::insertAvailableSlot(size_t offset, size_t size) diff --git a/src/vsg/io/DatabasePager.cpp b/src/vsg/io/DatabasePager.cpp index ee7527b172..4b3fd61da8 100644 --- a/src/vsg/io/DatabasePager.cpp +++ b/src/vsg/io/DatabasePager.cpp @@ -394,7 +394,7 @@ void DatabaseQueue::add(ref_ptr plod, const CompileResult& cr) _compileResult.add(cr); } -ref_ptr DatabaseQueue::take_when_available() +ref_ptr DatabaseQueue::take_when_available(uint64_t frameCount) { // debug("DatabaseQueue::take_when_available() A size = ", _queue.size()); @@ -419,20 +419,60 @@ ref_ptr DatabaseQueue::take_when_available() // find the PagedLOD with the highest priority; auto itr = _queue.begin(); + + size_t skipped = 0; + + // find first PagedLOD in queue that can be loaded/compiled + for (; itr != _queue.end(); ++itr) + { + if ((*itr)->frameNextLoadAttempt.load() <= frameCount) break; + ++skipped; + } + + if (itr == _queue.end()) + { + // info("DatabaseQueue::take_when_available(", frameCount, ") no suitable PagedLOD despite ", _queue.size(), " in queue."); + return {}; + } + auto highest_itr = itr++; + // find lowest priority PagedLOD in queue. for (; itr != _queue.end(); ++itr) { - if ((*itr)->priority > (*highest_itr)->priority) highest_itr = itr; + if ((*itr)->frameNextLoadAttempt.load() <= frameCount && (*itr)->priority > (*highest_itr)->priority) highest_itr = itr; } ref_ptr plod = *highest_itr; _queue.erase(highest_itr); - // debug("Returning ", plod.get(), std::dec, ", size = ", _queue.size()); + // info("DatabaseQueue::take_when_available(", frameCount, ") plod = ", plod.get(), std::dec, ", size = ", _queue.size(), " after skipping ", skipped); return plod; } +uint32_t DatabaseQueue::prune(uint64_t frameCount) +{ + std::unique_lock lock(_mutex); + + uint32_t numRemoved = 0; + for (auto itr = _queue.begin(); itr != _queue.end();) + { + if (((*itr)->frameHighResLastUsed.load() + 1) < frameCount) + { + // info("pruning ", *itr, ", lastUsed = ", (*itr)->frameHighResLastUsed.load(), " vs ", frameCount, " after ", (*itr)->loadAttempts.load(), " loadAttempts"); + ++numRemoved; + (*itr)->requestCount.exchange(0); + (*itr)->requestStatus.exchange(PagedLOD::NoRequest); + itr = _queue.erase(itr); + } + else + { + ++itr; + } + } + return numRemoved; +} + DatabaseQueue::Nodes DatabaseQueue::take_all(CompileResult& cr) { std::scoped_lock lock(_mutex); @@ -449,13 +489,13 @@ DatabaseQueue::Nodes DatabaseQueue::take_all(CompileResult& cr) // DatabasePager::DatabasePager() { - if (!_status) _status = ActivityStatus::create(); + if (!status) status = ActivityStatus::create(); culledPagedLODs = CulledPagedLODs::create(); - _requestQueue = DatabaseQueue::create(_status); - _toMergeQueue = DatabaseQueue::create(_status); - _deleteQueue = DeleteQueue::create(_status); + _requestQueue = DatabaseQueue::create(status); + _toMergeQueue = DatabaseQueue::create(status); + deleteQueue = DeleteQueue::create(status); pagedLODContainer = PagedLODContainer::create(4000); } @@ -464,7 +504,7 @@ DatabasePager::~DatabasePager() { debug("DatabasePager::~DatabasePager()"); - _status->set(false); + status->set(false); for (auto& thread : threads) { @@ -484,29 +524,43 @@ void DatabasePager::start(uint32_t numReadThreads) // // set up read thread(s) // - auto readThread = [](ref_ptr requestQueue, ref_ptr status, DatabasePager& databasePager, const std::string& threadName) { + auto readThread = [](DatabasePager& databasePager, const std::string& threadName) { debug("Started DatabaseThread read thread"); auto local_instrumentation = shareOrDuplicateForThreadSafety(databasePager.instrumentation); if (local_instrumentation) local_instrumentation->setThreadName(threadName); - while (status->active()) + while (databasePager.status->active()) { - auto plod = requestQueue->take_when_available(); + auto plod = databasePager._requestQueue->take_when_available(databasePager.frameCount.load()); if (plod) { CPU_INSTRUMENTATION_L1_NC(databasePager.instrumentation, "DatabasePager read", COLOR_PAGER); uint64_t frameDelta = databasePager.frameCount - plod->frameHighResLastUsed.load(); + if (frameDelta > 1 || !compare_exchange(plod->requestStatus, PagedLOD::ReadRequest, PagedLOD::Reading)) { - // debug("Expire read request"); + info("Expire read request : databasePager.frameCount = ", databasePager.frameCount, ", plod->frameHighResLastUsed.load() = ", plod->frameHighResLastUsed.load()); databasePager.requestDiscarded(plod); continue; } - auto read_object = vsg::read(plod->filename, plod->options); - auto subgraph = read_object.cast(); + ++plod->loadAttempts; + + ref_ptr subgraph = plod->pending; + ref_ptr read_object; + + if (!subgraph) + { + // vsg::info("read ", subgraph, " from ", plod->filename, " frameDelta = ", frameDelta, ", databasePager.frameCount = ", databasePager.frameCount, ", plod->frameHighResLastUsed.load() = ", plod->frameHighResLastUsed.load(), ", numActiveRequests = ", databasePager.numActiveRequests.load()); + read_object = vsg::read(plod->filename, plod->options); + subgraph = read_object.cast(); + } + else + { + // vsg::info("already read ", subgraph, " from ", plod->filename, " frameDelta = ", frameDelta, ", databasePager.frameCount = ", databasePager.frameCount, ", plod->frameHighResLastUsed.load() = ", plod->frameHighResLastUsed.load(), ", numActiveRequests = ", databasePager.numActiveRequests.load()); + } if (subgraph && compare_exchange(plod->requestStatus, PagedLOD::Reading, PagedLOD::Compiling)) { @@ -522,6 +576,8 @@ void DatabasePager::start(uint32_t numReadThreads) { plod->requestStatus.exchange(PagedLOD::MergeRequest); + // info("DatabaserPager::start() compiled ", subgraph, ", success after ", plod->loadAttempts.load(), " loadAttempts"); + // move to the merge queue; databasePager._toMergeQueue->add(plod, result); } @@ -547,56 +603,43 @@ void DatabasePager::start(uint32_t numReadThreads) databasePager.requestDiscarded(plod); } } + else + { + // sleep for a frame. + std::this_thread::sleep_for(std::chrono::milliseconds(16 * 2)); + } } debug("Finished DatabaseThread read thread"); }; - auto deleteThread = [](ref_ptr deleteQueue, ref_ptr status, const DatabasePager& databasePager, const std::string& threadName) { + auto deleteThread = [](DatabasePager& databasePager, const std::string& threadName) { debug("Started DatabaseThread deletethread"); auto local_instrumentation = shareOrDuplicateForThreadSafety(databasePager.instrumentation); if (local_instrumentation) local_instrumentation->setThreadName(threadName); - while (status->active()) + while (databasePager.status->active()) { - deleteQueue->wait_then_clear(); + databasePager.deleteQueue->wait_then_clear(); } debug("Finished DatabaseThread delete thread"); }; for (uint32_t i = 0; i < numReadThreads; ++i) { - threads.emplace_back(readThread, std::ref(_requestQueue), std::ref(_status), std::ref(*this), make_string("DatabasePager read thread ", i)); + threads.emplace_back(readThread, std::ref(*this), make_string("DatabasePager read thread ", i)); } - threads.emplace_back(deleteThread, std::ref(_deleteQueue), std::ref(_status), std::ref(*this), "DatabasePager delete thread "); + threads.emplace_back(deleteThread, std::ref(*this), "DatabasePager delete thread "); } void DatabasePager::request(ref_ptr plod) { - ++numActiveRequests; - - bool hasPending = false; + if (compare_exchange(plod->requestStatus, PagedLOD::NoRequest, PagedLOD::ReadRequest)) { - std::scoped_lock lock(pendingPagedLODMutex); - hasPending = plod->pending.valid(); - } - - if (!hasPending) - { - if (compare_exchange(plod->requestStatus, PagedLOD::NoRequest, PagedLOD::ReadRequest)) - { - // debug("DatabasePager::request(", plod.get(), ") adding to requestQueue ", plod->filename, ", ", plod->priority, " plod=", plod.get()); - _requestQueue->add(plod); - } - else - { - // debug("Attempted DatabasePager::request(", plod.get(), ") but plod.requestState() = ", plod->requestStatus.load(), " is not NoRequest"); - } - } - else - { - // debug("Attempted DatabasePager::request(", plod.get(), ") but plod.pending is not null."); + debug("DatabasePager::request(", plod.get(), ") adding to requestQueue ", plod->filename, ", ", plod->priority, " plod=", plod.get()); + _requestQueue->add(plod); + ++numActiveRequests; } } @@ -606,7 +649,11 @@ void DatabasePager::requestDiscarded(PagedLOD* plod) //plod->pending = nullptr; plod->requestCount.exchange(0); plod->requestStatus.exchange(PagedLOD::NoRequest); - plod->pending = {}; + + // plod->pending = {}; + + plod->frameNextLoadAttempt = frameCount.load() + delayBeforeNextLoadAttempt; + --numActiveRequests; } @@ -615,7 +662,9 @@ void DatabasePager::updateSceneGraph(ref_ptr frameStamp, CompileResu CPU_INSTRUMENTATION_L1(instrumentation); frameCount.exchange(frameStamp ? frameStamp->frameCount : 0); - _deleteQueue->advance(frameStamp); + deleteQueue->advance(frameStamp); + + numActiveRequests -= _requestQueue->prune(frameCount.load()); auto nodes = _toMergeQueue->take_all(cr); @@ -739,5 +788,5 @@ void DatabasePager::updateSceneGraph(ref_ptr frameStamp, CompileResu debug("DatabasePager::updateSceneGraph() nothing to merge"); } - if (!deleteList.empty() || !sharedObjectsToPrune.empty()) _deleteQueue->add_prune(deleteList, sharedObjectsToPrune); + if (!deleteList.empty() || !sharedObjectsToPrune.empty()) deleteQueue->add_prune(deleteList, sharedObjectsToPrune); } diff --git a/src/vsg/io/JSONParser.cpp b/src/vsg/io/JSONParser.cpp index dee3ee2872..770a707ff4 100644 --- a/src/vsg/io/JSONParser.cpp +++ b/src/vsg/io/JSONParser.cpp @@ -370,7 +370,7 @@ void JSONParser::read_object(JSONParser::Schema& schema) break; } - // make sure next charater is the {name : value} deliminator + // make sure next character is the {name : value} deliminator if (buffer[pos] != ':') { warning("read_object() deliminator error buffer[", pos, "] = ", buffer[pos]); diff --git a/src/vsg/io/json.cpp b/src/vsg/io/json.cpp index 0476c1c87d..d5be3bafdd 100644 --- a/src/vsg/io/json.cpp +++ b/src/vsg/io/json.cpp @@ -75,11 +75,11 @@ ref_ptr json::_read(std::istream& fin, ref_ptr) const warn("Parsing error, could not find opening { or [."); } - if ( !parser.warnings.empty() ) + if (!parser.warnings.empty()) { - warn( "JSONParser recorded following warnings:" ); - for ( auto w : parser.warnings ) - warn( "\t", w ); + warn("JSONParser recorded following warnings:"); + for (auto w : parser.warnings) + warn("\t", w); } return result; } diff --git a/src/vsg/lighting/AmbientLight.cpp b/src/vsg/lighting/AmbientLight.cpp index 6878dc4490..72f59aaf58 100644 --- a/src/vsg/lighting/AmbientLight.cpp +++ b/src/vsg/lighting/AmbientLight.cpp @@ -22,13 +22,3 @@ AmbientLight::AmbientLight(const AmbientLight& rhs, const CopyOp& copyop) : Inherit(rhs, copyop) { } - -void AmbientLight::read(Input& input) -{ - Light::read(input); -} - -void AmbientLight::write(Output& output) const -{ - Light::write(output); -} diff --git a/src/vsg/lighting/HardShadows.cpp b/src/vsg/lighting/HardShadows.cpp index bdd702c9f6..f9811747dc 100644 --- a/src/vsg/lighting/HardShadows.cpp +++ b/src/vsg/lighting/HardShadows.cpp @@ -23,18 +23,3 @@ HardShadows::HardShadows(const HardShadows& rhs, const CopyOp& copyop) : Inherit(rhs, copyop) { } - -int HardShadows::compare(const Object& rhs_object) const -{ - return ShadowSettings::compare(rhs_object); -} - -void HardShadows::read(Input& input) -{ - ShadowSettings::read(input); -} - -void HardShadows::write(Output& output) const -{ - ShadowSettings::write(output); -} diff --git a/src/vsg/lighting/PercentageCloserSoftShadows.cpp b/src/vsg/lighting/PercentageCloserSoftShadows.cpp index 85de950484..ede15efdcd 100644 --- a/src/vsg/lighting/PercentageCloserSoftShadows.cpp +++ b/src/vsg/lighting/PercentageCloserSoftShadows.cpp @@ -23,18 +23,3 @@ PercentageCloserSoftShadows::PercentageCloserSoftShadows(const PercentageCloserS Inherit(rhs, copyop) { } - -int PercentageCloserSoftShadows::compare(const Object& rhs_object) const -{ - return ShadowSettings::compare(rhs_object); -} - -void PercentageCloserSoftShadows::read(Input& input) -{ - ShadowSettings::read(input); -} - -void PercentageCloserSoftShadows::write(Output& output) const -{ - ShadowSettings::write(output); -} diff --git a/src/vsg/meshshaders/DrawMeshTasks.cpp b/src/vsg/meshshaders/DrawMeshTasks.cpp index da2bca13cc..df6e13430c 100644 --- a/src/vsg/meshshaders/DrawMeshTasks.cpp +++ b/src/vsg/meshshaders/DrawMeshTasks.cpp @@ -43,7 +43,7 @@ void DrawMeshTasks::write(Output& output) const void DrawMeshTasks::record(vsg::CommandBuffer& commandBuffer) const { - Device* device = commandBuffer.getDevice(); + auto device = commandBuffer.getDevice(); auto extensions = device->getExtensions(); extensions->vkCmdDrawMeshTasksEXT(commandBuffer, groupCountX, groupCountY, groupCountZ); } diff --git a/src/vsg/meshshaders/DrawMeshTasksIndirect.cpp b/src/vsg/meshshaders/DrawMeshTasksIndirect.cpp index 3e0a6a60e4..cd0a49a186 100644 --- a/src/vsg/meshshaders/DrawMeshTasksIndirect.cpp +++ b/src/vsg/meshshaders/DrawMeshTasksIndirect.cpp @@ -72,7 +72,7 @@ void DrawMeshTasksIndirect::compile(Context& context) void DrawMeshTasksIndirect::record(vsg::CommandBuffer& commandBuffer) const { - Device* device = commandBuffer.getDevice(); + auto device = commandBuffer.getDevice(); auto extensions = device->getExtensions(); extensions->vkCmdDrawMeshTasksIndirectEXT(commandBuffer, drawParameters->buffer->vk(commandBuffer.deviceID), drawParameters->offset, drawCount, stride); } diff --git a/src/vsg/meshshaders/DrawMeshTasksIndirectCount.cpp b/src/vsg/meshshaders/DrawMeshTasksIndirectCount.cpp index c8e7e53c17..ab7c18462f 100644 --- a/src/vsg/meshshaders/DrawMeshTasksIndirectCount.cpp +++ b/src/vsg/meshshaders/DrawMeshTasksIndirectCount.cpp @@ -83,7 +83,7 @@ void DrawMeshTasksIndirectCount::compile(Context& context) void DrawMeshTasksIndirectCount::record(vsg::CommandBuffer& commandBuffer) const { - Device* device = commandBuffer.getDevice(); + auto device = commandBuffer.getDevice(); auto extensions = device->getExtensions(); extensions->vkCmdDrawMeshTasksIndirectCountEXT(commandBuffer, drawParameters->buffer->vk(commandBuffer.deviceID), drawParameters->offset, drawCount->buffer->vk(commandBuffer.deviceID), drawCount->offset, maxDrawCount, stride); } diff --git a/src/vsg/nodes/Transform.cpp b/src/vsg/nodes/Transform.cpp index 52cc4cb362..ae70dd756d 100644 --- a/src/vsg/nodes/Transform.cpp +++ b/src/vsg/nodes/Transform.cpp @@ -38,9 +38,13 @@ int Transform::compare(const Object& rhs_object) const void Transform::read(Input& input) { Group::read(input); + + // subclasses currently serialize subgraphRequiresLocalFrustum } void Transform::write(Output& output) const { Group::write(output); + + // subclasses currently serialize subgraphRequiresLocalFrustum } diff --git a/src/vsg/platform/macos/MacOS_Window.mm b/src/vsg/platform/macos/MacOS_Window.mm index 8b0da4bea9..4df5927d08 100644 --- a/src/vsg/platform/macos/MacOS_Window.mm +++ b/src/vsg/platform/macos/MacOS_Window.mm @@ -708,10 +708,58 @@ void createApplicationMenus(void) } MacOS_Window::MacOS_Window(vsg::ref_ptr traits) : - Inherit(traits) + Inherit(traits), + _window(nil), + _view(nil), + _metalLayer(nil) { _keyboard = new KeyboardMap; + // When nativeWindow is set, embed into the provided NSView rather than + // creating a standalone NSWindow. This mirrors Win32_Window's handling + // of an external HWND. + if (traits->nativeWindow.has_value()) + { + auto nativeHandle = std::any_cast(traits->nativeWindow); + if (nativeHandle) + { + NSView* externalView = reinterpret_cast(nativeHandle); + _view = (vsg_MacOS_NSView*)externalView; + [_view setWantsLayer:YES]; + + _metalLayer = (CAMetalLayer*)[_view layer]; + if (!_metalLayer || ![_metalLayer isKindOfClass:[CAMetalLayer class]]) + { + _metalLayer = [[CAMetalLayer alloc] init]; + if (!_metalLayer) + { + throw Exception{"Error: vsg::MacOS_Window::MacOS_Window(...) failed to create CAMetalLayer for embedded view.", VK_ERROR_INVALID_EXTERNAL_HANDLE}; + } + [_view setLayer:_metalLayer]; + } + + auto devicePixelScale = _traits->hdpi ? [[_view window] backingScaleFactor] : 1.0f; + [_metalLayer setContentsScale:devicePixelScale]; + + uint32_t finalwidth = traits->width * devicePixelScale; + uint32_t finalheight = traits->height * devicePixelScale; + + if (traits->device) share(traits->device); + + _extent2D.width = finalwidth; + _extent2D.height = finalheight; + + _first_macos_timestamp = [[NSProcessInfo processInfo] systemUptime]; + _first_macos_time_point = vsg::clock::now(); + + vsg::clock::time_point event_time = vsg::clock::now(); + bufferedEvents.emplace_back(vsg::ConfigureWindowEvent::create(this, event_time, _traits->x, _traits->y, finalwidth, finalheight)); + + return; + } + } + + // Standalone window path NSRect contentRect = NSMakeRect(0, 0, traits->width, traits->height); NSWindowStyleMask styleMask = 0; @@ -822,16 +870,20 @@ void createApplicationMenus(void) bool MacOS_Window::pollEvents(vsg::UIEvents& events) { - for (;;) + // Skip NSApp event polling when embedded — the host owns the event loop. + if (_window) { - NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (event == nil) - break; - - [NSApp sendEvent:event]; + for (;;) + { + NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + if (event == nil) + break; + + [NSApp sendEvent:event]; + } } return Window::pollEvents(events); @@ -841,7 +893,8 @@ void createApplicationMenus(void) { const NSRect contentRect = [_view frame]; - auto devicePixelScale = _traits->hdpi ? [_window backingScaleFactor] : 1.0f; + NSWindow* hostWindow = _window ? _window : [_view window]; + auto devicePixelScale = _traits->hdpi ? [hostWindow backingScaleFactor] : 1.0f; //[_metalLayer setContentsScale:devicePixelScale]; _extent2D.width = contentRect.size.width * devicePixelScale; diff --git a/src/vsg/state/BufferInfo.cpp b/src/vsg/state/BufferInfo.cpp index 58246d9249..7b4c8af496 100644 --- a/src/vsg/state/BufferInfo.cpp +++ b/src/vsg/state/BufferInfo.cpp @@ -84,7 +84,7 @@ void BufferInfo::take(BufferInfo& src) if (buffer && !parent) { - bool identical = (buffer==src.buffer && offset==src.offset && range==src.range); + bool identical = (buffer == src.buffer && offset == src.offset && range == src.range); if (!identical) { @@ -106,7 +106,6 @@ void BufferInfo::take(BufferInfo& src) src.range = 0; } - void BufferInfo::release() { if (parent) @@ -225,7 +224,6 @@ bool vsg::createBufferAndTransferData(Context& context, const BufferInfoList& bu else if (usage == VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) alignment = device->getPhysicalDevice()->getProperties().limits.minStorageBufferOffsetAlignment; - debug("vsg::createBufferAndTransferData(Context& context, const BufferInfoList& bufferInfoList, VkBufferUsageFlags usage, VkSharingMode sharingMode) usage = ", usage, ", alignment = ", alignment); //transferTask = nullptr; diff --git a/src/vsg/state/ColorBlendState.cpp b/src/vsg/state/ColorBlendState.cpp index 105f50ea37..eb9993dca5 100644 --- a/src/vsg/state/ColorBlendState.cpp +++ b/src/vsg/state/ColorBlendState.cpp @@ -85,7 +85,7 @@ int ColorBlendState::compare(const Object& rhs_object) const if ((result = compare_value(logicOpEnable, rhs.logicOpEnable))) return result; if ((result = compare_value(logicOp, rhs.logicOp))) return result; if ((result = compare_value_container(attachments, rhs.attachments))) return result; - return compare_values(blendConstants, rhs.blendConstants, 3); + return compare_values(blendConstants, rhs.blendConstants, 4); } void ColorBlendState::read(Input& input) diff --git a/src/vsg/state/DescriptorBuffer.cpp b/src/vsg/state/DescriptorBuffer.cpp index 3d3ad666e7..3bbd0295e9 100644 --- a/src/vsg/state/DescriptorBuffer.cpp +++ b/src/vsg/state/DescriptorBuffer.cpp @@ -140,7 +140,7 @@ void DescriptorBuffer::compile(Context& context) VkDeviceSize totalSize = 0; - debug("DescriptorBuffer::compile() bufferUsageFlags = ",bufferUsageFlags, ", alignment = ", alignment); + debug("DescriptorBuffer::compile() bufferUsageFlags = ", bufferUsageFlags, ", alignment = ", alignment); // compute the total size of BufferInfo that needs to be allocated. { diff --git a/src/vsg/state/Image.cpp b/src/vsg/state/Image.cpp index 923557cc12..0cd45d04d1 100644 --- a/src/vsg/state/Image.cpp +++ b/src/vsg/state/Image.cpp @@ -161,7 +161,7 @@ VkResult Image::allocateAndBindMemory(Device* device, VkMemoryPropertyFlags memo auto [allocated, offset] = memory->reserve(memRequirements.size); if (!allocated) { - throw Exception{"Error: Failed to allocate DeviceMemory."}; + throw Exception{"Error: vsg::Image::allocateAndBindMemory() Failed to allocate DeviceMemory."}; } return bind(memory, offset); diff --git a/src/vsg/state/ShaderModule.cpp b/src/vsg/state/ShaderModule.cpp index e3f566e0e3..2a666ba3a6 100644 --- a/src/vsg/state/ShaderModule.cpp +++ b/src/vsg/state/ShaderModule.cpp @@ -40,7 +40,7 @@ ShaderCompileSettings::ShaderCompileSettings(const ShaderCompileSettings& rhs, c { } -int ShaderCompileSettings::compare(const Object& rhs_object) const +int ShaderCompileSettings::compare_except_defines(const Object& rhs_object) const { int result = Object::compare(rhs_object); if (result != 0) return result; @@ -54,7 +54,15 @@ int ShaderCompileSettings::compare(const Object& rhs_object) const if ((result = compare_value(target, rhs.target))) return result; if ((result = compare_value(forwardCompatible, rhs.forwardCompatible))) return result; if ((result = compare_value(generateDebugInfo, rhs.generateDebugInfo))) return result; - if ((result = compare_value(optimize, rhs.optimize))) return result; + return compare_value(optimize, rhs.optimize); +} + +int ShaderCompileSettings::compare(const Object& rhs_object) const +{ + int result = compare_except_defines(rhs_object); + if (result != 0) return result; + + const auto& rhs = static_cast(rhs_object); return compare_container(defines, rhs.defines); } diff --git a/src/vsg/state/ViewDependentState.cpp b/src/vsg/state/ViewDependentState.cpp index 984664b316..0d194f9fbc 100644 --- a/src/vsg/state/ViewDependentState.cpp +++ b/src/vsg/state/ViewDependentState.cpp @@ -421,7 +421,7 @@ void ViewDependentState::update(ResourceRequirements& requirements) { if (preRenderCommandGraph) { - preRenderCommandGraph->maxSlots.merge(requirements.maxSlots); + preRenderCommandGraph->maxSlots.update(requirements.maxSlots); } } @@ -658,7 +658,7 @@ void ViewDependentState::traverse(RecordTraversal& rt) const dbox eyeSpaceRegionBounds; for (auto& [mv, regionOfInterest] : rt.regionsOfInterest) { - for (auto& v : regionOfInterest->points) + for (const auto& v : regionOfInterest->points) { eyeSpaceRegionBounds.add(mv * v); } diff --git a/src/vsg/threading/DeleteQueue.cpp b/src/vsg/threading/DeleteQueue.cpp index 8165842082..df97f8155e 100644 --- a/src/vsg/threading/DeleteQueue.cpp +++ b/src/vsg/threading/DeleteQueue.cpp @@ -41,7 +41,7 @@ void DeleteQueue::advance(ref_ptr frameStamp) } } -void DeleteQueue::wait_then_clear() +size_t DeleteQueue::wait_then_clear() { ObjectsToDelete objectsToDelete; std::list> sharedObjectsToPrune; @@ -77,29 +77,45 @@ void DeleteQueue::wait_then_clear() } sharedObjectsToPrune.clear(); } + + deletedCount += numObjectsToDelete; + + return numObjectsToDelete; } -void DeleteQueue::clear() +size_t DeleteQueue::clear() { ObjectsToDelete objectsToDelete; + std::list> sharedObjectsToPrune; // use a swap of the container to keep the time the mutex is acquired as short as possible { std::scoped_lock lock(_mutex); - objectsToDelete.swap(objectsToDelete); + + auto last_itr = std::find_if(_objectsToDelete.begin(), _objectsToDelete.end(), [&](const ObjectToDelete& otd) { return otd.frameCount > frameCount; }); + + // use a swap of the container to keep the time the mutex is acquired as short as possible + objectsToDelete.splice(objectsToDelete.end(), _objectsToDelete, _objectsToDelete.begin(), last_itr); + + sharedObjectsToPrune.swap(_sharedObjectsToPrune); } size_t numObjectsToDelete = objectsToDelete.size(); //vsg::info("DeleteQueue::clear(), releasing ", nodesToRelease.size()); + objectsToDelete.clear(); if (numObjectsToDelete > 0) { - for (auto& sharedObjects : _sharedObjectsToPrune) + for (auto& sharedObjects : sharedObjectsToPrune) { sharedObjects->prune(); } - _sharedObjectsToPrune.clear(); + sharedObjectsToPrune.clear(); } + + deletedCount += numObjectsToDelete; + + return numObjectsToDelete; } diff --git a/src/vsg/ui/FrameStamp.cpp b/src/vsg/ui/FrameStamp.cpp index cc62e02ce1..c270b511d9 100644 --- a/src/vsg/ui/FrameStamp.cpp +++ b/src/vsg/ui/FrameStamp.cpp @@ -22,7 +22,6 @@ FrameStamp::FrameStamp(const FrameStamp& rhs, const CopyOp& copyop) : { } - void FrameStamp::read(Input& input) { Object::read(input); diff --git a/src/vsg/utils/ComputeBounds.cpp b/src/vsg/utils/ComputeBounds.cpp index 11fed2b290..a055996bca 100644 --- a/src/vsg/utils/ComputeBounds.cpp +++ b/src/vsg/utils/ComputeBounds.cpp @@ -302,7 +302,7 @@ void ComputeBounds::add(const dbox& bb) } else { - auto& matrix = matrixStack.back(); + const auto& matrix = matrixStack.back(); bounds.add(matrix * bb.min); bounds.add(matrix * dvec3(bb.max.x, bb.min.y, bb.min.z)); bounds.add(matrix * dvec3(bb.max.x, bb.max.y, bb.min.z)); @@ -323,7 +323,7 @@ void ComputeBounds::add(const dsphere& bs) } else { - auto& matrix = matrixStack.back(); + const auto& matrix = matrixStack.back(); bounds.add(matrix * dvec3(bs.center.x - bs.radius, bs.center.y - bs.radius, bs.center.z - bs.radius)); bounds.add(matrix * dvec3(bs.center.x + bs.radius, bs.center.y - bs.radius, bs.center.z - bs.radius)); bounds.add(matrix * dvec3(bs.center.x - bs.radius, bs.center.y + bs.radius, bs.center.z - bs.radius)); diff --git a/src/vsg/utils/GraphicsPipelineConfigurator.cpp b/src/vsg/utils/GraphicsPipelineConfigurator.cpp index c15e3aa99c..0a5a698272 100644 --- a/src/vsg/utils/GraphicsPipelineConfigurator.cpp +++ b/src/vsg/utils/GraphicsPipelineConfigurator.cpp @@ -535,8 +535,136 @@ int GraphicsPipelineConfigurator::compare(const Object& rhs_object) const if ((result = compare_value(baseAttributeBinding, rhs.baseAttributeBinding))) return result; if ((result = compare_pointer(shaderSet, rhs.shaderSet))) return result; - if ((result = compare_pointer(shaderHints, rhs.shaderHints))) return result; - if ((result = compare_pointer_container(inheritedState, rhs.inheritedState))) return result; + // + // defines settings for ShaderHints may not yet be in final state, so comparing them between compatible GraphicsPipelineConfigurator + // objects can lead is not returning a match when just comparing shaderHint->defines. + // To resolve this do the shint hint compare wihtout the defines, and then do the comparison of defines + // by handling both the respective descriptorConfigurator->defines and shaderHints->defines when comparing to the rhs. + // + // The compare_shaderHints, IteratorPair and Iterator structs all exist in service of this mutliset comparison. + // + + auto compare_shaderHints = [](const ref_ptr& lsh, const ref_ptr& rsh) -> int { + if (lsh == rsh) return 0; + return lsh ? (rsh ? lsh->compare_except_defines(*rsh) : 1) : (rsh ? -1 : 0); + }; + + if ((result = compare_shaderHints(shaderHints, rhs.shaderHints))) return result; + + struct IteratorPair + { + using iterator = std::set::const_iterator; + iterator itr; + iterator end; + + explicit IteratorPair(const ref_ptr& hints) + { + if (hints) + { + itr = hints->defines.begin(); + end = hints->defines.end(); + } + else + { + itr = end = {}; + } + } + + explicit IteratorPair(const ref_ptr& config) + { + if (config) + { + itr = config->defines.begin(); + end = config->defines.end(); + } + else + { + itr = end = {}; + } + } + + bool valid() const { return itr != end; } + }; + + struct Iterator + { + IteratorPair lhs; + IteratorPair rhs; + + explicit Iterator(IteratorPair in_lhs, IteratorPair in_rhs) : + lhs(in_lhs), rhs(in_rhs) {} + + bool valid() const { return lhs.valid() || rhs.valid(); } + + /// only call when valid() return true + const std::string& value() const + { + if (lhs.valid()) + { + if (rhs.valid()) + { + if (*lhs.itr < *rhs.itr) + return *lhs.itr; + else if (*rhs.itr < *lhs.itr) + return *rhs.itr; + else + return *rhs.itr; + } + else + return *lhs.itr; + } + else + return *rhs.itr; + } + + bool advance() + { + if (lhs.valid()) + { + if (rhs.valid()) + { + if (*lhs.itr < *rhs.itr) + ++lhs.itr; + else if (*rhs.itr < *lhs.itr) + ++rhs.itr; + else + { + ++lhs.itr; + ++rhs.itr; + } + } + else + ++lhs.itr; + } + else if (rhs.valid()) + ++rhs.itr; + + return valid(); + } + }; + + auto local_compare = [](Iterator ilhs, Iterator irhs) -> int { + while (ilhs.valid() && irhs.valid()) + { + const auto& lhs_value = ilhs.value(); + const auto& rhs_value = irhs.value(); + if (lhs_value < rhs_value) + return -1; + else if (lhs_value > rhs_value) + return 1; + + ilhs.advance(); + irhs.advance(); + } + + if (ilhs.valid()) return 1; + return irhs.valid() ? -1 : 0; + }; + + result = local_compare(Iterator(IteratorPair(descriptorConfigurator), IteratorPair(shaderHints)), + Iterator(IteratorPair(rhs.descriptorConfigurator), IteratorPair(rhs.shaderHints))); + + if (result) return result; return compare_pointer(descriptorConfigurator, rhs.descriptorConfigurator); } @@ -612,8 +740,6 @@ void GraphicsPipelineConfigurator::_assignInheritedSets() void GraphicsPipelineConfigurator::init() { - // if (!descriptorConfigurator) descriptorConfigurator = DescriptorConfigurator::create(shaderSet); - _assignInheritedSets(); if (descriptorConfigurator) diff --git a/src/vsg/utils/PolytopeIntersector.cpp b/src/vsg/utils/PolytopeIntersector.cpp index 14f4525b33..e5d3a04245 100644 --- a/src/vsg/utils/PolytopeIntersector.cpp +++ b/src/vsg/utils/PolytopeIntersector.cpp @@ -220,7 +220,7 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub clipspace.push_back(dplane(0.0, 0.0, 1.0, ndc_far)); // far vsg::Polytope eyespace; - for (auto& pl : clipspace) + for (const auto& pl : clipspace) { eyespace.push_back(pl * projectionMatrix); } @@ -228,7 +228,7 @@ PolytopeIntersector::PolytopeIntersector(const Camera& camera, double xMin, doub _polytopeStack.push_back(eyespace); vsg::Polytope worldspace; - for (auto& pl : eyespace) + for (const auto& pl : eyespace) { worldspace.push_back(pl * viewMatrix); } @@ -276,7 +276,7 @@ void PolytopeIntersector::pushTransform(const Transform& transform) const auto& worldspace = _polytopeStack.front(); Polytope localspace; - for (auto& pl : worldspace) + for (const auto& pl : worldspace) { localspace.push_back(pl * localToWorld); } diff --git a/src/vsg/utils/ShaderCompiler.cpp b/src/vsg/utils/ShaderCompiler.cpp index ff1364a1bb..9e79e395a4 100644 --- a/src/vsg/utils/ShaderCompiler.cpp +++ b/src/vsg/utils/ShaderCompiler.cpp @@ -281,7 +281,7 @@ bool ShaderCompiler::compile(ShaderStages& shaders, const std::vectormodule->source, options); std::vector combinedDefines(defines); - for (auto& define : settings->defines) combinedDefines.push_back(define); + for (const auto& define : settings->defines) combinedDefines.push_back(define); if (!combinedDefines.empty()) finalShaderSource = combineSourceAndDefines(finalShaderSource, combinedDefines); vsg::debug("ShaderCompiler::compile() combinedDefines = ", combinedDefines); @@ -472,8 +472,6 @@ std::string ShaderCompiler::combineSourceAndDefines(const std::string& source, c const std::string versionmatch = "#version"; const std::string importdefinesmatch = "#pragma import_defines"; - std::vector finaldefines; - for (std::string line; std::getline(iss, line);) { std::string sanitisedline = line; diff --git a/src/vsg/vk/Context.cpp b/src/vsg/vk/Context.cpp index dc4d9b8b68..38e4c5ef5b 100644 --- a/src/vsg/vk/Context.cpp +++ b/src/vsg/vk/Context.cpp @@ -201,7 +201,7 @@ VkResult Context::reserve(ResourceRequirements& requirements) if (deviceMemoryBufferPools->compileTraversalUseReserve) result = deviceMemoryBufferPools->reserve(requirements); - resourceRequirements.maxSlots.merge(requirements.maxSlots); + resourceRequirements.maxSlots.update(requirements.maxSlots); descriptorPools->reserve(requirements); diff --git a/src/vsg/vk/Device.cpp b/src/vsg/vk/Device.cpp index 61f00211b5..a13a24c857 100644 --- a/src/vsg/vk/Device.cpp +++ b/src/vsg/vk/Device.cpp @@ -22,7 +22,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI using namespace vsg; -// thread safe container for managing the deviceID for each vsg;:Device +// thread safe container for managing the deviceID for each vsg::Device static std::mutex s_DeviceCountMutex; static std::vector s_ActiveDevices; @@ -53,7 +53,6 @@ static void releaseDeviceID(uint32_t deviceID) Device::Device(PhysicalDevice* physicalDevice, const QueueSettings& queueSettings, Names layers, Names deviceExtensions, const DeviceFeatures* deviceFeatures, AllocationCallbacks* allocator) : deviceID(getUniqueDeviceID()), - enabledExtensions(deviceExtensions), _instance(physicalDevice->getInstance()), _physicalDevice(physicalDevice), _allocator(allocator) @@ -115,6 +114,11 @@ Device::Device(PhysicalDevice* physicalDevice, const QueueSettings& queueSetting deviceExtensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME); #endif + if (supportsApiVersion(VK_API_VERSION_1_1) && _physicalDevice->supportsDeviceExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME)) + { + deviceExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); + } + VkDeviceCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -162,6 +166,7 @@ Device::Device(PhysicalDevice* physicalDevice, const QueueSettings& queueSetting } } + const_cast(enabledExtensions) = deviceExtensions; _extensions = DeviceExtensions::create(this); } @@ -206,46 +211,61 @@ bool Device::supportsDeviceExtension(const char* extensionName) const return (std::find_if(enabledExtensions.begin(), enabledExtensions.end(), compare) != enabledExtensions.end()); } -VkDeviceSize Device::availableMemory(bool includeMemoryPools) const +VkDeviceSize Device::availableMemory(VkMemoryPropertyFlags memoryPropertiesFlags, double allocatedMemoryLimit) const { - VkDeviceSize available = 0; + if (_extensions->memory_budget) + { + VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget; + memoryBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; + memoryBudget.pNext = nullptr; - VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget; - memoryBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; - memoryBudget.pNext = nullptr; + VkPhysicalDeviceMemoryProperties2 dmp; + dmp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; + dmp.pNext = &memoryBudget; - VkPhysicalDeviceMemoryProperties2 dmp; - dmp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; - dmp.pNext = &memoryBudget; + vkGetPhysicalDeviceMemoryProperties2(*(getPhysicalDevice()), &dmp); - vkGetPhysicalDeviceMemoryProperties2(*(getPhysicalDevice()), &dmp); + auto& memoryProperties = dmp.memoryProperties; - auto& memoryProperties = dmp.memoryProperties; + VkDeviceSize availableSpace = 0; + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) + { + if ((memoryProperties.memoryTypes[i].propertyFlags & memoryPropertiesFlags) == memoryPropertiesFlags) // supported + { + uint32_t heapIndex = memoryProperties.memoryTypes[i].heapIndex; - VkMemoryPropertyFlags requiredPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + VkDeviceSize heapBudget = static_cast(static_cast(memoryBudget.heapBudget[heapIndex]) * allocatedMemoryLimit); + VkDeviceSize heapUsage = memoryBudget.heapUsage[heapIndex]; + VkDeviceSize heapAvailable = (heapUsage < heapBudget) ? heapBudget - heapUsage : 0; + availableSpace += heapAvailable; - std::set compatibleHeaps; - for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) - { - if ((memoryProperties.memoryTypes[i].propertyFlags & requiredPropertyFlags) == requiredPropertyFlags) // supported - { - compatibleHeaps.insert(memoryProperties.memoryTypes[i].heapIndex); + break; + } } - } - for (const auto& heapIndex : compatibleHeaps) - { - VkDeviceSize heapAvailable = memoryBudget.heapBudget[heapIndex] - memoryBudget.heapUsage[heapIndex]; - available += heapAvailable; + return availableSpace; } - - if (includeMemoryPools) + else { - if (auto pool = deviceMemoryBufferPools.ref_ptr()) + VkPhysicalDeviceMemoryProperties memoryProperties; + vkGetPhysicalDeviceMemoryProperties(*(getPhysicalDevice()), &memoryProperties); + + VkDeviceSize availableSpace = 0; + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) { - available += pool->computeMemoryTotalAvailable(); + if ((memoryProperties.memoryTypes[i].propertyFlags & memoryPropertiesFlags) == memoryPropertiesFlags) // supported + { + uint32_t heapIndex = memoryProperties.memoryTypes[i].heapIndex; + + VkDeviceSize heapBudget = static_cast(static_cast(memoryProperties.memoryHeaps[heapIndex].size) * allocatedMemoryLimit);; + + // unable to estimate usage, so assume whole budget is available and let calling code gracefully handle any memory allocation failures. + availableSpace += heapBudget; + + break; + } } - } - return available; + return availableSpace; + } } diff --git a/src/vsg/vk/DeviceExtensions.cpp b/src/vsg/vk/DeviceExtensions.cpp index 4390229c38..d2f668c5f8 100644 --- a/src/vsg/vk/DeviceExtensions.cpp +++ b/src/vsg/vk/DeviceExtensions.cpp @@ -77,4 +77,6 @@ DeviceExtensions::DeviceExtensions(Device* device) device->getProcAddr(vkCmdSetStencilTestEnable, "vkCmdSetStencilTestEnableEXT"); device->getProcAddr(vkCmdSetStencilOp, "vkCmdSetStencilOpEXT"); } + + memory_budget = device->supportsApiVersion(VK_API_VERSION_1_1) && device->supportsDeviceExtension(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME); } diff --git a/src/vsg/vk/DeviceMemory.cpp b/src/vsg/vk/DeviceMemory.cpp index 086637fcc1..621b0b6f18 100644 --- a/src/vsg/vk/DeviceMemory.cpp +++ b/src/vsg/vk/DeviceMemory.cpp @@ -87,13 +87,13 @@ DeviceMemory::DeviceMemory(Device* device, const VkMemoryRequirements& memRequir if (VkResult result = vkAllocateMemory(*device, &allocateInfo, _device->getAllocationCallbacks(), &_deviceMemory); result != VK_SUCCESS) { - throw Exception{"Error: Failed to allocate DeviceMemory.", result}; + throw Exception{"Error: Failed to allocate vsg::DeviceMemory.", result}; } { std::scoped_lock lock(s_DeviceMemoryListMutex); s_DeviceMemoryList.emplace_back(this); - vsg::debug("DeviceMemory::DeviceMemory() added to s_DeviceMemoryList, s_DeviceMemoryList.size() = ", s_DeviceMemoryList.size()); + debug("DeviceMemory::DeviceMemory() added to s_DeviceMemoryList, s_DeviceMemoryList.size() = ", s_DeviceMemoryList.size()); } } @@ -156,6 +156,12 @@ MemorySlots::OptionalOffset DeviceMemory::reserve(VkDeviceSize size) return _memorySlots.reserve(size, _memoryRequirements.alignment); } +MemorySlots::OptionalOffset DeviceMemory::reserve(VkDeviceSize size, VkDeviceSize alignment) +{ + std::scoped_lock lock(_mutex); + return _memorySlots.reserve(size, alignment); +} + void DeviceMemory::release(VkDeviceSize offset, VkDeviceSize size) { std::scoped_lock lock(_mutex); @@ -190,3 +196,12 @@ size_t DeviceMemory::totalMemorySize() const { return _memorySlots.totalMemorySize(); } + +void DeviceMemory::report(LogOutput& out) const +{ + out.enter("DeviceMemory::report(..)"); + out("_memoryRequirements = { size = ", _memoryRequirements.size, ", alignment = ", _memoryRequirements.alignment, ", memoryTypeBits = ", _memoryRequirements.memoryTypeBits, "}"); + out("_properties = ", _properties); + _memorySlots.report(out); + out.leave(); +} diff --git a/src/vsg/vk/Instance.cpp b/src/vsg/vk/Instance.cpp index d34e3b9297..9c500ed371 100644 --- a/src/vsg/vk/Instance.cpp +++ b/src/vsg/vk/Instance.cpp @@ -156,7 +156,7 @@ Instance::Instance(Names instanceExtensions, Names layers, uint32_t vulkanApiVer std::vector enabledValidationFeatures; std::vector disabledValidationFeatures; - // syncronization validation requires VkValidationFeaturesEXT + // synchronization validation requires VkValidationFeaturesEXT if (containsInstanceLayerName(layers, "VK_LAYER_KHRONOS_synchronization2")) enabledValidationFeatures.push_back(VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT); // set up the VkValidationFeaturesEXT if required diff --git a/src/vsg/vk/MemoryBufferPools.cpp b/src/vsg/vk/MemoryBufferPools.cpp index e338a0723c..e81ca6e227 100644 --- a/src/vsg/vk/MemoryBufferPools.cpp +++ b/src/vsg/vk/MemoryBufferPools.cpp @@ -95,7 +95,14 @@ ref_ptr MemoryBufferPools::reserveBuffer(VkDeviceSize totalSize, VkD } } - VkDeviceSize deviceSize = std::max(totalSize, minimumBufferSize); + VkDeviceSize availableMemory = device->availableMemory(memoryPropertiesFlags, allocatedMemoryLimit); + if (totalSize > availableMemory) + { + // info("MemoryBufferPools::reserveBuffer(", totalSize, ") insufficient memory ", availableMemory); + return {}; + } + + VkDeviceSize deviceSize = std::max(totalSize, std::min(availableMemory, minimumBufferSize)); bufferInfo->buffer = Buffer::create(deviceSize, bufferUsageFlags, sharingMode); bufferInfo->buffer->compile(device); @@ -146,11 +153,10 @@ MemoryBufferPools::DeviceMemoryOffset MemoryBufferPools::reserveMemory(VkMemoryR for (auto& memoryPool : memoryPools) { - if (memoryPool->getMemoryRequirements().memoryTypeBits == memRequirements.memoryTypeBits && - memoryPool->getMemoryRequirements().alignment == memRequirements.alignment && + if (((memoryPool->getMemoryRequirements().memoryTypeBits & memRequirements.memoryTypeBits) == memRequirements.memoryTypeBits) && memoryPool->maximumAvailableSpace() >= totalSize) { - reservedSlot = memoryPool->reserve(totalSize); + reservedSlot = memoryPool->reserve(totalSize, memRequirements.alignment); if (reservedSlot.first) { deviceMemory = memoryPool; @@ -161,61 +167,28 @@ MemoryBufferPools::DeviceMemoryOffset MemoryBufferPools::reserveMemory(VkMemoryR if (!deviceMemory) { - VkDeviceSize availableSpace = std::max(minimumDeviceMemorySize, totalSize); - if (allocatedMemoryLimit < 1.0) + VkDeviceSize availableMemory = device->availableMemory(memoryPropertiesFlags, allocatedMemoryLimit); + if (totalSize > availableMemory) { - VkPhysicalDeviceMemoryBudgetPropertiesEXT memoryBudget; - memoryBudget.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT; - memoryBudget.pNext = nullptr; - - VkPhysicalDeviceMemoryProperties2 dmp; - dmp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2; - dmp.pNext = &memoryBudget; + debug("MemoryBufferPools::reserveBuffer(", totalSize, ") insufficient memory ", availableMemory); + return {}; + } - vkGetPhysicalDeviceMemoryProperties2(*(device->getPhysicalDevice()), &dmp); + VkDeviceSize deviceSize = std::max(totalSize, std::min(availableMemory, minimumDeviceMemorySize)); - auto& memoryProperties = dmp.memoryProperties; + if (deviceSize <= availableMemory) + { - for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; ++i) + try { - if ((memoryProperties.memoryTypes[i].propertyFlags & memoryPropertiesFlags) == memoryPropertiesFlags) // supported - { - uint32_t heapIndex = memoryProperties.memoryTypes[i].heapIndex; - - VkDeviceSize heapBudget = static_cast(static_cast(memoryBudget.heapBudget[heapIndex]) * allocatedMemoryLimit); - VkDeviceSize heapUsage = memoryBudget.heapUsage[heapIndex]; - VkDeviceSize heapAvailable = (heapUsage < heapBudget) ? heapBudget - heapUsage : 0; - availableSpace = heapAvailable; - - break; - } + deviceMemory = vsg::DeviceMemory::create(device, memRequirements, memoryPropertiesFlags, pNextAllocInfo); } - - VkDeviceSize minimumSpare = 0; //16*1024*1024; - if (availableSpace < minimumSpare) - availableSpace = 0; - else - availableSpace -= minimumSpare; - } - - if (totalSize <= availableSpace) - { - if (availableSpace < minimumDeviceMemorySize) + catch (...) { - debug("MemoryBufferPools::reserveMemory(", totalSize, ") reducing minimumDeviceMemorySize = ", minimumDeviceMemorySize, " to ", availableSpace); - minimumDeviceMemorySize = availableSpace; + // info("Could not allocate vsg::DeviceMemory(..) memRequirements.size = ", memRequirements.size); } - VkDeviceSize deviceMemorySize = std::max(totalSize, minimumDeviceMemorySize); - - // clamp to an aligned size - deviceMemorySize = ((deviceMemorySize + memRequirements.alignment - 1) / memRequirements.alignment) * memRequirements.alignment; - - //debug("Creating new local DeviceMemory"); - if (memRequirements.size < deviceMemorySize) memRequirements.size = deviceMemorySize; - - deviceMemory = vsg::DeviceMemory::create(device, memRequirements, memoryPropertiesFlags, pNextAllocInfo); if (deviceMemory) { reservedSlot = deviceMemory->reserve(totalSize); @@ -226,10 +199,15 @@ MemoryBufferPools::DeviceMemoryOffset MemoryBufferPools::reserveMemory(VkMemoryR } } } + + // vsg::info(" MemoryBufferPools::reserveMemory(totalSize = ", totalSize, " availableSpace = ", availableSpace, ") deviceMemory = ", deviceMemory); + +#if 0 else if (throwOutOfDeviceMemoryException) { throw vsg::Exception{"MemoryBufferPools::reserve() out of memory", VK_ERROR_OUT_OF_DEVICE_MEMORY}; } +#endif } if (!reservedSlot.first) @@ -251,66 +229,92 @@ VkResult MemoryBufferPools::reserve(ResourceRequirements& requirements) VkMemoryPropertyFlags memoryPropertiesFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; // VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + decltype(requirements.bufferInfos) failed_bufferInfos; + decltype(requirements.imageInfos) failed_imageInfos; + // allocate bufferInfos - VkDeviceSize failedBufferMemory = 0; + bool allocationSuccess = true; for (auto& [properties, bufferInfos] : requirements.bufferInfos) { + VkDeviceSize alignment = 4; + if ((properties.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 0) + alignment = limits.minUniformBufferOffsetAlignment; + else if ((properties.usageFlags & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) != 0) + alignment = limits.minStorageBufferOffsetAlignment; + for (auto& bufferInfo : bufferInfos) { if (!bufferInfo->buffer) { - VkDeviceSize alignment = 4; - if ((properties.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 0) - alignment = limits.minUniformBufferOffsetAlignment; - else if ((properties.usageFlags & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) != 0) - alignment = limits.minStorageBufferOffsetAlignment; - - debug("MemoryBufferPools::reserve(ResourceRequirements& requirements) properties.usageFlags = ", properties.usageFlags, ", alignment = ", alignment); - - auto newBufferInfo = reserveBuffer(bufferInfo->data->dataSize(), alignment, properties.usageFlags, properties.sharingMode, memoryPropertiesFlags); - if (newBufferInfo) + if (allocationSuccess) { - bufferInfo->take(*newBufferInfo); - - //info(" ALLOCATED usage = ", properties.usageFlags, ", alignment = ", alignment, ", bufferInfo->data = ", bufferInfo->data, ", offset = ", bufferInfo->offset, ", range = ", bufferInfo->range, ", buffer = ", bufferInfo->buffer, " ----- size = ", computeSize(*bufferInfo)); + debug("MemoryBufferPools::reserve(ResourceRequirements& requirements) properties.usageFlags = ", properties.usageFlags, ", alignment = ", alignment); + + auto newBufferInfo = reserveBuffer(bufferInfo->data->dataSize(), alignment, properties.usageFlags, properties.sharingMode, memoryPropertiesFlags); + if (newBufferInfo) + { + bufferInfo->take(*newBufferInfo); + } + else + { + debug("MemoryBufferPools::reserve() failed on ", bufferInfo, ", data = ", bufferInfo->data); + allocationSuccess = false; + } } - else + + if (!allocationSuccess) { - failedBufferMemory += bufferInfo->computeDataSize(); + failed_bufferInfos[properties].insert(bufferInfo); } } } } // allocate images - VkDeviceSize failedImageMemory = 0; for (auto& imageInfo : requirements.imageInfos) { if (imageInfo->imageView && imageInfo->imageView->image && imageInfo->imageView->image->getDeviceMemory(deviceID) == 0) { - if (imageInfo->imageView->image->compile(*this) == VK_SUCCESS && imageInfo->imageView->image->getDeviceMemory(deviceID) != 0) + if (allocationSuccess) { - //info(" ALLOCATED imageInfo = ", imageInfo, ", imageView = ", imageInfo->imageView, " ----- size = ", computeSize(*imageInfo), " device memory = ", imageInfo->imageView->image->getDeviceMemory(deviceID), " offset = ", imageInfo->imageView->image->getMemoryOffset(deviceID)); + auto image_result = imageInfo->imageView->image->compile(*this); + if (image_result != VK_SUCCESS || imageInfo->imageView->image->getDeviceMemory(deviceID) == 0) + { + debug("MemoryBufferPools::reserve() failed on ", imageInfo, ", data = ", imageInfo->imageView->image->data); + allocationSuccess = false; + } } - else + + if (!allocationSuccess) { - failedImageMemory += imageInfo->computeDataSize(); + failed_imageInfos.insert(imageInfo); } } } - VkDeviceSize memoryRequired = failedBufferMemory + failedImageMemory; - // all required resources allocated - if (memoryRequired == 0) + if (allocationSuccess) { - //info("MemoryBufferPools::reserve() memoryRequired = ", memoryRequired); return VK_SUCCESS; } else { - //VkDeviceSize memoryAvailable = device->availableMemory(false); - //info("MemoryBufferPools::reserve() out of memory: memoryAvailable = ", memoryAvailable, " memoryRequired = ", memoryRequired); + requirements.bufferInfos.swap(failed_bufferInfos); + requirements.imageInfos.swap(failed_imageInfos); + + // LogOutput output; + // report(output); + return VK_ERROR_OUT_OF_DEVICE_MEMORY; } } + +void MemoryBufferPools::report(LogOutput& out) const +{ + out.enter("MemoryBufferPools::report(..)"); + for (const auto& memoryPool : memoryPools) + { + memoryPool->report(out); + } + out.leave(); +} diff --git a/src/vsg/vk/ResourceRequirements.cpp b/src/vsg/vk/ResourceRequirements.cpp index 6a5bb6ae76..6ca2196714 100644 --- a/src/vsg/vk/ResourceRequirements.cpp +++ b/src/vsg/vk/ResourceRequirements.cpp @@ -66,7 +66,7 @@ DescriptorPoolSizes ResourceRequirements::computeDescriptorPoolSizes() const void ResourceRequirements::apply(const ResourceHints& resourceHints) { - maxSlots.merge(resourceHints.maxSlots); + maxSlots.update(resourceHints.maxSlots); if (!resourceHints.descriptorPoolSizes.empty() || resourceHints.numDescriptorSets > 0) { @@ -90,7 +90,7 @@ void ResourceRequirements::apply(const ResourceHints& resourceHints) viewportStateHint = resourceHints.viewportStateHint; dynamicData.add(resourceHints.dynamicData); - containsPagedLOD = containsPagedLOD | resourceHints.containsPagedLOD; + containsPagedLOD = containsPagedLOD || resourceHints.containsPagedLOD; } ////////////////////////////////////////////////////////////////////// diff --git a/src/vsg/vk/Swapchain.cpp b/src/vsg/vk/Swapchain.cpp index 24b1963651..612e604661 100644 --- a/src/vsg/vk/Swapchain.cpp +++ b/src/vsg/vk/Swapchain.cpp @@ -141,7 +141,7 @@ namespace vsg } protected: - virtual ~SwapchainImage() + ~SwapchainImage() override { for (auto& vd : _vulkanData) {