diff --git a/base/vulkanTextureLoader.hpp b/base/vulkanTextureLoader.hpp index d97e21ce..e09dde0b 100644 --- a/base/vulkanTextureLoader.hpp +++ b/base/vulkanTextureLoader.hpp @@ -74,8 +74,6 @@ namespace vkTools texture->height = (uint32_t)tex2D[0].dimensions().y; texture->mipLevels = tex2D.levels(); - VkResult err; - // Get device properites for the requested texture format VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); @@ -104,8 +102,7 @@ namespace vkTools // Use a separate command buffer for texture loading VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); - err = vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo); - assert(!err); + vkTools::checkResult(vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo)); if (useStaging) { @@ -125,16 +122,13 @@ namespace vkTools imageCreateInfo.extent.height = tex2D[level].dimensions().y; imageCreateInfo.extent.depth = 1; - err = vkCreateImage(device, &imageCreateInfo, nullptr, &mipLevels[level].image); - assert(!err); + vkTools::checkResult(vkCreateImage(device, &imageCreateInfo, nullptr, &mipLevels[level].image)); vkGetImageMemoryRequirements(device, mipLevels[level].image, &memReqs); memAllocInfo.allocationSize = memReqs.size; getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAllocInfo.memoryTypeIndex); - err = vkAllocateMemory(device, &memAllocInfo, nullptr, &mipLevels[level].memory); - assert(!err); - err = vkBindImageMemory(device, mipLevels[level].image, mipLevels[level].memory, 0); - assert(!err); + vkTools::checkResult(vkAllocateMemory(device, &memAllocInfo, nullptr, &mipLevels[level].memory)); + vkTools::checkResult(vkBindImageMemory(device, mipLevels[level].image, mipLevels[level].memory, 0)); VkImageSubresource subRes = {}; subRes.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -143,9 +137,7 @@ namespace vkTools void *data; vkGetImageSubresourceLayout(device, mipLevels[level].image, &subRes, &subResLayout); - assert(!err); - err = vkMapMemory(device, mipLevels[level].memory, 0, memReqs.size, 0, &data); - assert(!err); + vkTools::checkResult(vkMapMemory(device, mipLevels[level].memory, 0, memReqs.size, 0, &data)); memcpy(data, tex2D[level].data(), tex2D[level].size()); vkUnmapMemory(device, mipLevels[level].memory); @@ -165,18 +157,15 @@ namespace vkTools imageCreateInfo.mipLevels = texture->mipLevels; imageCreateInfo.extent = { texture->width, texture->height, 1 }; - err = vkCreateImage(device, &imageCreateInfo, nullptr, &texture->image); - assert(!err); + vkTools::checkResult(vkCreateImage(device, &imageCreateInfo, nullptr, &texture->image)); vkGetImageMemoryRequirements(device, texture->image, &memReqs); memAllocInfo.allocationSize = memReqs.size; getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex); - err = vkAllocateMemory(device, &memAllocInfo, nullptr, &texture->deviceMemory); - assert(!err); - err = vkBindImageMemory(device, texture->image, texture->deviceMemory, 0); - assert(!err); + vkTools::checkResult(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture->deviceMemory)); + vkTools::checkResult(vkBindImageMemory(device, texture->image, texture->deviceMemory, 0)); VkImageSubresourceRange subresourceRange = {}; subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -239,25 +228,24 @@ namespace vkTools subresourceRange); // Submit command buffer containing copy and image layout commands - err = vkEndCommandBuffer(cmdBuffer); - assert(!err); + vkTools::checkResult(vkEndCommandBuffer(cmdBuffer)); - VkFence nullFence = { VK_NULL_HANDLE }; + // Create a fence to make sure that the copies have finished before continuing + VkFence copyFence; + VkFenceCreateInfo fenceCreateInfo = vkTools::initializers::fenceCreateInfo(VK_FLAGS_NONE); + vkTools::checkResult(vkCreateFence(device, &fenceCreateInfo, nullptr, ©Fence)); VkSubmitInfo submitInfo = vkTools::initializers::submitInfo(); - submitInfo.waitSemaphoreCount = 0; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &cmdBuffer; - err = vkQueueSubmit(queue, 1, &submitInfo, nullFence); - assert(!err); + vkTools::checkResult(vkQueueSubmit(queue, 1, &submitInfo, copyFence)); - err = vkQueueWaitIdle(queue); - assert(!err); + vkWaitForFences(device, 1, ©Fence, VK_TRUE, DEFAULT_FENCE_TIMEOUT); - // Clean up linear images - // No longer required after mip levels - // have been transformed over to optimal tiling + vkDestroyFence(device, copyFence, nullptr); + + // Destroy linear images used as staging buffers after copies have been finished for (auto& level : mipLevels) { vkDestroyImage(device, level.image, nullptr); @@ -277,8 +265,7 @@ namespace vkTools VkDeviceMemory mappableMemory; // Load mip map level 0 to linear tiling image - err = vkCreateImage(device, &imageCreateInfo, nullptr, &mappableImage); - assert(!err); + vkTools::checkResult(vkCreateImage(device, &imageCreateInfo, nullptr, &mappableImage)); // Get memory requirements for this image // like size and alignment @@ -290,12 +277,10 @@ namespace vkTools getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAllocInfo.memoryTypeIndex); // Allocate host memory - err = vkAllocateMemory(device, &memAllocInfo, nullptr, &mappableMemory); - assert(!err); + vkTools::checkResult(vkAllocateMemory(device, &memAllocInfo, nullptr, &mappableMemory)); // Bind allocated image for use - err = vkBindImageMemory(device, mappableImage, mappableMemory, 0); - assert(!err); + vkTools::checkResult(vkBindImageMemory(device, mappableImage, mappableMemory, 0)); // Get sub resource layout // Mip map count, array layer, etc. @@ -309,11 +294,9 @@ namespace vkTools // Get sub resources layout // Includes row pitch, size offsets, etc. vkGetImageSubresourceLayout(device, mappableImage, &subRes, &subResLayout); - assert(!err); // Map image memory - err = vkMapMemory(device, mappableMemory, 0, memReqs.size, 0, &data); - assert(!err); + vkTools::checkResult(vkMapMemory(device, mappableMemory, 0, memReqs.size, 0, &data)); // Copy image data into memory memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size()); @@ -335,8 +318,7 @@ namespace vkTools texture->imageLayout); // Submit command buffer containing copy and image layout commands - err = vkEndCommandBuffer(cmdBuffer); - assert(!err); + vkTools::checkResult(vkEndCommandBuffer(cmdBuffer)); VkFence nullFence = { VK_NULL_HANDLE }; @@ -345,11 +327,8 @@ namespace vkTools submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &cmdBuffer; - err = vkQueueSubmit(queue, 1, &submitInfo, nullFence); - assert(!err); - - err = vkQueueWaitIdle(queue); - assert(!err); + vkTools::checkResult(vkQueueSubmit(queue, 1, &submitInfo, nullFence)); + vkTools::checkResult(vkQueueWaitIdle(queue)); } // Create sampler @@ -370,9 +349,8 @@ namespace vkTools sampler.maxAnisotropy = 8; sampler.anisotropyEnable = VK_TRUE; sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - err = vkCreateSampler(device, &sampler, nullptr, &texture->sampler); - assert(!err); - + vkTools::checkResult(vkCreateSampler(device, &sampler, nullptr, &texture->sampler)); + // Create image view // Textures are not directly accessed by the shaders and // are abstracted by image views containing additional @@ -389,8 +367,7 @@ namespace vkTools // Only set mip map count if optimal tiling is used view.subresourceRange.levelCount = (useStaging) ? texture->mipLevels : 1; view.image = texture->image; - err = vkCreateImageView(device, &view, nullptr, &texture->view); - assert(!err); + vkTools::checkResult(vkCreateImageView(device, &view, nullptr, &texture->view)); } // Clean up vulkan resources used by a texture object @@ -418,8 +395,7 @@ namespace vkTools cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; cmdBufInfo.commandBufferCount = 1; - VkResult vkRes = vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuffer); - assert(vkRes == VK_SUCCESS); + vkTools:checkResult(vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuffer)); } ~VulkanTextureLoader() @@ -431,7 +407,6 @@ namespace vkTools void loadCubemap(const char* filename, VkFormat format, VulkanTexture *texture) { VkFormatProperties formatProperties; - VkResult err; gli::textureCube texCube(gli::load(filename)); assert(!texCube.empty()); @@ -462,26 +437,20 @@ namespace vkTools VkDeviceMemory memory; } cubeFace[6]; - VkCommandBufferBeginInfo cmdBufInfo = {}; - cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmdBufInfo.pNext = NULL; + VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); - err = vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo); - assert(!err); + vkTools::checkResult(vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo)); // Load separate cube map faces into linear tiled textures for (uint32_t face = 0; face < 6; ++face) { - err = vkCreateImage(device, &imageCreateInfo, nullptr, &cubeFace[face].image); - assert(!err); + vkTools::checkResult(vkCreateImage(device, &imageCreateInfo, nullptr, &cubeFace[face].image)); vkGetImageMemoryRequirements(device, cubeFace[face].image, &memReqs); memAllocInfo.allocationSize = memReqs.size; getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAllocInfo.memoryTypeIndex); - err = vkAllocateMemory(device, &memAllocInfo, nullptr, &cubeFace[face].memory); - assert(!err); - err = vkBindImageMemory(device, cubeFace[face].image, cubeFace[face].memory, 0); - assert(!err); + vkTools::checkResult(vkAllocateMemory(device, &memAllocInfo, nullptr, &cubeFace[face].memory)); + vkTools::checkResult(vkBindImageMemory(device, cubeFace[face].image, cubeFace[face].memory, 0)); VkImageSubresource subRes = {}; subRes.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -490,9 +459,7 @@ namespace vkTools void *data; vkGetImageSubresourceLayout(device, cubeFace[face].image, &subRes, &subResLayout); - assert(!err); - err = vkMapMemory(device, cubeFace[face].memory, 0, memReqs.size, 0, &data); - assert(!err); + vkTools::checkResult(vkMapMemory(device, cubeFace[face].memory, 0, memReqs.size, 0, &data)); memcpy(data, texCube[face][subRes.mipLevel].data(), texCube[face][subRes.mipLevel].size()); vkUnmapMemory(device, cubeFace[face].memory); @@ -514,18 +481,15 @@ namespace vkTools imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; imageCreateInfo.arrayLayers = 6; - err = vkCreateImage(device, &imageCreateInfo, nullptr, &texture->image); - assert(!err); + vkTools::checkResult(vkCreateImage(device, &imageCreateInfo, nullptr, &texture->image)); vkGetImageMemoryRequirements(device, texture->image, &memReqs); memAllocInfo.allocationSize = memReqs.size; getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex); - err = vkAllocateMemory(device, &memAllocInfo, nullptr, &texture->deviceMemory); - assert(!err); - err = vkBindImageMemory(device, texture->image, texture->deviceMemory, 0); - assert(!err); + vkTools::checkResult(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture->deviceMemory)); + vkTools::checkResult(vkBindImageMemory(device, texture->image, texture->deviceMemory, 0)); // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy @@ -586,21 +550,22 @@ namespace vkTools texture->imageLayout, subresourceRange); - err = vkEndCommandBuffer(cmdBuffer); - assert(!err); + vkTools::checkResult(vkEndCommandBuffer(cmdBuffer)); - VkFence nullFence = { VK_NULL_HANDLE }; + // Create a fence to make sure that the copies have finished before continuing + VkFence copyFence; + VkFenceCreateInfo fenceCreateInfo = vkTools::initializers::fenceCreateInfo(VK_FLAGS_NONE); + vkTools::checkResult(vkCreateFence(device, &fenceCreateInfo, nullptr, ©Fence)); VkSubmitInfo submitInfo = vkTools::initializers::submitInfo(); - submitInfo.waitSemaphoreCount = 0; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &cmdBuffer; - err = vkQueueSubmit(queue, 1, &submitInfo, nullFence); - assert(!err); + vkTools::checkResult(vkQueueSubmit(queue, 1, &submitInfo, copyFence)); - err = vkQueueWaitIdle(queue); - assert(!err); + vkWaitForFences(device, 1, ©Fence, VK_TRUE, DEFAULT_FENCE_TIMEOUT); + + vkDestroyFence(device, copyFence, nullptr); // Create sampler VkSamplerCreateInfo sampler = vkTools::initializers::samplerCreateInfo(); @@ -616,8 +581,7 @@ namespace vkTools sampler.minLod = 0.0f; sampler.maxLod = 0.0f; sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - err = vkCreateSampler(device, &sampler, nullptr, &texture->sampler); - assert(!err); + vkTools::checkResult(vkCreateSampler(device, &sampler, nullptr, &texture->sampler)); // Create image view VkImageViewCreateInfo view = vkTools::initializers::imageViewCreateInfo(); @@ -628,8 +592,7 @@ namespace vkTools view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; view.subresourceRange.layerCount = 6; view.image = texture->image; - err = vkCreateImageView(device, &view, nullptr, &texture->view); - assert(!err); + vkTools::checkResult(vkCreateImageView(device, &view, nullptr, &texture->view)); // Cleanup for (auto& face : cubeFace) @@ -643,7 +606,6 @@ namespace vkTools void loadTextureArray(const char* filename, VkFormat format, VulkanTexture *texture) { VkFormatProperties formatProperties; - VkResult err; gli::texture2DArray tex2DArray(gli::load(filename)); assert(!tex2DArray.empty()); @@ -684,28 +646,23 @@ namespace vkTools cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - err = vkAllocateCommandBuffers(device, &cmdBufAlllocatInfo, &cmdBuffer); - assert(!err); + vkTools::checkResult(vkAllocateCommandBuffers(device, &cmdBufAlllocatInfo, &cmdBuffer)); VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo(); - err = vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo); - assert(!err); + vkTools::checkResult(vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo)); // Load separate cube map faces into linear tiled textures for (uint32_t i = 0; i < texture->layerCount; ++i) { - err = vkCreateImage(device, &imageCreateInfo, nullptr, &arrayLayer[i].image); - assert(!err); + vkTools::checkResult(vkCreateImage(device, &imageCreateInfo, nullptr, &arrayLayer[i].image)); vkGetImageMemoryRequirements(device, arrayLayer[i].image, &memReqs); memAllocInfo.allocationSize = memReqs.size; getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAllocInfo.memoryTypeIndex); - err = vkAllocateMemory(device, &memAllocInfo, nullptr, &arrayLayer[i].memory); - assert(!err); - err = vkBindImageMemory(device, arrayLayer[i].image, arrayLayer[i].memory, 0); - assert(!err); + vkTools::checkResult(vkAllocateMemory(device, &memAllocInfo, nullptr, &arrayLayer[i].memory)); + vkTools::checkResult(vkBindImageMemory(device, arrayLayer[i].image, arrayLayer[i].memory, 0)); VkImageSubresource subRes = {}; subRes.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -714,9 +671,7 @@ namespace vkTools void *data; vkGetImageSubresourceLayout(device, arrayLayer[i].image, &subRes, &subResLayout); - assert(!err); - err = vkMapMemory(device, arrayLayer[i].memory, 0, memReqs.size, 0, &data); - assert(!err); + vkTools::checkResult(vkMapMemory(device, arrayLayer[i].memory, 0, memReqs.size, 0, &data)); memcpy(data, tex2DArray[i].data(), tex2DArray[i].size()); vkUnmapMemory(device, arrayLayer[i].memory); @@ -737,18 +692,15 @@ namespace vkTools imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; imageCreateInfo.arrayLayers = texture->layerCount; - err = vkCreateImage(device, &imageCreateInfo, nullptr, &texture->image); - assert(!err); + vkTools::checkResult(vkCreateImage(device, &imageCreateInfo, nullptr, &texture->image)); vkGetImageMemoryRequirements(device, texture->image, &memReqs); memAllocInfo.allocationSize = memReqs.size; getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAllocInfo.memoryTypeIndex); - err = vkAllocateMemory(device, &memAllocInfo, nullptr, &texture->deviceMemory); - assert(!err); - err = vkBindImageMemory(device, texture->image, texture->deviceMemory, 0); - assert(!err); + vkTools::checkResult(vkAllocateMemory(device, &memAllocInfo, nullptr, &texture->deviceMemory)); + vkTools::checkResult(vkBindImageMemory(device, texture->image, texture->deviceMemory, 0)); // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy @@ -808,21 +760,22 @@ namespace vkTools texture->imageLayout, subresourceRange); - err = vkEndCommandBuffer(cmdBuffer); - assert(!err); + vkTools::checkResult(vkEndCommandBuffer(cmdBuffer)); - VkFence nullFence = { VK_NULL_HANDLE }; + // Create a fence to make sure that the copies have finished before continuing + VkFence copyFence; + VkFenceCreateInfo fenceCreateInfo = vkTools::initializers::fenceCreateInfo(VK_FLAGS_NONE); + vkTools::checkResult(vkCreateFence(device, &fenceCreateInfo, nullptr, ©Fence)); - // Submit command buffer to graphis queue VkSubmitInfo submitInfo = vkTools::initializers::submitInfo(); submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &cmdBuffer; - err = vkQueueSubmit(queue, 1, &submitInfo, nullFence); - assert(!err); + vkTools::checkResult(vkQueueSubmit(queue, 1, &submitInfo, copyFence)); - err = vkQueueWaitIdle(queue); - assert(!err); + vkWaitForFences(device, 1, ©Fence, VK_TRUE, DEFAULT_FENCE_TIMEOUT); + + vkDestroyFence(device, copyFence, nullptr); // Create sampler VkSamplerCreateInfo sampler = vkTools::initializers::samplerCreateInfo(); @@ -838,8 +791,7 @@ namespace vkTools sampler.minLod = 0.0f; sampler.maxLod = 0.0f; sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; - err = vkCreateSampler(device, &sampler, nullptr, &texture->sampler); - assert(!err); + vkTools::checkResult(vkCreateSampler(device, &sampler, nullptr, &texture->sampler)); // Create image view VkImageViewCreateInfo view = vkTools::initializers::imageViewCreateInfo(); @@ -850,8 +802,7 @@ namespace vkTools view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; view.subresourceRange.layerCount = texture->layerCount; view.image = texture->image; - err = vkCreateImageView(device, &view, nullptr, &texture->view); - assert(!err); + vkTools::checkResult(vkCreateImageView(device, &view, nullptr, &texture->view)); // Cleanup for (auto& layer : arrayLayer) diff --git a/base/vulkantools.h b/base/vulkantools.h index dd9351de..5f76199f 100644 --- a/base/vulkantools.h +++ b/base/vulkantools.h @@ -29,6 +29,8 @@ // Custom define for better code readability #define VK_FLAGS_NONE 0 +// Default fence timeout in nanoseconds +#define DEFAULT_FENCE_TIMEOUT 100000000000 namespace vkTools {