Implement a basic VulkanRenderDevice

This commit is contained in:
Magnus Norddahl 2023-10-06 00:08:43 +02:00
parent 3572d81010
commit 0b09fa9793
2 changed files with 148 additions and 12 deletions

View file

@ -50,20 +50,37 @@ VulkanRenderDevice::~VulkanRenderDevice()
VkCommandBufferManager::VkCommandBufferManager(VulkanRenderDevice* fb) : fb(fb)
{
mCommandPool = CommandPoolBuilder()
.QueueFamily(fb->GetDevice()->GraphicsFamily)
.DebugName("mCommandPool")
.Create(fb->GetDevice());
}
void VkCommandBufferManager::SubmitAndWait()
{
if (mTransferCommands)
{
mTransferCommands->end();
QueueSubmit()
.AddCommandBuffer(mTransferCommands.get())
.Execute(fb->GetDevice(), fb->GetDevice()->GraphicsQueue);
vkDeviceWaitIdle(fb->GetDevice()->device);
}
TransferDeleteList = std::make_unique<DeleteList>();
DrawDeleteList = std::make_unique<DeleteList>();
}
VulkanCommandBuffer* VkCommandBufferManager::GetTransferCommands()
{
return TransferCommands.get();
}
VulkanCommandBuffer* VkCommandBufferManager::GetDrawCommands()
{
return DrawCommands.get();
if (!mTransferCommands)
{
mTransferCommands = mCommandPool->createBuffer();
mTransferCommands->begin();
}
return mTransferCommands.get();
}
/////////////////////////////////////////////////////////////////////////////
@ -72,8 +89,109 @@ VkTextureManager::VkTextureManager(VulkanRenderDevice* fb) : fb(fb)
{
}
void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount)
{
if (LMTextureSize == newLMTextureSize && LMTextureCount == newLMTextureCount + 1)
return;
LMTextureSize = newLMTextureSize;
LMTextureCount = newLMTextureCount + 1; // the extra texture is for the dynamic lightmap
int w = newLMTextureSize;
int h = newLMTextureSize;
int count = newLMTextureCount;
int pixelsize = 8;
Lightmap.Reset(fb);
Lightmap.Image = ImageBuilder()
.Size(w, h, 1, LMTextureCount)
.Format(VK_FORMAT_R16G16B16A16_SFLOAT)
.Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.DebugName("VkRenderBuffers.Lightmap")
.Create(fb->GetDevice());
PipelineBarrier()
.AddImage(Lightmap.Image.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, LMTextureCount)
.Execute(fb->GetCommands()->GetTransferCommands(), 0, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
void VkTextureManager::DownloadLightmap(int arrayIndex, TArray<uint16_t>& buffer)
{
unsigned int totalSize = LMTextureSize * LMTextureSize;
buffer.Resize(totalSize);
auto stagingBuffer = BufferBuilder()
.Size(totalSize * sizeof(uint16_t))
.Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
.DebugName("DownloadLightmap")
.Create(fb->GetDevice());
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
PipelineBarrier()
.AddImage(Lightmap.Image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, arrayIndex, 1)
.Execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VkBufferImageCopy region = {};
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.baseArrayLayer = arrayIndex;
region.imageSubresource.layerCount = 1;
region.imageSubresource.mipLevel = 0;
region.imageExtent.width = LMTextureSize;
region.imageExtent.height = LMTextureSize;
region.imageExtent.depth = 1;
cmdbuffer->copyImageToBuffer(Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer->buffer, 1, &region);
PipelineBarrier()
.AddImage(Lightmap.Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, arrayIndex, 1)
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
fb->GetCommands()->SubmitAndWait();
uint16_t* srcdata = (uint16_t*)stagingBuffer->Map(0, totalSize * sizeof(uint16_t));
memcpy(buffer.Data(), srcdata, totalSize * sizeof(uint16_t));
stagingBuffer->Unmap();
}
/////////////////////////////////////////////////////////////////////////////
VkDescriptorSetManager::VkDescriptorSetManager(VulkanRenderDevice* fb) : fb(fb)
{
CreateBindlessDescriptorSet();
}
void VkDescriptorSetManager::CreateBindlessDescriptorSet()
{
BindlessDescriptorPool = DescriptorPoolBuilder()
.Flags(VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)
.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MaxBindlessTextures)
.MaxSets(MaxBindlessTextures)
.DebugName("BindlessDescriptorPool")
.Create(fb->GetDevice());
BindlessDescriptorSetLayout = DescriptorSetLayoutBuilder()
.Flags(VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)
.AddBinding(
0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
MaxBindlessTextures,
VK_SHADER_STAGE_FRAGMENT_BIT,
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT)
.DebugName("BindlessDescriptorSetLayout")
.Create(fb->GetDevice());
BindlessDescriptorSet = BindlessDescriptorPool->allocate(BindlessDescriptorSetLayout.get(), MaxBindlessTextures);
}
void VkDescriptorSetManager::UpdateBindlessDescriptorSet()
{
WriteBindless.Execute(fb->GetDevice());
WriteBindless = WriteDescriptors();
}
int VkDescriptorSetManager::AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler)
{
int index = NextBindlessIndex++;
WriteBindless.AddCombinedImageSampler(BindlessDescriptorSet.get(), 0, index, imageview, sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
return index;
}

View file

@ -2,6 +2,7 @@
#include "framework/zstring.h"
#include "zvulkan/vulkanobjects.h"
#include "zvulkan/vulkanbuilders.h"
#include "textureid.h"
#include <stdexcept>
@ -45,7 +46,6 @@ public:
void SubmitAndWait();
VulkanCommandBuffer* GetTransferCommands();
VulkanCommandBuffer* GetDrawCommands();
void PushGroup(VulkanCommandBuffer* cmdbuffer, const FString& name) { }
void PopGroup(VulkanCommandBuffer* cmdbuffer) { }
@ -82,8 +82,9 @@ public:
private:
VulkanRenderDevice* fb = nullptr;
std::unique_ptr<VulkanCommandBuffer> TransferCommands;
std::unique_ptr<VulkanCommandBuffer> DrawCommands;
std::unique_ptr<VulkanCommandPool> mCommandPool;
std::unique_ptr<VulkanCommandBuffer> mTransferCommands;
std::unique_ptr<VulkanCommandBuffer> mDrawCommands;
};
class VkTextureImage
@ -111,8 +112,12 @@ class VkTextureManager
public:
VkTextureManager(VulkanRenderDevice* fb);
void CreateLightmap(int newLMTextureSize, int newLMTextureCount);
void DownloadLightmap(int arrayIndex, TArray<uint16_t>& buffer);
VkTextureImage Lightmap;
int LMTextureSize = 1024;
int LMTextureSize = 0;
int LMTextureCount = 0;
private:
VulkanRenderDevice* fb = nullptr;
@ -123,11 +128,24 @@ class VkDescriptorSetManager
public:
VkDescriptorSetManager(VulkanRenderDevice* fb);
VulkanDescriptorSetLayout* GetBindlessSetLayout() { return nullptr; }
VulkanDescriptorSet* GetBindlessDescriptorSet() { return nullptr; }
VulkanDescriptorSetLayout* GetBindlessSetLayout() { return BindlessDescriptorSetLayout.get(); }
VulkanDescriptorSet* GetBindlessDescriptorSet() { return BindlessDescriptorSet.get(); }
void UpdateBindlessDescriptorSet();
int AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler);
private:
void CreateBindlessDescriptorSet();
VulkanRenderDevice* fb = nullptr;
std::unique_ptr<VulkanDescriptorPool> BindlessDescriptorPool;
std::unique_ptr<VulkanDescriptorSet> BindlessDescriptorSet;
std::unique_ptr<VulkanDescriptorSetLayout> BindlessDescriptorSetLayout;
WriteDescriptors WriteBindless;
int NextBindlessIndex = 0;
static const int MaxBindlessTextures = 16536;
};
inline void I_FatalError(const char* reason) { throw std::runtime_error(reason); }