08/09/2020
文章目录
图像介绍(VkImage)
图像相当于外部的图片,带有着像素,格式等等信息。
图像布局
图像有不同的布局,表示实际像素在内存中的分布不同。GPU不适合逐行存储像素,对图像执行操作,必须有最佳的布局,比如:
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: 用于呈现,使用最佳
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: 当使用附件从片段着色器进行写入时候,使用最佳
- VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: 作为传送源操作的时候,使用最佳,比如vkCmdCopyImageToBuffer
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: 作为传输目的地的时候,使用最佳,比如vkCmdCopyBufferToImage
- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: 着色器中用于采样,使用最佳
管线屏障
变换图像布局最常见的方式之一是管线屏障(pipeline barrier),管线屏障主要用作同步访问资源,注入确保图像在读之前写入,但是也可以用于布局变换。也可以用于VK_SHARING_MODE_EXCLUSIVE模式下队列族宿主的变换。
创建图像用于纹理
基本步骤:与创建缓冲区类型
- 创建临时缓冲区保存像素数据
- 从临时缓冲区传入到图像对象中去
第一步:加载图片
使用stb库读取图片像素信息,现在的排布方式是线性的char数组排列。
void createTextureImage() {
int texWidth, texHeight, texChannels;
stbi_uc* pixels = stbi_load("textures/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha); //读取rgba数据
VkDeviceSize imageSize = texWidth * texHeight * 4; // 图片大小,宽高,一个像素占4个字节
if (!pixels) {
throw std::runtime_error("failed to load texture image!");
}
}
第二步:像素拷贝到临时缓冲区
void createTextureImage() {
//第一步:load pixel
//第二步:拷贝到临时缓冲区
VkBuffer stagingBuffer;
VkDeviceMemory stagingBufferMemory;
createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
void* data;
vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data);
memcpy(data, pixels, static_cast<size_t>(imageSize