Rework buffers synchronization
This commit is contained in:
parent
63547fcd4e
commit
b774a879b6
|
|
@ -130,9 +130,6 @@ int main()
|
||||||
|
|
||||||
Nz::UInt32 uniformSize = sizeof(ubo);
|
Nz::UInt32 uniformSize = sizeof(ubo);
|
||||||
|
|
||||||
Nz::UniformBuffer uniformBuffer(uniformSize, Nz::DataStorage_Hardware, Nz::BufferUsage_Dynamic);
|
|
||||||
uniformBuffer.Fill(&ubo, 0, uniformSize);
|
|
||||||
|
|
||||||
Nz::RenderPipelineLayoutInfo pipelineLayoutInfo;
|
Nz::RenderPipelineLayoutInfo pipelineLayoutInfo;
|
||||||
auto& bindingInfo = pipelineLayoutInfo.bindings.emplace_back();
|
auto& bindingInfo = pipelineLayoutInfo.bindings.emplace_back();
|
||||||
bindingInfo.index = 0;
|
bindingInfo.index = 0;
|
||||||
|
|
@ -162,13 +159,14 @@ int main()
|
||||||
|
|
||||||
Nz::Vk::DescriptorSet descriptorSet = descriptorPool.AllocateDescriptorSet(descriptorLayout);
|
Nz::Vk::DescriptorSet descriptorSet = descriptorPool.AllocateDescriptorSet(descriptorLayout);
|
||||||
|
|
||||||
Nz::RenderBuffer* renderBufferUB = static_cast<Nz::RenderBuffer*>(uniformBuffer.GetBuffer()->GetImpl());
|
std::unique_ptr<Nz::AbstractBuffer> uniformBuffer = device->InstantiateBuffer(Nz::BufferType_Uniform);
|
||||||
if (!renderBufferUB->Synchronize(&vulkanDevice))
|
if (!uniformBuffer->Initialize(uniformSize, Nz::BufferUsage_DeviceLocal))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to create uniform buffer");
|
NazaraError("Failed to create uniform buffer");
|
||||||
return __LINE__;
|
return __LINE__;
|
||||||
}
|
}
|
||||||
Nz::VulkanBuffer* uniformBufferImpl = static_cast<Nz::VulkanBuffer*>(renderBufferUB->GetHardwareBuffer(&vulkanDevice));
|
|
||||||
|
Nz::VulkanBuffer* uniformBufferImpl = static_cast<Nz::VulkanBuffer*>(uniformBuffer.get());
|
||||||
descriptorSet.WriteUniformDescriptor(0, uniformBufferImpl->GetBufferHandle(), 0, uniformSize);
|
descriptorSet.WriteUniformDescriptor(0, uniformBufferImpl->GetBufferHandle(), 0, uniformSize);
|
||||||
|
|
||||||
Nz::RenderPipelineInfo pipelineInfo;
|
Nz::RenderPipelineInfo pipelineInfo;
|
||||||
|
|
@ -353,18 +351,6 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateUniforms)
|
|
||||||
{
|
|
||||||
ubo.viewMatrix = Nz::Matrix4f::ViewMatrix(viewerPos, camAngles);
|
|
||||||
|
|
||||||
uniformBuffer.Fill(&ubo, 0, uniformSize);
|
|
||||||
if (!renderBufferUB->Synchronize(&vulkanDevice))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to synchronize render buffer");
|
|
||||||
return __LINE__;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageSync& syncPrimitives = frameSync[currentFrame];
|
ImageSync& syncPrimitives = frameSync[currentFrame];
|
||||||
syncPrimitives.inflightFence.Wait();
|
syncPrimitives.inflightFence.Wait();
|
||||||
|
|
||||||
|
|
@ -381,6 +367,18 @@ int main()
|
||||||
inflightFences[imageIndex] = &syncPrimitives.inflightFence;
|
inflightFences[imageIndex] = &syncPrimitives.inflightFence;
|
||||||
inflightFences[imageIndex]->Reset();
|
inflightFences[imageIndex]->Reset();
|
||||||
|
|
||||||
|
if (updateUniforms)
|
||||||
|
{
|
||||||
|
ubo.viewMatrix = Nz::Matrix4f::ViewMatrix(viewerPos, camAngles);
|
||||||
|
|
||||||
|
void* mappedPtr = uniformBufferImpl->Map(Nz::BufferAccess_DiscardAndWrite, 0, sizeof(ubo));
|
||||||
|
if (mappedPtr)
|
||||||
|
{
|
||||||
|
std::memcpy(mappedPtr, &ubo, sizeof(ubo));
|
||||||
|
uniformBufferImpl->Unmap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!graphicsQueue.Submit(renderCmds[imageIndex], syncPrimitives.imageAvailableSemaphore, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, syncPrimitives.renderFinishedSemaphore, syncPrimitives.inflightFence))
|
if (!graphicsQueue.Submit(renderCmds[imageIndex], syncPrimitives.imageAvailableSemaphore, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, syncPrimitives.renderFinishedSemaphore, syncPrimitives.inflightFence))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class Buffer;
|
|
||||||
class ShaderStageImpl;
|
class ShaderStageImpl;
|
||||||
|
|
||||||
class NAZARA_RENDERER_API RenderDevice
|
class NAZARA_RENDERER_API RenderDevice
|
||||||
|
|
@ -27,7 +26,7 @@ namespace Nz
|
||||||
RenderDevice() = default;
|
RenderDevice() = default;
|
||||||
virtual ~RenderDevice();
|
virtual ~RenderDevice();
|
||||||
|
|
||||||
virtual std::unique_ptr<AbstractBuffer> InstantiateBuffer(Buffer* parent, BufferType type) = 0;
|
virtual std::unique_ptr<AbstractBuffer> InstantiateBuffer(BufferType type) = 0;
|
||||||
virtual std::unique_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0;
|
virtual std::unique_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) = 0;
|
||||||
virtual std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0;
|
virtual std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) = 0;
|
||||||
virtual std::shared_ptr<ShaderStageImpl> InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0;
|
virtual std::shared_ptr<ShaderStageImpl> InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) = 0;
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,10 @@ namespace Nz
|
||||||
|
|
||||||
enum BufferUsage
|
enum BufferUsage
|
||||||
{
|
{
|
||||||
BufferUsage_Dynamic,
|
BufferUsage_DeviceLocal,
|
||||||
BufferUsage_FastRead,
|
BufferUsage_DirectMapping,
|
||||||
|
|
||||||
BufferUsage_Max = BufferUsage_FastRead
|
BufferUsage_Max = BufferUsage_DirectMapping
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,11 @@
|
||||||
#include <Nazara/Renderer/Enums.hpp>
|
#include <Nazara/Renderer/Enums.hpp>
|
||||||
#include <Nazara/Utility/Enums.hpp>
|
#include <Nazara/Utility/Enums.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Loader.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
inline VkBufferUsageFlags ToVulkan(BufferType bufferType);
|
||||||
inline VkFormat ToVulkan(ComponentType componentType);
|
inline VkFormat ToVulkan(ComponentType componentType);
|
||||||
inline VkCullModeFlagBits ToVulkan(FaceSide faceSide);
|
inline VkCullModeFlagBits ToVulkan(FaceSide faceSide);
|
||||||
inline VkPolygonMode ToVulkan(FaceFilling faceFilling);
|
inline VkPolygonMode ToVulkan(FaceFilling faceFilling);
|
||||||
|
|
@ -26,7 +28,7 @@ namespace Nz
|
||||||
inline VkStencilOp ToVulkan(StencilOperation stencilOp);
|
inline VkStencilOp ToVulkan(StencilOperation stencilOp);
|
||||||
inline VkVertexInputRate ToVulkan(VertexInputRate inputRate);
|
inline VkVertexInputRate ToVulkan(VertexInputRate inputRate);
|
||||||
|
|
||||||
NAZARA_VULKANRENDERER_API String TranslateVulkanError(VkResult code);
|
NAZARA_VULKANRENDERER_API std::string TranslateVulkanError(VkResult code);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/VulkanRenderer/Utils.inl>
|
#include <Nazara/VulkanRenderer/Utils.inl>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,19 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
VkBufferUsageFlags ToVulkan(BufferType bufferType)
|
||||||
|
{
|
||||||
|
switch (bufferType)
|
||||||
|
{
|
||||||
|
case BufferType_Index: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||||
|
case BufferType_Vertex: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||||
|
case BufferType_Uniform: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
NazaraError("Unhandled BufferType 0x" + String::Number(bufferType, 16));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
VkFormat ToVulkan(ComponentType componentType)
|
VkFormat ToVulkan(ComponentType componentType)
|
||||||
{
|
{
|
||||||
switch (componentType)
|
switch (componentType)
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,10 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class Buffer;
|
|
||||||
|
|
||||||
class NAZARA_VULKANRENDERER_API VulkanBuffer : public AbstractBuffer
|
class NAZARA_VULKANRENDERER_API VulkanBuffer : public AbstractBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline VulkanBuffer(Vk::Device& device, Buffer* parent, BufferType type);
|
inline VulkanBuffer(Vk::Device& device, BufferType type);
|
||||||
VulkanBuffer(const VulkanBuffer&) = delete;
|
VulkanBuffer(const VulkanBuffer&) = delete;
|
||||||
VulkanBuffer(VulkanBuffer&&) = delete; ///TODO
|
VulkanBuffer(VulkanBuffer&&) = delete; ///TODO
|
||||||
virtual ~VulkanBuffer();
|
virtual ~VulkanBuffer();
|
||||||
|
|
@ -35,18 +33,22 @@ namespace Nz
|
||||||
|
|
||||||
DataStorage GetStorage() const override;
|
DataStorage GetStorage() const override;
|
||||||
|
|
||||||
void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) override;
|
void* Map(BufferAccess access, UInt32 offset, UInt32 size) override;
|
||||||
bool Unmap() override;
|
bool Unmap() override;
|
||||||
|
|
||||||
VulkanBuffer& operator=(const VulkanBuffer&) = delete;
|
VulkanBuffer& operator=(const VulkanBuffer&) = delete;
|
||||||
VulkanBuffer& operator=(VulkanBuffer&&) = delete; ///TODO
|
VulkanBuffer& operator=(VulkanBuffer&&) = delete; ///TODO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Buffer* m_parent;
|
Vk::Buffer m_stagingBuffer;
|
||||||
|
Vk::DeviceMemory m_stagingMemory;
|
||||||
BufferType m_type;
|
BufferType m_type;
|
||||||
Nz::Vk::Buffer m_buffer;
|
BufferUsageFlags m_usage;
|
||||||
Nz::Vk::DeviceMemory m_memory;
|
UInt32 m_size;
|
||||||
|
Vk::Buffer m_buffer;
|
||||||
|
Vk::Fence m_stagingFence;
|
||||||
Vk::Device& m_device;
|
Vk::Device& m_device;
|
||||||
|
Vk::DeviceMemory m_memory;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,13 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
inline VulkanBuffer::VulkanBuffer(Vk::Device& device, Buffer* /*parent*/, BufferType type) :
|
inline VulkanBuffer::VulkanBuffer(Vk::Device& device, BufferType type) :
|
||||||
m_device(device),
|
m_device(device),
|
||||||
m_parent(parent),
|
|
||||||
m_type(type)
|
m_type(type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Nz::Vk::Buffer& Nz::VulkanBuffer::GetBufferHandle()
|
inline Vk::Buffer& VulkanBuffer::GetBufferHandle()
|
||||||
{
|
{
|
||||||
return m_buffer;
|
return m_buffer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Nz
|
||||||
VulkanDevice(VulkanDevice&&) = delete; ///TODO?
|
VulkanDevice(VulkanDevice&&) = delete; ///TODO?
|
||||||
~VulkanDevice();
|
~VulkanDevice();
|
||||||
|
|
||||||
std::unique_ptr<AbstractBuffer> InstantiateBuffer(Buffer* parent, BufferType type) override;
|
std::unique_ptr<AbstractBuffer> InstantiateBuffer(BufferType type) override;
|
||||||
std::unique_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
std::unique_ptr<RenderPipeline> InstantiateRenderPipeline(RenderPipelineInfo pipelineInfo) override;
|
||||||
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
|
std::shared_ptr<RenderPipelineLayout> InstantiateRenderPipelineLayout(RenderPipelineLayoutInfo pipelineLayoutInfo) override;
|
||||||
std::shared_ptr<ShaderStageImpl> InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override;
|
std::shared_ptr<ShaderStageImpl> InstantiateShaderStage(ShaderStageType type, ShaderLanguage lang, const void* source, std::size_t sourceSize) override;
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,8 @@ namespace Nz
|
||||||
inline void ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, const VkImageSubresourceRange& range);
|
inline void ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, const VkImageSubresourceRange& range);
|
||||||
inline void ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, UInt32 rangeCount, const VkImageSubresourceRange* ranges);
|
inline void ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, UInt32 rangeCount, const VkImageSubresourceRange* ranges);
|
||||||
|
|
||||||
|
inline void CopyBuffer(VkBuffer source, VkBuffer target, UInt32 size, UInt32 sourceOffset = 0, UInt32 targetOffset = 0);
|
||||||
|
|
||||||
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
|
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
|
||||||
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, Int32 vertexOffset = 0, UInt32 firstInstance = 0);
|
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, Int32 vertexOffset = 0, UInt32 firstInstance = 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,16 @@ namespace Nz
|
||||||
return m_pool->GetDevice()->vkCmdClearDepthStencilImage(m_handle, image, imageLayout, &depthStencil, rangeCount, ranges);
|
return m_pool->GetDevice()->vkCmdClearDepthStencilImage(m_handle, image, imageLayout, &depthStencil, rangeCount, ranges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void CommandBuffer::CopyBuffer(VkBuffer source, VkBuffer target, UInt32 size, UInt32 sourceOffset, UInt32 targetOffset)
|
||||||
|
{
|
||||||
|
VkBufferCopy region;
|
||||||
|
region.dstOffset = targetOffset;
|
||||||
|
region.size = size;
|
||||||
|
region.srcOffset = sourceOffset;
|
||||||
|
|
||||||
|
return m_pool->GetDevice()->vkCmdCopyBuffer(m_handle, source, target, 1, ®ion);
|
||||||
|
}
|
||||||
|
|
||||||
inline void CommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
inline void CommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
||||||
{
|
{
|
||||||
return m_pool->GetDevice()->vkCmdDraw(m_handle, vertexCount, instanceCount, firstVertex, firstInstance);
|
return m_pool->GetDevice()->vkCmdDraw(m_handle, vertexCount, instanceCount, firstVertex, firstInstance);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
namespace Vk
|
namespace Vk
|
||||||
{
|
{
|
||||||
|
class CommandBuffer;
|
||||||
class Instance;
|
class Instance;
|
||||||
class Queue;
|
class Queue;
|
||||||
|
|
||||||
|
|
@ -34,6 +35,8 @@ namespace Nz
|
||||||
Device(Device&&) = delete;
|
Device(Device&&) = delete;
|
||||||
~Device();
|
~Device();
|
||||||
|
|
||||||
|
CommandBuffer AllocateTransferCommandBuffer();
|
||||||
|
|
||||||
bool Create(const Vk::PhysicalDevice& deviceInfo, const VkDeviceCreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr);
|
bool Create(const Vk::PhysicalDevice& deviceInfo, const VkDeviceCreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr);
|
||||||
inline void Destroy();
|
inline void Destroy();
|
||||||
|
|
||||||
|
|
@ -47,6 +50,8 @@ namespace Nz
|
||||||
inline VkPhysicalDevice GetPhysicalDevice() const;
|
inline VkPhysicalDevice GetPhysicalDevice() const;
|
||||||
inline const Vk::PhysicalDevice& GetPhysicalDeviceInfo() const;
|
inline const Vk::PhysicalDevice& GetPhysicalDeviceInfo() const;
|
||||||
|
|
||||||
|
inline UInt32 GetTransferQueueFamilyIndex() const;
|
||||||
|
|
||||||
inline bool IsExtensionLoaded(const std::string& extensionName);
|
inline bool IsExtensionLoaded(const std::string& extensionName);
|
||||||
inline bool IsLayerLoaded(const std::string& layerName);
|
inline bool IsLayerLoaded(const std::string& layerName);
|
||||||
|
|
||||||
|
|
@ -90,11 +95,15 @@ namespace Nz
|
||||||
|
|
||||||
inline PFN_vkVoidFunction GetProcAddr(const char* name);
|
inline PFN_vkVoidFunction GetProcAddr(const char* name);
|
||||||
|
|
||||||
|
struct InternalData;
|
||||||
|
|
||||||
|
std::unique_ptr<InternalData> m_internalData;
|
||||||
Instance& m_instance;
|
Instance& m_instance;
|
||||||
const Vk::PhysicalDevice* m_physicalDevice;
|
const Vk::PhysicalDevice* m_physicalDevice;
|
||||||
VkAllocationCallbacks m_allocator;
|
VkAllocationCallbacks m_allocator;
|
||||||
VkDevice m_device;
|
VkDevice m_device;
|
||||||
VkResult m_lastErrorCode;
|
VkResult m_lastErrorCode;
|
||||||
|
UInt32 m_transferQueueFamilyIndex;
|
||||||
std::unordered_set<std::string> m_loadedExtensions;
|
std::unordered_set<std::string> m_loadedExtensions;
|
||||||
std::unordered_set<std::string> m_loadedLayers;
|
std::unordered_set<std::string> m_loadedLayers;
|
||||||
std::vector<QueueFamilyInfo> m_enabledQueuesInfos;
|
std::vector<QueueFamilyInfo> m_enabledQueuesInfos;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,11 @@ namespace Nz
|
||||||
return *m_physicalDevice;
|
return *m_physicalDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline UInt32 Device::GetTransferQueueFamilyIndex() const
|
||||||
|
{
|
||||||
|
return m_transferQueueFamilyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool Device::IsExtensionLoaded(const std::string& extensionName)
|
inline bool Device::IsExtensionLoaded(const std::string& extensionName)
|
||||||
{
|
{
|
||||||
return m_loadedExtensions.count(extensionName) > 0;
|
return m_loadedExtensions.count(extensionName) > 0;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ namespace Nz
|
||||||
inline bool Create(Device& device, VkDeviceSize size, UInt32 memoryType, const VkAllocationCallbacks* allocator = nullptr);
|
inline bool Create(Device& device, VkDeviceSize size, UInt32 memoryType, const VkAllocationCallbacks* allocator = nullptr);
|
||||||
inline bool Create(Device& device, VkDeviceSize size, UInt32 typeBits, VkFlags properties, const VkAllocationCallbacks* allocator = nullptr);
|
inline bool Create(Device& device, VkDeviceSize size, UInt32 typeBits, VkFlags properties, const VkAllocationCallbacks* allocator = nullptr);
|
||||||
|
|
||||||
|
inline bool FlushMemory();
|
||||||
|
inline bool FlushMemory(UInt64 offset, UInt64 size);
|
||||||
|
|
||||||
inline void* GetMappedPointer();
|
inline void* GetMappedPointer();
|
||||||
|
|
||||||
inline bool Map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags = 0);
|
inline bool Map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags = 0);
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,31 @@ namespace Nz
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool DeviceMemory::FlushMemory()
|
||||||
|
{
|
||||||
|
return FlushMemory(0, VK_WHOLE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DeviceMemory::FlushMemory(UInt64 offset, UInt64 size)
|
||||||
|
{
|
||||||
|
VkMappedMemoryRange memoryRange = {
|
||||||
|
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,
|
||||||
|
nullptr,
|
||||||
|
m_handle,
|
||||||
|
offset,
|
||||||
|
size
|
||||||
|
};
|
||||||
|
|
||||||
|
m_lastErrorCode = m_device->vkFlushMappedMemoryRanges(*m_device, 1, &memoryRange);
|
||||||
|
if (m_lastErrorCode != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
NazaraError("Failed to flush memory: " + TranslateVulkanError(m_lastErrorCode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
inline void* DeviceMemory::GetMappedPointer()
|
inline void* DeviceMemory::GetMappedPointer()
|
||||||
{
|
{
|
||||||
return m_mappedPtr;
|
return m_mappedPtr;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace Nz
|
||||||
if (it == m_hardwareBuffers.end())
|
if (it == m_hardwareBuffers.end())
|
||||||
{
|
{
|
||||||
HardwareBuffer hwBuffer;
|
HardwareBuffer hwBuffer;
|
||||||
hwBuffer.buffer = device->InstantiateBuffer(m_parent, m_type);
|
hwBuffer.buffer = device->InstantiateBuffer(m_type);
|
||||||
if (!hwBuffer.buffer->Initialize(m_size, m_usage))
|
if (!hwBuffer.buffer->Initialize(m_size, m_usage))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to initialize hardware buffer");
|
NazaraError("Failed to initialize hardware buffer");
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ namespace Nz
|
||||||
bool largeIndices = (vertexCount > std::numeric_limits<UInt16>::max());
|
bool largeIndices = (vertexCount > std::numeric_limits<UInt16>::max());
|
||||||
|
|
||||||
IndexBufferRef indexBuffer = IndexBuffer::New(largeIndices, UInt32(indexCount), parameters.storage, parameters.indexBufferFlags);
|
IndexBufferRef indexBuffer = IndexBuffer::New(largeIndices, UInt32(indexCount), parameters.storage, parameters.indexBufferFlags);
|
||||||
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent_Skinning), UInt32(vertexCount), parameters.storage, parameters.vertexBufferFlags | BufferUsage_Dynamic);
|
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent_Skinning), UInt32(vertexCount), parameters.storage, parameters.vertexBufferFlags);
|
||||||
|
|
||||||
// Index buffer
|
// Index buffer
|
||||||
IndexMapper indexMapper(indexBuffer, BufferAccess_DiscardAndWrite);
|
IndexMapper indexMapper(indexBuffer, BufferAccess_DiscardAndWrite);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
String TranslateVulkanError(VkResult code)
|
std::string TranslateVulkanError(VkResult code)
|
||||||
{
|
{
|
||||||
// From https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#VkResult
|
// From https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html#VkResult
|
||||||
switch (code)
|
switch (code)
|
||||||
|
|
@ -97,7 +97,7 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Unknown Vulkan error (0x" + String::Number(code, 16) + ')';
|
return "Unknown Vulkan error (0x" + String::Number(code, 16).ToStdString() + ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
#include <Nazara/VulkanRenderer/VulkanBuffer.hpp>
|
||||||
#include <Nazara/Core/CallOnExit.hpp>
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Wrapper/Queue.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -26,37 +28,30 @@ namespace Nz
|
||||||
|
|
||||||
bool VulkanBuffer::Initialize(UInt32 size, BufferUsageFlags usage)
|
bool VulkanBuffer::Initialize(UInt32 size, BufferUsageFlags usage)
|
||||||
{
|
{
|
||||||
VkBufferUsageFlags type;
|
m_size = size;
|
||||||
switch (m_type)
|
m_usage = usage;
|
||||||
|
|
||||||
|
VkBufferUsageFlags bufferUsage = ToVulkan(m_type);
|
||||||
|
VkMemoryPropertyFlags memoryProperties = 0;
|
||||||
|
if (usage & BufferUsage_DeviceLocal)
|
||||||
|
memoryProperties |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
||||||
|
|
||||||
|
if (usage & BufferUsage_DirectMapping)
|
||||||
|
memoryProperties |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||||
|
else
|
||||||
|
bufferUsage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
|
|
||||||
|
if (!m_buffer.Create(m_device, 0, size, bufferUsage))
|
||||||
{
|
{
|
||||||
case BufferType_Index:
|
NazaraError("Failed to create vulkan buffer");
|
||||||
type = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BufferType_Vertex:
|
|
||||||
type = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BufferType_Uniform:
|
|
||||||
type = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
NazaraError("Unhandled buffer usage 0x" + String::Number(m_type, 16));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_buffer.Create(m_device, 0, size, type))
|
|
||||||
{
|
|
||||||
NazaraError("Failed to create vertex buffer");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkMemoryRequirements memRequirement = m_buffer.GetMemoryRequirements();
|
VkMemoryRequirements memRequirement = m_buffer.GetMemoryRequirements();
|
||||||
|
|
||||||
if (!m_memory.Create(m_device, memRequirement.size, memRequirement.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
|
if (!m_memory.Create(m_device, memRequirement.size, memRequirement.memoryTypeBits, memoryProperties))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to allocate vertex buffer memory");
|
NazaraError("Failed to allocate buffer memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,15 +71,76 @@ namespace Nz
|
||||||
|
|
||||||
void* VulkanBuffer::Map(BufferAccess /*access*/, UInt32 offset, UInt32 size)
|
void* VulkanBuffer::Map(BufferAccess /*access*/, UInt32 offset, UInt32 size)
|
||||||
{
|
{
|
||||||
if (!m_memory.Map(offset, size))
|
if (m_usage & BufferUsage_DirectMapping)
|
||||||
return nullptr;
|
{
|
||||||
|
if (!m_memory.Map(offset, size))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
return m_memory.GetMappedPointer();
|
return m_memory.GetMappedPointer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!m_stagingFence.Create(m_device))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create staging fence");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_stagingBuffer.Create(m_device, 0, m_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create staging buffer");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
||||||
|
|
||||||
|
VkMemoryRequirements memRequirement = m_stagingBuffer.GetMemoryRequirements();
|
||||||
|
if (!m_stagingMemory.Create(m_device, memRequirement.size, memRequirement.memoryTypeBits, memoryProperties))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to allocate vertex buffer memory");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_stagingBuffer.BindBufferMemory(m_stagingMemory))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to bind vertex buffer to its memory");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_stagingMemory.Map(offset, size))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return m_stagingMemory.GetMappedPointer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanBuffer::Unmap()
|
bool VulkanBuffer::Unmap()
|
||||||
{
|
{
|
||||||
m_memory.Unmap();
|
if (m_usage & BufferUsage_DirectMapping)
|
||||||
return true;
|
{
|
||||||
|
m_memory.Unmap();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_stagingMemory.FlushMemory();
|
||||||
|
m_stagingMemory.Unmap();
|
||||||
|
|
||||||
|
Vk::CommandBuffer copyCommandBuffer = m_device.AllocateTransferCommandBuffer();
|
||||||
|
copyCommandBuffer.Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
||||||
|
copyCommandBuffer.CopyBuffer(m_stagingBuffer, m_buffer, m_size);
|
||||||
|
copyCommandBuffer.End();
|
||||||
|
|
||||||
|
Vk::Queue transferQueue = m_device.GetQueue(m_device.GetTransferQueueFamilyIndex(), 0);
|
||||||
|
if (!transferQueue.Submit(copyCommandBuffer, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, m_stagingFence))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_stagingFence.Wait();
|
||||||
|
|
||||||
|
m_stagingBuffer.Destroy();
|
||||||
|
m_stagingFence.Destroy();
|
||||||
|
m_stagingMemory.Destroy();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
#include <Nazara/Core/CallOnExit.hpp>
|
#include <Nazara/Core/CallOnExit.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/ErrorFlags.hpp>
|
#include <Nazara/Core/ErrorFlags.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp>
|
||||||
|
#include <Nazara/VulkanRenderer/Wrapper/CommandPool.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Queue.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Queue.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Debug.hpp>
|
#include <Nazara/VulkanRenderer/Debug.hpp>
|
||||||
|
|
||||||
|
|
@ -13,6 +15,11 @@ namespace Nz
|
||||||
{
|
{
|
||||||
namespace Vk
|
namespace Vk
|
||||||
{
|
{
|
||||||
|
struct Device::InternalData
|
||||||
|
{
|
||||||
|
Vk::CommandPool transferCommandPool;
|
||||||
|
};
|
||||||
|
|
||||||
Device::Device(Instance& instance) :
|
Device::Device(Instance& instance) :
|
||||||
m_instance(instance),
|
m_instance(instance),
|
||||||
m_physicalDevice(nullptr),
|
m_physicalDevice(nullptr),
|
||||||
|
|
@ -26,6 +33,11 @@ namespace Nz
|
||||||
WaitAndDestroyDevice();
|
WaitAndDestroyDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandBuffer Device::AllocateTransferCommandBuffer()
|
||||||
|
{
|
||||||
|
return m_internalData->transferCommandPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
||||||
|
}
|
||||||
|
|
||||||
void Device::Destroy()
|
void Device::Destroy()
|
||||||
{
|
{
|
||||||
if (m_device != VK_NULL_HANDLE)
|
if (m_device != VK_NULL_HANDLE)
|
||||||
|
|
@ -83,6 +95,8 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
// And retains informations about queues
|
// And retains informations about queues
|
||||||
|
m_transferQueueFamilyIndex = UINT32_MAX;
|
||||||
|
|
||||||
UInt32 maxFamilyIndex = 0;
|
UInt32 maxFamilyIndex = 0;
|
||||||
m_enabledQueuesInfos.resize(createInfo.queueCreateInfoCount);
|
m_enabledQueuesInfos.resize(createInfo.queueCreateInfoCount);
|
||||||
for (UInt32 i = 0; i < createInfo.queueCreateInfoCount; ++i)
|
for (UInt32 i = 0; i < createInfo.queueCreateInfoCount; ++i)
|
||||||
|
|
@ -107,12 +121,30 @@ namespace Nz
|
||||||
queueInfo.priority = queueCreateInfo.pQueuePriorities[queueIndex];
|
queueInfo.priority = queueCreateInfo.pQueuePriorities[queueIndex];
|
||||||
vkGetDeviceQueue(m_device, info.familyIndex, queueIndex, &queueInfo.queue);
|
vkGetDeviceQueue(m_device, info.familyIndex, queueIndex, &queueInfo.queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info.flags & (VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT))
|
||||||
|
{
|
||||||
|
if (m_transferQueueFamilyIndex == UINT32_MAX)
|
||||||
|
m_transferQueueFamilyIndex = info.familyIndex;
|
||||||
|
else if ((info.flags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT)) == 0)
|
||||||
|
{
|
||||||
|
m_transferQueueFamilyIndex = info.familyIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_queuesByFamily.resize(maxFamilyIndex + 1);
|
m_queuesByFamily.resize(maxFamilyIndex + 1);
|
||||||
for (const QueueFamilyInfo& familyInfo : m_enabledQueuesInfos)
|
for (const QueueFamilyInfo& familyInfo : m_enabledQueuesInfos)
|
||||||
m_queuesByFamily[familyInfo.familyIndex] = &familyInfo.queues;
|
m_queuesByFamily[familyInfo.familyIndex] = &familyInfo.queues;
|
||||||
|
|
||||||
|
m_internalData = std::make_unique<InternalData>();
|
||||||
|
if (!m_internalData->transferCommandPool.Create(*this, m_transferQueueFamilyIndex, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT))
|
||||||
|
{
|
||||||
|
NazaraError("Failed to create transfer command pool: " + TranslateVulkanError(m_internalData->transferCommandPool.GetLastErrorCode()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
destroyOnFailure.Reset();
|
destroyOnFailure.Reset();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue