Hi!
Ok I moved this post to the vulkan section.
I’m developping my own game engine and I’ve a problem, I have one per pixel linked list per cubemap face.
I’m using a 3D image to store head pointers, and I use multiview to draw to each cubemap faces.
So I create my 3D image like this :
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_3D;
imageInfo.extent.width = static_cast<uint32_t>(window.getView().getSize().x);
imageInfo.extent.height = static_cast<uint32_t>(window.getView().getSize().y);
imageInfo.extent.depth = 6;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.format = VK_FORMAT_R32_UINT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.flags = 0; // Optionnel
if (vkCreateImage(window.getDevice().getDevice(), &imageInfo, nullptr, &headPtrTextureImage) != VK_SUCCESS) {
throw std::runtime_error("echec de la creation d'une image!");
}
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(window.getDevice().getDevice(), headPtrTextureImage, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (vkAllocateMemory(window.getDevice().getDevice(), &allocInfo, nullptr, &headPtrTextureImageMemory) != VK_SUCCESS) {
throw std::runtime_error("echec de l'allocation de la memoire d'une image!");
}
vkBindImageMemory(window.getDevice().getDevice(), headPtrTextureImage, headPtrTextureImageMemory, 0);
transitionImageLayout(headPtrTextureImage, VK_FORMAT_R32_UINT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
Then I create the image view :
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = headPtrTextureImage;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
viewInfo.format = VK_FORMAT_R32_UINT;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(vkDevice.getDevice(), &viewInfo, nullptr, &headPtrTextureImageView) != VK_SUCCESS) {
throw std::runtime_error("failed to create head ptr texture image view!");
}
I specified r32ui format for atomic operations.
But there is a problem in this fragment shader :
const std::string fragmentShader = R"(#version 460
#extension GL_EXT_nonuniform_qualifier : enable
#extension GL_EXT_debug_printf : enable
struct NodeType {
vec4 color;
float depth;
uint next;
};
layout(set = 0, binding = 0) buffer CounterSSBO {
uint count[6];
uint maxNodes;
};
layout(set = 0, binding = 1, r32ui) uniform coherent uimage3D headPointers;
layout(set = 0, binding = 2) buffer linkedLists {
NodeType nodes[];
};
layout(set = 0, binding = 3) uniform sampler2D textures[];
layout (location = 0) in vec4 frontColor;
layout (location = 1) in vec2 fTexCoords;
layout (location = 2) in flat uint texIndex;
layout (location = 3) in vec3 normal;
layout (location = 4) in flat int viewIndex;
layout(location = 0) out vec4 fcolor;
void main() {
uint nodeIdx = atomicAdd(count[viewIndex], 1);
vec4 texel = (texIndex != 0) ? frontColor * texture(textures[texIndex-1], fTexCoords.xy) : frontColor;
if (nodeIdx < maxNodes) {
uint prevHead = imageAtomicExchange(headPointers, ivec3(gl_FragCoord.xy, viewIndex), nodeIdx);
nodes[nodeIdx+viewIndex*maxNodes].color = texel;
nodes[nodeIdx+viewIndex*maxNodes].depth = gl_FragCoord.z;
nodes[nodeIdx+viewIndex*maxNodes].next = prevHead;
debugPrintfEXT("prev head : %i, node Idx : %i, view index : %i\n", prevHead, nodeIdx, viewIndex);
}
fcolor = vec4(0, 0, 0, 0);
})";
The imageAtomicExchange set always 0 to my image, si the returned value is always -1 or 0 which is incorrect. I haven’t this problem with 2D images.
Thanks.
EDIT : does nvidia drivers support atomic operations on 3D images ?
This works with opengl…