diff --git a/include/vsg/state/BufferInfo.h b/include/vsg/state/BufferInfo.h index f592ef608..8b8407c35 100644 --- a/include/vsg/state/BufferInfo.h +++ b/include/vsg/state/BufferInfo.h @@ -59,7 +59,13 @@ namespace vsg ref_ptr data; ref_ptr parent; - /// return true if the BufferInfo's data has been modified and should be copied to the buffer + /// return true if the BufferInfo's has not been assigned a buffer or that buffer doesn't yet have device memory allocated for it. + bool requiresAllocation(uint32_t deviceID) const + { + return !buffer || buffer->getDeviceMemory(deviceID)==nullptr; + } + + /// returns true if the data and associated buffers are not in sync and the data needs to be transferred to synchronize them bool requiresCopy(uint32_t deviceID) const { return data && data->differentModifiedCount(copiedModifiedCounts[deviceID]); diff --git a/include/vsg/state/ImageView.h b/include/vsg/state/ImageView.h index 828e239a3..1c4e2b009 100644 --- a/include/vsg/state/ImageView.h +++ b/include/vsg/state/ImageView.h @@ -50,8 +50,8 @@ namespace vsg { VkImageView imageView = VK_NULL_HANDLE; ref_ptr device; + ref_ptr image; - ~VulkanData() { release(); } void release(); }; diff --git a/include/vsg/utils/SharedObjects.h b/include/vsg/utils/SharedObjects.h index 23f3dd76d..d94591038 100644 --- a/include/vsg/utils/SharedObjects.h +++ b/include/vsg/utils/SharedObjects.h @@ -72,10 +72,11 @@ namespace vsg /// write out stats of objects held, types of objects and their reference counts void report(vsg::LogOutput& output); + mutable std::recursive_mutex mutex; + protected: ~SharedObjects() override; - mutable std::recursive_mutex _mutex; std::map> _defaults; std::map, DereferenceLess>> _sharedObjects; }; @@ -127,7 +128,7 @@ namespace vsg template ref_ptr SharedObjects::shared_default() { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); auto id = std::type_index(typeid(T)); auto& def = _defaults[id]; @@ -155,7 +156,7 @@ namespace vsg template void SharedObjects::share(ref_ptr& object) { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); if (suitableForSharing && !suitableForSharing->suitable(object.get())) return; @@ -175,7 +176,7 @@ namespace vsg void SharedObjects::share(ref_ptr& object, Func init) { { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); auto id = std::type_index(typeid(T)); auto& shared_objects = _sharedObjects[id]; @@ -189,7 +190,7 @@ namespace vsg init(object); { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); auto id = std::type_index(typeid(T)); auto& shared_objects = _sharedObjects[id]; if (suitableForSharing && suitableForSharing->suitable(object.get())) diff --git a/include/vsg/vk/CommandBuffer.h b/include/vsg/vk/CommandBuffer.h index a4091d81d..e3eef6903 100644 --- a/include/vsg/vk/CommandBuffer.h +++ b/include/vsg/vk/CommandBuffer.h @@ -15,6 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #include #include #include +#include namespace vsg { @@ -42,6 +43,7 @@ namespace vsg ViewDependentState* viewDependentState = nullptr; State* state = nullptr; const InstanceNode* instanceNode = nullptr; + ref_ptr frameStamp; ref_ptr gpuStats; VkCommandBufferLevel level() const { return _level; } diff --git a/include/vsg/vk/Context.h b/include/vsg/vk/Context.h index 02d0e5144..11a166298 100644 --- a/include/vsg/vk/Context.h +++ b/include/vsg/vk/Context.h @@ -72,6 +72,9 @@ namespace vsg ~Context() override; + // clear any recorded commands for next frame to avoid accumulating work to next compile traversal. + void reset(); + const uint32_t deviceID = 0; ref_ptr device; ResourceRequirements resourceRequirements; @@ -126,6 +129,9 @@ namespace vsg std::vector> commands; + BufferInfoList bufferInfosToCopy; + ImageInfoList imageInfosToCopy; + ref_ptr copyImageCmd; void copy(ref_ptr data, ref_ptr dest); void copy(ref_ptr data, ref_ptr dest, uint32_t numMipMapLevels); @@ -146,6 +152,10 @@ namespace vsg std::vector> buildAccelerationStructureCommands; ref_ptr transferTask; + + bool createBufferAndTransferData(const BufferInfoList& bufferInfoList, VkBufferUsageFlags usage, VkSharingMode sharingMode); + bool copy(const ImageInfoList& imageInfoList); + }; VSG_type_name(vsg::Context); diff --git a/include/vsg/vk/MemoryBufferPools.h b/include/vsg/vk/MemoryBufferPools.h index d6c27ebfa..7487cfb0f 100644 --- a/include/vsg/vk/MemoryBufferPools.h +++ b/include/vsg/vk/MemoryBufferPools.h @@ -55,6 +55,7 @@ namespace vsg using DeviceMemoryOffset = std::pair, VkDeviceSize>; DeviceMemoryOffset reserveMemory(VkMemoryRequirements memRequirements, VkMemoryPropertyFlags memoryProperties, void* pNextAllocInfo = nullptr); + VkResult reserve(const BufferInfoList& bufferInfoList, VkDeviceSize alignment, VkBufferUsageFlags bufferUsageFlags, VkSharingMode sharingMode, VkMemoryPropertyFlags memoryProperties); VkResult reserve(ResourceRequirements& requirements); void report(LogOutput& out) const; diff --git a/src/vsg/app/CommandGraph.cpp b/src/vsg/app/CommandGraph.cpp index f0f870d7c..7ab5c3b1e 100644 --- a/src/vsg/app/CommandGraph.cpp +++ b/src/vsg/app/CommandGraph.cpp @@ -112,6 +112,7 @@ void CommandGraph::record(ref_ptr recordedCommandBuffers commandBuffer->reset(); } + commandBuffer->frameStamp = frameStamp; commandBuffer->numDependentSubmissions().fetch_add(1); recordTraversal->getState()->connect(commandBuffer); diff --git a/src/vsg/app/CompileManager.cpp b/src/vsg/app/CompileManager.cpp index 55a1c53c6..7581d0c09 100644 --- a/src/vsg/app/CompileManager.cpp +++ b/src/vsg/app/CompileManager.cpp @@ -253,6 +253,11 @@ CompileResult CompileManager::compile(ref_ptr object, ContextSelectionFu auto run_compile_traversal = [&]() -> void { try { + for (auto& context : compileTraversal->contexts) + { + context->reset(); + } + for (auto& context : compileTraversal->contexts) { ref_ptr view = context->view; @@ -345,6 +350,11 @@ CompileResult CompileManager::compile(ref_ptr object, ContextSelectionFu else { ++failedCompileCount; + + for (auto& context : compileTraversal->contexts) + { + context->reset(); + } } return result; @@ -362,6 +372,11 @@ CompileResult CompileManager::compileTask(ref_ptr task, Res auto compileTraversal = CompileTraversal::create(task->device, resourceRequirements); auto deviceMemoryBufferPools = task->device->deviceMemoryBufferPools.ref_ptr(); + for (auto& context : compileTraversal->contexts) + { + context->reset(); + } + for (const auto& context : compileTraversal->contexts) { if (resourceRequirements.dataTransferHint == COMPILE_TRAVERSAL_USE_TRANSFER_TASK) diff --git a/src/vsg/app/SecondaryCommandGraph.cpp b/src/vsg/app/SecondaryCommandGraph.cpp index 356cc18c9..8714c618b 100644 --- a/src/vsg/app/SecondaryCommandGraph.cpp +++ b/src/vsg/app/SecondaryCommandGraph.cpp @@ -109,6 +109,7 @@ void SecondaryCommandGraph::record(ref_ptr recordedComma commandBuffer->reset(); } + commandBuffer->frameStamp = frameStamp; commandBuffer->numDependentSubmissions().fetch_add(1); recordTraversal->getState()->connect(commandBuffer); diff --git a/src/vsg/nodes/VertexDraw.cpp b/src/vsg/nodes/VertexDraw.cpp index 628879c61..2d2ce9d07 100644 --- a/src/vsg/nodes/VertexDraw.cpp +++ b/src/vsg/nodes/VertexDraw.cpp @@ -128,8 +128,7 @@ void VertexDraw::compile(Context& context) if (requiresCreateAndCopy) { - BufferInfoList combinedBufferInfos(arrays); - createBufferAndTransferData(context, combinedBufferInfos, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE); + createBufferAndTransferData(context, arrays, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE); // info("VertexDraw::compile() create and copy ", this); } diff --git a/src/vsg/state/BufferInfo.cpp b/src/vsg/state/BufferInfo.cpp index 7b4c8af49..2a5fc6143 100644 --- a/src/vsg/state/BufferInfo.cpp +++ b/src/vsg/state/BufferInfo.cpp @@ -207,186 +207,18 @@ ref_ptr vsg::copyDataToStagingBuffer(Context& context, const Data* d return stagingBufferInfo; } +VkDeviceSize BufferInfo::computeDataSize() const +{ + return data ? data->dataSize() : 0; +} + ///////////////////////////////////////////////////////////////////////////////////////// // // vsg::createBufferAndTransferData // bool vsg::createBufferAndTransferData(Context& context, const BufferInfoList& bufferInfoList, VkBufferUsageFlags usage, VkSharingMode sharingMode) { - if (bufferInfoList.empty()) return false; - - Device* device = context.device; - auto deviceID = context.deviceID; - auto transferTask = context.transferTask.get(); - VkDeviceSize alignment = 4; - if (usage == VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) - alignment = device->getPhysicalDevice()->getProperties().limits.minUniformBufferOffsetAlignment; - 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; - - ref_ptr deviceBufferInfo; - size_t numBuffersRequired = 0; - bool containsMultipleParents = false; - for (auto& bufferInfo : bufferInfoList) - { - if (bufferInfo->data) - { - if (bufferInfo->data->getModifiedCount(bufferInfo->copiedModifiedCounts[deviceID])) - { - ++numBuffersRequired; - } - } - - if (bufferInfo->parent) - { - if (deviceBufferInfo && bufferInfo->parent != deviceBufferInfo) containsMultipleParents = true; - deviceBufferInfo = bufferInfo->parent; - } - } - - if (numBuffersRequired == 0) - { - debug("\nvsg::createBufferAndTransferData(...) already all compiled. deviceID = ", deviceID); - return false; - } - - if (containsMultipleParents) - { - warn("vsg::createBufferAndTransferData(...) does not support multiple parent BufferInfo."); - return false; - } - - VkDeviceSize totalSize = 0; - VkDeviceSize offset = 0; - for (const auto& bufferInfo : bufferInfoList) - { - if (bufferInfo->data) - { - bufferInfo->offset = offset; - bufferInfo->range = bufferInfo->data->dataSize(); - VkDeviceSize endOfEntry = offset + bufferInfo->range; - offset = (alignment == 1 || (endOfEntry % alignment) == 0) ? endOfEntry : ((endOfEntry / alignment) + 1) * alignment; - //info(" BufferInfo.data = ", bufferInfo->data, ", dynamic = ", bufferInfo->data->getLayout().dynamic); - } - } - - totalSize = offset; - if (totalSize == 0) return false; - - if (deviceBufferInfo && deviceBufferInfo->buffer) - { - if (totalSize != deviceBufferInfo->range) - { - warn("Existing deviceBufferInfo, ", deviceBufferInfo, ", deviceBufferInfo->range = ", deviceBufferInfo->range, ", ", totalSize, " NOT compatible"); - return false; - } - else - { - debug("Existing deviceBufferInfo, ", deviceBufferInfo, ", deviceBufferInfo->range = ", deviceBufferInfo->range, ", ", totalSize, " with compatible size"); - - // make sure the VkBuffer is created - deviceBufferInfo->buffer->compile(context); - - if (!deviceBufferInfo->buffer->getDeviceMemory(deviceID)) - { - VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(*device, deviceBufferInfo->buffer->vk(device->deviceID), &memRequirements); - - auto deviceMemoryOffset = context.deviceMemoryBufferPools->reserveMemory(memRequirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - if (deviceMemoryOffset.first) - deviceBufferInfo->buffer->bind(deviceMemoryOffset.first, deviceMemoryOffset.second); - else - { - debug("vsg::createBufferAndTransferData() Failure to assign memory to existing BufferInfo"); - return false; - } - } - } - } - - if (!deviceBufferInfo) - { - VkBufferUsageFlags bufferUsageFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage; - deviceBufferInfo = context.deviceMemoryBufferPools->reserveBuffer(totalSize, alignment, bufferUsageFlags, sharingMode, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - } - - if (!deviceBufferInfo) - { - debug("vsg::createBufferAndTransferData() Failure to assign Buffer"); - return false; - } - - debug("deviceBufferInfo->buffer ", deviceBufferInfo->buffer, ", ", deviceBufferInfo->offset, ", ", deviceBufferInfo->range, ")"); - - // assign the buffer to the bufferData entries and shift the offsets to offset within the buffer - for (const auto& bufferInfo : bufferInfoList) - { - bufferInfo->buffer = deviceBufferInfo->buffer; - bufferInfo->offset += deviceBufferInfo->offset; - } - - if (transferTask) - { - vsg::debug("vsg::createBufferAndTransferData(..)"); - - for (auto& bufferInfo : bufferInfoList) - { - vsg::debug(" ", bufferInfo, ", ", bufferInfo->data, ", ", bufferInfo->buffer, ", ", bufferInfo->offset); - bufferInfo->data->dirty(); - bufferInfo->parent = deviceBufferInfo; - } - - transferTask->assign(bufferInfoList); - - return true; - } - - auto stagingBufferInfo = context.stagingMemoryBufferPools->reserveBuffer(totalSize, alignment, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, sharingMode, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - - debug("stagingBufferInfo->buffer ", stagingBufferInfo->buffer.get(), ", ", stagingBufferInfo->offset, ", ", stagingBufferInfo->range, ")"); - - ref_ptr stagingBuffer(stagingBufferInfo->buffer); - ref_ptr stagingMemory(stagingBuffer->getDeviceMemory(context.deviceID)); - - if (!stagingMemory) - { - return false; - } - - void* buffer_data; - stagingMemory->map(stagingBuffer->getMemoryOffset(context.deviceID) + stagingBufferInfo->offset, stagingBufferInfo->range, 0, &buffer_data); - char* ptr = reinterpret_cast(buffer_data); - - debug(" buffer_data ", buffer_data, ", stagingBufferInfo->offset=", stagingBufferInfo->offset, ", ", totalSize); - - for (const auto& bufferInfo : bufferInfoList) - { - const Data* data = bufferInfo->data; - if (data) - { - std::memcpy(ptr + bufferInfo->offset - deviceBufferInfo->offset, data->dataPointer(), data->dataSize()); - if (data->properties.dataVariance == STATIC_DATA_UNREF_AFTER_TRANSFER) - { - bufferInfo->data.reset(); - } - } - bufferInfo->parent = deviceBufferInfo; - } - - stagingMemory->unmap(); - - context.copy(stagingBufferInfo, deviceBufferInfo); - - return true; -} - -VkDeviceSize BufferInfo::computeDataSize() const -{ - return data ? data->dataSize() : 0; + return context.createBufferAndTransferData(bufferInfoList, usage, sharingMode); } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/vsg/state/ImageView.cpp b/src/vsg/state/ImageView.cpp index e8d8a722e..d4d260643 100644 --- a/src/vsg/state/ImageView.cpp +++ b/src/vsg/state/ImageView.cpp @@ -40,6 +40,8 @@ void ImageView::VulkanData::release() vkDestroyImageView(*device, imageView, device->getAllocationCallbacks()); imageView = VK_NULL_HANDLE; device = {}; + image = {}; + } } @@ -137,6 +139,8 @@ void ImageView::compile(Device* device) { throw Exception{"Error: Failed to create VkImageView.", result}; } + + vd.image = image; } void ImageView::compile(Context& context) @@ -166,6 +170,8 @@ void ImageView::compile(Context& context) { throw Exception{"Error: Failed to create VkImageView.", result}; } + + vd.image = image; } ref_ptr vsg::createImageView(vsg::Context& context, ref_ptr image, VkImageAspectFlags aspectFlags) diff --git a/src/vsg/utils/GraphicsPipelineConfigurator.cpp b/src/vsg/utils/GraphicsPipelineConfigurator.cpp index 8094d056d..d517ecbb4 100644 --- a/src/vsg/utils/GraphicsPipelineConfigurator.cpp +++ b/src/vsg/utils/GraphicsPipelineConfigurator.cpp @@ -834,13 +834,13 @@ bool GraphicsPipelineConfigurator::copyTo(StateCommands& stateCommands, ref_ptr< // create StateGroup as the root of the scene/command graph to hold the GraphicsPipeline, and binding of Descriptors to decorate the whole graph if (sharedObjects) { - for (auto& dsl : layout->setLayouts) - { - sharedObjects->share(dsl); - } + std::scoped_lock lock(sharedObjects->mutex); + + sharedObjects->share(layout->setLayouts); sharedObjects->share(layout); + graphicsPipeline->layout = layout; + sharedObjects->share(graphicsPipeline); - layout = graphicsPipeline->layout; sharedObjects->share(bindGraphicsPipeline); } diff --git a/src/vsg/utils/SharedObjects.cpp b/src/vsg/utils/SharedObjects.cpp index 9d455d7e0..1e15a0ede 100644 --- a/src/vsg/utils/SharedObjects.cpp +++ b/src/vsg/utils/SharedObjects.cpp @@ -21,7 +21,7 @@ bool SharedObjects::suitable(const Path& filename) const bool SharedObjects::contains(const Path& filename, ref_ptr options) const { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); auto loadedObject_id = std::type_index(typeid(LoadedObject)); auto itr = _sharedObjects.find(loadedObject_id); @@ -34,7 +34,7 @@ bool SharedObjects::contains(const Path& filename, ref_ptr option void SharedObjects::add(ref_ptr object, const Path& filename, ref_ptr options) { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); auto loadedObject_id = std::type_index(typeid(LoadedObject)); auto& loadedObjects = _sharedObjects[loadedObject_id]; @@ -45,7 +45,7 @@ void SharedObjects::add(ref_ptr object, const Path& filename, ref_ptr options) { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); auto loadedObject_id = std::type_index(typeid(LoadedObject)); auto itr = _sharedObjects.find(loadedObject_id); @@ -67,14 +67,14 @@ bool SharedObjects::remove(const Path& filename, ref_ptr options) void SharedObjects::clear() { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); _defaults.clear(); _sharedObjects.clear(); } void SharedObjects::prune() { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); auto loadedObject_id = std::type_index(typeid(LoadedObject)); @@ -156,7 +156,7 @@ void SharedObjects::prune() void SharedObjects::report(vsg::LogOutput& output) { - std::scoped_lock lock(_mutex); + std::scoped_lock lock(mutex); output("SharedObjects::report(..) ", this, " {"); output.in(); output("SharedObjects::_defaults ", _defaults.size(), " {"); diff --git a/src/vsg/vk/Context.cpp b/src/vsg/vk/Context.cpp index 38e4c5ef5..f087fc096 100644 --- a/src/vsg/vk/Context.cpp +++ b/src/vsg/vk/Context.cpp @@ -166,6 +166,22 @@ Context::~Context() } } +void Context::reset() +{ + if ((commands.size()>0) || bufferInfosToCopy.size()>0 || copyImageCmd || copyBufferCmd) + { + vsg::info("Context::reset() commands.size() = ", commands.size(), ", bufferInfosToCopy.size() = ", bufferInfosToCopy.size(), ", copyImageCmd = ", copyBufferCmd, ", copyBufferCmd= ", copyBufferCmd); + } + + commands.clear(); + + bufferInfosToCopy.clear(); + + copyImageCmd.reset(); + copyBufferCmd.reset(); +} + + ref_ptr Context::getOrCreateCommandBuffer() { if (!commandBuffer) @@ -262,6 +278,22 @@ bool Context::record() { CPU_INSTRUMENTATION_L1_NC(instrumentation, "Context record", COLOR_COMPILE) + // vsg::info("Context::record() ", this, ", commands.size() = ", commands.size(), ", bufferInfosToCopy.size() = ", bufferInfosToCopy.size(), ", imageInfosToCopy.size() = ", imageInfosToCopy.size()); + + if (transferTask) + { + if (!bufferInfosToCopy.empty()) + { + transferTask->assign(bufferInfosToCopy); + bufferInfosToCopy.clear(); + } + if (!imageInfosToCopy.empty()) + { + transferTask->assign(imageInfosToCopy); + imageInfosToCopy.clear(); + } + } + if (commands.empty() && buildAccelerationStructureCommands.empty()) return false; if (!fence) @@ -284,6 +316,9 @@ bool Context::record() { COMMAND_BUFFER_INSTRUMENTATION(instrumentation, *commandBuffer, "Context record", COLOR_COMPILE) + vsg::warn("Context::record() Need to implement copying of data."); + + // issue commands of interest { for (auto& command : commands) command->record(*commandBuffer); @@ -338,6 +373,8 @@ void Context::waitForCompletion() { CPU_INSTRUMENTATION_L1_NC(instrumentation, "Context waitForCompletion", COLOR_COMPILE) + vsg::info("Context::waitForCompletion() ", this); + if (!requiresWaitForCompletion || !commandBuffer || !fence) { return; @@ -366,3 +403,202 @@ void Context::waitForCompletion() copyImageCmd = nullptr; copyBufferCmd = nullptr; } + +bool Context::createBufferAndTransferData(const BufferInfoList& bufferInfoList, VkBufferUsageFlags usage, VkSharingMode sharingMode) +{ + if (bufferInfoList.empty()) return false; + + VkDeviceSize alignment = 4; + if (usage == VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) + alignment = device->getPhysicalDevice()->getProperties().limits.minUniformBufferOffsetAlignment; + else if (usage == VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + alignment = device->getPhysicalDevice()->getProperties().limits.minStorageBufferOffsetAlignment; + +#if 1 + if (VkResult result = deviceMemoryBufferPools->reserve(bufferInfoList, alignment, usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT, sharingMode, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); result == VK_SUCCESS) + { +#if 1 + bufferInfosToCopy.reserve(bufferInfosToCopy.size() + bufferInfoList.size()); + bufferInfosToCopy.insert(bufferInfosToCopy.end(), bufferInfoList.begin(), bufferInfoList.end()); +#else + if (transferTask) transferTask->assign(bufferInfoList); + else warn("vsg::createBufferAndTransferData() transfer task missing, need to implement transfer."); +#endif + return true; + } + else + { + return false; + } +#else + + // info("vsg::createBufferAndTransferData(const BufferInfoList& bufferInfoList, VkBufferUsageFlags usage, VkSharingMode sharingMode) usage = ", usage, ", alignment = ", alignment); + + //transferTask = nullptr; + + ref_ptr deviceBufferInfo; + size_t numBuffersRequired = 0; + bool containsMultipleParents = false; + for (auto& bufferInfo : bufferInfoList) + { + if (bufferInfo->data) + { + if (bufferInfo->data->getModifiedCount(bufferInfo->copiedModifiedCounts[deviceID])) + { + ++numBuffersRequired; + } + } + + if (bufferInfo->parent) + { + if (deviceBufferInfo && bufferInfo->parent != deviceBufferInfo) containsMultipleParents = true; + deviceBufferInfo = bufferInfo->parent; + } + } + + if (numBuffersRequired == 0) + { + debug("\nvsg::createBufferAndTransferData(...) already all compiled. deviceID = ", deviceID); + return false; + } + + if (containsMultipleParents) + { + warn("vsg::createBufferAndTransferData(...) does not support multiple parent BufferInfo."); + return false; + } + + VkDeviceSize totalSize = 0; + VkDeviceSize offset = 0; + for (const auto& bufferInfo : bufferInfoList) + { + if (bufferInfo->data) + { + bufferInfo->offset = offset; + bufferInfo->range = bufferInfo->data->dataSize(); + VkDeviceSize endOfEntry = offset + bufferInfo->range; + offset = (alignment == 1 || (endOfEntry % alignment) == 0) ? endOfEntry : ((endOfEntry / alignment) + 1) * alignment; + //info(" BufferInfo.data = ", bufferInfo->data, ", dynamic = ", bufferInfo->data->getLayout().dynamic); + } + } + + totalSize = offset; + if (totalSize == 0) return false; + + if (deviceBufferInfo && deviceBufferInfo->buffer) + { + if (totalSize != deviceBufferInfo->range) + { + warn("Existing deviceBufferInfo, ", deviceBufferInfo, ", deviceBufferInfo->range = ", deviceBufferInfo->range, ", ", totalSize, " NOT compatible"); + return false; + } + else + { + debug("Existing deviceBufferInfo, ", deviceBufferInfo, ", deviceBufferInfo->range = ", deviceBufferInfo->range, ", ", totalSize, " with compatible size"); + + // make sure the VkBuffer is created + deviceBufferInfo->buffer->compile(*this); + + if (!deviceBufferInfo->buffer->getDeviceMemory(deviceID)) + { + VkMemoryRequirements memRequirements; + vkGetBufferMemoryRequirements(*device, deviceBufferInfo->buffer->vk(device->deviceID), &memRequirements); + + auto deviceMemoryOffset = deviceMemoryBufferPools->reserveMemory(memRequirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + if (deviceMemoryOffset.first) + deviceBufferInfo->buffer->bind(deviceMemoryOffset.first, deviceMemoryOffset.second); + else + { + debug("vsg::createBufferAndTransferData() Failure to assign memory to existing BufferInfo"); + return false; + } + } + } + } + + if (!deviceBufferInfo) + { + VkBufferUsageFlags bufferUsageFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage; + deviceBufferInfo = deviceMemoryBufferPools->reserveBuffer(totalSize, alignment, bufferUsageFlags, sharingMode, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + + if (!deviceBufferInfo) + { + debug("vsg::createBufferAndTransferData() Failure to assign Buffer"); + return false; + } + + debug("deviceBufferInfo->buffer ", deviceBufferInfo->buffer, ", ", deviceBufferInfo->offset, ", ", deviceBufferInfo->range, ")"); + + // assign the buffer to the bufferData entries and shift the offsets to offset within the buffer + for (const auto& bufferInfo : bufferInfoList) + { + bufferInfo->buffer = deviceBufferInfo->buffer; + bufferInfo->offset += deviceBufferInfo->offset; + } + + if (transferTask) + { + vsg::debug("vsg::createBufferAndTransferData(..)"); + + for (auto& bufferInfo : bufferInfoList) + { + vsg::debug(" ", bufferInfo, ", ", bufferInfo->data, ", ", bufferInfo->buffer, ", ", bufferInfo->offset); + bufferInfo->data->dirty(); + bufferInfo->parent = deviceBufferInfo; + } + + transferTask->assign(bufferInfoList); + + return true; + } + + auto stagingBufferInfo = stagingMemoryBufferPools->reserveBuffer(totalSize, alignment, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, sharingMode, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + + debug("stagingBufferInfo->buffer ", stagingBufferInfo->buffer.get(), ", ", stagingBufferInfo->offset, ", ", stagingBufferInfo->range, ")"); + + ref_ptr stagingBuffer(stagingBufferInfo->buffer); + ref_ptr stagingMemory(stagingBuffer->getDeviceMemory(deviceID)); + + if (!stagingMemory) + { + return false; + } + + void* buffer_data; + stagingMemory->map(stagingBuffer->getMemoryOffset(deviceID) + stagingBufferInfo->offset, stagingBufferInfo->range, 0, &buffer_data); + char* ptr = reinterpret_cast(buffer_data); + + debug(" buffer_data ", buffer_data, ", stagingBufferInfo->offset=", stagingBufferInfo->offset, ", ", totalSize); + + for (const auto& bufferInfo : bufferInfoList) + { + const Data* data = bufferInfo->data; + if (data) + { + std::memcpy(ptr + bufferInfo->offset - deviceBufferInfo->offset, data->dataPointer(), data->dataSize()); + if (data->properties.dataVariance == STATIC_DATA_UNREF_AFTER_TRANSFER) + { + bufferInfo->data.reset(); + } + } + bufferInfo->parent = deviceBufferInfo; + } + + stagingMemory->unmap(); + + copy(stagingBufferInfo, deviceBufferInfo); + + return true; +#endif +} + +bool Context::copy(const ImageInfoList& imageInfoList) +{ + if (imageInfoList.empty()) return false; + + imageInfosToCopy.reserve(imageInfosToCopy.size() + imageInfoList.size()); + imageInfosToCopy.insert(imageInfosToCopy.end(), imageInfoList.begin(), imageInfoList.end()); + + return true; +} diff --git a/src/vsg/vk/MemoryBufferPools.cpp b/src/vsg/vk/MemoryBufferPools.cpp index e81ca6e22..496046a25 100644 --- a/src/vsg/vk/MemoryBufferPools.cpp +++ b/src/vsg/vk/MemoryBufferPools.cpp @@ -220,6 +220,34 @@ MemoryBufferPools::DeviceMemoryOffset MemoryBufferPools::reserveMemory(VkMemoryR return MemoryBufferPools::DeviceMemoryOffset(deviceMemory, reservedSlot.second); } + +VkResult MemoryBufferPools::reserve(const BufferInfoList& bufferInfos, VkDeviceSize alignment, VkBufferUsageFlags bufferUsageFlags, VkSharingMode sharingMode, VkMemoryPropertyFlags memoryProperties) +{ + bool allocationSuccess = true; + + for (auto& bufferInfo : bufferInfos) + { + if (!bufferInfo->buffer) + { + if (allocationSuccess) + { + auto newBufferInfo = reserveBuffer(bufferInfo->data->dataSize(), alignment, bufferUsageFlags, sharingMode, memoryProperties); + if (newBufferInfo) + { + bufferInfo->take(*newBufferInfo); + } + else + { + debug("MemoryBufferPools::reserve() failed on ", bufferInfo, ", data = ", bufferInfo->data); + allocationSuccess = false; + } + } + } + } + + return allocationSuccess ? VK_SUCCESS : VK_ERROR_OUT_OF_DEVICE_MEMORY; +} + VkResult MemoryBufferPools::reserve(ResourceRequirements& requirements) { //vsg::info("MemoryBufferPools::reserve(ResourceRequirements& requirements) { ");