vulkan游戏引擎的vulkan/shaders下的image实现

发布于:2025-05-27 ⋅ 阅读:(31) ⋅ 点赞:(0)

1.vulkan_image.h

#pragma once

#include "vulkan_types.inl"

void vulkan_image_create(

    vulkan_context* context,

    VkImageType image_type,

    u32 width,

    u32 height,

    VkFormat format,

    VkImageTiling tiling,

    VkImageUsageFlags usage,

    VkMemoryPropertyFlags memory_flags,

    b32 create_view,

    VkImageAspectFlags view_aspect_flags,

    vulkan_image* out_image);


 

void vulkan_image_view_create(

    vulkan_context* context,

    VkFormat format,

    vulkan_image* image,

    VkImageAspectFlags aspect_flags

);


 

void vulkan_image_transtion_layout(

    vulkan_context* context,

    vulkan_command_buffer* command_buffer,

    vulkan_image* image,

    VkImageLayout old_layout,

    VkImageLayout new_layout

);

void vulkan_image_copy_from_buffer(

    vulkan_context* context,

    vulkan_image* image,

    VkBuffer buffer,

    vulkan_command_buffer* command_buffer

);



 

void vulkan_image_destroy(vulkan_context* context,vulkan_image* image);

2.vulkan_image.c

#include "vulkan_image.h"

#include "vulkan_device.h"

#include "core/kmemory.h"

#include "core/logger.h"


 

void vulkan_image_create(

    vulkan_context* context,

    VkImageType image_type,

    u32 width,

    u32 height,

    VkFormat format,

    VkImageTiling tiling,

    VkImageUsageFlags usage,

    VkMemoryPropertyFlags memory_flags,

    b32 create_view,

    VkImageAspectFlags view_aspect_flags,

    vulkan_image* out_image

){

    out_image->width = width;

    out_image->height = height;


 

    VkImageCreateInfo image_create_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};

    image_create_info.imageType = VK_IMAGE_TYPE_2D;

    image_create_info.extent.width = width;

    image_create_info.extent.height = height;

    image_create_info.extent.depth = 1;

    image_create_info.mipLevels = 4;

    image_create_info.arrayLayers = 1;

     image_create_info.format = format;

    image_create_info.tiling = tiling;

    image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;

    image_create_info.usage = usage;

    image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;

    image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;


 

    VK_CHECK(vkCreateImage(context->device.logical_device,&image_create_info,context->allocator,&out_image->handle));

    VkMemoryRequirements memory_requirements;

    vkGetImageMemoryRequirements(context->device.logical_device,out_image->handle,&memory_requirements);

    i32 memory_type = context->find_memory_index(memory_requirements.memoryTypeBits,memory_flags);

    if(memory_type == -1)

    {

        KERROR("Required memory type not found. Image not valid.");



 

    }

    //Allocate memory

    VkMemoryAllocateInfo memory_allocate_info = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};

    memory_allocate_info.allocationSize = memory_requirements.size;

    memory_allocate_info.memoryTypeIndex = memory_type;

    VK_CHECK(vkAllocateMemory(context->device.logical_device,&memory_allocate_info,context->allocator,&out_image->memory));



 

    //Bind the memory

    VK_CHECK(vkBindImageMemory(context->device.logical_device,out_image->handle,out_image->memory,0));

    if(create_view)

    {

        out_image->view =0 ;

        vulkan_image_view_create(context,format,out_image,view_aspect_flags);      


 

    }

}

void vulkan_image_view_create(

    vulkan_context* context,

    VkFormat format,

    vulkan_image* image,

    VkImageAspectFlags aspect_flags)

    {

        VkImageViewCreateInfo view_create_info = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO};

        view_create_info.image = image->handle;

        view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;

        view_create_info.format = format;

        view_create_info.subresourceRange.aspectMask = aspect_flags;


 

        view_create_info.subresourceRange.baseMipLevel = 0;

        view_create_info.subresourceRange.levelCount = 1;

        view_create_info.subresourceRange.baseArrayLayer = 0;

        view_create_info.subresourceRange.layerCount  = 1;

        VK_CHECK(vkCreateImageView(context->device.logical_device,&view_create_info,context->allocator,&image->view));



 

    }



 

void vulkan_image_transtion_layout(

    vulkan_context* context,

    vulkan_command_buffer* command_buffer,

    vulkan_image* image,

    VkImageLayout old_layout,

    VkImageLayout new_layout

)

{

    VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER};

    barrier.oldLayout = old_layout;

    barrier.newLayout = new_layout;

    barrier.srcQueueFamilyIndex = context->device.graphics_queue_index;

    barrier.dstQueueFamilyIndex = context->device.graphics_queue_index;

    barrier.image = image->handle;

    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 source_stage;

    VkPipelineStageFlags dest_stage;

    if(old_layout == VK_IMAGE_LAYOUT_UNDEFINED && new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)

    {

        barrier.srcAccessMask = 0;

        barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;

        source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;

       

        dest_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;

    }else if(old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)

    {

        barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;

        barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;

        source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;

        dest_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;


 

    } else

    {

        KFATAL("unsupport layout transtion!");

        return;


 

    }


 

    vkCmdPipelineBarrier(

        command_buffer->handle,

        source_stage,dest_stage,

        0,

        0,0,

        0,0,

        1,&barrier


 

    );




 

}

void vulkan_image_copy_from_buffer(

    vulkan_context* context,

    vulkan_image* image,

    VkBuffer buffer,

    vulkan_command_buffer* command_buffer

)

{

    VkBufferImageCopy region;

    kzero_memory(&region, sizeof(VkBufferImageCopy));

    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.imageExtent.width = image->width;

    region.imageExtent.height = image->height;

    region.imageExtent.depth = 1;

    vkCmdCopyBufferToImage(

        command_buffer->handle,

        buffer,

        image->handle,

        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,

        1,

        &region




 

    );



 

}



 

void vulkan_image_destroy(vulkan_context* context,vulkan_image* image)

{

    if(image->view)

    {

        vkDestroyImageView(context->device.logical_device,image->view,context->allocator);

        image->view = 0;

    }

    if(image->memory)

    {

        vkFreeMemory(context->device.logical_device,image->memory,context->allocator);

        image->memory = 0;



 

    }

    if(image->handle)

    {

        vkDestroyImage(context->device.logical_device,image->handle,context->allocator);

        image->handle = 0;


 

    }




 

}