在Vulkan中加载非2的幂的纹理 [英] Loading non-power-of-two textures in Vulkan
问题描述
如果我的纹理尺寸为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屋!