/** Vulkan Example - Texture arrays and instanced rendering** Copyright (C) 2016 by Sascha Willems - www.saschawillems.de** This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <time.h>#include <vector>#define GLM_FORCE_RADIANS#define GLM_FORCE_DEPTH_ZERO_TO_ONE#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>#include <vulkan/vulkan.h>#include "vulkanexamplebase.h"#include "VulkanTexture.hpp"#include "VulkanBuffer.hpp"#define VERTEX_BUFFER_BIND_ID 0#define ENABLE_VALIDATION false// Vertex layout for this examplestruct Vertex {float pos[3];float uv[2];};class VulkanExample : public VulkanExampleBase{public:// Number of array layers in texture array// Also used as instance countuint32_t layerCount;vks::Texture textureArray;struct {VkPipelineVertexInputStateCreateInfo inputState;std::vector<VkVertexInputBindingDescription> bindingDescriptions;std::vector<VkVertexInputAttributeDescription> attributeDescriptions;} vertices;vks::Buffer vertexBuffer;vks::Buffer indexBuffer;uint32_t indexCount;vks::Buffer uniformBufferVS;struct UboInstanceData {// Model matrixglm::mat4 model;// Texture array index// Vec4 due to paddingglm::vec4 arrayIndex;};struct {// Global matricesstruct {glm::mat4 projection;glm::mat4 view;} matrices;// Seperate data for each instanceUboInstanceData *instance;} uboVS;VkPipeline pipeline;VkPipelineLayout pipelineLayout;VkDescriptorSet descriptorSet;VkDescriptorSetLayout descriptorSetLayout;VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION){zoom = -15.0f;rotationSpeed = 0.25f;rotation = { -15.0f, 35.0f, 0.0f };title = "Texture arrays";settings.overlay = true;}~VulkanExample(){// Clean up used Vulkan resources// Note : Inherited destructor cleans up resources stored in base class// Clean up texture resourcesvkDestroyImageView(device, textureArray.view, nullptr);vkDestroyImage(device, textureArray.image, nullptr);vkDestroySampler(device, textureArray.sampler, nullptr);vkFreeMemory(device, textureArray.deviceMemory, nullptr);vkDestroyPipeline(device, pipeline, nullptr);vkDestroyPipelineLayout(device, pipelineLayout, nullptr);vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);vertexBuffer.destroy();indexBuffer.destroy();uniformBufferVS.destroy();delete[] uboVS.instance;}void loadTextureArray(std::string filename, VkFormat format){#if defined(__ANDROID__)// Textures are stored inside the apk on Android (compressed)// So they need to be loaded via the asset managerAAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);assert(asset);size_t size = AAsset_getLength(asset);assert(size > 0);void *textureData = malloc(size);AAsset_read(asset, textureData, size);AAsset_close(asset);gli::texture2d_array tex2DArray(gli::load((const char*)textureData, size));#elsegli::texture2d_array tex2DArray(gli::load(filename));#endifassert(!tex2DArray.empty());textureArray.width = tex2DArray.extent().x;textureArray.height = tex2DArray.extent().y;layerCount = tex2DArray.layers();VkMemoryAllocateInfo memAllocInfo = vks::initializers::memoryAllocateInfo();VkMemoryRequirements memReqs;// Create a host-visible staging buffer that contains the raw image dataVkBuffer stagingBuffer;VkDeviceMemory stagingMemory;VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo();bufferCreateInfo.size = tex2DArray.size();// This buffer is used as a transfer source for the buffer copybufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;VK_CHECK_RESULT(vkCreateBuffer(device, &bufferCreateInfo, nullptr, &stagingBuffer));// Get memory requirements for the staging buffer (alignment, memory type bits)vkGetBufferMemoryRequirements(device, stagingBuffer, &memReqs);memAllocInfo.allocationSize = memReqs.size;// Get memory type index for a host visible buffermemAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &stagingMemory));VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffer, stagingMemory, 0));// Copy texture data into staging bufferuint8_t *data;VK_CHECK_RESULT(vkMapMemory(device, stagingMemory, 0, memReqs.size, 0, (void **)&data));memcpy(data, tex2DArray.data(), tex2DArray.size());vkUnmapMemory(device, stagingMemory);// Setup buffer copy regions for array layersstd::vector<VkBufferImageCopy> bufferCopyRegions;size_t offset = 0;for (uint32_t layer = 0; layer < layerCount; layer++){VkBufferImageCopy bufferCopyRegion = {};bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;bufferCopyRegion.imageSubresource.mipLevel = 0;bufferCopyRegion.imageSubresource.baseArrayLayer = layer;bufferCopyRegion.imageSubresource.layerCount = 1;bufferCopyRegion.imageExtent.width = static_cast<uint32_t>(tex2DArray[layer][0].extent().x);bufferCopyRegion.imageExtent.height = static_cast<uint32_t>(tex2DArray[layer][0].extent().y);bufferCopyRegion.imageExtent.depth = 1;bufferCopyRegion.bufferOffset = offset;bufferCopyRegions.push_back(bufferCopyRegion);// Increase offset into staging buffer for next level / faceoffset += tex2DArray[layer][0].size();}// Create optimal tiled target imageVkImageCreateInfo imageCreateInfo = vks::initializers::imageCreateInfo();imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;imageCreateInfo.format = format;imageCreateInfo.mipLevels = 1;imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;imageCreateInfo.extent = { textureArray.width, textureArray.height, 1 };imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;imageCreateInfo.arrayLayers = layerCount;VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &textureArray.image));vkGetImageMemoryRequirements(device, textureArray.image, &memReqs);memAllocInfo.allocationSize = memReqs.size;memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &textureArray.deviceMemory));VK_CHECK_RESULT(vkBindImageMemory(device, textureArray.image, textureArray.deviceMemory, 0));VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);// Image barrier for optimal image (target)// Set initial layout for all array layers (faces) of the optimal (target) tiled textureVkImageSubresourceRange subresourceRange = {};subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;subresourceRange.baseMipLevel = 0;subresourceRange.levelCount = 1;subresourceRange.layerCount = layerCount;vks::tools::setImageLayout(copyCmd,textureArray.image,VK_IMAGE_LAYOUT_UNDEFINED,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,subresourceRange);// Copy the cube map faces from the staging buffer to the optimal tiled imagevkCmdCopyBufferToImage(copyCmd,stagingBuffer,textureArray.image,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,bufferCopyRegions.size(),bufferCopyRegions.data());// Change texture image layout to shader read after all faces have been copiedtextureArray.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;vks::tools::setImageLayout(copyCmd,textureArray.image,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,textureArray.imageLayout,subresourceRange);VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);// Create samplerVkSamplerCreateInfo sampler = vks::initializers::samplerCreateInfo();sampler.magFilter = VK_FILTER_LINEAR;sampler.minFilter = VK_FILTER_LINEAR;sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;sampler.addressModeV = sampler.addressModeU;sampler.addressModeW = sampler.addressModeU;sampler.mipLodBias = 0.0f;sampler.maxAnisotropy = 8;sampler.compareOp = VK_COMPARE_OP_NEVER;sampler.minLod = 0.0f;sampler.maxLod = 0.0f;sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &textureArray.sampler));// Create image viewVkImageViewCreateInfo view = vks::initializers::imageViewCreateInfo();view.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;view.format = format;view.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };view.subresourceRange.layerCount = layerCount;view.subresourceRange.levelCount = 1;view.image = textureArray.image;VK_CHECK_RESULT(vkCreateImageView(device, &view, nullptr, &textureArray.view));// Clean up staging resourcesvkFreeMemory(device, stagingMemory, nullptr);vkDestroyBuffer(device, stagingBuffer, nullptr);}void loadTextures(){// Vulkan core supports three different compressed texture formats// As the support differs between implemementations we need to check device features and select a proper format and filestd::string filename;VkFormat format;if (deviceFeatures.textureCompressionBC) {filename = "texturearray_bc3_unorm.ktx";format = VK_FORMAT_BC3_UNORM_BLOCK;}else if (deviceFeatures.textureCompressionASTC_LDR) {filename = "texturearray_astc_8x8_unorm.ktx";format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK;}else if (deviceFeatures.textureCompressionETC2) {filename = "texturearray_etc2_unorm.ktx";format = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;}else {vks::tools::exitFatal("Device does not support any compressed texture format!", VK_ERROR_FEATURE_NOT_PRESENT);}loadTextureArray(getAssetPath() + "textures/" + filename, format);}void buildCommandBuffers(){VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();VkClearValue clearValues[2];clearValues[0].color = defaultClearColor;clearValues[1].depthStencil = { 1.0f, 0 };VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();renderPassBeginInfo.renderPass = renderPass;renderPassBeginInfo.renderArea.offset.x = 0;renderPassBeginInfo.renderArea.offset.y = 0;renderPassBeginInfo.renderArea.extent.width = width;renderPassBeginInfo.renderArea.extent.height = height;renderPassBeginInfo.clearValueCount = 2;renderPassBeginInfo.pClearValues = clearValues;for (int32_t i = 0; i < drawCmdBuffers.size(); ++i){// Set target frame bufferrenderPassBeginInfo.framebuffer = frameBuffers[i];VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, NULL);vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);VkDeviceSize offsets[1] = { 0 };vkCmdBindVertexBuffers(drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, &vertexBuffer.buffer, offsets);vkCmdBindIndexBuffer(drawCmdBuffers[i], indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32);vkCmdDrawIndexed(drawCmdBuffers[i], indexCount, layerCount, 0, 0, 0);vkCmdEndRenderPass(drawCmdBuffers[i]);VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));}}void generateQuad(){// Setup vertices for a single uv-mapped quad made from two trianglesstd::vector<Vertex> vertices ={{ { 2.5f, 2.5f, 0.0f }, { 1.0f, 1.0f } },{ { -2.5f, 2.5f, 0.0f }, { 0.0f, 1.0f } },{ { -2.5f, -2.5f, 0.0f }, { 0.0f, 0.0f } },{ { 2.5f, -2.5f, 0.0f }, { 1.0f, 0.0f } }};// Setup indicesstd::vector<uint32_t> indices = { 0,1,2, 2,3,0 };indexCount = static_cast<uint32_t>(indices.size());// Create buffers// For the sake of simplicity we won't stage the vertex data to the gpu memory// Vertex bufferVK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,&vertexBuffer,vertices.size() * sizeof(Vertex),vertices.data()));// Index bufferVK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,&indexBuffer,indices.size() * sizeof(uint32_t),indices.data()));}void setupVertexDescriptions(){// Binding descriptionvertices.bindingDescriptions.resize(1);vertices.bindingDescriptions[0] =vks::initializers::vertexInputBindingDescription(VERTEX_BUFFER_BIND_ID,sizeof(Vertex),VK_VERTEX_INPUT_RATE_VERTEX);// Attribute descriptions// Describes memory layout and shader positionsvertices.attributeDescriptions.resize(2);// Location 0 : Positionvertices.attributeDescriptions[0] =vks::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID,0,VK_FORMAT_R32G32B32_SFLOAT,0);// Location 1 : Texture coordinatesvertices.attributeDescriptions[1] =vks::initializers::vertexInputAttributeDescription(VERTEX_BUFFER_BIND_ID,1,VK_FORMAT_R32G32_SFLOAT,sizeof(float) * 3);vertices.inputState = vks::initializers::pipelineVertexInputStateCreateInfo();vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size();vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data();vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size();vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data();}void setupDescriptorPool(){std::vector<VkDescriptorPoolSize> poolSizes ={vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1)};VkDescriptorPoolCreateInfo descriptorPoolInfo =vks::initializers::descriptorPoolCreateInfo(poolSizes.size(),poolSizes.data(),2);VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));}void setupDescriptorSetLayout(){std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings ={// Binding 0 : Vertex shader uniform buffervks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,VK_SHADER_STAGE_VERTEX_BIT,0),// Binding 1 : Fragment shader image sampler (texture array)vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,VK_SHADER_STAGE_FRAGMENT_BIT,1)};VkDescriptorSetLayoutCreateInfo descriptorLayout =vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings.data(),setLayoutBindings.size());VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout,1);VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout));}void setupDescriptorSet(){VkDescriptorSetAllocateInfo allocInfo =vks::initializers::descriptorSetAllocateInfo(descriptorPool,&descriptorSetLayout,1);VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));// Image descriptor for the texture arrayVkDescriptorImageInfo textureDescriptor =vks::initializers::descriptorImageInfo(textureArray.sampler,textureArray.view,textureArray.imageLayout);std::vector<VkWriteDescriptorSet> writeDescriptorSets ={// Binding 0 : Vertex shader uniform buffervks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,0,&uniformBufferVS.descriptor),// Binding 1 : Fragment shader cubemap samplervks::initializers::writeDescriptorSet(descriptorSet,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,1,&textureDescriptor)};vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL);}void preparePipelines(){VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,0,VK_FALSE);VkPipelineRasterizationStateCreateInfo rasterizationState =vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL,VK_CULL_MODE_NONE,VK_FRONT_FACE_COUNTER_CLOCKWISE,0);VkPipelineColorBlendAttachmentState blendAttachmentState =vks::initializers::pipelineColorBlendAttachmentState(0xf,VK_FALSE);VkPipelineColorBlendStateCreateInfo colorBlendState =vks::initializers::pipelineColorBlendStateCreateInfo(1,&blendAttachmentState);VkPipelineDepthStencilStateCreateInfo depthStencilState =vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE,VK_TRUE,VK_COMPARE_OP_LESS_OR_EQUAL);VkPipelineViewportStateCreateInfo viewportState =vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0);VkPipelineMultisampleStateCreateInfo multisampleState =vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT,0);std::vector<VkDynamicState> dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT,VK_DYNAMIC_STATE_SCISSOR};VkPipelineDynamicStateCreateInfo dynamicState =vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables.data(),dynamicStateEnables.size(),0);// Instacing pipeline// Load shadersstd::array<VkPipelineShaderStageCreateInfo, 2> shaderStages;shaderStages[0] = loadShader(getAssetPath() + "shaders/texturearray/instancing.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);shaderStages[1] = loadShader(getAssetPath() + "shaders/texturearray/instancing.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);VkGraphicsPipelineCreateInfo pipelineCreateInfo =vks::initializers::pipelineCreateInfo(pipelineLayout,renderPass,0);pipelineCreateInfo.pVertexInputState = &vertices.inputState;pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;pipelineCreateInfo.pRasterizationState = &rasterizationState;pipelineCreateInfo.pColorBlendState = &colorBlendState;pipelineCreateInfo.pMultisampleState = &multisampleState;pipelineCreateInfo.pViewportState = &viewportState;pipelineCreateInfo.pDepthStencilState = &depthStencilState;pipelineCreateInfo.pDynamicState = &dynamicState;pipelineCreateInfo.stageCount = shaderStages.size();pipelineCreateInfo.pStages = shaderStages.data();VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipeline));}void prepareUniformBuffers(){uboVS.instance = new UboInstanceData[layerCount];uint32_t uboSize = sizeof(uboVS.matrices) + (layerCount * sizeof(UboInstanceData));// Vertex shader uniform buffer blockVK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,&uniformBufferVS,uboSize));// Array indices and model matrices are fixedfloat offset = -1.5f;float center = (layerCount*offset) / 2;for (int32_t i = 0; i < layerCount; i++){// Instance model matrixuboVS.instance[i].model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, i * offset - center, 0.0f));uboVS.instance[i].model = glm::rotate(uboVS.instance[i].model, glm::radians(60.0f), glm::vec3(1.0f, 0.0f, 0.0f));// Instance texture array indexuboVS.instance[i].arrayIndex.x = i;}// Update instanced part of the uniform bufferuint8_t *pData;uint32_t dataOffset = sizeof(uboVS.matrices);uint32_t dataSize = layerCount * sizeof(UboInstanceData);VK_CHECK_RESULT(vkMapMemory(device, uniformBufferVS.memory, dataOffset, dataSize, 0, (void **)&pData));memcpy(pData, uboVS.instance, dataSize);vkUnmapMemory(device, uniformBufferVS.memory);// Map persistentVK_CHECK_RESULT(uniformBufferVS.map());updateUniformBufferMatrices();}void updateUniformBufferMatrices(){// Only updates the uniform buffer block part containing the global matrices// ProjectionuboVS.matrices.projection = glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.001f, 256.0f);// ViewuboVS.matrices.view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -1.0f, zoom));uboVS.matrices.view = glm::rotate(uboVS.matrices.view, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));uboVS.matrices.view = glm::rotate(uboVS.matrices.view, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));uboVS.matrices.view = glm::rotate(uboVS.matrices.view, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));// Only update the matrices part of the uniform buffermemcpy(uniformBufferVS.mapped, &uboVS.matrices, sizeof(uboVS.matrices));}void draw(){VulkanExampleBase::prepareFrame();submitInfo.commandBufferCount = 1;submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));VulkanExampleBase::submitFrame();}void prepare(){VulkanExampleBase::prepare();loadTextures();setupVertexDescriptions();generateQuad();prepareUniformBuffers();setupDescriptorSetLayout();preparePipelines();setupDescriptorPool();setupDescriptorSet();buildCommandBuffers();prepared = true;}virtual void render(){if (!prepared)return;draw();}virtual void viewChanged(){updateUniformBufferMatrices();}};VULKAN_EXAMPLE_MAIN()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。