我创建了一个存储纹理并存储了显示在屏幕上的相同片段。但是当我从另一个管道的片段着色器中读取相同的纹理时,它似乎无法正常工作......
代码使用相同的渲染通道和相同的管线布局。我开始渲染通道并通过第一个管道然后结束它并为存储图像纹理执行 vkCmdPipelineBarrier,然后再次启动相同的渲染通道并执行第二个管道,然后结束渲染通道。
不知道我哪里弄错了?
这里是 vkCmdPipelineBarrier 在第一个结束渲染通道之后和第二个开始渲染通道调用之前...
VkImageMemoryBarrier imageMemoryBarrier = {};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
// We won't be changing the layout of the image
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.image = outlineTexture->getTeximage();
imageMemoryBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkCmdPipelineBarrier(
commandBuffer,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
0,
0, nullptr,
0, nullptr,
1, &imageMemoryBarrier);
这是纹理创建过程...
VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(creDevice.physical_Device(), VK_FORMAT_R8G8B8A8_UNORM, &formatProperties);
// Check if requested image format supports image storage operations
assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT);
VkImageCreateInfo imageCreateInfo{};
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
imageCreateInfo.extent = { (uint32_t)texWidth, (uint32_t)texHeight, 1 };
imageCreateInfo.mipLevels = 1;
imageCreateInfo.arrayLayers = 1;
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
// Image will be sampled in the fragment shader and used as storage target in the compute shader
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
imageCreateInfo.flags = 0;
// If compute and graphics queue family indices differ, we create an image that can be shared between them
// This can result in worse performance than exclusive sharing mode, but save some synchronization to keep the sample simple
/*
std::vector<uint32_t> queueFamilyIndices;
if (vulkanDevice->queueFamilyIndices.graphics != vulkanDevice->queueFamilyIndices.compute) {
queueFamilyIndices = {
vulkanDevice->queueFamilyIndices.graphics,
vulkanDevice->queueFamilyIndices.compute
};
imageCreateInfo.sharingMode = VK_SHARING_MODE_CONCURRENT;
imageCreateInfo.queueFamilyIndexCount = 2;
imageCreateInfo.pQueueFamilyIndices = queueFamilyIndices.data();
}
*/
QueueFamilyIndices indices = creDevice.findPhysicalQueueFamilies();
uint32_t queueFamilyIndices[] = { indices.graphicsFamily, indices.presentFamily };
if (indices.graphicsFamily != indices.presentFamily) {
imageCreateInfo.sharingMode = VK_SHARING_MODE_CONCURRENT;
imageCreateInfo.queueFamilyIndexCount = 2;
imageCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else {
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageCreateInfo.queueFamilyIndexCount = 0; // Optional
imageCreateInfo.pQueueFamilyIndices = nullptr; // Optional
}
//imageCreateInfo.sharingMode = VK_SHARING_MODE_CONCURRENT;
//imageCreateInfo.queueFamilyIndexCount = 2;
//imageCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
creDevice.createImageWithInfo(imageCreateInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);
if (auto commandBuffer = creDevice.beginSingleTimeCommands()) {
VkImageSubresourceRange subresourceRange = {};
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subresourceRange.baseMipLevel = 0;
subresourceRange.levelCount = 1;
subresourceRange.layerCount = 1;
VkImageMemoryBarrier imageMemoryBarrier{};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
imageMemoryBarrier.image = textureImage;
imageMemoryBarrier.subresourceRange = subresourceRange;
imageMemoryBarrier.srcAccessMask = 0;
vkCmdPipelineBarrier(
commandBuffer,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
0,
0, nullptr,
0, nullptr,
1, &imageMemoryBarrier);
creDevice.endSingleTimeCommands(commandBuffer);
}
// Create sampler
VkSamplerCreateInfo sampler{};
sampler.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
sampler.magFilter = VK_FILTER_LINEAR;
sampler.minFilter = VK_FILTER_LINEAR;
sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
sampler.addressModeV = sampler.addressModeU;
sampler.addressModeW = sampler.addressModeU;
sampler.mipLodBias = 0.0f;
sampler.maxAnisotropy = 1.0f;
sampler.compareOp = VK_COMPARE_OP_NEVER;
sampler.minLod = 0.0f;
sampler.maxLod = creDevice.msaaSamples;
//sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
if (vkCreateSampler(creDevice.device(), &sampler, nullptr, &textureSampler) != VK_SUCCESS) {
throw std::runtime_error("failed to create texture sampler!");
};
// Create image view
VkImageViewCreateInfo view{};
view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
view.image = VK_NULL_HANDLE;
view.viewType = VK_IMAGE_VIEW_TYPE_2D;
view.format = VK_FORMAT_R8G8B8A8_UNORM;
view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
view.image = textureImage;
if (vkCreateImageView(creDevice.device(), &view, nullptr, &textureImageView) != VK_SUCCESS) {
throw std::runtime_error("failed to create texture image view!");
}
这是纹理着色器的存储...
#version 450
layout (location = 0) in vec3 fragColor;
layout (location = 1) in vec2 screenSize;
layout (set = 0, binding = 2, rgba8) uniform image2D otlImage;
layout (set = 1, binding = 1) uniform sampler2D texSampler;
layout (location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0) * texture(texSampler, fragTextureCoord);
imageStore(otlImage, ivec2((gl_FragCoord.x + 0.5)/screenSize.x, (gl_FragCoord.y + 0.5)/screenSize.y), outColor);
}
这是来自相同纹理部分的阅读...
"""Vertex shader"""
#version 450
layout (location = 0) out vec2 outUV;
void main()
{
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outUV * 2.0f + -1.0f, 0.0f, 1.0f);
}
"""Fragment Shader"""
#version 450
layout (location = 0) in vec2 outUV;
layout (location = 0) out vec4 outColor;
layout (set = 0, binding = 2, rgba8) uniform image2D otlImage;
void main()
{
outColor = imageLoad(otlImage, ivec2(outUV));
}