我如何将3D vkimage传递给计算着色器,而不会更改数据? 我正在尝试将体素的随机3D图像传递给计算着色器,但是当我运行着色器时,整个着色器会导致这样做: 如您所见,这看起来不像随机生成...

问题描述 投票:0回答:1

您可以看到,除了第二个体素的第一和半部分外,这看起来不像随机生成的体素。老实说,我对数据正在发生的事情绝对不知道。我知道我的计算着色器输出到Swapchain映像上不是问题,因为我检查了其他计算着色器(例如噪声等)是否有效,并且它们做到了。我已经将错误的位置缩小到从我的std::vector<std::vector<std::vector<glm::vec4>>>Compute Shader OutputvoxelImage

voxelImage

的复制数据的位置,它可能是在传递到Compute着色器的位置。
我也检查了体素的产生不仅仅是生成屏幕上看到的内容。 VEC4S的向量确实是随机的,我保证错误是在我将其缩小到的两个地方中的任何一个。
I只会发布voxelImage
voxelImageView
创建的代码,以及描述符可能是错误发生的。 (发布其余的代码将不必要地过多,并且太长了)

voxel图像创建:

void createVoxelImage() { VkDeviceSize imageSize = voxelDataInit.size(); VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; VmaAllocation stagingAllocation; createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_GPU_ONLY, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, stagingBuffer, stagingAllocation, stagingBufferMemory); void* data; vmaMapMemory(allocator, stagingAllocation, &data); memcpy(data, &voxelDataInit, imageSize); vmaUnmapMemory(allocator, stagingAllocation); VkDeviceMemory temp; createImage(voxWidth, voxHeight, voxDepth, VK_IMAGE_TYPE_3D, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, voxelImage, voxelAllocation, VMA_MEMORY_USAGE_GPU_ONLY, temp, 5); //vkFreeMemory(device, temp, NULL); //VkDeviceMemory temp; //createImage(voxWidth, voxHeight, voxDepth, VK_IMAGE_TYPE_3D, VK_FORMAT_B8G8R8_UNORM, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_STORAGE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, voxelImage, voxelAllocation, VMA_MEMORY_USAGE_CPU_TO_GPU, temp, 5); transitionImageLayout(voxelImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); copyBufferToImage(stagingBuffer, voxelImage, static_cast<uint32_t>(voxWidth), static_cast<uint32_t>(voxHeight), static_cast<uint32_t>(voxDepth)); transitionImageLayout(voxelImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); vmaDestroyBuffer(allocator, stagingBuffer, stagingAllocation); }

voxel图像视图创建:
void createVoxelImageView() {
        VkImageViewCreateInfo viewInfo{};
        viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        viewInfo.image = voxelImage;
        viewInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
        viewInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
        //viewInfo.flags = VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
        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(device, &viewInfo, nullptr, &voxelImageView) != VK_SUCCESS) {
            throw std::runtime_error("Failed to create image view! (voxel)");
        }
    }

将数据输入到着色器中 layout(binding = 4, rgba8) uniform image3D voxels;

createImage

void createImage(uint32_t width, uint32_t height, uint32_t depth, VkImageType imgType, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkImageLayout layout, VkMemoryPropertyFlags properties, VkImage& image, VmaAllocation& allocation, VmaMemoryUsage memUsage, VkDeviceMemory& imageMemory, int callNum) { VkImageCreateInfo imageInfo{}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.imageType = imgType; imageInfo.extent.width = width; imageInfo.extent.height = height; imageInfo.extent.depth = depth; imageInfo.mipLevels = 1; imageInfo.arrayLayers = 1; imageInfo.format = format; imageInfo.tiling = tiling; imageInfo.initialLayout = layout; imageInfo.usage = usage; imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.flags = VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT; VmaAllocationCreateInfo vmaAllocInfo = {}; vmaAllocInfo.usage = memUsage; vmaAllocInfo.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; if (vmaCreateImage(allocator, &imageInfo, &vmaAllocInfo, &image, &allocation, nullptr) != VK_SUCCESS) { throw std::runtime_error(std::to_string(callNum)); throw std::runtime_error("failed to create image!"); } }

transitionImageLayout

	
如果确实是类型的变量,那么void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlagBits srcAccess, VkAccessFlagBits dstAccess, VkPipelineStageFlagBits srcStage, VkPipelineStageFlagBits dstStage) { VkCommandBuffer commandBuffer = beginSingleTimeCommands(); VkImageMemoryBarrier barrier{}; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.oldLayout = oldLayout; barrier.newLayout = newLayout; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.image = image; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; barrier.subresourceRange.baseMipLevel = 0; barrier.subresourceRange.levelCount = 1; barrier.subresourceRange.baseArrayLayer = 0; barrier.subresourceRange.layerCount = 1; VkPipelineStageFlags sourceStage; VkPipelineStageFlags destinationStage; if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { barrier.srcAccessMask = 0; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; } else { if (srcStage == VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT) { barrier.srcAccessMask = 0; } else { barrier.srcAccessMask = srcAccess; } barrier.dstAccessMask = dstAccess; sourceStage = srcStage; destinationStage = dstStage; //throw std::runtime_error("Unsupported layout transition."); } vkCmdPipelineBarrier(commandBuffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier); endSingleTimeCommands(commandBuffer); }

永远不会工作。
copyBufferToImage
是指向A

void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t depth){ VkCommandBuffer commandBuffer = beginSingleTimeCommands(); VkBufferImageCopy region{}; region.bufferOffset = 0; region.bufferRowLength = 0; region.bufferImageHeight = 0; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; region.imageSubresource.mipLevel = 0; region.imageSubresource.baseArrayLayer = 0; region.imageSubresource.layerCount = 1; region.imageOffset = { 0, 0, 0 }; region.imageExtent = { width, height, depth }; vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); endSingleTimeCommands(commandBuffer); } 的指针。指向voxelDataInit

的指针总是相同的大小(忽略分配器本身):3个指针的大小。
记录:astd::vector<std::vector<std::vector<glm::vec4>>>是一个to to的

或更确切地说,这是3个阵列的指针。但是无论如何,一个不是
它只是一个。因此,复制一个字节不会复制数组本身。
c++ glsl shader vulkan
1个回答
2
投票
memcpy(data, &voxelDataInit, imageSize);

&voxelDataInit
只是元素的数量,而不是数组中的
bytes
的数量。
复制这种数据结构的最佳方法是停止使用这种数据结构。如果您想要一个3D阵列,那么您想要的是一个尺寸长度×宽度×宽度×高度的
尺寸。您可以使用长度,宽度,高度将3D坐标转换为1D坐标。
	
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.