Problems loading HDR textures Vulkan - c++

I am attempting to make a game engine. Currently I am trying to implement a HDR skybox which also has mip maps, however have been stuck with an error for a while. The Example runs completely fine loading non-HDR 8 bit colour textures. But the moment I attempt to use VK_FORMAT_R32G32B32A32_SFLOAT (which I'm fairly sure is the correct format in order to correspond to 4 bit floats loaded from stbi) the command buffer fails to ever complete and seems to always be in a pending state, I have tried giving the texture manager its own command buffer with no luck and using both vkQueueWaitIdle as well as fences but they both return VK_SUCCEED. The validation layers then throw an error once vkResetCommandBuffer is invoked because the command buffer is in pending state. Seemingly it sometimes rarely works if I click to focus on the console, more errors appear afterwards but was not always the case and HDR seemed to be working once it loaded but was still a 1/3 occasion mostly throwing the same error.
This is the code that is used to load the cubemaps in:
Cubemap::Cubemap(CubemapInfo cubemapInfo)
{
RenderSystem& renderSystem = RenderSystem::instance();
TextureManager& textureManager = TextureManager::instance();
VkImageFormatProperties formatProperties;
assert(("[ERROR] Unsupported texture format", !vkGetPhysicalDeviceImageFormatProperties(renderSystem.mPhysicalDevice, cubemapInfo.format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 0, &formatProperties)));
FormatInfo formatInfo = getFormatInfo(cubemapInfo.format);
#pragma region Create cubemap resources
stbi_set_flip_vertically_on_load(true);
void* textureData[6];
// Load images
int width, height, channels;
bool hdr = cubemapInfo.format == VK_FORMAT_R16_SFLOAT || cubemapInfo.format == VK_FORMAT_R16G16_SFLOAT || cubemapInfo.format == VK_FORMAT_R16G16B16_SFLOAT || cubemapInfo.format == VK_FORMAT_R16G16B16A16_SFLOAT || cubemapInfo.format == VK_FORMAT_R32_SFLOAT || cubemapInfo.format == VK_FORMAT_R32G32_SFLOAT || cubemapInfo.format == VK_FORMAT_R32G32B32_SFLOAT || cubemapInfo.format == VK_FORMAT_R32G32B32A32_SFLOAT;
if (hdr)
{
if (formatInfo.bytesPerChannel == 4)
{
for (unsigned int i = 0; i < 6; i++)
{
textureData[i] = stbi_loadf(cubemapInfo.directories[i].c_str(), &width, &height, &channels, formatInfo.nChannels);
}
}
else if (formatInfo.bytesPerChannel == 2)
{
for (unsigned int i = 0; i < 6; i++)
{
float* data = stbi_loadf(cubemapInfo.directories[i].c_str(), &width, &height, &channels, formatInfo.nChannels);
unsigned long long dataSize = width * height * formatInfo.nChannels;
textureData[i] = new float16[dataSize];
for (unsigned long long j = 0; j < dataSize; j++)
{
((float16*)textureData[i])[j] = floatToFloat16(data[j]);
}
stbi_image_free((void*)data);
}
}
}
else
{
for (unsigned int i = 0; i < 6; i++)
{
textureData[i] = stbi_load(cubemapInfo.directories[i].c_str(), &width, &height, &channels, formatInfo.nChannels);
}
}
const VkDeviceSize imageSize = 6 * VkDeviceSize(width) * height * formatInfo.nChannels * formatInfo.bytesPerChannel;
unsigned int nMips = unsigned int(std::floor(std::log2(width > height ? width : height))) + 1;
assert(("[ERROR] Unsupported texture format", formatProperties.maxExtent.width >= width && formatProperties.maxExtent.height >= height && formatProperties.maxExtent.depth >= 1 && formatProperties.maxMipLevels >= 1 && formatProperties.maxArrayLayers >= 1 && formatProperties.sampleCounts & VK_SAMPLE_COUNT_1_BIT && formatProperties.maxResourceSize >= imageSize));
// Create image
VkImageCreateInfo imageCreateInfo = {};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.pNext = nullptr;
imageCreateInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = cubemapInfo.format;
imageCreateInfo.extent = { unsigned int(width), unsigned int(height), 1 };
imageCreateInfo.mipLevels = nMips;
imageCreateInfo.arrayLayers = 6;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.queueFamilyIndexCount = 0;
imageCreateInfo.pQueueFamilyIndices = nullptr;
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkResult result = vkCreateImage(renderSystem.mDevice, &imageCreateInfo, nullptr, &mImage);
validateResult(result);
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(renderSystem.mDevice, mImage, &memoryRequirements);
VkMemoryAllocateInfo memoryAllocateInfo = {};
memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memoryAllocateInfo.allocationSize = memoryRequirements.size;
memoryAllocateInfo.memoryTypeIndex = memoryTypeFromProperties(renderSystem.mPhysicalDeviceMemoryProperties, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
result = vkAllocateMemory(renderSystem.mDevice, &memoryAllocateInfo, nullptr, &mImageMemory);
validateResult(result);
result = vkBindImageMemory(renderSystem.mDevice, mImage, mImageMemory, 0);
validateResult(result);
// Create staging buffer
VkBuffer stagingBuffer;
VkDeviceMemory stagingMemory;
VkBufferCreateInfo bufferCreateInfo = {};
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferCreateInfo.pNext = nullptr;
bufferCreateInfo.flags = 0;
bufferCreateInfo.size = imageSize;
bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufferCreateInfo.queueFamilyIndexCount = 0;
bufferCreateInfo.pQueueFamilyIndices = nullptr;
result = vkCreateBuffer(renderSystem.mDevice, &bufferCreateInfo, nullptr, &stagingBuffer);
validateResult(result);
vkGetBufferMemoryRequirements(renderSystem.mDevice, stagingBuffer, &memoryRequirements);
memoryAllocateInfo.allocationSize = memoryRequirements.size;
memoryAllocateInfo.memoryTypeIndex = memoryTypeFromProperties(renderSystem.mPhysicalDeviceMemoryProperties, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
result = vkAllocateMemory(renderSystem.mDevice, &memoryAllocateInfo, nullptr, &stagingMemory);
validateResult(result);
result = vkBindBufferMemory(renderSystem.mDevice, stagingBuffer, stagingMemory, 0);
validateResult(result);
unsigned char* data;
result = vkMapMemory(renderSystem.mDevice, stagingMemory, 0, imageSize, 0, (void**)&data);
validateResult(result);
unsigned long long dataLayer = unsigned long long(width) * height * formatInfo.nChannels * formatInfo.bytesPerChannel;
for (unsigned int i = 0; i < 6; i++)
{
memcpy((void*)(data + i * dataLayer), textureData[i], dataLayer);
stbi_image_free(textureData[i]);
}
vkUnmapMemory(renderSystem.mDevice, stagingMemory);
result = vkBeginCommandBuffer(textureManager.mCommandBuffer, &renderSystem.mCommandBufferBeginInfo);
validateResult(result);
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.pNext = nullptr;
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT /* Additional >> */ | VK_ACCESS_TRANSFER_READ_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = mImage;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = nMips;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 6;
vkCmdPipelineBarrier(textureManager.mCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
VkBufferImageCopy copyRegion = {};
copyRegion.bufferOffset = 0;
copyRegion.bufferRowLength = 0;
copyRegion.bufferImageHeight = 0;
copyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyRegion.imageSubresource.mipLevel = 0;
copyRegion.imageSubresource.baseArrayLayer = 0;
copyRegion.imageSubresource.layerCount = 6;
copyRegion.imageOffset = { 0, 0, 0 };
copyRegion.imageExtent = { unsigned int(width), unsigned int(height), 1 };
vkCmdCopyBufferToImage(textureManager.mCommandBuffer, stagingBuffer, mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copyRegion);
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.subresourceRange.levelCount = 1;
VkImageBlit imageBlit = {};
imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageBlit.srcSubresource.baseArrayLayer = 0;
imageBlit.srcSubresource.layerCount = 6;
imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageBlit.dstSubresource.baseArrayLayer = 0;
imageBlit.dstSubresource.layerCount = 6;
unsigned int mipWidth = width, mipHeight = height;
for (unsigned int i = 1; i < nMips; i++)
{
barrier.subresourceRange.baseMipLevel = i - 1;
vkCmdPipelineBarrier(textureManager.mCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
imageBlit.srcSubresource.mipLevel = i - 1;
imageBlit.srcOffsets[0] = { 0, 0, 0 };
imageBlit.srcOffsets[1] = { int(mipWidth), int(mipHeight), 1 };
imageBlit.dstSubresource.mipLevel = i;
if (mipWidth > 1)
mipWidth /= 2;
if (mipHeight > 1)
mipHeight /= 2;
imageBlit.dstOffsets[0] = { 0, 0, 0 };
imageBlit.dstOffsets[1] = { int(mipWidth), int(mipHeight), 1 };
vkCmdBlitImage(textureManager.mCommandBuffer, mImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_LINEAR);
}
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
for (unsigned int i = 0; i < nMips; i++)
{
barrier.oldLayout = i == nMips - 1 ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.subresourceRange.baseMipLevel = i;
vkCmdPipelineBarrier(textureManager.mCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
}
result = vkEndCommandBuffer(textureManager.mCommandBuffer);
validateResult(result);
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = nullptr;
submitInfo.waitSemaphoreCount = 0;
submitInfo.pWaitSemaphores = nullptr;
submitInfo.pWaitDstStageMask = nullptr;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &textureManager.mCommandBuffer;
submitInfo.signalSemaphoreCount = 0;
submitInfo.pSignalSemaphores = nullptr;
result = vkQueueSubmit(renderSystem.mGraphicsQueue, 1, &submitInfo, NULL);
validateResult(result);
// Create image view
VkImageViewCreateInfo imageViewCreateInfo = {};
imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCreateInfo.pNext = nullptr;
imageViewCreateInfo.flags = 0;
imageViewCreateInfo.image = mImage;
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
imageViewCreateInfo.format = cubemapInfo.format;
imageViewCreateInfo.components = formatInfo.componentMapping;
imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
imageViewCreateInfo.subresourceRange.levelCount = nMips;
imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
imageViewCreateInfo.subresourceRange.layerCount = 6;
result = vkCreateImageView(renderSystem.mDevice, &imageViewCreateInfo, nullptr, &mImageView);
validateResult(result);
// Create sampler
VkSamplerCreateInfo samplerCreateInfo = {};
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerCreateInfo.pNext = nullptr;
samplerCreateInfo.flags = 0;
samplerCreateInfo.magFilter = VK_FILTER_LINEAR;
samplerCreateInfo.minFilter = VK_FILTER_LINEAR;
samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerCreateInfo.mipLodBias = 0.0f;
samplerCreateInfo.minLod = 0.0f;
samplerCreateInfo.maxLod = float(nMips);
samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;;
samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
samplerCreateInfo.anisotropyEnable = VK_TRUE;
samplerCreateInfo.maxAnisotropy = renderSystem.mPhysicalDeviceProperties.limits.maxSamplerAnisotropy;
samplerCreateInfo.compareEnable = VK_FALSE;
samplerCreateInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerCreateInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
result = vkCreateSampler(renderSystem.mDevice, &samplerCreateInfo, nullptr, &mSampler);
validateResult(result);
result = vkQueueWaitIdle(renderSystem.mGraphicsQueue);
validateResult(result);
result = vkResetCommandBuffer(textureManager.mCommandBuffer, 0);
validateResult(result);
vkDestroyBuffer(renderSystem.mDevice, stagingBuffer, nullptr);
vkFreeMemory(renderSystem.mDevice, stagingMemory, nullptr);
#pragma endregion
}
Exact errors that occurr:
VUID-vkResetCommandBuffer-commandBuffer-00045(ERROR / SPEC): msgNum: 511214570 - Validation Error: [ VUID-vkResetCommandBuffer-commandBuffer-00045 ] Object 0: handle = 0x19323492138, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x1e7883ea | Attempt to reset VkCommandBuffer 0x19323492138[] which is in use. The Vulkan spec states: commandBuffer must not be in the pending state (https://vulkan.lunarg.com/doc/view/1.2.162.1/windows/1.2-extensions/vkspec.html#VUID-vkResetCommandBuffer-commandBuffer-00045)
Objects: 1
[0] 0x19323492138, type: 6, name: NULL
UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout(ERROR / SPEC): msgNum: 1303270965 - Validation Error: [ UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout ] Object 0: handle = 0x19323492138, type = VK_OBJECT_TYPE_COMMAND_BUFFER; | MessageID = 0x4dae5635 | Submitted command buffer expects VkImage 0x5fb0e800000000cd[] (subresource: aspectMask 0x1 array layer 0, mip level 0) to be in layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL--instead, current layout is VK_IMAGE_LAYOUT_UNDEFINED.
Objects: 1
[0] 0x19323492138, type: 6, name: NULL
(^ This error is thrown continuously for mip levels 0-12 ^)
View full source:
https://github.com/finnbuhse/Vulkan-Engine-V1.0
Although assets and shader binaries are not on the github so compile the shader sources into files with names identical to those found in mesh.cpp line 1083 and adjust main.cpp to include custom models if you wish to try compile and run the source.
Any clue as to why this might be happening would be greatly appreciated

So, after almost an entire year of agonising over this one error... I found what seemed to have happened was the GPU memory ran out, and the skybox I picked initially was simply too large; each face was 4K and I found the whole cubemap had to be allocated over a gigabyte of video memory, and having a mere NVIDIA GTX 1050 Ti, is a quarter of it. However I did think this was possible early on, which is why I validated every VkResult I could thinking if this happened, VK_ERROR_OUT_OF_DEVICE_MEMORY would be returned. However nothing but success from what the 'results' could tell. Perhaps it wasn't so much video memory but the GPU had a hard time mip-mapping such a large image. Either way, with a different HDR skybox (1k) it works perfectly fine with both 16 bit floating point images aswell as 32 bits.

Related

I'm having some problems getting a Irradiance Map working in Vulkan

I'm having some problems getting a Irradiance Map working in Vulkan for multiple days.
It seems like the texture aren't stretching to fit the plain it's projected on. I've tried multiple way to figure out how to get the get the full text displayed and nothings working. If the cube map is 512 x 512 the CubeMap will only show the 512x512 pixels and cut off the rest. And if it's 2048x2048 it shows all of the texture but the rest of it just blank space.
The irradiance part isn't applied here. It just taking the 6 views of the cube and projecting them.
2048 x 2048 view
512x512 View
This is irradiance code I've been working with.
#pragma once
#include "BaseRenderPass.h"
#include "RenderedDepthTexture.h"
#include "BlinnPhongPipeline.h"
#include "MeshManager.h"
#include "RenderedColorTexture.h"
#include "SkyBoxRenderPipeline.h"
#include "RenderedCubeMapTexture.h"
#include "IrradiancePipeline.h"
class IrradianceRenderPass : public BaseRenderPass
{
private:
void CreateRenderPass();
void CreateRendererFramebuffers();
void SetUpCommandBuffers();
uint32_t CubeMapSize;
VkFramebuffer IrradianceMapFrameBuffer;
public:
IrradianceRenderPass();
IrradianceRenderPass(std::shared_ptr<VulkanEngine> engine);
~IrradianceRenderPass();
std::shared_ptr<RenderedCubeMapTexture> RenderedCubeMap;
std::shared_ptr<IrradiancePipeline> irradiancePipeline;
void RebuildSwapChain();
void Draw();
void Destroy();
};
#include "IrradianceRenderPass.h"
#include "GraphicsPipeline.h"
#include "Skybox.h"
IrradianceRenderPass::IrradianceRenderPass() : BaseRenderPass()
{
}
IrradianceRenderPass::IrradianceRenderPass(std::shared_ptr<VulkanEngine> engine) : BaseRenderPass()
{
CubeMapSize = 512.0f;
RenderedCubeMap = std::make_shared<RenderedCubeMapTexture>(RenderedCubeMapTexture(glm::ivec2(CubeMapSize)));
CreateRenderPass();
CreateRendererFramebuffers();
irradiancePipeline = std::make_shared<IrradiancePipeline>(IrradiancePipeline(RenderPass));
SetUpCommandBuffers();
Draw();
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex];
VkFenceCreateInfo fenceCreateInfo{};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = 0;
VkFence fence;
vkCreateFence(VulkanPtr::GetDevice(), &fenceCreateInfo, nullptr, &fence);
vkQueueSubmit(VulkanPtr::GetGraphicsQueue(), 1, &submitInfo, fence);
vkWaitForFences(VulkanPtr::GetDevice(), 1, &fence, VK_TRUE, UINT64_MAX);
vkDestroyFence(VulkanPtr::GetDevice(), fence, nullptr);
}
IrradianceRenderPass::~IrradianceRenderPass()
{
}
void IrradianceRenderPass::CreateRenderPass()
{
std::vector<VkAttachmentDescription> AttachmentDescriptionList;
VkAttachmentDescription CubeMapAttachment = {};
CubeMapAttachment.format = VK_FORMAT_R8G8B8A8_UNORM;
CubeMapAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
CubeMapAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
CubeMapAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
CubeMapAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
CubeMapAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
CubeMapAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
CubeMapAttachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
AttachmentDescriptionList.emplace_back(CubeMapAttachment);
std::vector<VkAttachmentReference> ColorRefsList;
ColorRefsList.emplace_back(VkAttachmentReference{ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
VkSubpassDescription subpassDescription = {};
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDescription.colorAttachmentCount = static_cast<uint32_t>(ColorRefsList.size());
subpassDescription.pColorAttachments = ColorRefsList.data();
std::vector<VkSubpassDependency> DependencyList;
VkSubpassDependency FirstDependency = {};
FirstDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
FirstDependency.dstSubpass = 0;
FirstDependency.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
FirstDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
FirstDependency.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
FirstDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
FirstDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
DependencyList.emplace_back(FirstDependency);
VkSubpassDependency SecondDependency = {};
SecondDependency.srcSubpass = 0;
SecondDependency.dstSubpass = VK_SUBPASS_EXTERNAL;
SecondDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
SecondDependency.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
SecondDependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
SecondDependency.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
SecondDependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
DependencyList.emplace_back(SecondDependency);
const uint32_t viewMask = 0b00111111;
const uint32_t correlationMask = 0b00111111;
VkRenderPassMultiviewCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
createInfo.subpassCount = 1;
createInfo.pViewMasks = &viewMask;
createInfo.correlationMaskCount = 1;
createInfo.pCorrelationMasks = &correlationMask;
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.attachmentCount = static_cast<uint32_t>(AttachmentDescriptionList.size());
renderPassInfo.pAttachments = AttachmentDescriptionList.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpassDescription;
renderPassInfo.dependencyCount = static_cast<uint32_t>(DependencyList.size());
renderPassInfo.pDependencies = DependencyList.data();
renderPassInfo.pNext = &createInfo;
if (vkCreateRenderPass(EnginePtr::GetEnginePtr()->Device, &renderPassInfo, nullptr, &RenderPass))
{
throw std::runtime_error("failed to create GBuffer RenderPass!");
}
}
void IrradianceRenderPass::CreateRendererFramebuffers()
{
SwapChainFramebuffers.resize(EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainImageCount());
for (size_t i = 0; i < EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainImageCount(); i++)
{
std::vector<VkImageView> AttachmentList;
AttachmentList.emplace_back(RenderedCubeMap->View);
VkFramebufferCreateInfo frameBufferCreateInfo = {};
frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
frameBufferCreateInfo.renderPass = RenderPass;
frameBufferCreateInfo.attachmentCount = static_cast<uint32_t>(AttachmentList.size());
frameBufferCreateInfo.pAttachments = AttachmentList.data();
frameBufferCreateInfo.width = CubeMapSize;
frameBufferCreateInfo.height = CubeMapSize;
frameBufferCreateInfo.layers = 1;
if (vkCreateFramebuffer(EnginePtr::GetEnginePtr()->Device, &frameBufferCreateInfo, nullptr, &SwapChainFramebuffers[i]))
{
throw std::runtime_error("Failed to create Gbuffer FrameBuffer.");
}
}
}
void IrradianceRenderPass::SetUpCommandBuffers()
{
CommandBuffer.resize(EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainImageCount());
for (size_t i = 0; i < EnginePtr::GetEnginePtr()->SwapChain.GetSwapChainImageCount(); i++)
{
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = EnginePtr::GetEnginePtr()->CommandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
if (vkAllocateCommandBuffers(EnginePtr::GetEnginePtr()->Device, &allocInfo, &CommandBuffer[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate command buffers!");
}
}
}
void IrradianceRenderPass::RebuildSwapChain()
{
irradiancePipeline->Destroy();
vkDestroyRenderPass(EnginePtr::GetEnginePtr()->Device, RenderPass, nullptr);
RenderPass = VK_NULL_HANDLE;
for (auto& framebuffer : SwapChainFramebuffers)
{
vkDestroyFramebuffer(EnginePtr::GetEnginePtr()->Device, framebuffer, nullptr);
framebuffer = VK_NULL_HANDLE;
}
CreateRenderPass();
CreateRendererFramebuffers();
irradiancePipeline->UpdateGraphicsPipeLine(RenderPass);
SetUpCommandBuffers();
}
void IrradianceRenderPass::Draw()
{
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
if (vkBeginCommandBuffer(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex], &beginInfo) != VK_SUCCESS) {
throw std::runtime_error("failed to begin recording command buffer!");
}
std::array<VkClearValue, 2> clearValues{};
clearValues[0].color = { {0.0f, 1.0f, 0.0f, 1.0f} };
clearValues[1].color = { {0.0f, 1.0f, 0.0f, 1.0f} };
VkRenderPassBeginInfo renderPassInfo{};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassInfo.renderPass = RenderPass;
renderPassInfo.framebuffer = SwapChainFramebuffers[EnginePtr::GetEnginePtr()->ImageIndex];
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent.width = CubeMapSize;
renderPassInfo.renderArea.extent.height = CubeMapSize;
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
renderPassInfo.pClearValues = clearValues.data();
vkCmdBindPipeline(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, irradiancePipeline->ShaderPipeline);
vkCmdBindDescriptorSets(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, irradiancePipeline->ShaderPipelineLayout, 0, 1, &irradiancePipeline->DescriptorSet, 0, nullptr);
vkCmdBeginRenderPass(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
static_cast<Skybox*>(MeshManagerPtr::GetMeshManagerPtr()->GetMeshByType(MeshTypeFlag::Mesh_Type_SkyBox)[0].get())->Draw(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex]);
vkCmdEndRenderPass(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex]);
if (vkEndCommandBuffer(CommandBuffer[EnginePtr::GetEnginePtr()->CMDIndex]) != VK_SUCCESS) {
throw std::runtime_error("failed to record command buffer!");
}
}
void IrradianceRenderPass::Destroy()
{
irradiancePipeline->Destroy();
BaseRenderPass::Destroy();
}

Vulkan - Loading depth attachment in the second renderpass not working

I'm trying to reuse the depth attachment from the first renderpass into the second renderpass. but, it's not loading the depth values in the second renderpass.
//code that creates attachments
void VulkanRenderTarget::addAttachment(AttachmentCreateInfo createinfo)
{
auto device = mRenderer->getDevice();
Attachment attachment;
attachment.format = createinfo.format;
VkImageAspectFlags aspectMask = 0;
// Select aspect mask and layout depending on usage
// Color attachment
if (createinfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
{
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
}
// Depth (and/or stencil) attachment
if (createinfo.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
{
if (attachment.hasDepth())
{
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
}
if (attachment.hasStencil())
{
aspectMask = aspectMask | VK_IMAGE_ASPECT_STENCIL_BIT;
}
}
assert(aspectMask > 0);
VkImageCreateInfo image = VulkanInitializers::imageCreateInfo();
image.imageType = VK_IMAGE_TYPE_2D;
image.format = createinfo.format;
image.extent.width = createinfo.width;
image.extent.height = createinfo.height;
image.extent.depth = 1;
image.mipLevels = 1;
image.arrayLayers = createinfo.layerCount;
image.samples = createinfo.imageSampleCount;
image.tiling = createinfo.tiling;
image.usage = createinfo.usage;
VkMemoryAllocateInfo memAlloc = VulkanInitializers::memoryAllocateInfo();
VkMemoryRequirements memReqs;
// Create image for this attachment
VERIFY(vkCreateImage(device, &image, nullptr, &attachment.image));
vkGetImageMemoryRequirements(device, attachment.image, &memReqs);
memAlloc.allocationSize = memReqs.size;
memAlloc.memoryTypeIndex = mRenderer->getMemoryType(memReqs.memoryTypeBits, createinfo.memoryFlag);
VERIFY(vkAllocateMemory(device, &memAlloc, nullptr, &attachment.memory));
VERIFY(vkBindImageMemory(device, attachment.image, attachment.memory, 0));
attachment.subresourceRange = {};
attachment.subresourceRange.aspectMask = aspectMask;
attachment.subresourceRange.levelCount = 1;
attachment.subresourceRange.layerCount = createinfo.layerCount;
VkImageViewCreateInfo imageView = VulkanInitializers::imageViewCreateInfo();
imageView.viewType = (createinfo.layerCount == 1) ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY;
imageView.format = createinfo.format;
imageView.subresourceRange = attachment.subresourceRange;
//todo: workaround for depth+stencil attachments
imageView.subresourceRange.aspectMask = (attachment.hasDepth()) ? VK_IMAGE_ASPECT_DEPTH_BIT : aspectMask;
imageView.image = attachment.image;
VERIFY(vkCreateImageView(device, &imageView, nullptr, &attachment.view));
// Fill attachment description
attachment.description = {};
attachment.description.samples = createinfo.imageSampleCount;
attachment.description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment.description.storeOp = (createinfo.usage & VK_IMAGE_USAGE_SAMPLED_BIT) ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment.description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment.description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment.description.format = createinfo.format;
attachment.description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
// Final layout
// If not, final layout depends on attachment type
if (attachment.hasDepth() || attachment.hasStencil())
{
attachment.description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
//attachment.description.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
}
else
{
attachment.description.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
mAttachments.push_back(attachment);
}
///first renderpass creation
// Four attachments (3 color, 1 depth)
AttachmentCreateInfo attachmentInfo = {};
attachmentInfo.width = mWidth;
attachmentInfo.height = mHeight;
attachmentInfo.layerCount = 1;
attachmentInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
attachmentInfo.imageSampleCount = mRenderer->getMSAAsamples();
// Color attachments
// Attachment 0: (World space) Positions
//attachmentInfo.format = VK_FORMAT_R16G16B16A16_SFLOAT;
attachmentInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
addAttachment(attachmentInfo);
// Attachment 1: (World space) Normals
attachmentInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
addAttachment(attachmentInfo);
// Attachment 2: Albedo (color)
attachmentInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
addAttachment(attachmentInfo);
//depth
attachmentInfo.format = mRenderer->getDepthFormat();
attachmentInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
addAttachment(attachmentInfo);
{
//create sampler
VkSamplerCreateInfo samplerInfo = VulkanInitializers::samplerCreateInfo();
samplerInfo.magFilter = VK_FILTER_NEAREST;
samplerInfo.minFilter = VK_FILTER_NEAREST;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.mipLodBias = 0.0f;
samplerInfo.maxAnisotropy = 1.0f;
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 1.0f;
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
VERIFY(vkCreateSampler(device, &samplerInfo, nullptr, &sampler));
}
//create renderpass and frame buffer
{
std::vector<VkAttachmentDescription> attachmentDescriptions;
for (auto& attachment : mAttachments)
{
attachmentDescriptions.push_back(attachment.description);
};
// Collect attachment references
std::vector<VkAttachmentReference> colorReferences;
VkAttachmentReference depthReference = {};
bool hasDepth = false;
bool hasColor = false;
uint32_t attachmentIndex = 0;
for (auto& attachment : mAttachments)
{
if (attachment.isDepthStencil())
{
// Only one depth attachment allowed
assert(!hasDepth);
depthReference.attachment = attachmentIndex;
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
hasDepth = true;
}
else
{
colorReferences.push_back({ attachmentIndex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
hasColor = true;
}
attachmentIndex++;
};
// Default render pass setup uses only one subpass
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
if (hasColor)
{
subpass.pColorAttachments = colorReferences.data();
subpass.colorAttachmentCount = static_cast<uint32_t>(colorReferences.size());
}
if (hasDepth)
{
subpass.pDepthStencilAttachment = &depthReference;
}
// Use subpass dependencies for attachment layout transitions
std::array<VkSubpassDependency, 2> dependencies;
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
// Create render pass
VkRenderPassCreateInfo renderPassInfo = {};
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassInfo.pAttachments = attachmentDescriptions.data();
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachmentDescriptions.size());
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassInfo.pDependencies = dependencies.data();
VERIFY(vkCreateRenderPass(device, &renderPassInfo, nullptr, &mRenderPass));
std::vector<VkImageView> attachmentViews;
for (auto attachment : mAttachments)
{
attachmentViews.push_back(attachment.view);
}
// Find. max number of layers across attachments
uint32_t maxLayers = 0;
for (auto attachment : mAttachments)
{
if (attachment.subresourceRange.layerCount > maxLayers)
{
maxLayers = attachment.subresourceRange.layerCount;
}
}
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = mRenderPass;
framebufferInfo.pAttachments = attachmentViews.data();
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachmentViews.size());
framebufferInfo.width = mWidth;
framebufferInfo.height = mHeight;
framebufferInfo.layers = maxLayers;
mFrameBuffers.clear();
mFrameBuffers.resize(1);
VERIFY(vkCreateFramebuffer(device, &framebufferInfo, nullptr, &mFrameBuffers[0]));
}
///second renderpass
finalImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
std::array<VkAttachmentDescription, 3> attachments = {};
// Multisampled attachment that we render to
attachments[0].format = mRenderer->getSCImageFormat();// swapChain.colorFormat;
attachments[0].samples = mRenderer->getMSAAsamples();// settings.sampleCount;
attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
// This is the frame buffer attachment to where the multisampled image
// will be resolved to and which will be presented to the swapchain
attachments[1].format = mRenderer->getSCImageFormat();;
attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[1].finalLayout = finalImageLayout;
// Multisampled depth attachment we render to
attachments[2].format = mRenderer->getDepthFormat();// depthFormat;
attachments[2].samples = mRenderer->getMSAAsamples();// settings.sampleCount;
attachments[2].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;// VK_ATTACHMENT_LOAD_OP_LOAD; //VK_ATTACHMENT_LOAD_OP_CLEAR; use depth from deferred renderer
attachments[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE;// VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachments[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[2].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference colorReference = {};
colorReference.attachment = 0;
colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference depthReference = {};
depthReference.attachment = 2;
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
// Resolve attachment reference for the color attachment
VkAttachmentReference resolveReference = {};
resolveReference.attachment = 1;
resolveReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorReference;
// Pass our resolve attachments to the sub pass
subpass.pResolveAttachments = &resolveReference;
subpass.pDepthStencilAttachment = &depthReference;
std::vector<VkSubpassDependency> dependencies;
dependencies.resize(2);
dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; // Both stages might have access the depth-buffer, so need both in src/dstStageMask;;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
VkRenderPassCreateInfo renderPassCI = {};
renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderPassCI.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassCI.pAttachments = attachments.data();
renderPassCI.subpassCount = 1;
renderPassCI.pSubpasses = &subpass;
renderPassCI.dependencyCount = static_cast<uint32_t>(dependencies.size());
renderPassCI.pDependencies = dependencies.data();
VERIFY(vkCreateRenderPass(device, &renderPassCI, nullptr, &mRenderPass));
VkImageCreateInfo imageCI{};
imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCI.imageType = VK_IMAGE_TYPE_2D;
imageCI.format = mRenderer->getSCImageFormat();// swapChain.colorFormat;
imageCI.extent.width = mWidth;// width;
imageCI.extent.height = mHeight;
imageCI.extent.depth = 1;
imageCI.mipLevels = 1;
imageCI.arrayLayers = 1;
imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCI.tiling = VK_IMAGE_TILING_OPTIMAL;
imageCI.samples = mRenderer->getMSAAsamples();// settings.sampleCount;
imageCI.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VERIFY(vkCreateImage(device, &imageCI, nullptr, &multisampleTarget.color.image));
VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements(device, multisampleTarget.color.image, &memReqs);
VkMemoryAllocateInfo memAllocInfo{};
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAllocInfo.allocationSize = memReqs.size;
VkBool32 lazyMemTypePresent;
memAllocInfo.memoryTypeIndex = mRenderer->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, &lazyMemTypePresent);
if (!lazyMemTypePresent) {
memAllocInfo.memoryTypeIndex = mRenderer->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
}
VERIFY(vkAllocateMemory(device, &memAllocInfo, nullptr, &multisampleTarget.color.memory));
vkBindImageMemory(device, multisampleTarget.color.image, multisampleTarget.color.memory, 0);
// Create image view for the MSAA target
VkImageViewCreateInfo imageViewCI{};
imageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewCI.image = multisampleTarget.color.image;
imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCI.format = mRenderer->getSCImageFormat();// swapChain.colorFormat;
imageViewCI.components.r = VK_COMPONENT_SWIZZLE_R;
imageViewCI.components.g = VK_COMPONENT_SWIZZLE_G;
imageViewCI.components.b = VK_COMPONENT_SWIZZLE_B;
imageViewCI.components.a = VK_COMPONENT_SWIZZLE_A;
imageViewCI.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
imageViewCI.subresourceRange.levelCount = 1;
imageViewCI.subresourceRange.layerCount = 1;
VERIFY(vkCreateImageView(device, &imageViewCI, nullptr, &multisampleTarget.color.view));
AttachmentCreateInfo attachmentInfo = {};
attachmentInfo.width = mWidth;
attachmentInfo.height = mHeight;
attachmentInfo.layerCount = 1;
attachmentInfo.imageSampleCount = mRenderer->getMSAAsamples();
attachmentInfo.format = mRenderer->getDepthFormat();
attachmentInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
addAttachment(attachmentInfo);
auto& depthAttachment = mAttachments.back();
multisampleTarget.depth.image = depthAttachment.image;
multisampleTarget.depth.view = depthAttachment.view;
multisampleTarget.depth.memory = depthAttachment.memory;
std::vector<VkImageView> attachments;
attachments.emplace_back(multisampleTarget.color.view);
attachments.emplace_back(color.view);
attachments.emplace_back(multisampleTarget.depth.view);
VkFramebufferCreateInfo frameBufferCI{};
frameBufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
frameBufferCI.pNext = NULL;
frameBufferCI.renderPass = mRenderPass;
frameBufferCI.attachmentCount = static_cast<uint32_t>(attachments.size());
frameBufferCI.pAttachments = attachments.data();
frameBufferCI.width = mWidth;
frameBufferCI.height = mHeight;
frameBufferCI.layers = 1;
mFrameBuffers.resize(1);
VERIFY(vkCreateFramebuffer(device, &frameBufferCI, nullptr, &mFrameBuffers[0]));
In renderDoc I could see the second renderpass depth attachment as 'undefined img'
I'm guessing that I'm using Load and StoreOps the right way and also created the subpass dependencies which takes care of transfering the depth values from first render pass to second. But!! it's not working. :( Apologies for my novice coding style. Most were from SaschaWillems examples.
In second pass, depth attachment description, it "loads" image in undefined state:
attachments[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
Based on your attachment creating code, I assume it should be VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL

Flickering screen when drawing multiple textured objects with Vulkan

I am new to Vulkan so please don't smite me into oblivion. I have been building a program which can load 3D models that are in fbx format. I ran into a problem when rendering multiple textured objects at once. I have been building the program based on a book called Learning Vulkan with some minor changes here and there.
EDIT:
I have now moved the rendering function to VulkanRenderer from VulkanDrawable. I gather the drawing command buffers from each VulkanDrawable into a vector and try to submit that to the queue but receive an error and the program crashes after drawing one of the objects to the screen for fraction of a second. Program fails with the following error, which I can't seem to be able to fix: [VK_DEBUG_REPORT] ERROR: [ObjectTracker] Code149:Invalid Command Buffer Object 0x21.
Below are the requested code snippets.
Here is the function (and possibly the bug too) in VulkanRenderer:
bool VulkanRenderer::render(){
while(!glfwWindowShouldClose(window))
{
glfwPollEvents();
uint32_t& currentColorImage = swapChainObject->scPublicVariables.currentColorBuffer;
VkSwapchainKHR& swapchain = swapChainObject->scPublicVariables.swapchain;
//Get the index of the next available swapchain image
VkResult result = swapChainObject->fpAcquireNextImageKHR(deviceObject->device,
swapchain,
UINT64_MAX,
presentCompleteSemaphore,
VK_NULL_HANDLE,
&currentColorImage);
//getDrawBuffer function inside VulkanDrawable looks like this (all in header file):
//inline VkCommandBuffer* getDrawBuffer(int index){return &vecCmdDraw[index];}
//This is a temporary solution and probably wrong as well. I am gathering pointers to
//the drawing buffers that I want to execute.
std::vector<VkCommandBuffer*> buffers{drawableObjects[0]->getDrawBuffer(currentColorImage),
drawableObjects[1]->getDrawBuffer(currentColorImage)};
//Create submit information
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = nullptr;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &presentCompleteSemaphore;
submitInfo.pWaitDstStageMask = &submitPipelineStages;
submitInfo.commandBufferCount = (uint32_t)sizeof(buffers) / sizeof(VkCommandBuffer);
//This *buffers.data looks dodgy but it won't compile otherwise
submitInfo.pCommandBuffers = *buffers.data();
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &drawingCompleteSemaphore;
CommandBufferManager::submitCommandBuffer(deviceObject->queue, *buffers.data(), &submitInfo);
//Present image in the window
VkPresentInfoKHR present = {};
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present.pNext = nullptr;
present.swapchainCount = 1;
present.pSwapchains = &swapchain;
present.pImageIndices = &currentColorImage;
present.pWaitSemaphores = &drawingCompleteSemaphore;
present.waitSemaphoreCount = 1;
present.pResults = nullptr;
//queue the image for presentation
result = swapChainObject->fpQueuePresentKHR(deviceObject->queue, &present);
}
}
Here is the submitCommandBuffer function (fence is VK_NULL_HANDLE as default):
//Submits given command buffer to given queue with provided submit info and fence.
void CommandBufferManager::submitCommandBuffer(const VkQueue &queue,
const VkCommandBuffer *cmdBuffer,
const VkSubmitInfo *submitInfo,
const VkFence &fence){
VkResult result;
//If submit information is provided, use it.
if(submitInfo)
{
result = vkQueueSubmit(queue, 1, submitInfo, fence);
assert(!result);
result = vkQueueWaitIdle(queue);
assert(!result);
return;
}
//If not, create default submit info
VkSubmitInfo defaultSubmitInfo = {};
defaultSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
defaultSubmitInfo.pNext = nullptr;
defaultSubmitInfo.waitSemaphoreCount = 0;
defaultSubmitInfo.pWaitSemaphores = nullptr;
defaultSubmitInfo.signalSemaphoreCount = 0;
defaultSubmitInfo.pSignalSemaphores = nullptr;
defaultSubmitInfo.pWaitDstStageMask = nullptr;
defaultSubmitInfo.commandBufferCount = (uint32_t) sizeof(cmdBuffer) / sizeof(VkCommandBuffer);
defaultSubmitInfo.pCommandBuffers = cmdBuffer;
result = vkQueueSubmit(queue, 1, &defaultSubmitInfo, fence);
assert(!result);
result = vkQueueWaitIdle(queue);
assert(!result);
}
Renderpass:
void VulkanRenderer::createRenderPass(bool includeDepth, bool clear)
{
//This function depends on the VulkanSwapchain to get the
//color image and VulkanRenderer to get the depth image
VkResult result;
//Attach color and depth buffers as an attachment to render pass instance.
VkAttachmentDescription attachments[2];
attachments[0].format = swapChainObject->scPublicVariables.format;
attachments[0].samples = NUM_SAMPLES;
//If clear is required, use it, else don't care.
attachments[0].loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
attachments[0].flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
//If depth buffer is presented, define the properties for depth buffer attachment
if(includeDepth)
{
attachments[1].format = Depth.format;
attachments[1].samples = NUM_SAMPLES;
attachments[1].loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR :
VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments[1].flags = VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT;
}
//Define color buffer attachment binding points and layout information
VkAttachmentReference colorReference = {};
colorReference.attachment = 0;
colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
//Define depth buffer attachment binding points and layout information
VkAttachmentReference depthReference = {};
depthReference.attachment = 1;
depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
//Specify attachments - color, depth, resolve, preserve etc.
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.flags = 0;
subpass.inputAttachmentCount = 0;
subpass.pInputAttachments = nullptr;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorReference;
subpass.pResolveAttachments = nullptr;
subpass.pDepthStencilAttachment = includeDepth ? &depthReference : nullptr;
subpass.preserveAttachmentCount = 0;
subpass.pPreserveAttachments = nullptr;
//Specify the attachment and subpass associated with render pass
VkRenderPassCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.attachmentCount = includeDepth ? 2 : 1;
createInfo.pAttachments = attachments;
createInfo.subpassCount = 1;
createInfo.pSubpasses = &subpass;
createInfo.dependencyCount = 0;
createInfo.pDependencies = nullptr;
//Create the render pass
result = vkCreateRenderPass(deviceObject->device, &createInfo, nullptr, &renderPass);
assert(result == VK_SUCCESS);
}
EDIT: forgot to add command buffer recording and parts of the api dump:
Thread 0, Frame 0:
vkBeginCommandBuffer(commandBuffer, pBeginInfo) returns VkResult VK_SUCCESS (0):
commandBuffer: VkCommandBuffer = 0x1fc0bf0
pBeginInfo: const VkCommandBufferBeginInfo* = 0x1f9c070:
sType: VkStructureType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO (42)
pNext: const void* = NULL
flags: VkCommandBufferUsageFlags = 0
pInheritanceInfo: const VkCommandBufferInheritanceInfo* = UNUSED
Thread 0, Frame 0:
vkCmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents) returns void:
commandBuffer: VkCommandBuffer = 0x1fc0bf0
pRenderPassBegin: const VkRenderPassBeginInfo* = 0x1fc2810:
sType: VkStructureType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO (43)
pNext: const void* = NULL
renderPass: VkRenderPass = 0x1f76d00
framebuffer: VkFramebuffer = 0x1f77b00
renderArea: VkRect2D = 0x1fc2830:
offset: VkOffset2D = 0x1fc2830:
x: int32_t = 0
y: int32_t = 0
extent: VkExtent2D = 0x1fc2838:
width: uint32_t = 800
height: uint32_t = 800
clearValueCount: uint32_t = 2
pClearValues: const VkClearValue* = 0x1fc2860
pClearValues[0]: const VkClearValue = 0x1fc2860 (Union):
color: VkClearColorValue = 0x1fc2860 (Union):
float32: float[4] = 0x1fc2860
float32[0]: float = 1
float32[1]: float = 1
float32[2]: float = 1
float32[3]: float = 1
int32: int32_t[4] = 0x1fc2860
int32[0]: int32_t = 1065353216
int32[1]: int32_t = 1065353216
int32[2]: int32_t = 1065353216
int32[3]: int32_t = 1065353216
uint32: uint32_t[4] = 0x1fc2860
uint32[0]: uint32_t = 1065353216
uint32[1]: uint32_t = 1065353216
uint32[2]: uint32_t = 1065353216
uint32[3]: uint32_t = 1065353216
depthStencil: VkClearDepthStencilValue = 0x1fc2860:
depth: float = 1
stencil: uint32_t = 1065353216
pClearValues[1]: const VkClearValue = 0x1fc2870 (Union):
color: VkClearColorValue = 0x1fc2870 (Union):
float32: float[4] = 0x1fc2870
float32[0]: float = 1
float32[1]: float = 0
float32[2]: float = 0
float32[3]: float = 0
int32: int32_t[4] = 0x1fc2870
int32[0]: int32_t = 1065353216
int32[1]: int32_t = 0
int32[2]: int32_t = 0
int32[3]: int32_t = 0
uint32: uint32_t[4] = 0x1fc2870
uint32[0]: uint32_t = 1065353216
uint32[1]: uint32_t = 0
uint32[2]: uint32_t = 0
uint32[3]: uint32_t = 0
depthStencil: VkClearDepthStencilValue = 0x1fc2870:
depth: float = 1
stencil: uint32_t = 0
contents: VkSubpassContents = VK_SUBPASS_CONTENTS_INLINE (0)
Thread 0, Frame 0:
vkCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline) returns void:
commandBuffer: VkCommandBuffer = 0x1fc0bf0
pipelineBindPoint: VkPipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS (0)
pipeline: VkPipeline = 0x1fa4ae0
Thread 0, Frame 0:
vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets) returns void:
commandBuffer: VkCommandBuffer = 0x1fc0bf0
pipelineBindPoint: VkPipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS (0)
layout: VkPipelineLayout = 0x1fa2fe0
firstSet: uint32_t = 0
descriptorSetCount: uint32_t = 1
pDescriptorSets: const VkDescriptorSet* = 0x1fc2970
pDescriptorSets[0]: const VkDescriptorSet = 0x1fa1f70
dynamicOffsetCount: uint32_t = 0
pDynamicOffsets: const uint32_t* = NULL
Thread 0, Frame 0:
vkCmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets) returns void:
commandBuffer: VkCommandBuffer = 0x1fc0bf0
firstBinding: uint32_t = 0
bindingCount: uint32_t = 1
pBuffers: const VkBuffer* = 0x1fc2a40
pBuffers[0]: const VkBuffer = 0x1f98020
pOffsets: const VkDeviceSize* = 0x7ffc731014c0
pOffsets[0]: const VkDeviceSize = 0
Thread 0, Frame 0:
vkCmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports) returns void:
commandBuffer: VkCommandBuffer = 0x1fc0bf0
firstViewport: uint32_t = 0
viewportCount: uint32_t = 1
pViewports: const VkViewport* = 0x1f95c58
pViewports[0]: const VkViewport = 0x1f95c58:
x: float = 0
y: float = 0
width: float = 800
height: float = 800
minDepth: float = 0
maxDepth: float = 1
Thread 0, Frame 0:
vkCmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors) returns void:
commandBuffer: VkCommandBuffer = 0x1fc0bf0
firstScissor: uint32_t = 0
scissorCount: uint32_t = 1
pScissors: const VkRect2D* = 0x1f95c70
pScissors[0]: const VkRect2D = 0x1f95c70:
offset: VkOffset2D = 0x1f95c70:
x: int32_t = 0
y: int32_t = 0
extent: VkExtent2D = 0x1f95c78:
width: uint32_t = 800
height: uint32_t = 800
Thread 0, Frame 0:
vkCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance) returns void:
commandBuffer: VkCommandBuffer = 0x1fc0bf0
vertexCount: uint32_t = 36
instanceCount: uint32_t = 1
firstVertex: uint32_t = 0
firstInstance: uint32_t = 0
Thread 0, Frame 0:
vkCmdEndRenderPass(commandBuffer) returns void:
commandBuffer: VkCommandBuffer = 0x1fc0bf0
Thread 0, Frame 0:
vkEndCommandBuffer(commandBuffer) returns VkResult VK_SUCCESS (0):
commandBuffer: VkCommandBuffer = 0x1fc0bf0
Thread 0, Frame 0:
vkAcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex) returns VkResult VK_SUCCESS (0):
device: VkDevice = 0x1d86dd0
swapchain: VkSwapchainKHR = 0x1f23c60
timeout: uint64_t = 18446744073709551615
semaphore: VkSemaphore = 0x1d8a560
fence: VkFence = 0
pImageIndex: uint32_t* = 0
Thread 0, Frame 0:
vkQueueSubmit(queue, submitCount, pSubmits, fence) returns VkResult VK_SUCCESS (0):
queue: VkQueue = 0x1eba560
submitCount: uint32_t = 1
pSubmits: const VkSubmitInfo* = 0x1efeaa8
pSubmits[0]: const VkSubmitInfo = 0x1efeaa8:
sType: VkStructureType = VK_STRUCTURE_TYPE_SUBMIT_INFO (4)
pNext: const void* = NULL
waitSemaphoreCount: uint32_t = 1
pWaitSemaphores: const VkSemaphore* = 0x1fc3820
pWaitSemaphores[0]: const VkSemaphore = 0x1d8a560
pWaitDstStageMask: const VkPipelineStageFlags* = 0x1fc3780
pWaitDstStageMask[0]: const VkPipelineStageFlags = 1024 (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
commandBufferCount: uint32_t = 3
pCommandBuffers: const VkCommandBuffer* = 0x1fc3730
pCommandBuffers[0]: const VkCommandBuffer = 0x1fa98a0
pCommandBuffers[1]: const VkCommandBuffer = 0x1fb01c0
pCommandBuffers[2]: const VkCommandBuffer = 0x1fb7d70
signalSemaphoreCount: uint32_t = 1
pSignalSemaphores: const VkSemaphore* = 0x1fc36e0
pSignalSemaphores[0]: const VkSemaphore = 0x1d8a710
fence: VkFence = 0
Thread 0, Frame 0:
vkQueuePresentKHR(queue, pPresentInfo) returns VkResult VK_SUCCESS (0):
queue: VkQueue = 0x1eba560
pPresentInfo: const VkPresentInfoKHR* = 0x1fc2810:
sType: VkStructureType = UNKNOWN (1000001001)
pNext: const void* = NULL
waitSemaphoreCount: uint32_t = 1
pWaitSemaphores: const VkSemaphore* = 0x1fc36e0
pWaitSemaphores[0]: const VkSemaphore = 0x1d8a710
swapchainCount: uint32_t = 1
pSwapchains: const VkSwapchainKHR* = 0x1fc3730
pSwapchains[0]: const VkSwapchainKHR = 0x1f23c60
pImageIndices: const uint32_t* = 0x1d8a418
pImageIndices[0]: const uint32_t = 0
pResults: VkResult* = NULL
Thread 0, Frame 1:
vkAcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex) returns VkResult VK_SUCCESS (0):
device: VkDevice = 0x1d86dd0
swapchain: VkSwapchainKHR = 0x1f23c60
timeout: uint64_t = 18446744073709551615
semaphore: VkSemaphore = 0x1d8a560
fence: VkFence = 0
pImageIndex: uint32_t* = 1
[VK_DEBUG_REPORT] ERROR: [ObjectTracker] Code149:Invalid Command Buffer Object 0x21. For more information refer to Vulkan Spec Section '5.4. Command Buffer Submission' which states 'If commandBufferCount is not 0, pCommandBuffers must be a pointer to an array of commandBufferCount valid VkCommandBuffer handles' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkSubmitInfo)
Command buffer recording:
void VulkanDrawable::recordCommandBuffer(int currentImage, VkCommandBuffer *cmdDraw){
//VulkanDevice* deviceObject = rendererObject->getDevice();
//Specify clear color values
VkClearValue clearValues[2];
clearValues[0].color.float32[0] = 1.0f;
clearValues[0].color.float32[1] = 1.0f;
clearValues[0].color.float32[2] = 1.0f;
clearValues[0].color.float32[3] = 1.0f;
//Specify depth/stencil clear value
clearValues[1].depthStencil.depth = 1.0f;
clearValues[1].depthStencil.stencil = 0;
VkRenderPassBeginInfo renderPassBegin = {};
renderPassBegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassBegin.pNext = nullptr;
renderPassBegin.renderPass = rendererObject->renderPass;
renderPassBegin.framebuffer = rendererObject->framebuffers[currentImage];
renderPassBegin.renderArea.offset.x = 0;
renderPassBegin.renderArea.offset.y = 0;
renderPassBegin.renderArea.extent.width = rendererObject->width;
renderPassBegin.renderArea.extent.height = rendererObject->height;
renderPassBegin.clearValueCount = 2;
renderPassBegin.pClearValues = clearValues;
//Start recording the render pass instance
vkCmdBeginRenderPass(*cmdDraw, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
//Bind the command buffer with the pipeline
vkCmdBindPipeline(*cmdDraw, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
//Bind descriptor sets
vkCmdBindDescriptorSets(*cmdDraw, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout,0, 1,
descriptorSets.data(),0,nullptr);
//Bind vertex data to the command buffer
const VkDeviceSize offsets[1] = {0};
vkCmdBindVertexBuffers(*cmdDraw, 0, 1, &VertexBuffer.buffer, offsets);
//Define the dynamic viewport
initViewports(cmdDraw);
//Define the scissoring also
initScissors(cmdDraw);
//Draw
vkCmdDraw(*cmdDraw, verticeAmount, 1,0,0);
//vkCmdDrawIndexed(*cmdDraw, indiceAmount, 1,0,0,0);
//End render pass instance recording
vkCmdEndRenderPass(*cmdDraw);
}
Thanks for your help. If there is any more information you might want to see let me know.

InstanceBuffer not working in DX 11_0

So I have this problem I have been stuck on for a few weeks now where the instance buffer is not working in my DX 11_0 application, the vertex buffer and index buffers are working just fin but for some reason nothing is getting passed in to the instance buffer even though the instance buffer was created with S_OK and throws no error.
Here is the definition and creation of the instance buffer
instanceDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
instanceDesc.ByteWidth = sizeof(InstanceVertex2) * MAX_INSTANCES;
instanceDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
instanceDesc.MiscFlags = 0;
instanceDesc.StructureByteStride = 0;
instanceDesc.Usage = D3D11_USAGE_DYNAMIC;
instanceData.pSysMem = new InstanceVertex2[MAX_INSTANCES];
instanceData.SysMemPitch = 0;
instanceData.SysMemSlicePitch = 0;
//create the instance buffer
result = device->CreateBuffer(&instanceDesc, &instanceData, &m_instanceBuffer);
if (FAILED(result))
{
return false;
}
Here is the polygon layout
//vertex position, by vertex
polygonLayout[0].AlignedByteOffset = 0;
polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
polygonLayout[0].InputSlot = 0;
polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[0].InstanceDataStepRate = 0;
polygonLayout[0].SemanticIndex = 0;
polygonLayout[0].SemanticName = "POSITION";
//uv coords, by vertex
polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
polygonLayout[1].InputSlot = 0;
polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
polygonLayout[1].InstanceDataStepRate = 0;
polygonLayout[1].SemanticIndex = 0;
polygonLayout[1].SemanticName = "TEXCOORD";
//texture ID, by instance
polygonLayout[2].AlignedByteOffset = 0;
polygonLayout[2].Format = DXGI_FORMAT_R32_SINT;
polygonLayout[2].InputSlot = 1;
polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
polygonLayout[2].InstanceDataStepRate = 1;
polygonLayout[2].SemanticIndex = 0;
polygonLayout[2].SemanticName = "TEXTUREID";
//color, by instance
polygonLayout[3].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[3].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
polygonLayout[3].InputSlot = 1;
polygonLayout[3].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
polygonLayout[3].InstanceDataStepRate = 1;
polygonLayout[3].SemanticIndex = 0;
polygonLayout[3].SemanticName = "COLOR";
//UVAdd , by instance
polygonLayout[4].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[4].Format = DXGI_FORMAT_R32G32_FLOAT;
polygonLayout[4].InputSlot = 1;
polygonLayout[4].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
polygonLayout[4].InstanceDataStepRate = 1;
polygonLayout[4].SemanticIndex = 0;
polygonLayout[4].SemanticName = "UVADD";
//UVMultiply, by instance
polygonLayout[5].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[5].Format = DXGI_FORMAT_R32G32_FLOAT;
polygonLayout[5].InputSlot = 1;
polygonLayout[5].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
polygonLayout[5].InstanceDataStepRate = 1;
polygonLayout[5].SemanticIndex = 0;
polygonLayout[5].SemanticName = "UVMULTIPLY";
//matrix row 1
polygonLayout[6].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[6].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
polygonLayout[6].InputSlot = 1;
polygonLayout[6].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
polygonLayout[6].InstanceDataStepRate = 1;
polygonLayout[6].SemanticIndex = 0;
polygonLayout[6].SemanticName = "MATRIX";
//matrix row 2
polygonLayout[7].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[7].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
polygonLayout[7].InputSlot = 1;
polygonLayout[7].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
polygonLayout[7].InstanceDataStepRate = 1;
polygonLayout[7].SemanticIndex = 1;
polygonLayout[7].SemanticName = "MATRIX";
//matrix row 3
polygonLayout[8].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[8].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
polygonLayout[8].InputSlot = 1;
polygonLayout[8].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
polygonLayout[8].InstanceDataStepRate = 1;
polygonLayout[8].SemanticIndex = 2;
polygonLayout[8].SemanticName = "MATRIX";
//matrix row 4
polygonLayout[9].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
polygonLayout[9].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
polygonLayout[9].InputSlot = 1;
polygonLayout[9].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
polygonLayout[9].InstanceDataStepRate = 1;
polygonLayout[9].SemanticIndex = 3;
polygonLayout[9].SemanticName = "MATRIX";
numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);
//create the input layout
result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &m_layout);
if (FAILED(result))
{
MessageBox(hwnd, TEXT("Failed to create the input layout"), TEXT("Error initializaing shader"), MB_OK);
return false;
}
Here is me actually updating the instance buffer(it is dynamic)
result = deviceContext->Map(m_instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &data);
if (FAILED(result))
{
return false;
}
instancesPtr = (InstanceVertex2*)data.pData;
memcpy(instancesPtr, (void*)instances, sizeof(&m_vertices[0]));
//now un map
deviceContext->Unmap(m_instanceBuffer, 0);
And finally this is the code where I put the buffers into the device context
//set the buffers
buffers[0] = m_vertexBuffer;
buffers[1] = m_instanceBuffer;
//set the strides
strides[0] = sizeof(InstanceVertex1);
strides[1] = sizeof(InstanceVertex2);
//set the offsets
offsets[0] = 0;
offsets[1] = 0;
//set the vertex buffers
deviceContext->IASetVertexBuffers(0, 2, buffers, strides, offsets);
//set the index buffers
deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
This does seem like a lot of code to look through but I don't know exactly what is going wrong, I have got instancing and dynamic vertex buffers to work in the past without problems and for some reason I can not get it to work when I combine them.I have nvidea nsight so I can look in the vertex shader and buffers directly, and from what I am looking at I can tell that nothing is getting passed into the instance buffer. I would appreciate any help or pointers anyone is willing to give me so that I can fix my problem.
I figured it out, it turned out the problem lay not in the initialization of the instance buffer but in the way I was updating it, I will include the answer to it so that others might be able to get help with a similar problem.
I changed :
result = deviceContext->Map(m_instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &data);
if (FAILED(result))
{
return false;
}
instancesPtr = (InstanceVertex2*)data.pData;
memcpy(instancesPtr, (void*)instances, sizeof(&m_vertices[0]));
//now un map
deviceContext->Unmap(m_instanceBuffer, 0);
To :
result = deviceContext->Map(m_instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &data);
if (FAILED(result))
{
return false;
}
instancesPtr = (InstanceVertex2*)data.pData;
for (int i = 0;i < m_vertices.size();i++)
{
instancesPtr[i].color = m_vertices[i].color;
instancesPtr[i].matrixInstance = m_vertices[i].matrixInstance;
instancesPtr[i].textureID = m_vertices[i].textureID;
instancesPtr[i].UVAdd = m_vertices[i].UVAdd;
instancesPtr[i].UVMultiply = m_vertices[i].UVMultiply;
}
//memcpy(instancesPtr, (void*)instances, sizeof(&m_vertices[0]));
//now un map
deviceContext->Unmap(m_instanceBuffer, 0);
I hope this helps someone else with there problem someday, it certainly took me long enough.

CreateTexture2D fail... (d3d)

I'm trying to create D3D texture 2d with STAGING usage.
Always, it fails with error : "Incorrect parameter" (code 0x80070057)...
I don't understand, I can create other than staging no problem, but can't succeed with this... Please help me before my computer goes flying through the window... Please...
Here is the problematic piece of code :
int w = 128;
int h = 128;
ID3D11Texture2D * tex;
D3D11_TEXTURE2D_DESC tdesc;
D3D11_SUBRESOURCE_DATA tbsd;
ZeroMemory(&tdesc, sizeof(D3D10_TEXTURE2D_DESC));
WORD *buf = new WORD[128*128];
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++)
{
buf[i*128 + j] = (WORD) 0xffffffff;
}
tbsd.pSysMem = (void *)buf;
tbsd.SysMemPitch = w * 4;
tbsd.SysMemSlicePitch = w * h * 4;
tdesc.Width = w;
tdesc.Height = h;
tdesc.MipLevels = 1;
tdesc.ArraySize = 1;
tdesc.SampleDesc.Count = 1;
tdesc.SampleDesc.Quality = 0;
tdesc.Usage = D3D11_USAGE_STAGING;
tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
tdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
// tdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; // Does'nt work either...
tdesc.MiscFlags = 0;
HRESULT eblah = 0; char tmpstr[128];
eblah = device->CreateTexture2D(&tdesc, &tbsd, &tex);
if (FAILED(eblah))
{
wsprintfA(tmpstr, "Error code : %lX", eblah); OutputDebugStringA(tmpstr);
ErrorMessage(eblah);
}
I've got this as device, earlier in code, in case of :
ID3D11Device* device = nullptr;
D3D_FEATURE_LEVEL level;
ID3D11DeviceContext* context = nullptr;
HRESULT hr = D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE::D3D_DRIVER_TYPE_NULL, // Tried D3D_DRIVER_TYPE_HARDWARE too
nullptr,
0,
nullptr,
0,
D3D11_SDK_VERSION,
&device,
&level,
&context
);
Found it :
_ I used D3D11_CREATE_DEVICE_FLAG::D3D11_CREATE_DEVICE_DEBUG flag when creating the device, which gave me very useful debug info. A must have for every beginner !!!
_ tdesc.BindFlags MUST be 0 when creating a ID3D11Texture2D for staging.
_ My computer didn't fly through the window !!!
Nice day to everyone :)