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.
Related
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, ©Region);
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.
I'm trying to add some images for using with IMGUI library. Basically, IMGUI can get directx or OpenGL raw texture data to draw. You can see example code from IMGUI for creating a texture ;
// Simple helper function to load an image into a DX11 texture with common settings
bool LoadTextureFromFile(const char* filename, ID3D11ShaderResourceView** out_srv, int* out_width, int* out_height)
{
// Load from disk into a raw RGBA buffer
int image_width = 0;
int image_height = 0;
unsigned char* image_data = stbi_load(filename, &image_width, &image_height, NULL, 4);
if (image_data == NULL)
return false;
// Create texture
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = image_width;
desc.Height = image_height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
ID3D11Texture2D *pTexture = NULL;
D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = image_data;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
// Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, out_srv);
pTexture->Release();
*out_width = image_width;
*out_height = image_height;
stbi_image_free(image_data);
return true;
}
Everything is ok except 'g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);' line. Because as you can see g_pd3dDevice is undefined. That's why I put a line for this like : ID3D11Device* g_pd3dDevice = nullptr; but when I run code it hangs.. I guess I must create a 3ddevice before using this part. But I can't. Any suggestions? Thanks
Now I can get some image but it's wrong:
Now my code like this ;
bool LoadTextureFromBufferDX11(unsigned char* address, ID3D11ShaderResourceView** out_srv, int* out_width, int* out_height)
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
::RegisterClassEx(&wc);
//HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX11 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, NULL, NULL, wc.hInstance, NULL);
HWND hwnd = GetForegroundWindow();
CreateDeviceD3D(hwnd);
/*
if (!CreateDeviceD3D(hwnd))
{
CleanupDeviceD3D();
::UnregisterClass(wc.lpszClassName, wc.hInstance);
return 1;
}
*/
//ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
// Load from disk into a raw RGBA buffer
int image_width = 0;
int image_height = 0;
const char* filename = "e:\\obama.png";
unsigned char* image_data = stbi_load(filename, &image_width, &image_height, NULL, 4);
//unsigned char* image_data = address;
if (image_data == NULL)
return false;
// Create texture
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = image_width;
desc.Height = image_height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
ID3D11Texture2D *pTexture = NULL;
D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = image_data;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
// Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, out_srv);
pTexture->Release();
*out_width = image_width;
*out_height = image_height;
return true;
}
And I trigger this function from host app.
static ID3D11ShaderResourceView* my_texture = NULL;
int my_image_width = 0;
int my_image_height = 0;
fn_export double imgui_showimage(unsigned char* address) {
bool ret = LoadTextureFromBufferDX11(address, &my_texture, &my_image_width, &my_image_height);
//IM_ASSERT(ret);
//ImGui::Image((void*)my_texture, ImVec2(my_image_width, my_image_height));
return 1;
}
And I draw imgu image from host like ;
fn_export double imgui_image(char* address) {
ImGui::Image((void*)my_texture, ImVec2(my_image_width, my_image_height));
return 1;
}
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
I'm trying to implement imGUI in my app which already have some render pass for rendering meshes. Its command buffer updates only when new meshes added to scene, while imGUI command buffer should be updated every frame. Secondary command buffer doesn't fits me because I always have to reference it from primary cb, which doesn't update so often.
I also want to mention that my code is based on this tutorial.
I came to conclusion that I should have two render passes with two primary command buffers. The only problem now is that I can't combine these two render passes.
There is the code for main rp:
vk::AttachmentDescription colorAttachment;
colorAttachment.format = swapChainImageFormat;
colorAttachment.samples = vk::SampleCountFlagBits::e1;
colorAttachment.loadOp = vk::AttachmentLoadOp::eClear;
colorAttachment.storeOp = vk::AttachmentStoreOp::eStore;
colorAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
colorAttachment.stencilStoreOp = vk::AttachmentStoreOp::eNoneQCOM;
colorAttachment.initialLayout = vk::ImageLayout::eUndefined;
colorAttachment.finalLayout = vk::ImageLayout::ePresentSrcKHR;
vk::AttachmentDescription depthAttachment;
depthAttachment.format = FindDepthFormat();
depthAttachment.samples = vk::SampleCountFlagBits::e1;
depthAttachment.loadOp = vk::AttachmentLoadOp::eClear;
depthAttachment.storeOp = vk::AttachmentStoreOp::eDontCare;
depthAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
depthAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
depthAttachment.initialLayout = vk::ImageLayout::eUndefined;
depthAttachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
std::array<vk::AttachmentDescription, 2> attachments = { colorAttachment, depthAttachment };
vk::AttachmentReference colorAttachmentRef;
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = vk::ImageLayout::eColorAttachmentOptimal;
vk::AttachmentReference depthAttachmentRef;
depthAttachmentRef.attachment = 1;
depthAttachmentRef.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
vk::SubpassDescription subpass;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
vk::SubpassDependency dependency;
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
dependency.srcAccessMask = vk::AccessFlagBits();
dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite;
vk::RenderPassCreateInfo renderPassInfo;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;
gameRenderPass = device.createRenderPass(renderPassInfo);
There is the code for ui rp:
vk::AttachmentDescription colorAttachment;
colorAttachment.format = swapChainImageFormat;
colorAttachment.samples = vk::SampleCountFlagBits::e1;
colorAttachment.loadOp = vk::AttachmentLoadOp::eLoad;
colorAttachment.storeOp = vk::AttachmentStoreOp::eStore;
colorAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
colorAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
colorAttachment.initialLayout = vk::ImageLayout::ePresentSrcKHR;
colorAttachment.finalLayout = vk::ImageLayout::ePresentSrcKHR;
vk::AttachmentDescription depthAttachment;
depthAttachment.format = FindDepthFormat();
depthAttachment.samples = vk::SampleCountFlagBits::e1;
depthAttachment.loadOp = vk::AttachmentLoadOp::eClear;
depthAttachment.storeOp = vk::AttachmentStoreOp::eDontCare;
depthAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
depthAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
depthAttachment.initialLayout = vk::ImageLayout::eUndefined;
depthAttachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
std::array<vk::AttachmentDescription, 2> attachments = { colorAttachment, depthAttachment };
vk::AttachmentReference colorAttachmentRef;
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = vk::ImageLayout::eColorAttachmentOptimal;
vk::AttachmentReference depthAttachmentRef;
depthAttachmentRef.attachment = 1;
depthAttachmentRef.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
vk::SubpassDescription subpass;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
subpass.pDepthStencilAttachment = &depthAttachmentRef;
vk::SubpassDependency dependency;
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
dependency.srcAccessMask = vk::AccessFlagBits();
dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput;
dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite;
vk::RenderPassCreateInfo renderPassInfo;
renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
renderPassInfo.pAttachments = attachments.data();
renderPassInfo.subpassCount = 1;
renderPassInfo.pSubpasses = &subpass;
renderPassInfo.dependencyCount = 1;
renderPassInfo.pDependencies = &dependency;
uiRenderPass = device.createRenderPass(renderPassInfo);
And there is the code of my DrawFrame function:
device.waitForFences(1, &inFlightFences[currentFrame], true, UINT64_MAX);
uint32_t imageIndex;
device.acquireNextImageKHR(swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], nullptr, &imageIndex);
if (imagesInFlight[imageIndex].operator!=(nullptr))
{
device.waitForFences(1, &imagesInFlight[imageIndex], true, UINT64_MAX);
}
imagesInFlight[imageIndex] = inFlightFences[currentFrame];
vk::SubmitInfo submitInfo;
vk::Semaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
vk::PipelineStageFlags waitStages[] = { vk::PipelineStageFlagBits::eColorAttachmentOutput };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;
vk::Semaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
device.resetFences(1, &inFlightFences[currentFrame]);
UpdateUniformBuffer(imageIndex);
UpdateUiCommandBuffer(imageIndex);
if (comandUpdateRequired[imageIndex])
{
UpdateGameCommandBuffer(imageIndex);
comandUpdateRequired[imageIndex] = false;
}
std::vector<vk::CommandBuffer> commands = { gameCommandBuffers[imageIndex], uiCommandBuffers[imageIndex] };
submitInfo.commandBufferCount = static_cast<uint32_t>(commands.size());
submitInfo.pCommandBuffers = commands.data();
graphicsQueue.submit(1, &submitInfo, inFlightFences[currentFrame]);
vk::PresentInfoKHR presentInfo;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
vk::SwapchainKHR swapChains[] = { swapChain };
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
presentQueue.presentKHR(presentInfo);
presentQueue.waitIdle();
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
And the result is:
As you can see, clear color is used to overwrite the results of my first render pass, what is not what I want.
Note that load and store operations already in use and it still doesn't work.
UPDATE
There is a code of my second cb:
device.freeCommandBuffers(commandPool, 1, &uiCommandBuffers[index]);
vk::CommandBufferAllocateInfo allocInfo;
allocInfo.commandPool = commandPool;
allocInfo.level = vk::CommandBufferLevel::ePrimary;
allocInfo.commandBufferCount = 1;
device.allocateCommandBuffers(&allocInfo, &uiCommandBuffers[index]);
vk::CommandBufferBeginInfo beginInfo;
uiCommandBuffers[index].begin(beginInfo);
std::array<vk::ClearValue, 2> clearValues;
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>{ 1.0f, 0.0f, 0.0f, 1.0f });
clearValues[1].depthStencil = { 1.0f, 0 };
vk::RenderPassBeginInfo renderPassInfo;
renderPassInfo.renderPass = gameRenderPass;
renderPassInfo.framebuffer = uiSwapChainFramebuffers[index];
renderPassInfo.renderArea.offset = { 0, 0 };
renderPassInfo.renderArea.extent = swapChainExtent;
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size()); // It doesn't work at all if I set clear values count to 0
renderPassInfo.pClearValues = clearValues.data();
//renderPassInfo.clearValueCount = 0;
//renderPassInfo.pClearValues = nullptr;
uiCommandBuffers[index].beginRenderPass(renderPassInfo, vk::SubpassContents::eInline);
auto drawData = ImGui::GetDrawData();
if (drawData)
{
ImGui_ImplVulkan_RenderDrawData(drawData, uiCommandBuffers[index]);
}
uiCommandBuffers[index].endRenderPass();
uiCommandBuffers[index].end();
If you want to render the UI using a second pass, just set the storeOp of the color attachment in the first render pass to VK_ATTACHMENT_STORE_OP_STORE and the loadOp for it in the second render pass to VK_ATTACHMENT_LOAD_OP_LOAD to keep the contents.
Another option would be to do this in a single render pass, like I do in my samples. Just render your scene, and put the draw calls for the UI in the same render pass.
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 :)