在Vulkan中加载非2的幂的纹理 [英] Loading non-power-of-two textures in Vulkan

查看:104
本文介绍了在Vulkan中加载非2的幂的纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我的纹理尺寸为2的幂,则我的2D纹理加载器可以正常工作,但如果不是2的幂,则纹理数据显示为歪斜.我该如何解决?我认为问题与内存对齐和行间距有关.这是我的加载程序代码的相关部分:

My 2D texture loader works fine if my texture dimensions are power-of-two, but when they are not, the texture data displays as skewed. How do I fix this? I assume the issue has something to do with memory alignment and row pitch. Here's relevant parts of my loader code:

VkMemoryRequirements memReqs;
vkGetImageMemoryRequirements( GfxDeviceGlobal::device, mappableImage, &memReqs );

VkMemoryAllocateInfo memAllocInfo = {};
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAllocInfo.pNext = nullptr;
memAllocInfo.memoryTypeIndex = 0;
memAllocInfo.allocationSize = memReqs.size;

GetMemoryType( memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAllocInfo.memoryTypeIndex );

VkDeviceMemory mappableMemory;
err = vkAllocateMemory( GfxDeviceGlobal::device, &memAllocInfo, nullptr, &mappableMemory );
CheckVulkanResult( err, "vkAllocateMemory in Texture2D" );

err = vkBindImageMemory( GfxDeviceGlobal::device, mappableImage, mappableMemory, 0 );
CheckVulkanResult( err, "vkBindImageMemory in Texture2D" );

VkImageSubresource subRes = {};
subRes.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
subRes.mipLevel = 0;
subRes.arrayLayer = 0;

VkSubresourceLayout subResLayout;
vkGetImageSubresourceLayout( GfxDeviceGlobal::device, mappableImage, &subRes, &subResLayout );

void* mapped;
err = vkMapMemory( GfxDeviceGlobal::device, mappableMemory, 0, memReqs.size, 0, &mapped );
CheckVulkanResult( err, "vkMapMemory in Texture2D" );

const int bytesPerPixel = 4;
std::size_t dataSize = bytesPerPixel * width * height;
std::memcpy( mapped, data, dataSize );

vkUnmapMemory( GfxDeviceGlobal::device, mappableMemory );

推荐答案

vkGetImageSubresourceLayout 获得的 VkSubresourceLayout 将在中包含纹理的间距> rowPitch 成员.它很可能不等于 width ,因此,当您对整个数据块执行 memcpy 时,您正在将相关数据复制到纹理的padding部分中

The VkSubresourceLayout, which you obtained from vkGetImageSubresourceLayout will contain the pitch of the texture in the rowPitch member. It's more than likely not equal to the width, thus, when you do a memcpy of the entire data block, you're copying relevant data into the padding section of the texture.

相反,您将需要逐行 memcpy ,跳过映射纹理中的填充内存:

Instead you will need to memcpy row-by-row, skipping the padding memory in the mapped texture:

const int bytesPerPixel = 4;
std::size_t dataRowSize = bytesPerPixel * width;
char* mappedBytes = (char*)mapped;
for(int i = 0; i < height; ++i)
{
    std::memcpy(mapped, data, dataSize);
    mappedBytes += rowPitch;
    data += dataRowSize;
}

(此代码还假定数据也是 char * -未给出其声明)

(this code assumes data is a char * as well - its declaration wasn't given)

这篇关于在Vulkan中加载非2的幂的纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆