1

i managed to load jpg images and use them as textures in vulkan, however different images give different results, with some images it works just fine, with others it does not map well.

here is the code block related to image loading and format transition:-

void Vulkan::createTextureImage()
{
    SDL_Surface *tempImg;
    SDL_RWops *rwop;

    rwop = SDL_RWFromFile("Textures/img1.jpg", "rb");
    tempImg = IMG_LoadJPG_RW(rwop);



    SDL_Surface *image = SDL_ConvertSurfaceFormat(tempImg, SDL_PIXELFORMAT_ABGR8888, 0);

    VkDeviceSize imageSize = image->format->BytesPerPixel * image->h * image->w;


    if (!image)
    {
        throw std::runtime_error("failed to load texture image!");
    }

    VkImage stagingImage;
    VkDeviceMemory staingImageMemory;

    createImage(
        image->w, image->h, 
        VK_FORMAT_R8G8B8A8_UNORM, 
        VK_IMAGE_TILING_LINEAR, 
        VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 
        VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 
        stagingImage, 
        staingImageMemory);

    std::cout << "the image size is " << imageSize << std::endl;

    void * data;
    vkMapMemory(device, staingImageMemory, 0, imageSize, 0, &data);
    memcpy(data, image->pixels, (size_t)imageSize);
    vkUnmapMemory(device, staingImageMemory);

    createImage(
        image->w, image->h,
        VK_FORMAT_R8G8B8A8_UNORM,
        VK_IMAGE_TILING_OPTIMAL,
        VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
        textureImage,
        textureImageMemory);

    transitionImageLayout(stagingImage, VK_FORMAT_R8G8B8A8_UNORM,
        VK_IMAGE_LAYOUT_PREINITIALIZED,
        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
    transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM,
        VK_IMAGE_LAYOUT_PREINITIALIZED,
        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);

    copyImage(stagingImage, textureImage, image->w, image->h);

    transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM,
        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
        VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);

}

the only modification i have done is to flip the V component of the texture to fix the mirrored images

image results: no problem loading this image

this one does not map well enter image description here

while it should show something like this enter image description here

BulBul
  • 1,159
  • 3
  • 24
  • 37
  • I think you are missing 'pitch' value in your calculations. – Orhun Apr 14 '17 at 16:52
  • @Orhun how should i put pitch value into my calculation, can you send me the exact calculation? – BulBul Apr 14 '17 at 17:05
  • I don't know SDL but looking at their documenation, it looks like your image size should be pitch * height. i.e. `VkDeviceSize imageSize = image->h * image->pitch;` – Orhun Apr 14 '17 at 17:45
  • @Orhun the result is the same, thank you anyway for your help. – BulBul Apr 14 '17 at 18:19
  • Check the row alignment requirements of vulkan with odd sized image widths that may be the issue – ratchet freak Apr 14 '17 at 18:28
  • @ratchetfreak i rather took the lazy approach and cropped the image so that it has a proper even horizontal pixel count, and the skewing issue is gone, is there a good approach or algorithm to compensate for such textures? – BulBul Apr 14 '17 at 21:02

1 Answers1

1

It looks like the row pitch of sdl doesn't match the row pitch that vulkan wants.

Instead you can use a buffer to image copy from staging memory with vkCmdCopyBufferToImage instead of a image to image blit there you pass the row pitch explicitly in the VkBufferImageCopy struct.

ratchet freak
  • 47,288
  • 5
  • 68
  • 106
  • thanks for your answer, i have a final question, which one is the most optimized way of copying image data? because what i have understood from your answer there is an additional step of creating a buffer then copying it to the image object. – BulBul Apr 14 '17 at 21:22
  • You already use a staging area to do the copy so it's not going to be that bad over your current solution. Only this time it's bound to a vkBuffer instead of a vkImage. And you can/should reuse that staging memory later. There is a optimalBufferCopyRowPitchAlignment limit in the limits section but it's not required to be followed. – ratchet freak Apr 14 '17 at 21:34