mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-21 04:51:18 +00:00
try fix vulkan sync error
This commit is contained in:
parent
6bf3a0eace
commit
3f1ef63a4e
@ -57,10 +57,15 @@ namespace engine {
|
|||||||
|
|
||||||
struct FrameData {
|
struct FrameData {
|
||||||
VkFence renderFence = VK_NULL_HANDLE;
|
VkFence renderFence = VK_NULL_HANDLE;
|
||||||
|
VkSemaphore transferSemaphore = VK_NULL_HANDLE;
|
||||||
VkSemaphore presentSemaphore = VK_NULL_HANDLE;
|
VkSemaphore presentSemaphore = VK_NULL_HANDLE;
|
||||||
VkSemaphore renderSemaphore = VK_NULL_HANDLE;
|
VkSemaphore renderSemaphore = VK_NULL_HANDLE;
|
||||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
|
||||||
|
VkCommandPool graphicsPool = VK_NULL_HANDLE;
|
||||||
VkCommandBuffer drawBuf = VK_NULL_HANDLE;
|
VkCommandBuffer drawBuf = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkCommandPool transferPool = VK_NULL_HANDLE;
|
||||||
|
VkCommandBuffer transferBuf = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
// handles
|
// handles
|
||||||
@ -92,7 +97,6 @@ namespace engine {
|
|||||||
FrameData frameData{};
|
FrameData frameData{};
|
||||||
uint32_t currentFrameIndex = 0; // corresponds to the frameData
|
uint32_t currentFrameIndex = 0; // corresponds to the frameData
|
||||||
uint32_t imageIndex = 0; // for swapchain present
|
uint32_t imageIndex = 0; // for swapchain present
|
||||||
std::unordered_set<gfx::DescriptorBuffer*>* buffersToWrite = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gfx::DescriptorSetLayout {
|
struct gfx::DescriptorSetLayout {
|
||||||
@ -224,77 +228,6 @@ namespace engine {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
static Swapchain::MSTarget createMSAATarget(VkSampleCountFlagBits msaaSamples, VkExtent2D extent, VkFormat colorFormat, VkDevice device, VmaAllocator allocator)
|
|
||||||
{
|
|
||||||
Swapchain::MSTarget target{};
|
|
||||||
|
|
||||||
[[maybe_unused]] VkResult res;
|
|
||||||
|
|
||||||
VkImageCreateInfo imageInfo{};
|
|
||||||
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
||||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
|
||||||
imageInfo.extent.width = extent.width;
|
|
||||||
imageInfo.extent.height = extent.height;
|
|
||||||
imageInfo.extent.depth = 1;
|
|
||||||
imageInfo.mipLevels = 1;
|
|
||||||
imageInfo.arrayLayers = 1;
|
|
||||||
imageInfo.format = colorFormat;
|
|
||||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
||||||
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
imageInfo.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
||||||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
imageInfo.samples = msaaSamples;
|
|
||||||
imageInfo.flags = 0;
|
|
||||||
|
|
||||||
VmaAllocationCreateInfo allocInfo{};
|
|
||||||
allocInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
|
||||||
allocInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
|
|
||||||
allocInfo.priority = 1.0f;
|
|
||||||
|
|
||||||
res = vmaCreateImage(allocator, &imageInfo, &allocInfo, &target.colorImage, &target.colorImageAllocation, nullptr);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
VkImageViewCreateInfo imageViewInfo{};
|
|
||||||
imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
||||||
imageViewInfo.image = target.colorImage;
|
|
||||||
imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
||||||
imageViewInfo.format = colorFormat;
|
|
||||||
imageViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
imageViewInfo.subresourceRange.baseMipLevel = 0;
|
|
||||||
imageViewInfo.subresourceRange.levelCount = 1;
|
|
||||||
imageViewInfo.subresourceRange.baseArrayLayer = 0;
|
|
||||||
imageViewInfo.subresourceRange.layerCount = 1;
|
|
||||||
res = vkCreateImageView(device, &imageViewInfo, nullptr, &target.colorImageView);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroyMSAATarget(const Swapchain::MSTarget& target, VkDevice device, VmaAllocator allocator)
|
|
||||||
{
|
|
||||||
vkDestroyImageView(device, target.colorImageView, nullptr);
|
|
||||||
vmaDestroyImage(allocator, target.colorImage, target.colorImageAllocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VkSampleCountFlagBits getMaxSampleCount(VkPhysicalDevice physicalDevice, gfx::MSAALevel maxLevel)
|
|
||||||
{
|
|
||||||
VkSampleCountFlags max = vkinternal::getSampleCountFlags(maxLevel);
|
|
||||||
VkPhysicalDeviceProperties physicalDeviceProperties;
|
|
||||||
vkGetPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
|
|
||||||
|
|
||||||
VkSampleCountFlags counts = physicalDeviceProperties.limits.framebufferColorSampleCounts & physicalDeviceProperties.limits.framebufferDepthSampleCounts;
|
|
||||||
counts %= (max << 1); // restricts sample count to maxLevel
|
|
||||||
if (counts & VK_SAMPLE_COUNT_64_BIT) { return VK_SAMPLE_COUNT_64_BIT; }
|
|
||||||
if (counts & VK_SAMPLE_COUNT_32_BIT) { return VK_SAMPLE_COUNT_32_BIT; }
|
|
||||||
if (counts & VK_SAMPLE_COUNT_16_BIT) { return VK_SAMPLE_COUNT_16_BIT; }
|
|
||||||
if (counts & VK_SAMPLE_COUNT_8_BIT) { return VK_SAMPLE_COUNT_8_BIT; }
|
|
||||||
if (counts & VK_SAMPLE_COUNT_4_BIT) { return VK_SAMPLE_COUNT_4_BIT; }
|
|
||||||
if (counts & VK_SAMPLE_COUNT_2_BIT) { return VK_SAMPLE_COUNT_2_BIT; }
|
|
||||||
throw std::runtime_error("MSAA is not supported");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
|
static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
|
||||||
{
|
{
|
||||||
[[maybe_unused]] VkResult res;
|
[[maybe_unused]] VkResult res;
|
||||||
@ -342,166 +275,6 @@ namespace engine {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
static VkCommandBuffer beginOneTimeCommands(VkDevice device, VkCommandPool commandPool)
|
|
||||||
{
|
|
||||||
[[maybe_unused]] VkResult res;
|
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
||||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
||||||
allocInfo.commandPool = commandPool;
|
|
||||||
allocInfo.commandBufferCount = 1;
|
|
||||||
|
|
||||||
VkCommandBuffer commandBuffer;
|
|
||||||
res = vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
VkCommandBufferBeginInfo beginInfo{};
|
|
||||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
||||||
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
|
||||||
|
|
||||||
res = vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
return commandBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void endOneTimeCommands(VkDevice device, VkCommandPool commandPool, VkCommandBuffer commandBuffer, VkQueue queue)
|
|
||||||
{
|
|
||||||
[[maybe_unused]] VkResult res;
|
|
||||||
res = vkEndCommandBuffer(commandBuffer);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
VkSubmitInfo submitInfo{};
|
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
||||||
submitInfo.commandBufferCount = 1;
|
|
||||||
submitInfo.pCommandBuffers = &commandBuffer;
|
|
||||||
|
|
||||||
res = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
res = vkQueueWaitIdle(queue);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels, VkImage image)
|
|
||||||
{
|
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier{};
|
|
||||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
||||||
barrier.oldLayout = oldLayout;
|
|
||||||
barrier.newLayout = newLayout;
|
|
||||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.image = image;
|
|
||||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
barrier.subresourceRange.baseMipLevel = 0;
|
|
||||||
barrier.subresourceRange.levelCount = mipLevels;
|
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
|
||||||
barrier.subresourceRange.layerCount = 1;
|
|
||||||
|
|
||||||
VkPipelineStageFlags sourceStage;
|
|
||||||
VkPipelineStageFlags destinationStage;
|
|
||||||
|
|
||||||
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
|
|
||||||
barrier.srcAccessMask = 0;
|
|
||||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
||||||
|
|
||||||
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
|
||||||
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
}
|
|
||||||
else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
|
|
||||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
||||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
|
|
||||||
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw std::invalid_argument("unsupported layout transition!");
|
|
||||||
}
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(commandBuffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cmdGenerateMipmaps(VkCommandBuffer commandBuffer, VkImage image, int32_t width, int32_t height, uint32_t mipLevels)
|
|
||||||
{
|
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier{};
|
|
||||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
||||||
barrier.image = image;
|
|
||||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
|
||||||
barrier.subresourceRange.layerCount = 1;
|
|
||||||
barrier.subresourceRange.levelCount = 1;
|
|
||||||
|
|
||||||
int32_t mipWidth = width;
|
|
||||||
int32_t mipHeight = height;
|
|
||||||
for (uint32_t i = 1; i < mipLevels; i++) {
|
|
||||||
barrier.subresourceRange.baseMipLevel = i - 1;
|
|
||||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
||||||
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
||||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
||||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
|
||||||
0, nullptr,
|
|
||||||
0, nullptr,
|
|
||||||
1, &barrier);
|
|
||||||
|
|
||||||
VkImageBlit blit{};
|
|
||||||
blit.srcOffsets[0] = { 0, 0, 0 };
|
|
||||||
blit.srcOffsets[1] = { mipWidth, mipHeight, 1 };
|
|
||||||
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
blit.srcSubresource.mipLevel = i - 1;
|
|
||||||
blit.srcSubresource.baseArrayLayer = 0;
|
|
||||||
blit.srcSubresource.layerCount = 1;
|
|
||||||
blit.dstOffsets[0] = { 0, 0, 0 };
|
|
||||||
blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 };
|
|
||||||
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
blit.dstSubresource.mipLevel = i;
|
|
||||||
blit.dstSubresource.baseArrayLayer = 0;
|
|
||||||
blit.dstSubresource.layerCount = 1;
|
|
||||||
|
|
||||||
vkCmdBlitImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR);
|
|
||||||
|
|
||||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
|
||||||
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
||||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
||||||
0,
|
|
||||||
0, nullptr,
|
|
||||||
0, nullptr,
|
|
||||||
1, &barrier);
|
|
||||||
|
|
||||||
if (mipWidth > 1) mipWidth /= 2;
|
|
||||||
if (mipHeight > 1) mipHeight /= 2;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
barrier.subresourceRange.baseMipLevel = mipLevels - 1;
|
|
||||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
||||||
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
||||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(commandBuffer,
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
|
|
||||||
0, nullptr,
|
|
||||||
0, nullptr,
|
|
||||||
1, &barrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// class definitions
|
// class definitions
|
||||||
|
|
||||||
struct GFXDevice::Impl {
|
struct GFXDevice::Impl {
|
||||||
@ -518,9 +291,10 @@ namespace engine {
|
|||||||
Swapchain swapchain{};
|
Swapchain swapchain{};
|
||||||
|
|
||||||
VkDescriptorPool descriptorPool;
|
VkDescriptorPool descriptorPool;
|
||||||
VkCommandPool transferCommandPool = VK_NULL_HANDLE;
|
|
||||||
std::array<std::unordered_set<gfx::DescriptorBuffer*>, FRAMES_IN_FLIGHT> descriptorBufferWriteQueues{};
|
std::array<std::unordered_set<gfx::DescriptorBuffer*>, FRAMES_IN_FLIGHT> descriptorBufferWriteQueues{};
|
||||||
|
|
||||||
|
VkCommandPool transferCommandPool = VK_NULL_HANDLE;
|
||||||
|
|
||||||
uint64_t FRAMECOUNT = 0;
|
uint64_t FRAMECOUNT = 0;
|
||||||
|
|
||||||
FrameData frameData[FRAMES_IN_FLIGHT] = {};
|
FrameData frameData[FRAMES_IN_FLIGHT] = {};
|
||||||
@ -643,10 +417,9 @@ namespace engine {
|
|||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.flags = 0
|
.flags = 0
|
||||||
};
|
};
|
||||||
res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].presentSemaphore);
|
VKCHECK(vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].transferSemaphore));
|
||||||
if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!");
|
VKCHECK(vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].presentSemaphore));
|
||||||
res = vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].renderSemaphore);
|
VKCHECK(vkCreateSemaphore(pimpl->device.device, &smphInfo, nullptr, &pimpl->frameData[i].renderSemaphore));
|
||||||
if (res != VK_SUCCESS) throw std::runtime_error("Failed to create semaphore!");
|
|
||||||
|
|
||||||
VkCommandPoolCreateInfo poolInfo{
|
VkCommandPoolCreateInfo poolInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
@ -654,19 +427,23 @@ namespace engine {
|
|||||||
.flags = 0, // Command buffers cannot be individually reset (more performant this way)
|
.flags = 0, // Command buffers cannot be individually reset (more performant this way)
|
||||||
.queueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily
|
.queueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily
|
||||||
};
|
};
|
||||||
VKCHECK(vkCreateCommandPool(pimpl->device.device, &poolInfo, nullptr, &pimpl->frameData[i].commandPool));
|
VKCHECK(vkCreateCommandPool(pimpl->device.device, &poolInfo, nullptr, &pimpl->frameData[i].graphicsPool));
|
||||||
|
poolInfo.queueFamilyIndex = pimpl->device.queues.transferQueueFamily;
|
||||||
|
VKCHECK(vkCreateCommandPool(pimpl->device.device, &poolInfo, nullptr, &pimpl->frameData[i].transferPool));
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo cmdAllocInfo{
|
VkCommandBufferAllocateInfo cmdAllocInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.commandPool = pimpl->frameData[i].commandPool,
|
.commandPool = pimpl->frameData[i].graphicsPool,
|
||||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
.commandBufferCount = 1
|
.commandBufferCount = 1
|
||||||
};
|
};
|
||||||
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->frameData[i].drawBuf));
|
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->frameData[i].drawBuf));
|
||||||
|
cmdAllocInfo.commandPool = pimpl->frameData[i].transferPool;
|
||||||
|
VKCHECK(vkAllocateCommandBuffers(pimpl->device.device, &cmdAllocInfo, &pimpl->frameData[i].transferBuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create command pool for transfer operations */
|
/* create command pool for one-off transfer operations */
|
||||||
VkCommandPoolCreateInfo transferPoolInfo{
|
VkCommandPoolCreateInfo transferPoolInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@ -676,7 +453,6 @@ namespace engine {
|
|||||||
VKCHECK(vkCreateCommandPool(pimpl->device.device, &transferPoolInfo, nullptr, &pimpl->transferCommandPool));
|
VKCHECK(vkCreateCommandPool(pimpl->device.device, &transferPoolInfo, nullptr, &pimpl->transferCommandPool));
|
||||||
|
|
||||||
/* create a global descriptor pool */
|
/* create a global descriptor pool */
|
||||||
|
|
||||||
std::vector<VkDescriptorPoolSize> poolSizes{};
|
std::vector<VkDescriptorPoolSize> poolSizes{};
|
||||||
poolSizes.push_back({ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100u }); // purposely low limit
|
poolSizes.push_back({ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100u }); // purposely low limit
|
||||||
|
|
||||||
@ -698,9 +474,11 @@ namespace engine {
|
|||||||
vkDestroyCommandPool(pimpl->device.device, pimpl->transferCommandPool, nullptr);
|
vkDestroyCommandPool(pimpl->device.device, pimpl->transferCommandPool, nullptr);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
||||||
vkDestroyCommandPool(pimpl->device.device, pimpl->frameData[i].commandPool, nullptr);
|
vkDestroyCommandPool(pimpl->device.device, pimpl->frameData[i].graphicsPool, nullptr);
|
||||||
|
vkDestroyCommandPool(pimpl->device.device, pimpl->frameData[i].transferPool, nullptr);
|
||||||
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].renderSemaphore, nullptr);
|
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].renderSemaphore, nullptr);
|
||||||
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].presentSemaphore, nullptr);
|
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].presentSemaphore, nullptr);
|
||||||
|
vkDestroySemaphore(pimpl->device.device, pimpl->frameData[i].transferSemaphore, nullptr);
|
||||||
vkDestroyFence(pimpl->device.device, pimpl->frameData[i].renderFence, nullptr);
|
vkDestroyFence(pimpl->device.device, pimpl->frameData[i].renderFence, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,8 +509,6 @@ namespace engine {
|
|||||||
{
|
{
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
|
||||||
gfx::DrawBuffer* drawBuffer = new gfx::DrawBuffer;
|
|
||||||
|
|
||||||
const uint32_t currentFrameIndex = pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT;
|
const uint32_t currentFrameIndex = pimpl->FRAMECOUNT % FRAMES_IN_FLIGHT;
|
||||||
const FrameData frameData = pimpl->frameData[currentFrameIndex];
|
const FrameData frameData = pimpl->frameData[currentFrameIndex];
|
||||||
|
|
||||||
@ -741,88 +517,57 @@ namespace engine {
|
|||||||
VKCHECK(res);
|
VKCHECK(res);
|
||||||
res = vkResetFences(pimpl->device.device, 1, &frameData.renderFence);
|
res = vkResetFences(pimpl->device.device, 1, &frameData.renderFence);
|
||||||
VKCHECK(res);
|
VKCHECK(res);
|
||||||
|
#if 0
|
||||||
|
/* perform any pending uniform buffer writes */
|
||||||
|
VKCHECK(vkResetCommandPool(pimpl->device.device, frameData.transferPool, 0));
|
||||||
|
|
||||||
uint32_t transferQueueIndex = 0;
|
VkCommandBufferBeginInfo transferBeginInfo{
|
||||||
if (pimpl->device.queues.transferQueues.size() >= 2) {
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
transferQueueIndex = 1;
|
.pNext = nullptr,
|
||||||
|
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||||
|
.pInheritanceInfo = nullptr // ignored
|
||||||
|
};
|
||||||
|
VKCHECK(vkBeginCommandBuffer(frameData.transferBuf, &transferBeginInfo));
|
||||||
|
|
||||||
|
// transfer cmds...
|
||||||
|
|
||||||
|
std::vector<VkBufferMemoryBarrier> barriers(pimpl->descriptorBufferWriteQueues[currentFrameIndex].size());
|
||||||
|
for (gfx::DescriptorBuffer* descriptorBuffer : pimpl->descriptorBufferWriteQueues[currentFrameIndex]) {
|
||||||
|
VkBufferMemoryBarrier& barrier = barriers.emplace_back();
|
||||||
|
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
||||||
|
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
barrier.dstAccessMask = 0;
|
||||||
|
barrier.srcQueueFamilyIndex = pimpl->device.queues.transferQueueFamily;
|
||||||
|
barrier.dstQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily;
|
||||||
|
barrier.buffer = descriptorBuffer->gpuBuffers[currentFrameIndex].buffer;
|
||||||
|
barrier.offset = 0;
|
||||||
|
barrier.size = descriptorBuffer->gpuBuffers[currentFrameIndex].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first empty the descriptor buffer write queue */
|
vkCmdPipelineBarrier(frameData.transferBuf,
|
||||||
auto& writeQueue = pimpl->descriptorBufferWriteQueues[currentFrameIndex];
|
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
if (writeQueue.empty() == false) {
|
|
||||||
// LOG_TRACE("write queue size: {}", writeQueue.size());
|
|
||||||
// vkQueueWaitIdle(pimpl->device.queues.drawQueues[0]);
|
|
||||||
}
|
|
||||||
for (gfx::DescriptorBuffer* buffer : writeQueue) {
|
|
||||||
|
|
||||||
// record the command buffer
|
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
||||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
||||||
allocInfo.commandPool = pimpl->transferCommandPool;
|
|
||||||
allocInfo.commandBufferCount = 1;
|
|
||||||
|
|
||||||
VkCommandBuffer commandBuffer;
|
|
||||||
res = vkAllocateCommandBuffers(pimpl->device.device, &allocInfo, &commandBuffer);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
// LOG_TRACE(" write command buffer: {}", (void*)commandBuffer);
|
|
||||||
|
|
||||||
VkCommandBufferBeginInfo beginInfo{};
|
|
||||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
||||||
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
|
||||||
res = vkBeginCommandBuffer(commandBuffer, &beginInfo);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
VkBufferCopy copyRegion{};
|
|
||||||
copyRegion.srcOffset = 0;
|
|
||||||
copyRegion.dstOffset = 0;
|
|
||||||
copyRegion.size = buffer->stagingBuffer.size;
|
|
||||||
vkCmdCopyBuffer(commandBuffer, buffer->stagingBuffer.buffer, buffer->gpuBuffers[currentFrameIndex].buffer, 1, ©Region);
|
|
||||||
|
|
||||||
/* barrier to perform ownership transfer from transferQueue to drawQueue (RELEASE) */
|
|
||||||
VkBufferMemoryBarrier bufferMemoryBarrier{};
|
|
||||||
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
|
||||||
bufferMemoryBarrier.pNext = nullptr;
|
|
||||||
bufferMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
||||||
bufferMemoryBarrier.dstAccessMask = 0;
|
|
||||||
bufferMemoryBarrier.srcQueueFamilyIndex = pimpl->device.queues.transferQueueFamily;
|
|
||||||
bufferMemoryBarrier.dstQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily;
|
|
||||||
bufferMemoryBarrier.buffer = buffer->gpuBuffers[currentFrameIndex].buffer;
|
|
||||||
bufferMemoryBarrier.offset = 0;
|
|
||||||
bufferMemoryBarrier.size = buffer->stagingBuffer.size;
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(
|
|
||||||
commandBuffer,
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask
|
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT, // dstStageMask
|
|
||||||
0,
|
0,
|
||||||
0,
|
0, nullptr,
|
||||||
nullptr,
|
(uint32_t)barriers.size(), barriers.data(),
|
||||||
1,
|
0, nullptr
|
||||||
&bufferMemoryBarrier,
|
|
||||||
0,
|
|
||||||
nullptr
|
|
||||||
);
|
);
|
||||||
|
|
||||||
res = vkEndCommandBuffer(commandBuffer);
|
VKCHECK(vkEndCommandBuffer(frameData.transferBuf));
|
||||||
|
|
||||||
|
VkSubmitInfo transferSubmitInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.waitSemaphoreCount = 0, // needs to wait for render but the fence does that
|
||||||
|
.pWaitSemaphores = nullptr,
|
||||||
|
.pWaitDstStageMask = nullptr,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
.pCommandBuffers = &frameData.transferBuf,
|
||||||
|
.signalSemaphoreCount = 1,
|
||||||
|
.pSignalSemaphores = &frameData.transferSemaphore,
|
||||||
|
};
|
||||||
|
res = vkQueueSubmit(pimpl->device.queues.transferQueues[0], 1, &transferSubmitInfo, VK_NULL_HANDLE);
|
||||||
assert(res == VK_SUCCESS);
|
assert(res == VK_SUCCESS);
|
||||||
|
#endif
|
||||||
// submit
|
|
||||||
VkSubmitInfo submitInfo{};
|
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
||||||
submitInfo.commandBufferCount = 1;
|
|
||||||
submitInfo.pCommandBuffers = &commandBuffer;
|
|
||||||
submitInfo.signalSemaphoreCount = 1;
|
|
||||||
submitInfo.pSignalSemaphores = &buffer->copySemaphores[currentFrameIndex];
|
|
||||||
submitInfo.waitSemaphoreCount = 0;
|
|
||||||
submitInfo.pWaitSemaphores = nullptr;
|
|
||||||
|
|
||||||
res = vkQueueSubmit(pimpl->device.queues.transferQueues[transferQueueIndex], 1, &submitInfo, VK_NULL_HANDLE);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t swapchainImageIndex;
|
uint32_t swapchainImageIndex;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -841,7 +586,7 @@ namespace engine {
|
|||||||
} while (pimpl->swapchainIsOutOfDate);
|
} while (pimpl->swapchainIsOutOfDate);
|
||||||
|
|
||||||
/* record command buffer */
|
/* record command buffer */
|
||||||
res = vkResetCommandPool(pimpl->device.device, frameData.commandPool, 0);
|
res = vkResetCommandPool(pimpl->device.device, frameData.graphicsPool, 0);
|
||||||
VKCHECK(res);
|
VKCHECK(res);
|
||||||
|
|
||||||
VkCommandBufferBeginInfo beginInfo{
|
VkCommandBufferBeginInfo beginInfo{
|
||||||
@ -855,33 +600,6 @@ namespace engine {
|
|||||||
|
|
||||||
{ // RECORDING
|
{ // RECORDING
|
||||||
|
|
||||||
for (gfx::DescriptorBuffer* buffer : writeQueue) {
|
|
||||||
/* barrier to perform ownership transfer from transferQueue to drawQueue (ACQUIRE) */
|
|
||||||
VkBufferMemoryBarrier bufferMemoryBarrier{};
|
|
||||||
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
|
||||||
bufferMemoryBarrier.pNext = nullptr;
|
|
||||||
bufferMemoryBarrier.srcAccessMask = 0;
|
|
||||||
bufferMemoryBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
|
|
||||||
bufferMemoryBarrier.srcQueueFamilyIndex = pimpl->device.queues.transferQueueFamily;
|
|
||||||
bufferMemoryBarrier.dstQueueFamilyIndex = pimpl->device.queues.presentAndDrawQueueFamily;
|
|
||||||
bufferMemoryBarrier.buffer = buffer->gpuBuffers[currentFrameIndex].buffer;
|
|
||||||
bufferMemoryBarrier.offset = 0;
|
|
||||||
bufferMemoryBarrier.size = buffer->stagingBuffer.size;
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(
|
|
||||||
frameData.drawBuf,
|
|
||||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, // srcStageMask
|
|
||||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, // dstStageMask
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
nullptr,
|
|
||||||
1,
|
|
||||||
&bufferMemoryBarrier,
|
|
||||||
0,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<VkClearValue, 2> clearValues{}; // Using same value for all components enables compression according to NVIDIA Best Practices
|
std::array<VkClearValue, 2> clearValues{}; // Using same value for all components enables compression according to NVIDIA Best Practices
|
||||||
clearValues[0].color.float32[0] = 1.0f;
|
clearValues[0].color.float32[0] = 1.0f;
|
||||||
clearValues[0].color.float32[1] = 1.0f;
|
clearValues[0].color.float32[1] = 1.0f;
|
||||||
@ -917,19 +635,18 @@ namespace engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// hand command buffer over to caller
|
// hand command buffer over to caller
|
||||||
|
gfx::DrawBuffer* drawBuffer = new gfx::DrawBuffer;
|
||||||
drawBuffer->frameData = frameData;
|
drawBuffer->frameData = frameData;
|
||||||
drawBuffer->currentFrameIndex = currentFrameIndex;
|
drawBuffer->currentFrameIndex = currentFrameIndex;
|
||||||
drawBuffer->imageIndex = swapchainImageIndex;
|
drawBuffer->imageIndex = swapchainImageIndex;
|
||||||
drawBuffer->buffersToWrite = &writeQueue;
|
|
||||||
return drawBuffer;
|
return drawBuffer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer)
|
void GFXDevice::finishRender(gfx::DrawBuffer* drawBuffer)
|
||||||
{
|
{
|
||||||
if (drawBuffer == nullptr) {
|
assert(drawBuffer != nullptr);
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t swapchainImageIndex = drawBuffer->imageIndex;
|
uint32_t swapchainImageIndex = drawBuffer->imageIndex;
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
|
||||||
@ -943,13 +660,10 @@ namespace engine {
|
|||||||
std::vector<VkSemaphore> waitSemaphores{};
|
std::vector<VkSemaphore> waitSemaphores{};
|
||||||
std::vector<VkPipelineStageFlags> waitDstStageMasks{};
|
std::vector<VkPipelineStageFlags> waitDstStageMasks{};
|
||||||
|
|
||||||
for (const gfx::DescriptorBuffer* buffer : *drawBuffer->buffersToWrite) {
|
|
||||||
waitSemaphores.push_back(buffer->copySemaphores[drawBuffer->currentFrameIndex]);
|
|
||||||
waitDstStageMasks.push_back(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
waitSemaphores.push_back(drawBuffer->frameData.presentSemaphore);
|
waitSemaphores.push_back(drawBuffer->frameData.presentSemaphore);
|
||||||
waitDstStageMasks.push_back(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
waitDstStageMasks.push_back(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||||
|
//waitSemaphores.push_back(drawBuffer->frameData.transferSemaphore);
|
||||||
|
//waitDstStageMasks.push_back(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
|
||||||
|
|
||||||
VkSubmitInfo submitInfo{
|
VkSubmitInfo submitInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
@ -987,9 +701,6 @@ namespace engine {
|
|||||||
|
|
||||||
pimpl->FRAMECOUNT++;
|
pimpl->FRAMECOUNT++;
|
||||||
|
|
||||||
/* empty the buffersToWrite queue */
|
|
||||||
drawBuffer->buffersToWrite->clear();
|
|
||||||
|
|
||||||
delete drawBuffer;
|
delete drawBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1510,211 +1221,12 @@ namespace engine {
|
|||||||
(void)useAnisotropy;
|
(void)useAnisotropy;
|
||||||
auto out = new gfx::Texture;
|
auto out = new gfx::Texture;
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
[[maybe_unused]] VkResult res;
|
|
||||||
|
|
||||||
size_t imageSize = width * height * 4;
|
|
||||||
|
|
||||||
if (mipmapSetting == gfx::MipmapSetting::OFF) {
|
|
||||||
out->mipLevels = 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
out->mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first load image into staging buffer
|
|
||||||
VkBuffer stagingBuffer;
|
|
||||||
VmaAllocation stagingAllocation;
|
|
||||||
{
|
|
||||||
VkBufferCreateInfo stagingBufferInfo{};
|
|
||||||
stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
||||||
stagingBufferInfo.size = imageSize;
|
|
||||||
stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
|
||||||
stagingBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
stagingBufferInfo.flags = 0;
|
|
||||||
|
|
||||||
VmaAllocationCreateInfo stagingAllocInfo{};
|
|
||||||
stagingAllocInfo.usage = VMA_MEMORY_USAGE_AUTO;
|
|
||||||
stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
|
||||||
stagingAllocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
||||||
|
|
||||||
res = vmaCreateBuffer(pimpl->allocator, &stagingBufferInfo, &stagingAllocInfo, &stagingBuffer, &stagingAllocation, nullptr);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
void* dataDest;
|
|
||||||
res = vmaMapMemory(pimpl->allocator, stagingAllocation, &dataDest);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
memcpy(dataDest, imageData, imageSize);
|
|
||||||
vmaUnmapMemory(pimpl->allocator, stagingAllocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the image
|
|
||||||
VkImageCreateInfo imageInfo{};
|
|
||||||
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
||||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
|
||||||
imageInfo.extent.width = width;
|
|
||||||
imageInfo.extent.height = height;
|
|
||||||
imageInfo.extent.depth = 1;
|
|
||||||
imageInfo.mipLevels = out->mipLevels;
|
|
||||||
imageInfo.arrayLayers = 1;
|
|
||||||
imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
|
||||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
||||||
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
|
||||||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
imageInfo.flags = 0;
|
|
||||||
|
|
||||||
VmaAllocationCreateInfo imageAllocInfo{};
|
|
||||||
imageAllocInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
|
||||||
|
|
||||||
res = vmaCreateImage(pimpl->allocator, &imageInfo, &imageAllocInfo, &out->image, &out->alloc, nullptr);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
// transition the image layout
|
|
||||||
{
|
|
||||||
VkCommandBuffer commandBuffer = beginOneTimeCommands(pimpl->device, pimpl->commandPool);
|
|
||||||
|
|
||||||
// begin cmd buffer
|
|
||||||
|
|
||||||
cmdTransitionImageLayout(commandBuffer, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, out->mipLevels, out->image);
|
|
||||||
|
|
||||||
VkBufferImageCopy region{};
|
|
||||||
region.bufferOffset = 0;
|
|
||||||
region.bufferRowLength = 0;
|
|
||||||
region.bufferImageHeight = 0;
|
|
||||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
region.imageSubresource.mipLevel = 0;
|
|
||||||
region.imageSubresource.baseArrayLayer = 0;
|
|
||||||
region.imageSubresource.layerCount = 1;
|
|
||||||
region.imageOffset = { 0, 0, 0 };
|
|
||||||
region.imageExtent.width = width;
|
|
||||||
region.imageExtent.height = height;
|
|
||||||
region.imageExtent.depth = 1;
|
|
||||||
|
|
||||||
vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, out->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
|
||||||
|
|
||||||
// Mipmap generation handles the transition to SHADER_READ_ONLY_OPTIMAL
|
|
||||||
cmdGenerateMipmaps(commandBuffer, out->image, width, height, out->mipLevels);
|
|
||||||
|
|
||||||
// end cmd buffer
|
|
||||||
endOneTimeCommands(pimpl->device, pimpl->commandPool, commandBuffer, pimpl->gfxQueue.handle);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// destroy staging buffer
|
|
||||||
vmaDestroyBuffer(pimpl->allocator, stagingBuffer, stagingAllocation);
|
|
||||||
|
|
||||||
// create image view
|
|
||||||
VkImageViewCreateInfo imageViewInfo{};
|
|
||||||
imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
||||||
imageViewInfo.image = out->image;
|
|
||||||
imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
||||||
imageViewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
|
||||||
imageViewInfo.subresourceRange = {
|
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
||||||
.baseMipLevel = 0,
|
|
||||||
.levelCount = out->mipLevels,
|
|
||||||
.baseArrayLayer = 0,
|
|
||||||
.layerCount = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
res = vkCreateImageView(pimpl->device, &imageViewInfo, nullptr, &out->imageView);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
VkFilter magFilterInternal = vkinternal::getTextureFilter(magFilter);
|
|
||||||
VkFilter minFilterInternal = vkinternal::getTextureFilter(minFilter);
|
|
||||||
|
|
||||||
// create texture sampler
|
|
||||||
{
|
|
||||||
|
|
||||||
VkSamplerCreateInfo samplerInfo{};
|
|
||||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
|
||||||
samplerInfo.magFilter = magFilterInternal;
|
|
||||||
samplerInfo.minFilter = minFilterInternal;
|
|
||||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
|
||||||
if (useAnisotropy) {
|
|
||||||
samplerInfo.anisotropyEnable = VK_TRUE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
samplerInfo.anisotropyEnable = VK_FALSE;
|
|
||||||
}
|
|
||||||
samplerInfo.maxAnisotropy = pimpl->maxSamplerAnisotropy;
|
|
||||||
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
|
||||||
samplerInfo.unnormalizedCoordinates = VK_FALSE;
|
|
||||||
samplerInfo.compareEnable = VK_FALSE;
|
|
||||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
|
||||||
if (mipmapSetting == gfx::MipmapSetting::LINEAR) {
|
|
||||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
|
||||||
}
|
|
||||||
samplerInfo.minLod = 0.0f;
|
|
||||||
samplerInfo.maxLod = static_cast<float>(out->mipLevels);
|
|
||||||
samplerInfo.mipLodBias = 0.0f;
|
|
||||||
|
|
||||||
res = vkCreateSampler(pimpl->device, &samplerInfo, nullptr, &out->sampler);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create descriptor pools
|
|
||||||
VkDescriptorPoolSize poolSize{};
|
|
||||||
poolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
||||||
poolSize.descriptorCount = FRAMES_IN_FLIGHT;
|
|
||||||
|
|
||||||
VkDescriptorPoolCreateInfo poolInfo{};
|
|
||||||
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
||||||
poolInfo.poolSizeCount = 1;
|
|
||||||
poolInfo.pPoolSizes = &poolSize;
|
|
||||||
poolInfo.maxSets = FRAMES_IN_FLIGHT;
|
|
||||||
res = vkCreateDescriptorPool(pimpl->device, &poolInfo, nullptr, &out->pool);
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
std::array<VkDescriptorSetLayout, FRAMES_IN_FLIGHT> layouts{};
|
|
||||||
layouts.fill(pimpl->samplerSetLayout);
|
|
||||||
VkDescriptorSetAllocateInfo dSetAllocInfo{};
|
|
||||||
dSetAllocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
||||||
dSetAllocInfo.descriptorPool = out->pool;
|
|
||||||
dSetAllocInfo.descriptorSetCount = FRAMES_IN_FLIGHT;
|
|
||||||
dSetAllocInfo.pSetLayouts = layouts.data();
|
|
||||||
res = vkAllocateDescriptorSets(pimpl->device, &dSetAllocInfo, out->descriptorSets.data());
|
|
||||||
assert(res == VK_SUCCESS);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) {
|
|
||||||
VkDescriptorImageInfo imageInfo{};
|
|
||||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
imageInfo.imageView = out->imageView;
|
|
||||||
imageInfo.sampler = out->sampler;
|
|
||||||
|
|
||||||
VkWriteDescriptorSet descriptorWrite{};
|
|
||||||
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
||||||
descriptorWrite.dstSet = out->descriptorSets[i];
|
|
||||||
descriptorWrite.dstBinding = 0;
|
|
||||||
descriptorWrite.dstArrayElement = 0;
|
|
||||||
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
||||||
descriptorWrite.descriptorCount = 1;
|
|
||||||
descriptorWrite.pImageInfo = &imageInfo;
|
|
||||||
|
|
||||||
vkUpdateDescriptorSets(pimpl->device, 1, &descriptorWrite, 0, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GFXDevice::destroyTexture(const gfx::Texture* texture)
|
void GFXDevice::destroyTexture(const gfx::Texture* texture)
|
||||||
{
|
{
|
||||||
(void)texture;
|
(void)texture;
|
||||||
#if 0
|
|
||||||
vkDestroyDescriptorPool(pimpl->device, texture->pool, nullptr);
|
|
||||||
vkDestroySampler(pimpl->device, texture->sampler, nullptr);
|
|
||||||
vkDestroyImageView(pimpl->device, texture->imageView, nullptr);
|
|
||||||
vmaDestroyImage(pimpl->allocator, texture->image, texture->alloc);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GFXDevice::getFrameCount()
|
uint64_t GFXDevice::getFrameCount()
|
||||||
|
Loading…
Reference in New Issue
Block a user