Changeset b794178 in opengl-game


Ignore:
Timestamp:
Oct 17, 2019, 9:30:18 PM (5 years ago)
Author:
Dmitry Portnoy <dmitry.portnoy@…>
Branches:
feature/imgui-sdl, master, points-test
Children:
e83b155
Parents:
771b33a
Message:

In vulkangame, add the ability to create vulkan resoirces and descriptor sets for shader uniforms (images and ubos)

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • graphics-pipeline_vulkan.cpp

    r771b33a rb794178  
    33#include <fstream>
    44#include <stdexcept>
    5 
    6 GraphicsPipeline_Vulkan::GraphicsPipeline_Vulkan(VkDevice device, Viewport viewport, int vertexSize) {
     5#include <iostream>
     6
     7using namespace std;
     8
     9// TODO: Remove any instances of cout and instead throw exceptions
     10
     11GraphicsPipeline_Vulkan::GraphicsPipeline_Vulkan(VkDevice device, VkRenderPass renderPass, Viewport viewport,
     12      int vertexSize) {
    713   this->device = device;
     14   this->renderPass = renderPass;
    815   this->viewport = viewport;
    916
     
    2532
    2633   this->attributeDescriptions.push_back(attributeDesc);
     34}
     35
     36void GraphicsPipeline_Vulkan::addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData) {
     37   this->descriptorInfoList.push_back({ type, stageFlags, bufferData, nullptr });
     38}
     39
     40void GraphicsPipeline_Vulkan::addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData) {
     41   this->descriptorInfoList.push_back({ type, stageFlags, nullptr, imageData });
    2742}
    2843
     
    131146   pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    132147   pipelineLayoutInfo.setLayoutCount = 1;
    133 
    134    vkDestroyShaderModule(device, vertShaderModule, nullptr);
    135    vkDestroyShaderModule(device, fragShaderModule, nullptr);
     148   pipelineLayoutInfo.pSetLayouts = &this->descriptorSetLayout;
     149   pipelineLayoutInfo.pushConstantRangeCount = 0;
     150
     151   if (vkCreatePipelineLayout(this->device, &pipelineLayoutInfo, nullptr, &this->pipelineLayout) != VK_SUCCESS) {
     152      throw runtime_error("failed to create pipeline layout!");
     153   }
     154
     155   VkGraphicsPipelineCreateInfo pipelineInfo = {};
     156   pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
     157   pipelineInfo.stageCount = 2;
     158   pipelineInfo.pStages = shaderStages;
     159   pipelineInfo.pVertexInputState = &vertexInputInfo;
     160   pipelineInfo.pInputAssemblyState = &inputAssembly;
     161   pipelineInfo.pViewportState = &viewportState;
     162   pipelineInfo.pRasterizationState = &rasterizer;
     163   pipelineInfo.pMultisampleState = &multisampling;
     164   pipelineInfo.pDepthStencilState = &depthStencil;
     165   pipelineInfo.pColorBlendState = &colorBlending;
     166   pipelineInfo.pDynamicState = nullptr;
     167   pipelineInfo.layout = this->pipelineLayout;
     168   pipelineInfo.renderPass = this->renderPass;
     169   pipelineInfo.subpass = 0;
     170   pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
     171   pipelineInfo.basePipelineIndex = -1;
     172
     173   if (vkCreateGraphicsPipelines(this->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &this->pipeline) != VK_SUCCESS) {
     174      throw runtime_error("failed to create graphics pipeline!");
     175   }
     176
     177   vkDestroyShaderModule(this->device, vertShaderModule, nullptr);
     178   vkDestroyShaderModule(this->device, fragShaderModule, nullptr);
     179}
     180
     181void GraphicsPipeline_Vulkan::createDescriptorSetLayout() {
     182   vector<VkDescriptorSetLayoutBinding> bindings(this->descriptorInfoList.size());
     183
     184   for (size_t i = 0; i < bindings.size(); i++) {
     185      bindings[i].binding = i;
     186      bindings[i].descriptorCount = 1;
     187      bindings[i].descriptorType = this->descriptorInfoList[i].type;
     188      bindings[i].stageFlags = this->descriptorInfoList[i].stageFlags;
     189      bindings[i].pImmutableSamplers = nullptr;
     190   }
     191
     192   VkDescriptorSetLayoutCreateInfo layoutInfo = {};
     193   layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
     194   layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
     195   layoutInfo.pBindings = bindings.data();
     196
     197   if (vkCreateDescriptorSetLayout(this->device, &layoutInfo, nullptr, &this->descriptorSetLayout) != VK_SUCCESS) {
     198      throw runtime_error("failed to create descriptor set layout!");
     199   }
     200}
     201
     202void GraphicsPipeline_Vulkan::createDescriptorPool(vector<VkImage>& swapChainImages) {
     203   vector<VkDescriptorPoolSize> poolSizes(this->descriptorInfoList.size());
     204
     205   for (size_t i = 0; i < poolSizes.size(); i++) {
     206      poolSizes[i].type = this->descriptorInfoList[i].type;
     207      poolSizes[i].descriptorCount = static_cast<uint32_t>(swapChainImages.size());
     208   }
     209
     210   VkDescriptorPoolCreateInfo poolInfo = {};
     211   poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
     212   poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
     213   poolInfo.pPoolSizes = poolSizes.data();
     214   poolInfo.maxSets = static_cast<uint32_t>(swapChainImages.size());
     215
     216   if (vkCreateDescriptorPool(this->device, &poolInfo, nullptr, &this->descriptorPool) != VK_SUCCESS) {
     217      throw runtime_error("failed to create descriptor pool!");
     218   }
     219}
     220
     221void GraphicsPipeline_Vulkan::createDescriptorSets(vector<VkImage>& swapChainImages) {
     222   vector<VkDescriptorSetLayout> layouts(swapChainImages.size(), this->descriptorSetLayout);
     223
     224   VkDescriptorSetAllocateInfo allocInfo = {};
     225   allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
     226   allocInfo.descriptorPool = this->descriptorPool;
     227   allocInfo.descriptorSetCount = static_cast<uint32_t>(swapChainImages.size());
     228   allocInfo.pSetLayouts = layouts.data();
     229
     230   this->descriptorSets.resize(swapChainImages.size());
     231   if (vkAllocateDescriptorSets(device, &allocInfo, this->descriptorSets.data()) != VK_SUCCESS) {
     232      throw runtime_error("failed to allocate descriptor sets!");
     233   }
     234
     235   for (size_t i = 0; i < swapChainImages.size(); i++) {
     236      vector<VkWriteDescriptorSet> descriptorWrites(this->descriptorInfoList.size());
     237
     238      for (size_t j = 0; j < descriptorWrites.size(); j++) {
     239         descriptorWrites[j].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
     240         descriptorWrites[j].dstSet = this->descriptorSets[i];
     241         descriptorWrites[j].dstBinding = j;
     242         descriptorWrites[j].dstArrayElement = 0;
     243         descriptorWrites[j].descriptorType = this->descriptorInfoList[j].type;
     244         descriptorWrites[j].descriptorCount = 1;
     245         descriptorWrites[j].pBufferInfo = nullptr;
     246         descriptorWrites[j].pImageInfo = nullptr;
     247         descriptorWrites[j].pTexelBufferView = nullptr;
     248
     249         switch (descriptorWrites[j].descriptorType) {
     250            case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
     251               descriptorWrites[j].pBufferInfo = &(*this->descriptorInfoList[j].bufferDataList)[i];
     252               break;
     253            case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
     254               descriptorWrites[j].pImageInfo = this->descriptorInfoList[j].imageData;
     255               break;
     256            default:
     257               cout << "Unknown descriptor type: " << descriptorWrites[j].descriptorType << endl;
     258         }
     259      }
     260
     261      vkUpdateDescriptorSets(this->device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
     262   }
    136263}
    137264
     
    143270
    144271   VkShaderModule shaderModule;
    145    if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
     272   if (vkCreateShaderModule(this->device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
    146273      throw runtime_error("failed to create shader module!");
    147274   }
     
    167294   return buffer;
    168295}
     296
     297void GraphicsPipeline_Vulkan::cleanup() {
     298   vkDestroyPipeline(this->device, this->pipeline, nullptr);
     299   vkDestroyDescriptorPool(this->device, this->descriptorPool, nullptr);
     300   vkDestroyPipelineLayout(this->device, this->pipelineLayout, nullptr);
     301}
     302
     303void GraphicsPipeline_Vulkan::cleanupBuffers() {
     304   vkDestroyDescriptorSetLayout(this->device, this->descriptorSetLayout, nullptr);
     305}
  • graphics-pipeline_vulkan.hpp

    r771b33a rb794178  
    88#include <vulkan/vulkan.h>
    99
     10// TODO: Maybe change the name of this struct so I can call the list something other than descriptorInfoList
     11struct DescriptorInfo {
     12   VkDescriptorType type;
     13   VkShaderStageFlags stageFlags;
     14
     15   // Only one of the below properties should be set
     16   vector<VkDescriptorBufferInfo>* bufferDataList;
     17   VkDescriptorImageInfo* imageData;
     18};
     19
    1020class GraphicsPipeline_Vulkan : public GraphicsPipeline {
    1121   public:
    12       GraphicsPipeline_Vulkan(VkDevice device, Viewport viewport, int vertexSize);
     22      GraphicsPipeline_Vulkan(VkDevice device, VkRenderPass renderPass, Viewport viewport, int vertexSize);
    1323      ~GraphicsPipeline_Vulkan();
    1424
     25      // Maybe I should rename these to addVertexAttribute (addVaryingAttribute) and addUniformAttribute
     26
    1527      void addAttribute(VkFormat format, size_t offset);
     28
     29      void addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData);
     30      void addDescriptorInfo(VkDescriptorType type, VkShaderStageFlags stageFlags, VkDescriptorImageInfo* imageData);
     31
    1632      void createPipeline(string vertShaderFile, string fragShaderFile);
     33      void createDescriptorSetLayout();
     34      void createDescriptorPool(vector<VkImage>& swapChainImages);
     35      void createDescriptorSets(vector<VkImage>& swapChainImages);
     36
     37      void cleanup();
     38      void cleanupBuffers();
    1739   
    1840   private:
    19       VkDevice device;
    20       VkVertexInputBindingDescription bindingDescription;
    21       vector<VkVertexInputAttributeDescription> attributeDescriptions;
    22 
    2341      VkShaderModule createShaderModule(const vector<char>& code);
    2442      vector<char> readFile(const string& filename);
     43
     44      VkDevice device;
     45      VkRenderPass renderPass;
     46
     47      VkPipeline pipeline;
     48      VkPipelineLayout pipelineLayout;
     49
     50      VkVertexInputBindingDescription bindingDescription;
     51
     52      vector<VkVertexInputAttributeDescription> attributeDescriptions;
     53      vector<DescriptorInfo> descriptorInfoList;
     54
     55      VkDescriptorSetLayout descriptorSetLayout;
     56      VkDescriptorPool descriptorPool;
     57      vector<VkDescriptorSet> descriptorSets;
    2558};
    2659
  • vulkan-game.cpp

    r771b33a rb794178  
    99
    1010#include "utils.hpp"
    11 #include "vulkan-utils.hpp"
    1211
    1312using namespace std;
     13
     14struct UniformBufferObject {
     15   alignas(16) mat4 model;
     16   alignas(16) mat4 view;
     17   alignas(16) mat4 proj;
     18};
    1419
    1520VulkanGame::VulkanGame() {
     
    8489      cout << gui->getError() << endl;
    8590      return RTWO_ERROR;
     91   }
     92
     93   SDL_VERSION(&sdlVersion);
     94
     95   // In SDL 2.0.10 (currently, the latest), SDL_TEXTUREACCESS_TARGET is required to get a transparent overlay working
     96   // However, the latest SDL version available through homebrew on Mac is 2.0.9, which requires SDL_TEXTUREACCESS_STREAMING
     97   // I tried building sdl 2.0.10 (and sdl_image and sdl_ttf) from source on Mac, but had some issues, so this is easier
     98   // until the homebrew recipe is updated
     99   if (sdlVersion.major == 2 && sdlVersion.minor == 0 && sdlVersion.patch == 9) {
     100      uiOverlay = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING,
     101         gui->getWindowWidth(), gui->getWindowHeight());
     102   } else {
     103      uiOverlay = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET,
     104         gui->getWindowWidth(), gui->getWindowHeight());
     105   }
     106
     107   if (uiOverlay == nullptr) {
     108      cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << endl;
     109   }
     110   if (SDL_SetTextureBlendMode(uiOverlay, SDL_BLENDMODE_BLEND) != 0) {
     111      cout << "Unable to set texture blend mode! SDL Error: " << SDL_GetError() << endl;
    86112   }
    87113
     
    107133   createCommandPool();
    108134
    109    graphicsPipelines.push_back(GraphicsPipeline_Vulkan(device, viewport, sizeof(Vertex)));
     135   createVulkanResources();
     136
     137   graphicsPipelines.push_back(GraphicsPipeline_Vulkan(device, renderPass, viewport, sizeof(Vertex)));
    110138
    111139   graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&Vertex::pos));
     
    113141   graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&Vertex::texCoord));
    114142
     143   graphicsPipelines.back().addDescriptorInfo(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
     144      VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList);
     145   graphicsPipelines.back().addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
     146      VK_SHADER_STAGE_FRAGMENT_BIT, &floorTextureImageDescriptor);
     147
     148   graphicsPipelines.back().createDescriptorSetLayout();
    115149   graphicsPipelines.back().createPipeline("shaders/scene-vert.spv", "shaders/scene-frag.spv");
    116 
    117    graphicsPipelines.push_back(GraphicsPipeline_Vulkan(device, viewport, sizeof(OverlayVertex)));
     150   graphicsPipelines.back().createDescriptorPool(swapChainImages);
     151   graphicsPipelines.back().createDescriptorSets(swapChainImages);
     152
     153   graphicsPipelines.push_back(GraphicsPipeline_Vulkan(device, renderPass, viewport, sizeof(OverlayVertex)));
    118154
    119155   graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32B32_SFLOAT, offset_of(&OverlayVertex::pos));
    120156   graphicsPipelines.back().addAttribute(VK_FORMAT_R32G32_SFLOAT, offset_of(&OverlayVertex::texCoord));
    121157
     158   graphicsPipelines.back().addDescriptorInfo(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
     159      VK_SHADER_STAGE_FRAGMENT_BIT, &sdlOverlayImageDescriptor);
     160
     161   graphicsPipelines.back().createDescriptorSetLayout();
    122162   graphicsPipelines.back().createPipeline("shaders/overlay-vert.spv", "shaders/overlay-frag.spv");
     163   graphicsPipelines.back().createDescriptorPool(swapChainImages);
     164   graphicsPipelines.back().createDescriptorSets(swapChainImages);
    123165
    124166   cout << "Created " << graphicsPipelines.size() << " graphics pipelines" << endl;
     
    189231   cleanupSwapChain();
    190232
     233   for (GraphicsPipeline_Vulkan pipeline : graphicsPipelines) {
     234      pipeline.cleanupBuffers();
     235   }
     236
    191237   vkDestroyCommandPool(device, commandPool, nullptr);
    192238   vkDestroyDevice(device, nullptr);
     
    198244
    199245   vkDestroyInstance(instance, nullptr);
     246
     247   // TODO: Check if any of these functions accept null parameters
     248   // If they do, I don't need to check for that
     249
     250   if (uiOverlay != nullptr) {
     251      SDL_DestroyTexture(uiOverlay);
     252      uiOverlay = nullptr;
     253   }
    200254
    201255   SDL_DestroyRenderer(renderer);
     
    343397   QueueFamilyIndices indices = VulkanUtils::findQueueFamilies(physicalDevice, surface);
    344398
    345    vector<VkDeviceQueueCreateInfo> queueCreateInfos;
     399   vector<VkDeviceQueueCreateInfo> queueCreateInfoList;
    346400   set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
    347401
     
    354408      queueCreateInfo.pQueuePriorities = &queuePriority;
    355409
    356       queueCreateInfos.push_back(queueCreateInfo);
     410      queueCreateInfoList.push_back(queueCreateInfo);
    357411   }
    358412
     
    362416   VkDeviceCreateInfo createInfo = {};
    363417   createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    364    createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
    365    createInfo.pQueueCreateInfos = queueCreateInfos.data();
     418   createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfoList.size());
     419   createInfo.pQueueCreateInfos = queueCreateInfoList.data();
    366420
    367421   createInfo.pEnabledFeatures = &deviceFeatures;
     
    529583}
    530584
     585void VulkanGame::createVulkanResources() {
     586   createTextureSampler();
     587   createUniformBuffers();
     588
     589   // TODO: Make sure that Vulkan complains about these images not being destroyed and then destroy them
     590
     591   VulkanUtils::createVulkanImageFromFile(device, physicalDevice, commandPool, "textures/texture.jpg",
     592      floorTextureImage, graphicsQueue);
     593   VulkanUtils::createVulkanImageFromSDLTexture(device, physicalDevice, uiOverlay, sdlOverlayImage);
     594
     595   floorTextureImageDescriptor = {};
     596   floorTextureImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
     597   floorTextureImageDescriptor.imageView = floorTextureImage.imageView;
     598   floorTextureImageDescriptor.sampler = textureSampler;
     599
     600   sdlOverlayImageDescriptor = {};
     601   sdlOverlayImageDescriptor.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
     602   sdlOverlayImageDescriptor.imageView = sdlOverlayImage.imageView;
     603   sdlOverlayImageDescriptor.sampler = textureSampler;
     604}
     605
     606void VulkanGame::createTextureSampler() {
     607   VkSamplerCreateInfo samplerInfo = {};
     608   samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
     609   samplerInfo.magFilter = VK_FILTER_LINEAR;
     610   samplerInfo.minFilter = VK_FILTER_LINEAR;
     611
     612   samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
     613   samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
     614   samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
     615
     616   samplerInfo.anisotropyEnable = VK_TRUE;
     617   samplerInfo.maxAnisotropy = 16;
     618   samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
     619   samplerInfo.unnormalizedCoordinates = VK_FALSE;
     620   samplerInfo.compareEnable = VK_FALSE;
     621   samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
     622   samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
     623   samplerInfo.mipLodBias = 0.0f;
     624   samplerInfo.minLod = 0.0f;
     625   samplerInfo.maxLod = 0.0f;
     626
     627   if (vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) {
     628      throw runtime_error("failed to create texture sampler!");
     629   }
     630}
     631
     632void VulkanGame::createUniformBuffers() {
     633   VkDeviceSize bufferSize = sizeof(UniformBufferObject);
     634
     635   uniformBuffers.resize(swapChainImages.size());
     636   uniformBuffersMemory.resize(swapChainImages.size());
     637   uniformBufferInfoList.resize(swapChainImages.size());
     638
     639   for (size_t i = 0; i < swapChainImages.size(); i++) {
     640      VulkanUtils::createBuffer(device, physicalDevice, bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
     641         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     642         uniformBuffers[i], uniformBuffersMemory[i]);
     643
     644      uniformBufferInfoList[i].buffer = uniformBuffers[i];
     645      uniformBufferInfoList[i].offset = 0;
     646      uniformBufferInfoList[i].range = sizeof(UniformBufferObject);
     647   }
     648}
     649
    531650void VulkanGame::cleanupSwapChain() {
     651   for (GraphicsPipeline_Vulkan pipeline : graphicsPipelines) {
     652      pipeline.cleanup();
     653   }
     654
    532655   vkDestroyRenderPass(device, renderPass, nullptr);
    533656
    534    for (auto imageView : swapChainImageViews) {
     657   for (VkImageView imageView : swapChainImageViews) {
    535658      vkDestroyImageView(device, imageView, nullptr);
    536659   }
  • vulkan-game.hpp

    r771b33a rb794178  
    66#include "game-gui-sdl.hpp"
    77#include "graphics-pipeline_vulkan.hpp"
     8
     9#include "vulkan-utils.hpp"
    810
    911#ifdef NDEBUG
     
    4042
    4143      SDL_version sdlVersion;
    42       SDL_Window* window;
    43       SDL_Renderer* renderer;
     44      SDL_Window* window = nullptr;
     45      SDL_Renderer* renderer = nullptr;
     46
     47      SDL_Texture* uiOverlay = nullptr;
    4448
    4549      VkInstance instance;
     
    5963      VkRenderPass renderPass;
    6064      VkCommandPool commandPool;
     65
     66      // TODO: Create these (and wrap them inside a VulkanImage)
     67      VkImage depthImage;
     68      VkDeviceMemory depthImageMemory;
     69      VkImageView depthImageView;
     70
     71      VkSampler textureSampler;
     72
     73      vector<VkDescriptorBufferInfo> uniformBufferInfoList;
     74
     75      // These are currently to store the MVP matrix
     76      // I should figure out if it makes sense to use them for other uniforms in the future
     77      // If not, I should rename them to better indicate their purpose.
     78      // I should also decide if I can use these for all shaders, or if I need a separapte set of buffers for each one
     79      vector<VkBuffer> uniformBuffers;
     80      vector<VkDeviceMemory> uniformBuffersMemory;
     81
     82      VulkanImage floorTextureImage;
     83      VkDescriptorImageInfo floorTextureImageDescriptor;
     84
     85      VulkanImage sdlOverlayImage;
     86      VkDescriptorImageInfo sdlOverlayImageDescriptor;
    6187
    6288      bool framebufferResized = false;
     
    83109      VkFormat findDepthFormat();
    84110      void createCommandPool();
     111      void createVulkanResources();
     112      void createTextureSampler();
     113      void createUniformBuffers();
    85114
    86115      void cleanupSwapChain();
  • vulkan-ref.cpp

    r771b33a rb794178  
    8080};
    8181
     82/*** START OF REFACTORED CODE ***/
    8283struct DescriptorInfo {
    8384   VkDescriptorType type;
     
    8788   VkDescriptorImageInfo* imageData;
    8889};
     90/*** END OF REFACTORED CODE ***/
    8991
    9092struct GraphicsPipelineInfo {
     93/*** START OF REFACTORED CODE ***/
    9194   VkPipelineLayout pipelineLayout;
    9295   VkPipeline pipeline;
     
    100103   VkDescriptorSetLayout descriptorSetLayout;
    101104   vector<VkDescriptorSet> descriptorSets;
     105/*** END OF REFACTORED CODE ***/
    102106
    103107   size_t numVertices; // Currently unused
     
    153157      SDL_Window* window = nullptr;
    154158      SDL_Renderer* gRenderer = nullptr;
    155 /*** END OF REFACTORED CODE ***/
    156159      SDL_Texture* uiOverlay = nullptr;
     160/*** END OF REFACTORED CODE ***/
    157161
    158162      TTF_Font* gFont = nullptr;
     
    176180/*** END OF REFACTORED CODE ***/
    177181      // (This was taken out of vulkan-game for now and replaced with Viewport)
    178       // It will definitely be needed when creating render passes and I could use it in a few other places
     182      // It will definitely be needed when creating command buffers and I could use it in a few other places
     183      // TODO: Check above ^
    179184      VkExtent2D swapChainExtent;
    180185/*** START OF REFACTORED CODE ***/
     
    190195      vector<VkCommandBuffer> commandBuffers;
    191196
     197/*** START OF REFACTORED CODE ***/
    192198      // The images and the sampler are used to store data for specific attributes. I probably
    193199      // want to keep them separate from the GraphicsPipelineInfo objects and start passing
     
    197203      VkDeviceMemory depthImageMemory;
    198204      VkImageView depthImageView;
     205/*** END OF REFACTORED CODE ***/
    199206
    200207      VkImage textureImage;
     
    202209      VkImageView textureImageView;
    203210
    204       VkImage overlayImage;
    205       VkDeviceMemory overlayImageMemory;
    206       VkImageView overlayImageView;
    207 
    208211      VkImage sdlOverlayImage;
    209212      VkDeviceMemory sdlOverlayImageMemory;
    210213      VkImageView sdlOverlayImageView;
    211214
     215/*** START OF REFACTORED CODE ***/
    212216      VkSampler textureSampler;
    213217
    214218      // These are currently to store the MVP matrix
    215219      // I should figure out if it makes sense to use them for other uniforms in the future
    216       // If not, I should rename them to better indicate their puprose.
     220      // If not, I should rename them to better indicate their purpose.
    217221      // I should also decide if I can use these for all shaders, or if I need a separapte set of buffers for each one
    218222      vector<VkBuffer> uniformBuffers;
    219223      vector<VkDeviceMemory> uniformBuffersMemory;
     224/*** END OF REFACTORED CODE ***/
    220225
    221226      VkDescriptorImageInfo sceneImageInfo;
    222227      VkDescriptorImageInfo overlayImageInfo;
    223228
     229/*** START OF REFACTORED CODE ***/
    224230      vector<VkDescriptorBufferInfo> uniformBufferInfoList;
     231/*** END OF REFACTORED CODE ***/
    225232
    226233      GraphicsPipelineInfo scenePipeline;
     
    257264            return RTWO_ERROR;
    258265         }
    259 /*** END OF REFACTORED CODE ***/
    260266
    261267         SDL_VERSION(&sdlVersion);
     
    277283            cout << "Unable to set texture blend mode! SDL Error: " << SDL_GetError() << endl;
    278284         }
     285/*** END OF REFACTORED CODE ***/
    279286
    280287         gFont = TTF_OpenFont("fonts/lazy.ttf", 28);
     
    334341/*** END OF REFACTORED CODE ***/
    335342
    336          // THIS SECTION IS WHERE TEXTURES ARE CREATED, MAYBE SPLIT IT OFF INTO A SEPARATE FUNCTION
    337          // MAY WANT TO CREATE A STRUCT TO HOLD SIMILAR VARIABLES< LIKE THOSE FOR A TEXTURE
    338 
    339343         createImageResources("textures/texture.jpg", textureImage, textureImageMemory, textureImageView);
     344/*** START OF REFACTORED CODE ***/
    340345         createImageResourcesFromSDLTexture(uiOverlay, sdlOverlayImage, sdlOverlayImageMemory, sdlOverlayImageView);
    341346         createTextureSampler();
     
    350355         overlayImageInfo.imageView = sdlOverlayImageView;
    351356         overlayImageInfo.sampler = textureSampler;
     357/*** END OF REFACTORED CODE ***/
    352358
    353359         // SHADER-SPECIFIC STUFF STARTS HERE
     
    377383         addAttributeDescription(scenePipeline, VK_FORMAT_R32G32B32_SFLOAT, offset_of(&Vertex::color));
    378384         addAttributeDescription(scenePipeline, VK_FORMAT_R32G32_SFLOAT, offset_of(&Vertex::texCoord));
    379 /*** END OF REFACTORED CODE ***/
    380385
    381386         addDescriptorInfo(scenePipeline, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, &uniformBufferInfoList, nullptr);
     
    383388
    384389         createDescriptorSetLayout(scenePipeline);
     390/*** END OF REFACTORED CODE ***/
    385391
    386392         numPlanes = 2;
     
    403409         addAttributeDescription(overlayPipeline, VK_FORMAT_R32G32B32_SFLOAT, offset_of(&OverlayVertex::pos));
    404410         addAttributeDescription(overlayPipeline, VK_FORMAT_R32G32_SFLOAT, offset_of(&OverlayVertex::texCoord));
    405 /*** END OF REFACTORED CODE ***/
    406411
    407412         addDescriptorInfo(overlayPipeline, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr, &overlayImageInfo);
    408413
    409414         createDescriptorSetLayout(overlayPipeline);
     415/*** END OF REFACTORED CODE ***/
    410416
    411417         createBufferResources();
     
    847853      }
    848854
     855/*** START OF REFACTORED CODE ***/
    849856      void addDescriptorInfo(GraphicsPipelineInfo& info, VkDescriptorType type, VkShaderStageFlags stageFlags, vector<VkDescriptorBufferInfo>* bufferData, VkDescriptorImageInfo* imageData) {
    850857         info.descriptorInfoList.push_back({ type, stageFlags, bufferData, imageData });
     
    873880
    874881      void createGraphicsPipeline(string vertShaderFile, string fragShaderFile, GraphicsPipelineInfo& info) {
    875 /*** START OF REFACTORED CODE ***/
    876882         vector<char> vertShaderCode = readFile(vertShaderFile);
    877883         vector<char> fragShaderCode = readFile(fragShaderFile);
     
    977983         pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    978984         pipelineLayoutInfo.setLayoutCount = 1;
    979 /*** END OF REFACTORED CODE ***/
    980985         pipelineLayoutInfo.pSetLayouts = &info.descriptorSetLayout;
    981986         pipelineLayoutInfo.pushConstantRangeCount = 0;
     
    10071012         }
    10081013
    1009 /*** START OF REFACTORED CODE ***/
    10101014         vkDestroyShaderModule(device, vertShaderModule, nullptr);
    10111015         vkDestroyShaderModule(device, fragShaderModule, nullptr);
    1012 /*** END OF REFACTORED CODE ***/
    1013       }
     1016      }
     1017/*** END OF REFACTORED CODE ***/
    10141018
    10151019      VkShaderModule createShaderModule(const vector<char>& code) {
     
    11341138         throw runtime_error("failed to find supported format!");
    11351139      }
    1136 /*** END OF REFACTORED CODE ***/
    11371140
    11381141      bool hasStencilComponent(VkFormat format) {
     
    11911194         view = createImageView(image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
    11921195      }
     1196/*** END OF REFACTORED CODE ***/
    11931197
    11941198      void populateImageFromSDLTexture(SDL_Texture* texture, VkImage& image) {
     
    13861390         return imageView;
    13871391      }
    1388 /*** END OF REFACTORED CODE ***/
    13891392
    13901393      void createTextureSampler() {
     
    14131416         }
    14141417      }
     1418/*** END OF REFACTORED CODE ***/
    14151419
    14161420      void createVertexBuffer(GraphicsPipelineInfo& info, const void* vertexData, int vertexSize) {
     
    14621466      }
    14631467
     1468/*** START OF REFACTORED CODE ***/
    14641469      void createUniformBuffers() {
    14651470         VkDeviceSize bufferSize = sizeof(UniformBufferObject);
     
    15051510         vkBindBufferMemory(device, buffer, bufferMemory, 0);
    15061511      }
     1512/*** END OF REFACTORED CODE ***/
    15071513
    15081514      void copyDataToBuffer(const void* srcData, VkBuffer dst, VkDeviceSize dstOffset, VkDeviceSize dataSize) {
     
    15671573      }
    15681574
     1575/*** START OF REFACTORED CODE ***/
    15691576      uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
    15701577         VkPhysicalDeviceMemoryProperties memProperties;
     
    16421649         }
    16431650      }
     1651/*** END OF REFACTORED CODE ***/
    16441652
    16451653      void createCommandBuffers() {
     
    19481956
    19491957      void createBufferResources() {
     1958         // TODO: The three functions below will be called in vulkan-game following the
     1959         // pipeline creation (createDescriptorSets()), and before createCommandBuffers()
    19501960         createDepthResources();
    19511961         createFramebuffers();
    19521962         createUniformBuffers();
    19531963
     1964/*** START OF REFACTORED CODE ***/
    19541965         createGraphicsPipeline("shaders/scene-vert.spv", "shaders/scene-frag.spv", scenePipeline);
    19551966         createDescriptorPool(scenePipeline);
     1967/*** END OF REFACTORED CODE ***/
    19561968         createDescriptorSets(scenePipeline);
    19571969
     1970/*** START OF REFACTORED CODE ***/
    19581971         createGraphicsPipeline("shaders/overlay-vert.spv", "shaders/overlay-frag.spv", overlayPipeline);
    19591972         createDescriptorPool(overlayPipeline);
     1973/*** END OF REFACTORED CODE ***/
    19601974         createDescriptorSets(overlayPipeline);
    19611975
     
    19631977      }
    19641978
    1965 /*** START OF REFACTORED CODE ***/
    19661979      void cleanup() {
     1980/*** START OF REFACTORED CODE ***/
    19671981         cleanupSwapChain();
    19681982/*** END OF REFACTORED CODE ***/
     
    19741988         vkFreeMemory(device, textureImageMemory, nullptr);
    19751989
    1976          vkDestroyImageView(device, overlayImageView, nullptr);
    1977          vkDestroyImage(device, overlayImage, nullptr);
    1978          vkFreeMemory(device, overlayImageMemory, nullptr);
    1979 
    19801990         vkDestroyImageView(device, sdlOverlayImageView, nullptr);
    19811991         vkDestroyImage(device, sdlOverlayImage, nullptr);
    19821992         vkFreeMemory(device, sdlOverlayImageMemory, nullptr);
    19831993
     1994/*** START OF REFACTORED CODE ***/
    19841995         cleanupPipelineBuffers(scenePipeline);
    19851996         cleanupPipelineBuffers(overlayPipeline);
     1997 /*** END OF REFACTORED CODE ***/
    19861998
    19871999         for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
     
    20012013
    20022014         vkDestroyInstance(instance, nullptr);
    2003 /*** END OF REFACTORED CODE ***/
    20042015
    20052016         // TODO: Check if any of these functions accept null parameters
     
    20102021            uiOverlay = nullptr;
    20112022         }
     2023/*** END OF REFACTORED CODE ***/
    20122024
    20132025         TTF_CloseFont(gFont);
     
    20452057         vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
    20462058
     2059/*** START OF REFACTORED CODE ***/
    20472060         cleanupPipeline(scenePipeline);
    20482061         cleanupPipeline(overlayPipeline);
    20492062
    2050 /*** START OF REFACTORED CODE ***/
    20512063         vkDestroyRenderPass(device, renderPass, nullptr);
    20522064
     
    20622074            vkFreeMemory(device, uniformBuffersMemory[i], nullptr);
    20632075         }
    2064 /*** START OF REFACTORED CODE ***/
    2065       }
    2066 /*** END OF REFACTORED CODE ***/
    2067 
     2076      }
     2077
     2078/*** START OF REFACTORED CODE ***/
    20682079      void cleanupPipeline(GraphicsPipelineInfo& pipeline) {
    20692080         vkDestroyPipeline(device, pipeline.pipeline, nullptr);
     
    20712082         vkDestroyPipelineLayout(device, pipeline.pipelineLayout, nullptr);
    20722083      }
     2084/*** END OF REFACTORED CODE ***/
    20732085
    20742086      void cleanupPipelineBuffers(GraphicsPipelineInfo& pipeline) {
     2087/*** START OF REFACTORED CODE ***/
    20752088         vkDestroyDescriptorSetLayout(device, pipeline.descriptorSetLayout, nullptr);
     2089/*** END OF REFACTORED CODE ***/
    20762090
    20772091         vkDestroyBuffer(device, pipeline.vertexBuffer, nullptr);
  • vulkan-utils.cpp

    r771b33a rb794178  
    44#include <set>
    55#include <stdexcept>
    6 #include <string>
     6
     7#define STB_IMAGE_IMPLEMENTATION
     8#include "stb_image.h" // TODO: Probably switch to SDL_image
     9
     10// TODO: Remove all instances of auto
    711
    812bool VulkanUtils::checkValidationLayerSupport(const vector<const char*> &validationLayers) {
     
    210214   throw runtime_error("failed to find supported format!");
    211215}
     216
     217void VulkanUtils::createBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage,
     218      VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
     219   VkBufferCreateInfo bufferInfo = {};
     220   bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
     221   bufferInfo.size = size;
     222   bufferInfo.usage = usage;
     223   bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
     224
     225   if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
     226      throw runtime_error("failed to create buffer!");
     227   }
     228
     229   VkMemoryRequirements memRequirements;
     230   vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
     231
     232   VkMemoryAllocateInfo allocInfo = {};
     233   allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
     234   allocInfo.allocationSize = memRequirements.size;
     235   allocInfo.memoryTypeIndex = findMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties);
     236
     237   if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
     238      throw runtime_error("failed to allocate buffer memory!");
     239   }
     240
     241   vkBindBufferMemory(device, buffer, bufferMemory, 0);
     242}
     243
     244uint32_t VulkanUtils::findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties) {
     245   VkPhysicalDeviceMemoryProperties memProperties;
     246   vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
     247
     248   for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
     249      if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
     250         return i;
     251      }
     252   }
     253
     254   throw runtime_error("failed to find suitable memory type!");
     255}
     256
     257void VulkanUtils::createVulkanImageFromFile(VkDevice device, VkPhysicalDevice physicalDevice,
     258      VkCommandPool commandPool, string filename, VulkanImage& image, VkQueue graphicsQueue) {
     259   int texWidth, texHeight, texChannels;
     260
     261   stbi_uc* pixels = stbi_load(filename.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
     262   VkDeviceSize imageSize = texWidth * texHeight * 4;
     263
     264   if (!pixels) {
     265      throw runtime_error("failed to load texture image!");
     266   }
     267
     268   VkBuffer stagingBuffer;
     269   VkDeviceMemory stagingBufferMemory;
     270
     271   createBuffer(device, physicalDevice, imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
     272      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
     273      stagingBuffer, stagingBufferMemory);
     274
     275   void* data;
     276
     277   vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data);
     278   memcpy(data, pixels, static_cast<size_t>(imageSize));
     279   vkUnmapMemory(device, stagingBufferMemory);
     280
     281   stbi_image_free(pixels);
     282
     283   createImage(device, physicalDevice, texWidth, texHeight, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL,
     284      VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image);
     285
     286   transitionImageLayout(device, commandPool, image.image, VK_FORMAT_R8G8B8A8_UNORM,
     287      VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, graphicsQueue);
     288   copyBufferToImage(device, commandPool, stagingBuffer, image.image,
     289      static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight), graphicsQueue);
     290   transitionImageLayout(device, commandPool, image.image, VK_FORMAT_R8G8B8A8_UNORM,
     291      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, graphicsQueue);
     292
     293   vkDestroyBuffer(device, stagingBuffer, nullptr);
     294   vkFreeMemory(device, stagingBufferMemory, nullptr);
     295
     296   image.imageView = createImageView(device, image.image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
     297}
     298
     299void VulkanUtils::createVulkanImageFromSDLTexture(VkDevice device, VkPhysicalDevice physicalDevice,
     300      SDL_Texture* texture, VulkanImage& image) {
     301   int a, w, h;
     302
     303   // I only need this here for the width and height, which are constants, so just use those instead
     304   SDL_QueryTexture(texture, nullptr, &a, &w, &h);
     305
     306   createImage(device, physicalDevice, w, h, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL,
     307      VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image);
     308
     309   image.imageView = createImageView(device, image.image, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
     310}
     311
     312void VulkanUtils::createImage(VkDevice device, VkPhysicalDevice physicalDevice, uint32_t width, uint32_t height,
     313      VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties,
     314      VulkanImage& image) {
     315   VkImageCreateInfo imageInfo = {};
     316   imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
     317   imageInfo.imageType = VK_IMAGE_TYPE_2D;
     318   imageInfo.extent.width = width;
     319   imageInfo.extent.height = height;
     320   imageInfo.extent.depth = 1;
     321   imageInfo.mipLevels = 1;
     322   imageInfo.arrayLayers = 1;
     323   imageInfo.format = format;
     324   imageInfo.tiling = tiling;
     325   imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
     326   imageInfo.usage = usage;
     327   imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
     328   imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
     329
     330   if (vkCreateImage(device, &imageInfo, nullptr, &image.image) != VK_SUCCESS) {
     331      throw runtime_error("failed to create image!");
     332   }
     333
     334   VkMemoryRequirements memRequirements;
     335   vkGetImageMemoryRequirements(device, image.image, &memRequirements);
     336
     337   VkMemoryAllocateInfo allocInfo = {};
     338   allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
     339   allocInfo.allocationSize = memRequirements.size;
     340   allocInfo.memoryTypeIndex = findMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties);
     341
     342   if (vkAllocateMemory(device, &allocInfo, nullptr, &image.imageMemory) != VK_SUCCESS) {
     343      throw runtime_error("failed to allocate image memory!");
     344   }
     345
     346   vkBindImageMemory(device, image.image, image.imageMemory, 0);
     347}
     348
     349void VulkanUtils::transitionImageLayout(VkDevice device, VkCommandPool commandPool, VkImage image,
     350      VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, VkQueue graphicsQueue) {
     351   VkCommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
     352
     353   VkImageMemoryBarrier barrier = {};
     354   barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
     355   barrier.oldLayout = oldLayout;
     356   barrier.newLayout = newLayout;
     357   barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     358   barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
     359   barrier.image = image;
     360
     361   if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
     362      barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
     363
     364      if (hasStencilComponent(format)) {
     365         barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
     366      }
     367   } else {
     368      barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
     369   }
     370
     371   barrier.subresourceRange.baseMipLevel = 0;
     372   barrier.subresourceRange.levelCount = 1;
     373   barrier.subresourceRange.baseArrayLayer = 0;
     374   barrier.subresourceRange.layerCount = 1;
     375
     376   VkPipelineStageFlags sourceStage;
     377   VkPipelineStageFlags destinationStage;
     378
     379   if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
     380      barrier.srcAccessMask = 0;
     381      barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
     382
     383      sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
     384      destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
     385   } else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
     386      barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
     387      barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
     388
     389      sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
     390      destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
     391   } else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
     392      barrier.srcAccessMask = 0;
     393      barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
     394
     395      sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
     396      destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
     397   } else {
     398      throw invalid_argument("unsupported layout transition!");
     399   }
     400
     401   vkCmdPipelineBarrier(
     402      commandBuffer,
     403      sourceStage, destinationStage,
     404      0,
     405      0, nullptr,
     406      0, nullptr,
     407      1, &barrier
     408   );
     409
     410   endSingleTimeCommands(device, commandPool, commandBuffer, graphicsQueue);
     411}
     412
     413VkCommandBuffer VulkanUtils::beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool) {
     414   VkCommandBufferAllocateInfo allocInfo = {};
     415   allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
     416   allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
     417   allocInfo.commandPool = commandPool;
     418   allocInfo.commandBufferCount = 1;
     419
     420   VkCommandBuffer commandBuffer;
     421   vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
     422
     423   VkCommandBufferBeginInfo beginInfo = {};
     424   beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
     425   beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
     426
     427   vkBeginCommandBuffer(commandBuffer, &beginInfo);
     428
     429   return commandBuffer;
     430}
     431
     432void VulkanUtils::endSingleTimeCommands(VkDevice device, VkCommandPool commandPool,
     433      VkCommandBuffer commandBuffer, VkQueue graphicsQueue) {
     434   vkEndCommandBuffer(commandBuffer);
     435
     436   VkSubmitInfo submitInfo = {};
     437   submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
     438   submitInfo.commandBufferCount = 1;
     439   submitInfo.pCommandBuffers = &commandBuffer;
     440
     441   vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
     442   vkQueueWaitIdle(graphicsQueue);
     443
     444   vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
     445}
     446
     447void VulkanUtils::copyBufferToImage(VkDevice device, VkCommandPool commandPool, VkBuffer buffer,
     448      VkImage image, uint32_t width, uint32_t height, VkQueue graphicsQueue) {
     449   VkCommandBuffer commandBuffer = beginSingleTimeCommands(device, commandPool);
     450
     451   VkBufferImageCopy region = {};
     452   region.bufferOffset = 0;
     453   region.bufferRowLength = 0;
     454   region.bufferImageHeight = 0;
     455   region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
     456   region.imageSubresource.mipLevel = 0;
     457   region.imageSubresource.baseArrayLayer = 0;
     458   region.imageSubresource.layerCount = 1;
     459   region.imageOffset = { 0, 0, 0 };
     460   region.imageExtent = { width, height, 1 };
     461
     462   vkCmdCopyBufferToImage(
     463      commandBuffer,
     464      buffer,
     465      image,
     466      VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
     467      1,
     468      &region
     469   );
     470
     471   endSingleTimeCommands(device, commandPool, commandBuffer, graphicsQueue);
     472}
     473
     474bool VulkanUtils::hasStencilComponent(VkFormat format) {
     475   return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
     476}
  • vulkan-utils.hpp

    r771b33a rb794178  
    33
    44#include <optional>
     5#include <string>
    56#include <vector>
    67
    78#include <vulkan/vulkan.h>
     9
     10#include <SDL2/SDL.h>
     11#include <SDL2/SDL_image.h>
     12#include <SDL2/SDL_vulkan.h>
    813
    914using namespace std;
     
    2429};
    2530
     31struct VulkanImage {
     32   VkImage image;
     33   VkDeviceMemory imageMemory;
     34   VkImageView imageView;
     35};
     36
    2637class VulkanUtils {
    2738   public:
     
    3849
    3950      static QueueFamilyIndices findQueueFamilies(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface);
    40       static bool checkDeviceExtensionSupport(VkPhysicalDevice physicalDevice, const vector<const char*>& deviceExtensions);
    41       static SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface);
     51      static bool checkDeviceExtensionSupport(VkPhysicalDevice physicalDevice,
     52            const vector<const char*>& deviceExtensions);
     53      static SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice physicalDevice,
     54            VkSurfaceKHR surface);
    4255      static VkSurfaceFormatKHR chooseSwapSurfaceFormat(const vector<VkSurfaceFormatKHR>& availableFormats);
    4356      static VkPresentModeKHR chooseSwapPresentMode(const vector<VkPresentModeKHR>& availablePresentModes);
    4457      static VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, int width, int height);
    45       static VkImageView createImageView(VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags);
     58      static VkImageView createImageView(VkDevice device, VkImage image, VkFormat format,
     59            VkImageAspectFlags aspectFlags);
    4660      static VkFormat findSupportedFormat(VkPhysicalDevice physicalDevice, const vector<VkFormat>& candidates,
    4761            VkImageTiling tiling, VkFormatFeatureFlags features);
     62      static void createBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size,
     63            VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer,
     64            VkDeviceMemory& bufferMemory);
     65      static uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter,
     66            VkMemoryPropertyFlags properties);
     67
     68      static void createVulkanImageFromFile(VkDevice device, VkPhysicalDevice physicalDevice,
     69            VkCommandPool commandPool, string filename, VulkanImage& image, VkQueue graphicsQueue);
     70      static void createVulkanImageFromSDLTexture(VkDevice device, VkPhysicalDevice physicalDevice,
     71            SDL_Texture* texture, VulkanImage& image);
     72      static void createImage(VkDevice device, VkPhysicalDevice physicalDevice, uint32_t width, uint32_t height,
     73            VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties,
     74            VulkanImage& image);
     75
     76      static void transitionImageLayout(VkDevice device, VkCommandPool commandPool, VkImage image,
     77            VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, VkQueue graphicsQueue);
     78      static VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool);
     79      static void endSingleTimeCommands(VkDevice device, VkCommandPool commandPool,
     80            VkCommandBuffer commandBuffer, VkQueue graphicsQueue);
     81      static void copyBufferToImage(VkDevice device, VkCommandPool commandPool, VkBuffer buffer, VkImage image,
     82            uint32_t width, uint32_t height, VkQueue graphicsQueue);
     83
     84      static bool hasStencilComponent(VkFormat format);
    4885};
    4986
Note: See TracChangeset for help on using the changeset viewer.