Changeset eea05dd in opengl-game for vulkan-game.cpp


Ignore:
Timestamp:
Jul 26, 2019, 5:23:30 AM (5 years ago)
Author:
Dmitry Portnoy <dmp1488@…>
Branches:
feature/imgui-sdl, master, points-test
Children:
88ebdc8
Parents:
c7fb883
Message:

Create a Vulkan image and fill it with image data loaded from a file

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vulkan-game.cpp

    rc7fb883 reea05dd  
    1616#include <glm/glm.hpp>
    1717#include <glm/gtc/matrix_transform.hpp>
     18
     19#define STB_IMAGE_IMPLEMENTATION
     20#include "stb_image.h"
    1821
    1922#include <iostream>
     
    189192      vector<VkSemaphore> renderFinishedSemaphores;
    190193      vector<VkFence> inFlightFences;
     194
     195      VkImage textureImage;
     196      VkDeviceMemory textureImageMemory;
    191197
    192198      size_t currentFrame = 0;
     
    223229         createFramebuffers();
    224230         createCommandPool();
     231         createTextureImage();
    225232         createVertexBuffer();
    226233         createIndexBuffer();
     
    919926      }
    920927
     928      void createTextureImage() {
     929         int texWidth, texHeight, texChannels;
     930
     931         stbi_uc* pixels = stbi_load("textures/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
     932         VkDeviceSize imageSize = texWidth * texHeight * 4;
     933
     934         if (!pixels) {
     935            throw runtime_error("failed to load texture image!");
     936         }
     937
     938         VkBuffer stagingBuffer;
     939         VkDeviceMemory stagingBufferMemory;
     940
     941         createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
     942            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     943            stagingBuffer, stagingBufferMemory);
     944
     945         void* data;
     946
     947         vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data);
     948         memcpy(data, pixels, static_cast<size_t>(imageSize));
     949         vkUnmapMemory(device, stagingBufferMemory);
     950
     951         stbi_image_free(pixels);
     952
     953         createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL,
     954            VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
     955            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory);
     956
     957         transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
     958         copyBufferToImage(stagingBuffer, textureImage, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));
     959         transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
     960
     961         vkDestroyBuffer(device, stagingBuffer, nullptr);
     962         vkDestroyMemory(device, stagingBufferMemory, nullptr);
     963      }
     964
     965      void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
     966            VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
     967         VkImageCreateInfo imageInfo = {};
     968         imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
     969         imageInfo.imageType = VK_IMAGE_TYPE_2D;
     970         imageInfo.extent.width = width;
     971         imageInfo.extent.height = height;
     972         imageInfo.extent.depth = 1;
     973         imageInfo.mipLevels = 1;
     974         imageInfo.arrayLayers = 1;
     975         imageInfo.format = format;
     976         imageInfo.tiling = tiling;
     977         imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
     978         imageInfo.usage = usage;
     979         imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
     980         imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
     981
     982         if (vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
     983            throw runtime_error("failed to create image!");
     984         }
     985
     986         VkMemoryRequirements memRequirements;
     987         vkGetImageMemoryRequirements(device, image, &memRequirements);
     988
     989         VkMemoryAllocateInfo allocInfo;
     990         allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
     991         allocInfo.allocationSize = memRequirements.size;
     992         allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
     993
     994         if (vkAllocateMemory(device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) {
     995            throw runtime_error("failed to allocate image memory!");
     996         }
     997
     998         vkBindImageMemory(device, image, imageMemory, 0);
     999      }
     1000
     1001      void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) {
     1002         VkCommandBuffer commandBuffer = beginSingleTimeCommands();
     1003
     1004         VkImageMemoryBarrier barrier = {};
     1005         barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
     1006         barrier.oldLayout = oldLayout;
     1007         barrier.newLayout = newLayout;
     1008         barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     1009         barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     1010         barrier.image = image;
     1011         barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
     1012         barrier.subresourceRange.baseMipLevel = 0;
     1013         barrier.subresourceRange.levelCount = 1;
     1014         barrier.subresourceRange.baseArrayLayer = 0;
     1015         barrier.subresourceRange.layerCount = 1;
     1016         
     1017         VkPipelineStageFlags sourceFlags;
     1018         VkPipelineStageFlags destinationFlags;
     1019
     1020         if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
     1021            barrier.srcAccessMask = 0;
     1022            barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
     1023
     1024            sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
     1025            destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
     1026         } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
     1027            barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
     1028            barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
     1029
     1030            sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
     1031            destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
     1032         } else {
     1033            throw invalid_argument("unsupported layout transition!");
     1034         }
     1035
     1036         vkCmdPipelineBarrier(
     1037            commandBuffer,
     1038            sourceFlags, destinationFlags,
     1039            0,
     1040            0, nullptr,
     1041            0, nullptr,
     1042            1, &barrier
     1043         );
     1044
     1045         endSingleTimeCommands(commandBuffer);
     1046      }
     1047
     1048      void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height) {
     1049         VkCommandBuffer commandBuffer = beginSingleTimeCommands();
     1050
     1051         VkBufferImageCopy region = {};
     1052         region.bufferOffset = 0;
     1053         region.bufferRowLength = 0;
     1054         region.bufferImageHeight = 0;
     1055
     1056         region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
     1057         region.imageSubresource.mipLevel = 0;
     1058         region.imageSubresource.baseArrayLayer = 0;
     1059         region.imageSubresource.layerCount = 1;
     1060
     1061         region.imageOffset = { 0, 0, 0 };
     1062         region.imageExtent = { width, height, 1 };
     1063
     1064         vkCmdCopyBufferToImage(
     1065            commandBuffer,
     1066            buffer,
     1067            image,
     1068            VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
     1069            1,
     1070            &region
     1071         );
     1072
     1073         endSingleTimeCommands(commandBuffer);
     1074      }
     1075
    9211076      void createVertexBuffer() {
    9221077         VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
     
    9931148
    9941149      void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
     1150         VkCommandBuffer commandBuffer = beginSingleTimeCommands();
     1151
     1152         VkBufferCopy copyRegion = {};
     1153         copyRegion.size = size;
     1154         vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
     1155
     1156         endSingleTimeCommands(commandBuffer);
     1157      }
     1158
     1159      VkCommandBuffer beginSingleTimeCommands() {
    9951160         VkCommandBufferAllocateInfo allocInfo = {};
    9961161         allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
     
    10081173         vkBeginCommandBuffer(commandBuffer, &beginInfo);
    10091174
    1010          VkBufferCopy copyRegion = {};
    1011          copyRegion.srcOffset = 0;
    1012          copyRegion.dstOffset = 0;
    1013          copyRegion.size = size;
    1014    
    1015          vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
    1016 
     1175         return commandBuffer;
     1176      }
     1177
     1178      void endSingleTimeCommands(VkCommandBuffer commandBuffer) {
    10171179         vkEndCommandBuffer(commandBuffer);
    10181180
     
    12961458         cleanupSwapChain();
    12971459
     1460         vkDestroyImage(device, textureImage, nullptr);
     1461         vkDestroyMemory(device, textureImageMemory, nullptr);
     1462
    12981463         vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
    12991464
Note: See TracChangeset for help on using the changeset viewer.