社区首页 >问答首页 >如何在不改变数据的情况下将三维VkImage传递给计算机着色器?

如何在不改变数据的情况下将三维VkImage传递给计算机着色器?
EN

Stack Overflow用户
提问于 2021-07-20 20:42:37
回答 1查看 163关注 0票数 3

我试图将体素的随机三维图像传递给计算着色器,但是当我运行着色器时,整个着色器的结果如下:

正如你所看到的,这看起来并不像随机生成的体素,除了第一个和第二个体素的一半。老实说,我完全不知道这些数据发生了什么。我知道我的计算机着色器输出到交换链图像并不是一个问题,因为我检查了其他计算机着色器(比如一个噪声屏幕等等)。会起作用的,而且他们做到了。我已经缩小了错误的位置,将数据从我的std::vector<std::vector<std::vector<glm::vec4>>>复制到voxelImage ,这可能是将voxelImage传递给计算机着色器。

此外,我已经检查过,体素的产生并不仅仅是产生屏幕上看到的东西。vec4s的向量确实是随机的,我保证误差在我缩小到的两个地方中的任何一个。

我将只发布用于创建voxelImagevoxelImageView的代码以及描述符,因为这很可能是错误发生的地方。(发布代码的其余部分不必要地过多,而且太长了)

Voxel图像创建:

代码语言:javascript
代码运行次数:0
复制
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图像视图创建:

代码语言:javascript
代码运行次数:0
复制
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)");
        }
    }

数据输入到阴影

代码语言:javascript
代码运行次数:0
复制
layout(binding = 4, rgba8) uniform image3D voxels;

Def of createImage

代码语言:javascript
代码运行次数:0
复制
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!");
        }
    }

Def of transitionImageLayout

代码语言:javascript
代码运行次数:0
复制
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);
    }

Def of copyBufferToImage

代码语言:javascript
代码运行次数:0
复制
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);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-20 22:44:11

如果voxelDataInit确实是std::vector<std::vector<std::vector<glm::vec4>>>类型的变量,那么memcpy(data, &voxelDataInit, imageSize);就永远无法工作。&voxelDataInit是指向vector的指针。指向vector<T>的指针总是相同的大小(忽略分配器本身):3个指针的大小。

记住:vector<T>是指向T数组的指针,或者更确切地说,是指向该数组的3个指针。但是无论如何,vector<T>本身并不是一个T数组;它只是拥有一个数组。因此,复制vector的字节不会复制数组本身。

而且,sizevector只是元素的数量,而不是数组中的字节数。

复制这样的数据结构的最好方法是停止使用这样的数据结构。如果你想要一个三维数组,那么你想要的是一个尺寸为length_width_height的一维数组。您可以通过使用长度、宽度、高度将3D坐标转换为一维坐标来索引数组的任何特定X、Y、Z组件。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68464085

复制
相关文章
如何在Linux中使用管道将命令的输出传递给其他命令?
在Linux中,管道使用竖线符号 | 表示,它位于两个命令之间。管道的基本语法如下:
网络技术联盟站
2023/09/06
1.5K0
如何在Linux中使用管道将命令的输出传递给其他命令?
如何在Linux中使用管道将命令的输出传递给其他命令?
在Linux系统中,管道(Pipeline)是一种强大的工具,它允许将一个命令的输出作为另一个命令的输入。通过管道,我们可以将多个命令串联在一起,实现数据的流动和处理。本文将详细介绍如何在Linux中使用管道将命令的输出传递给其他命令,并提供一些常见的使用示例。
网络技术联盟站
2023/06/14
1.4K0
如何在Linux中使用管道将命令的输出传递给其他命令?
使用WebP Server在不改变URL的情况下将网站图像转换为WebP
WebP Server这是一个基于 Golang 的服务器,允许您动态提供 WebP 图像,在不改变图片URL路径的情况下,自动将JPEG、PNG、BMP、GIF等图像转换为WebP格式,从而减小图片体积,降低流量消耗和提高加载速度。
星哥玩云
2022/08/13
2.2K0
使用WebP Server在不改变URL的情况下将网站图像转换为WebP
【建议收藏】30 分钟入门 Vulkan (中文翻译版)
关于 Vulkan 的学习,网上有一篇很火的文章:《Vulkan in 30 minutes》。
音视频开发进阶
2021/10/14
7.5K0
将多个属性传递给 Vue 组件的几种方式
所有使用基于组件的体系结构(如Vue和React)的开发人员都知道,创建可重用组件是很困难的,而且大多数情况下,最终会通过传入大量的属性,以便从外部更容易地控制和自定义组件。这并不坏,但是传递大量属性确实会变得有点麻烦和丑陋。
前端小智@大迁世界
2020/05/11
1.9K0
「音视频直播技术」OpenGL渲染之着色器
本文介绍一下OpenGL的基本概念。在OpenGL中,只能画三种图元,点、线、三角型。在OpenGLES2.0之后,引用也GLSL(OpenGL Shader Languge),它类似于C语言的语法。
音视频_李超
2020/04/02
8240
如何将多个参数传递给 React 中的 onChange?
在 React 中,一些 HTML 元素,比如 input 和 textarea,具有 onChange 事件。onChange 事件是一个非常有用、非常常见的事件,用于捕获输入框中的文本变化。有时候,我们需要将多个参数同时传递给 onChange 事件处理函数,在本文中,我们将介绍如何实现这一目标。
网络技术联盟站
2023/06/07
2.7K0
iframe怎么将参数传递给vue 父组件
在子页面的iframe中想将参数传递给Vue父组件,可以使用postMessage()方法将数据发送给父窗口。父组件可以通过监听message事件来接收并处理这些数据。
王小婷
2023/08/10
1.4K0
[Linux] tcpdump 过滤传递给指定端口的数据
tcpdump想要捕获发送给imap服务器的数据 , 可以使用下面的参数 , 默认端口是143
唯一Chat
2020/04/16
9720
ASP.NET MVC 5 - 将数据从控制器传递给视图
在我们讨论数据库和数据模型之前,让我们先讨论一下如何将数据从控制器传递给视图。控制器类将响应请求来的URL。控制器类是给您写代码来处理传入请求的地方,并从数据库中检索数据,并最终决定什么类型的返回结果会发送回浏览器。视图模板可以被控制器用来产生格式化过的HTML从而返回给浏览器。 控制器负责给任何数据或者对象提供一个必需的视图模板,用这个视图模板来Render返回给浏览器的HTML。最佳做法是:一个视图模板应该永远不会执行业务逻辑或者直接和数据库进行交互。相应的,一个视图模板应该只和控制器所提供的数据进行交
葡萄城控件
2018/01/10
5K0
ASP.NET MVC 5 - 将数据从控制器传递给视图
网络数据是如何传递给进程的
在用户态空间,调用发送数据接口 send/sento/wirte 等写数据包,在内核空间会根据不同的协议走不同的流程。以TCP为例,TCP是一种流协议,内核只是将数据包追加到套接字的发送队列中,真正发送数据的时刻,则是由TCP协议来控制的。TCP协议处理完成之后会交给IP协议继续处理,最后会调用网卡的发送函数,将数据包发送到网卡。
luoxn28
2020/05/18
1.6K0
Spring在无RedirectAttributes的情况下(如Interceptor中)使用Flash scope
判断逻辑很简单,但是重定向的时候需要前台有消息提示,如果是在Controller中,可以在方法上注入RedirectAttributes参数,但是Interceptor中默认没有这个参数,那么我们如何实现RedirectAttributes的flashMessage功能呢?
飞奔去旅行
2019/06/13
5.4K0
Android OpenGL开发实践 - GLSurfaceView对摄像头数据的再处理
文首先对GLSurfaceView相关知识进行讲解,然后介绍Android系统如何获取摄像头数据并利用GLSurfaceView渲染到屏幕上。
天天P图攻城狮
2018/02/02
13.1K0
Android OpenGL开发实践 - GLSurfaceView对摄像头数据的再处理
Vue 中,如何将函数作为 props 传递给组件
作者:Michael Thiessen 译者:前端小智 来源:medium 点赞再看,养成习惯本文 GitHub https://github.com/qq44924588... 上已经收录,更多往
前端小智@大迁世界
2020/05/18
8.2K0
OpenGLES_理论01_介绍
学习是一件开心的额事情 你应该思考的问题 问题1:什么是OpenGL? OpenGL 是图形硬件的一种软件接口,接口函数包含了超过700个 问题2:OpenGL 的函数主要作用是什么? 用于指
酷走天涯
2018/09/14
6270
OpenGLES_理论01_介绍
【实作】一个将Jetson NANO数据流传递给物联网平台的实验
物联网云是指为物联网提供动力的任何数量的云服务。这些包括处理和存储物联网数据所需的底层基础设施,无论这些数据是否是实时的。
GPUS Lady
2020/05/07
2.6K0
如何在缺乏沟通的情况下,发现数据背后的问题【搞笑版】
之前我们分享过,数据分析给建议的标准做法:{数据分析报告中“建议”该怎么写}看完这篇后,相当多的同学抱怨,说业务部门根本不想沟通。净把做数据当算命的,希望他们什么都不说,我们一看面相就能说出:产品线需要调整,A产品价格再降低25元就能拉动500万销量这种话。该怎么破!
接地气的陈老师
2019/12/09
5110
解剖 WebGL & Three.js 工作原理
本文主要介绍了WebGL和Three.js的渲染流程,从加载模型到生成纹理和片元着色器,再到进行矩阵计算和坐标转换,最终完成3D渲染。
万技师
2017/05/03
9.8K2
解剖 WebGL & Three.js 工作原理
WebGL: 从 2D 开始
腾讯IVWEB团队
2017/10/13
5K0
WebGL: 从 2D 开始
点击加载更多

相似问题

如何在不改变值的情况下将向量传递给模块?

20

如何在不改变原色的情况下使用着色器

12

无法将值传递给DocuS传模板

14

如何在不改变指令范围的情况下将额外的参数传递给指令

28

将正常数据传递给着色器

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文