From 8f8f270cfc094e97c0cd88663a6c6d342e965d4a Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Sun, 6 Oct 2019 14:31:39 +0200 Subject: [PATCH] vulkan: use separate command buffer to upload tex. Limit desc set size. --- core/rend/vulkan/buffer.h | 42 ----------------------------- core/rend/vulkan/texture.cpp | 26 +++++++++++++----- core/rend/vulkan/texture.h | 2 +- core/rend/vulkan/vulkan.h | 2 ++ core/rend/vulkan/vulkan_context.cpp | 22 +++++++-------- 5 files changed, 34 insertions(+), 60 deletions(-) diff --git a/core/rend/vulkan/buffer.h b/core/rend/vulkan/buffer.h index a7ae2e091..3ddc76a47 100644 --- a/core/rend/vulkan/buffer.h +++ b/core/rend/vulkan/buffer.h @@ -36,48 +36,6 @@ struct BufferData device.unmapMemory(*this->deviceMemory); } - template - void upload(vk::Device const& device, DataType const& data) const - { - assert((m_propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent) && (m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)); - assert(sizeof(DataType) <= m_size); - - void* dataPtr = device.mapMemory(*this->deviceMemory, 0, sizeof(DataType)); - memcpy(dataPtr, &data, sizeof(DataType)); - device.unmapMemory(*this->deviceMemory); - } - - template - void upload(vk::Device const& device, std::vector const& data, size_t stride = 0) const - { - assert(m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible); - - size_t elementSize = stride ? stride : sizeof(DataType); - assert(sizeof(DataType) <= elementSize); - - copyToDevice(device, deviceMemory, data.data(), data.size(), elementSize); - } - - template - void upload(vk::PhysicalDevice const& physicalDevice, vk::Device const& device, vk::CommandPool const& commandPool, vk::Queue queue, std::vector const& data, - size_t stride) const - { - assert(m_usage & vk::BufferUsageFlagBits::eTransferDst); - assert(m_propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal); - - size_t elementSize = stride ? stride : sizeof(DataType); - assert(sizeof(DataType) <= elementSize); - - size_t dataSize = data.size() * elementSize; - assert(dataSize <= m_size); - - BufferData stagingBuffer(physicalDevice, device, dataSize, vk::BufferUsageFlagBits::eTransferSrc); - copyToDevice(device, stagingBuffer.deviceMemory, data.data(), data.size(), elementSize); - - oneTimeSubmit(device, commandPool, queue, - [&](vk::CommandBuffer const& commandBuffer) { commandBuffer.copyBuffer(*stagingBuffer.buffer, *this->buffer, vk::BufferCopy(0, 0, dataSize)); }); - } - vk::UniqueDeviceMemory deviceMemory; vk::UniqueBuffer buffer; vk::DeviceSize m_size; diff --git a/core/rend/vulkan/texture.cpp b/core/rend/vulkan/texture.cpp index bf905c8f6..49518e9ed 100644 --- a/core/rend/vulkan/texture.cpp +++ b/core/rend/vulkan/texture.cpp @@ -147,7 +147,7 @@ void Texture::UploadToGPU(int width, int height, u8 *data) break; } Init(width, height, format); - SetImage(VulkanContext::Instance()->GetCurrentCommandBuffer(), dataSize, data); + SetImage(VulkanContext::Instance()->GetCurrentCommandPool(), dataSize, data); } void Texture::Init(u32 width, u32 height, vk::Format format) @@ -201,8 +201,12 @@ void Texture::CreateImage(vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk: imageView = device.createImageViewUnique(imageViewCreateInfo); } -void Texture::SetImage(vk::CommandBuffer const& commandBuffer, u32 srcSize, void *srcData) +void Texture::SetImage(const vk::CommandPool& commandPool, u32 srcSize, void *srcData) { + vk::UniqueCommandBuffer commandBuffer = std::move(device.allocateCommandBuffersUnique( + vk::CommandBufferAllocateInfo(commandPool, vk::CommandBufferLevel::ePrimary, 1)).front()); + commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit)); + vk::DeviceSize size = needsStaging ? device.getBufferMemoryRequirements(stagingBufferData->buffer.get()).size : device.getImageMemoryRequirements(image.get()).size; @@ -215,15 +219,25 @@ void Texture::SetImage(vk::CommandBuffer const& commandBuffer, u32 srcSize, void if (needsStaging) { // Since we're going to blit to the texture image, set its layout to eTransferDstOptimal - setImageLayout(commandBuffer, image.get(), format, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); + setImageLayout(*commandBuffer, image.get(), format, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); vk::BufferImageCopy copyRegion(0, extent.width, extent.height, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), vk::Extent3D(extent, 1)); - commandBuffer.copyBufferToImage(stagingBufferData->buffer.get(), image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion); + commandBuffer->copyBufferToImage(stagingBufferData->buffer.get(), image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion); // Set the layout for the texture image from eTransferDstOptimal to SHADER_READ_ONLY - setImageLayout(commandBuffer, image.get(), format, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); + setImageLayout(*commandBuffer, image.get(), format, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); } else { // If we can use the linear tiled image as a texture, just do it - setImageLayout(commandBuffer, image.get(), format, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eShaderReadOnlyOptimal); + setImageLayout(*commandBuffer, image.get(), format, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eShaderReadOnlyOptimal); + } + commandBuffer->end(); + VulkanContext::Instance()->GetGraphicsQueue().submit(vk::SubmitInfo(0, nullptr, nullptr, 1, &(*commandBuffer)), nullptr); + + // FIXME we need to wait for the command buffer to finish executing before freeing the staging and command buffers + VulkanContext::Instance()->GetGraphicsQueue().waitIdle(); + if (needsStaging) + { + // Free staging buffer + stagingBufferData = nullptr; } } diff --git a/core/rend/vulkan/texture.h b/core/rend/vulkan/texture.h index 205c7aa7b..1aa525df0 100644 --- a/core/rend/vulkan/texture.h +++ b/core/rend/vulkan/texture.h @@ -37,7 +37,7 @@ struct Texture : BaseTextureCacheData private: void Init(u32 width, u32 height, vk::Format format); - void SetImage(vk::CommandBuffer const& commandBuffer, u32 size, void *data); + void SetImage(const vk::CommandPool& commandPool, u32 size, void *data); void CreateImage(vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::ImageLayout initialLayout, vk::MemoryPropertyFlags memoryProperties, vk::ImageAspectFlags aspectMask); diff --git a/core/rend/vulkan/vulkan.h b/core/rend/vulkan/vulkan.h index 94eea7b2d..db9b39793 100644 --- a/core/rend/vulkan/vulkan.h +++ b/core/rend/vulkan/vulkan.h @@ -61,6 +61,7 @@ public: vk::UniqueDevice& GetDevice() { return device; } vk::PipelineCache GetPipelineCache() const { return *pipelineCache; } vk::RenderPass GetRenderPass() const { return *renderPass; } + vk::CommandPool GetCurrentCommandPool() const { return *commandPools[currentImage]; } vk::CommandBuffer GetCurrentCommandBuffer() const { return *commandBuffers[currentImage]; } vk::DescriptorPool GetDescriptorPool() const { return *descriptorPool; } vk::Extent2D GetViewPort() const { return { width, height }; } @@ -68,6 +69,7 @@ public: int GetCurrentImageIndex() const { return currentImage; } void WaitIdle() const { graphicsQueue.waitIdle(); } bool IsRendering() const { return rendering; } + vk::Queue GetGraphicsQueue() const { return graphicsQueue; } static VulkanContext *Instance() { return contextInstance; } diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index db647dfe5..b6a4d3586 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -282,20 +282,20 @@ void VulkanContext::InitDevice() // Descriptor pool vk::DescriptorPoolSize pool_sizes[] = { - { vk::DescriptorType::eSampler, 1000 }, + { vk::DescriptorType::eSampler, 2 }, { vk::DescriptorType::eCombinedImageSampler, 1000 }, - { vk::DescriptorType::eSampledImage, 1000 }, - { vk::DescriptorType::eStorageImage, 1000 }, - { vk::DescriptorType::eUniformTexelBuffer, 1000 }, - { vk::DescriptorType::eStorageTexelBuffer, 1000 }, - { vk::DescriptorType::eUniformBuffer, 1000 }, - { vk::DescriptorType::eStorageBuffer, 1000 }, - { vk::DescriptorType::eUniformBufferDynamic, 1000 }, - { vk::DescriptorType::eStorageBufferDynamic, 1000 }, - { vk::DescriptorType::eInputAttachment, 1000 } + { vk::DescriptorType::eSampledImage, 2 }, + { vk::DescriptorType::eStorageImage, 2 }, + { vk::DescriptorType::eUniformTexelBuffer, 2 }, + { vk::DescriptorType::eStorageTexelBuffer, 2 }, + { vk::DescriptorType::eUniformBuffer, 4 }, + { vk::DescriptorType::eStorageBuffer, 2 }, + { vk::DescriptorType::eUniformBufferDynamic, 2 }, + { vk::DescriptorType::eStorageBufferDynamic, 2 }, + { vk::DescriptorType::eInputAttachment, 2 } }; descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, - 1000 * ARRAY_SIZE(pool_sizes), ARRAY_SIZE(pool_sizes), pool_sizes)); + 10000, ARRAY_SIZE(pool_sizes), pool_sizes)); std::string cachePath = get_writable_data_path(PipelineCacheFileName);