// Fixed sub resource on first mip level and layer static void setImageLayout( vk::CommandBuffer cmdbuffer, vk::Image image, vk::ImageAspectFlags aspectMask, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout) { vk::ImageSubresourceRange subresourceRange; subresourceRange.aspectMask = aspectMask; subresourceRange.baseMipLevel = 0; subresourceRange.levelCount = 1; subresourceRange.layerCount = 1; setImageLayout(cmdbuffer, image, aspectMask, oldImageLayout, newImageLayout, subresourceRange); }
// Fixed sub resource on first mip level and layer void setImageLayout( VkCommandBuffer cmdbuffer, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout) { VkImageSubresourceRange subresourceRange = {}; subresourceRange.aspectMask = aspectMask; subresourceRange.baseMipLevel = 0; subresourceRange.levelCount = 1; subresourceRange.layerCount = 1; setImageLayout(cmdbuffer, image, aspectMask, oldImageLayout, newImageLayout, subresourceRange); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void WritePoleFigure::readFilterParameters(AbstractFilterParametersReader* reader, int index) { reader->openFilterGroup(this, index); setGoodVoxelsArrayPath(reader->readDataArrayPath("GoodVoxelsArrayPath", getGoodVoxelsArrayPath() ) ); setCrystalStructuresArrayPath(reader->readDataArrayPath("CrystalStructuresArrayPath", getCrystalStructuresArrayPath() ) ); setCellPhasesArrayPath(reader->readDataArrayPath("CellPhasesArrayPath", getCellPhasesArrayPath() ) ); setCellEulerAnglesArrayPath(reader->readDataArrayPath("CellEulerAnglesArrayPath", getCellEulerAnglesArrayPath() ) ); setImagePrefix( reader->readString("ImagePrefix", getImagePrefix())); setOutputPath( reader->readString("OutputPath", getOutputPath())); setImageFormat( reader->readValue("ImageFormat", getImageFormat())); setImageLayout( reader->readValue("ImageLayout", getImageLayout())); setImageSize( reader->readValue("ImageSize", getImageSize())); setLambertSize( reader->readValue("LambertSize", getLambertSize())); reader->closeFilterGroup(); }
// Fixed sub resource on first mip level and layer void setImageLayout( VkCommandBuffer cmdbuffer, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask) { VkImageSubresourceRange subresourceRange = {}; subresourceRange.aspectMask = aspectMask; subresourceRange.baseMipLevel = 0; subresourceRange.levelCount = 1; subresourceRange.layerCount = 1; setImageLayout(cmdbuffer, image, oldImageLayout, newImageLayout, subresourceRange, srcStageMask, dstStageMask); }
bool initSwapChains() { std::cout << "initing swapchain..."; if( !getSurfaceFormats() || !getSurfacePresentModes() ) { return false; } VkResult res; res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( gDevices[0], gSurface, &gSurfaceCaps ); if( res != VK_SUCCESS ) { std::cout << "error getting surface capabilities\n"; } VkExtent2D swapChainExtent = gSurfaceCaps.currentExtent; if( std::find( gPresentModes.begin(), gPresentModes.end(), VK_PRESENT_MODE_MAILBOX_KHR ) != gPresentModes.end() ) gPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; else if( std::find( gPresentModes.begin(), gPresentModes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR ) != gPresentModes.end() ) gPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; else gPresentMode = VK_PRESENT_MODE_FIFO_KHR; uint32_t desiredNumberOfSwapChainImages = gSurfaceCaps.minImageCount + 1; desiredNumberOfSwapChainImages = gSurfaceCaps.maxImageCount ? max( desiredNumberOfSwapChainImages, gSurfaceCaps.maxImageCount ) : desiredNumberOfSwapChainImages; VkSurfaceTransformFlagBitsKHR preTransform; preTransform = gSurfaceCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : gSurfaceCaps.currentTransform; VkSwapchainCreateInfoKHR swapChain = {}; swapChain.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapChain.pNext = nullptr; swapChain.surface = gSurface; swapChain.minImageCount = desiredNumberOfSwapChainImages; swapChain.imageFormat = gFormat; swapChain.imageExtent = swapChainExtent; swapChain.preTransform = preTransform; swapChain.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapChain.imageArrayLayers = 1; swapChain.presentMode = gPresentMode; swapChain.oldSwapchain = NULL; swapChain.clipped = true; swapChain.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; swapChain.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapChain.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapChain.queueFamilyIndexCount = 0; swapChain.pQueueFamilyIndices = nullptr; res = vkCreateSwapchainKHR( gDevice, &swapChain, nullptr, &gSwapchain ); if( res != VK_SUCCESS ) { std::cout << "error creating swapchain "<< res << std::endl; return false; } std::vector<VkImage> images; u32 imagesCount = 0; HR( vkGetSwapchainImagesKHR(gDevice, gSwapchain, &imagesCount, nullptr ) ); images.resize( imagesCount ); HR( vkGetSwapchainImagesKHR(gDevice, gSwapchain, &imagesCount, images.data() ) ); beginCommandBuffer( gCmd ); vkGetDeviceQueue( gDevice, gQueueFamilyIndex, 0, &gQueue ); gSwapBuffers.resize( imagesCount ); for( u32 i = 0; i < gSwapBuffers.size(); ++i ) { VkImageViewCreateInfo imageView = {}; imageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageView.pNext = nullptr; imageView.format = gFormat; imageView.components.r = VK_COMPONENT_SWIZZLE_R; imageView.components.g = VK_COMPONENT_SWIZZLE_G; imageView.components.b = VK_COMPONENT_SWIZZLE_B; imageView.components.a = VK_COMPONENT_SWIZZLE_A; imageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageView.subresourceRange.baseMipLevel = 0; imageView.subresourceRange.levelCount = 1; imageView.subresourceRange.baseArrayLayer = 0; imageView.subresourceRange.layerCount = 1; imageView.viewType = VK_IMAGE_VIEW_TYPE_2D; imageView.flags = 0; imageView.image = images[i]; setImageLayout( gCmd, gSwapBuffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ); HR( vkCreateImageView( gDevice, &imageView, nullptr, &gSwapBuffers[i].view ) ); } endCommandBuffer( gCmd ); executeQueue( gCmd ); std::cout << "inited\n"; return true; }
int XdevLSwapChainVulkan::create(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height) { VkResult result; VkSwapchainKHR oldSwapchain = m_swapChain; // Get physical device surface properties and formats. VkSurfaceCapabilitiesKHR surfCaps; result = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &surfCaps); if(VK_SUCCESS != result) { std::cerr << "vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } // ------------------------------------------------------------------------- // Get available present modes. // // Get the number of modes. uint32_t presentModeCount; result = fpGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr); if(VK_SUCCESS != result) { std::cerr << "vkGetPhysicalDeviceSurfacePresentModesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } // Use the number of modes and create an array of modes. std::vector<VkPresentModeKHR> presentModes(presentModeCount); result = fpGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, presentModes.data()); if(VK_SUCCESS != result) { std::cerr << "vkGetPhysicalDeviceSurfacePresentModesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } // ------------------------------------------------------------------------- VkExtent2D swapchainExtent = {}; // width and height are either both -1, or both not -1. if(surfCaps.currentExtent.width == UINT32_MAX) { // If the surface size is undefined, the size is set to // the size of the images requested. swapchainExtent.width = *width; swapchainExtent.height = *height; } else { // If the surface size is defined, the swap chain size must match swapchainExtent = surfCaps.currentExtent; *width = surfCaps.currentExtent.width; *height = surfCaps.currentExtent.height; } VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; for(size_t i = 0; i < presentModeCount; i++) { if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } if((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) { swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } } // Determine the number of images uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1; if((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount)) { desiredNumberOfSwapchainImages = surfCaps.maxImageCount; } VkSurfaceTransformFlagsKHR preTransform; if(surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; } else { preTransform = surfCaps.currentTransform; } VkSwapchainCreateInfoKHR swapchainCI = {}; swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCI.pNext = NULL; swapchainCI.surface = m_surface; swapchainCI.minImageCount = desiredNumberOfSwapchainImages; swapchainCI.imageFormat = m_colorFormat; swapchainCI.imageColorSpace = m_colorSpace; swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height }; swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform; swapchainCI.imageArrayLayers = 1; swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainCI.queueFamilyIndexCount = 0; swapchainCI.pQueueFamilyIndices = NULL; swapchainCI.presentMode = swapchainPresentMode; swapchainCI.oldSwapchain = oldSwapchain; swapchainCI.clipped = true; swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // If we recreate a SwapChain we have to destroy the previous one. // Note: destroying the swapchain also cleans up all its associated // presentable images once the platform is done with them. if(m_oldSwapChain != VK_NULL_HANDLE) { fpDestroySwapchainKHR(m_device, m_oldSwapChain, nullptr); } result = fpCreateSwapchainKHR(m_device, &swapchainCI, nullptr, &m_swapChain); if(VK_SUCCESS != result) { std::cerr << "vkCreateSwapchainKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } result = fpGetSwapchainImagesKHR(m_device, m_swapChain, &m_imageCount, nullptr); if(VK_SUCCESS != result) { std::cerr << "vkGetSwapchainImagesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } m_images.reserve(m_imageCount); m_images.resize(m_imageCount); result = fpGetSwapchainImagesKHR(m_device, m_swapChain, &m_imageCount, m_images.data()); if(VK_SUCCESS != result) { std::cerr << "vkGetSwapchainImagesKHR failed: " << vkVkResultToString(result) << std::endl; return 1; } m_buffers.reserve(m_imageCount); m_buffers.resize(m_imageCount); for(uint32_t i = 0; i < m_imageCount; i++) { VkImageViewCreateInfo colorAttachmentView = {}; colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; colorAttachmentView.pNext = NULL; colorAttachmentView.format = m_colorFormat; colorAttachmentView.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; colorAttachmentView.subresourceRange.baseMipLevel = 0; colorAttachmentView.subresourceRange.levelCount = 1; colorAttachmentView.subresourceRange.baseArrayLayer = 0; colorAttachmentView.subresourceRange.layerCount = 1; colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D; colorAttachmentView.flags = 0; m_buffers[i].image = m_images[i]; // Transform images from initial (undefined) to present layout setImageLayout( cmdBuffer, m_buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); colorAttachmentView.image = m_buffers[i].image; result = vkCreateImageView(m_device, &colorAttachmentView, nullptr, &m_buffers[i].view); assert(!result); } return 0; }
void vkImageBase::createMipLevels(VkFormatProperties formatProperties, VulkanRenderer *vk_renderer, VkCommandBufferBeginInfo setupCmdsBeginInfo, std::vector<VkBufferImageCopy> &bufferCopyRegions, int mipLevels, std::vector<ImageInfo> &bitmapInfos, VkImageMemoryBarrier imageMemoryBarrier, VkSubmitInfo submit_info, VkCommandBuffer *buffers, VkQueue queue) { assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT); assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT); VkCommandBuffer blitCmd; vk_renderer->initCmdBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, blitCmd); vkResetCommandBuffer(blitCmd, 0); // Begin recording to the command buffer. vkBeginCommandBuffer(blitCmd, &setupCmdsBeginInfo); // Copy down mips from n-1 to n for(int j=0; j< bufferCopyRegions.size(); j++) { for (int32_t i = 1; i < mipLevels; i++) { VkImageBlit imageBlit{}; // Source imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageBlit.srcSubresource.layerCount = 1; imageBlit.srcSubresource.mipLevel = i-1; imageBlit.srcSubresource.baseArrayLayer = j; imageBlit.srcOffsets[1].x = int32_t(bitmapInfos[j].width >> (i - 1)) == 0 ? 1 : int32_t(bitmapInfos[j].width >> (i - 1)); imageBlit.srcOffsets[1].y = int32_t(bitmapInfos[j].height >> (i - 1)) == 0 ? 1 : int32_t(bitmapInfos[j].height >> (i - 1)); imageBlit.srcOffsets[1].z = 1; // Destination imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageBlit.dstSubresource.layerCount = 1; imageBlit.dstSubresource.baseArrayLayer = j; imageBlit.dstSubresource.mipLevel = i; imageBlit.dstOffsets[1].x = int32_t(bitmapInfos[j].width >> i) == 0 ? 1 : int32_t(bitmapInfos[j].width >> i); imageBlit.dstOffsets[1].y = int32_t(bitmapInfos[j].height >> i) == 0 ? 1 : int32_t(bitmapInfos[j].height >> i); imageBlit.dstOffsets[1].z = 1; VkImageMemoryBarrier imageMemoryBarrier = {}; imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; imageMemoryBarrier.pNext = NULL; imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageMemoryBarrier.subresourceRange.baseMipLevel = i; imageMemoryBarrier.subresourceRange.levelCount = 1; imageMemoryBarrier.subresourceRange.baseArrayLayer = j; imageMemoryBarrier.subresourceRange.layerCount = 1; // change layout of current mip level to transfer dest setImageLayout(imageMemoryBarrier, blitCmd, imageHandle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageMemoryBarrier.subresourceRange, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT); // Do blit operation from previous mip level vkCmdBlitImage( blitCmd, imageHandle, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_LINEAR); // change layout of current mip level to source for next iteration setImageLayout(imageMemoryBarrier, blitCmd, imageHandle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageMemoryBarrier.subresourceRange, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); } } // Change layout of all mip levels to shader read imageMemoryBarrier.subresourceRange.levelCount = mipLevels; setImageLayout(imageMemoryBarrier, blitCmd, imageHandle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageLayout, imageMemoryBarrier.subresourceRange); // We are finished recording operations. vkEndCommandBuffer(blitCmd); buffers[0] = blitCmd; submit_info.pCommandBuffers = &buffers[0]; // Submit to our shared graphics queue. VkResult err = vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); assert(!err); // Wait for the queue to become idle. err = vkQueueWaitIdle(queue); assert(!err); }
void vkImageBase::updateMipVkImage(uint64_t texSize, std::vector<void *> &pixels, std::vector<ImageInfo> &bitmapInfos, std::vector<VkBufferImageCopy> &bufferCopyRegions, VkImageViewType target, VkFormat internalFormat, int mipLevels, VkImageCreateFlags flags) { VkResult err; bool pass; VulkanRenderer *vk_renderer = static_cast<VulkanRenderer *>(Renderer::getInstance()); VkDevice device = vk_renderer->getDevice(); VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(vk_renderer->getPhysicalDevice(), internalFormat, &formatProperties); VkBuffer texBuffer; VkDeviceMemory texMemory; VkMemoryAllocateInfo memoryAllocateInfo = {}; memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; memoryAllocateInfo.pNext = NULL; memoryAllocateInfo.allocationSize = 0; memoryAllocateInfo.memoryTypeIndex = 0; err = vkCreateBuffer(device, gvr::BufferCreateInfo(texSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT), nullptr, &texBuffer); GVR_VK_CHECK(!err); // Obtain the requirements on memory for this buffer VkMemoryRequirements mem_reqs; vkGetBufferMemoryRequirements(device, texBuffer, &mem_reqs); assert(!err); memoryAllocateInfo.allocationSize = mem_reqs.size; pass = vk_renderer->GetMemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memoryAllocateInfo.memoryTypeIndex); assert(pass); size = mem_reqs.size; err = vkAllocateMemory(device, gvr::MemoryAllocateInfo(mem_reqs.size, memoryAllocateInfo.memoryTypeIndex), NULL, &texMemory); unsigned char *texData; err = vkMapMemory(device, texMemory, 0, memoryAllocateInfo.allocationSize, 0, (void **) &texData); assert(!err); int i = 0; for (auto &buffer_copy_region: bufferCopyRegions) { memcpy(texData + buffer_copy_region.bufferOffset, pixels[i], bitmapInfos[i].size); i++; } vkUnmapMemory(device, texMemory); // Bind our buffer to the memory err = vkBindBufferMemory(device, texBuffer, texMemory, 0); assert(!err); err = vkCreateImage(device, gvr::ImageCreateInfo(VK_IMAGE_TYPE_2D, internalFormat, bitmapInfos[0].width, bitmapInfos[0].height, 1, mipLevels, pixels.size(), VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, flags, getVKSampleBit(mSampleCount), VK_IMAGE_LAYOUT_UNDEFINED), NULL, &imageHandle); assert(!err); vkGetImageMemoryRequirements(device, imageHandle, &mem_reqs); memoryAllocateInfo.allocationSize = mem_reqs.size; pass = vk_renderer->GetMemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memoryAllocateInfo.memoryTypeIndex); assert(pass); /* allocate memory */ err = vkAllocateMemory(device, &memoryAllocateInfo, NULL, &device_memory); assert(!err); /* bind memory */ err = vkBindImageMemory(device, imageHandle, device_memory, 0); assert(!err); // Reset the setup command buffer VkCommandBuffer textureCmdBuffer; vk_renderer->initCmdBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, textureCmdBuffer); vkResetCommandBuffer(textureCmdBuffer, 0); VkCommandBufferInheritanceInfo commandBufferInheritanceInfo = {}; commandBufferInheritanceInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; commandBufferInheritanceInfo.pNext = NULL; commandBufferInheritanceInfo.renderPass = VK_NULL_HANDLE; commandBufferInheritanceInfo.subpass = 0; commandBufferInheritanceInfo.framebuffer = VK_NULL_HANDLE; commandBufferInheritanceInfo.occlusionQueryEnable = VK_FALSE; commandBufferInheritanceInfo.queryFlags = 0; commandBufferInheritanceInfo.pipelineStatistics = 0; VkCommandBufferBeginInfo setupCmdsBeginInfo; setupCmdsBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; setupCmdsBeginInfo.pNext = NULL; setupCmdsBeginInfo.flags = 0; setupCmdsBeginInfo.pInheritanceInfo = &commandBufferInheritanceInfo; // Begin recording to the command buffer. vkBeginCommandBuffer(textureCmdBuffer, &setupCmdsBeginInfo); VkImageMemoryBarrier imageMemoryBarrier = {}; imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; imageMemoryBarrier.pNext = NULL; imageMemoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imageMemoryBarrier.subresourceRange.baseMipLevel = 0; imageMemoryBarrier.subresourceRange.levelCount = 1; imageMemoryBarrier.subresourceRange.baseArrayLayer = 0; imageMemoryBarrier.subresourceRange.layerCount = pixels.size(); imageMemoryBarrier.srcAccessMask = 0; imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; // Optimal image will be used as destination for the copy, so we must transfer from our initial undefined image layout to the transfer destination layout setImageLayout(imageMemoryBarrier, textureCmdBuffer, imageHandle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageMemoryBarrier.subresourceRange); vkCmdCopyBufferToImage( textureCmdBuffer, texBuffer, imageHandle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<uint32_t>(bufferCopyRegions.size()), bufferCopyRegions.data()); imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; setImageLayout(imageMemoryBarrier, textureCmdBuffer, imageHandle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageMemoryBarrier.subresourceRange); // We are finished recording operations. vkEndCommandBuffer(textureCmdBuffer); VkCommandBuffer buffers[1]; buffers[0] = textureCmdBuffer; VkSubmitInfo submit_info; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.pNext = NULL; submit_info.waitSemaphoreCount = 0; submit_info.pWaitSemaphores = NULL; submit_info.pWaitDstStageMask = NULL; submit_info.commandBufferCount = 1; submit_info.pCommandBuffers = &buffers[0]; submit_info.signalSemaphoreCount = 0; submit_info.pSignalSemaphores = NULL; VkQueue queue = vk_renderer->getQueue(); // Submit to our shared graphics queue. err = vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE); assert(!err); // Wait for the queue to become idle. err = vkQueueWaitIdle(queue); assert(!err); vkFreeMemory(device, texMemory, nullptr); vkDestroyBuffer(device, texBuffer, nullptr); if(mipLevels > 1) createMipLevels(formatProperties, vk_renderer, setupCmdsBeginInfo, bufferCopyRegions, mipLevels, bitmapInfos, imageMemoryBarrier, submit_info, buffers, queue); err = vkCreateImageView(device, gvr::ImageViewCreateInfo(imageHandle, target, internalFormat, mipLevels,0, pixels.size(), VK_IMAGE_ASPECT_COLOR_BIT), NULL, &imageView); assert(!err); }
LOGICAL swapChainCreate( struct SwapChain *swapChain, VkCommandBuffer commandBuffer, uint32_t *width, uint32_t *height ) { VkSwapchainKHR oldSwapChain = swapChain->swapChain; // Get physical device surface properties and formats. This was not // covered in previous tutorials. Effectively does what it says it does. // We will be using the result of this to determine the number of // images we should use for our swap chain and set the appropriate // sizes for them. uint32_t presentModeCount; VkSurfaceCapabilitiesKHR surfaceCapabilities; VkExtent2D swapChainExtent = { 0 };// = {}; VkPresentModeKHR *presentModes; if( swapChain->fpGetPhysicalDeviceSurfaceCapabilitiesKHR( swapChain->physicalDevice, swapChain->surface, &surfaceCapabilities ) != VK_SUCCESS ) return FALSE; // Also not covered in previous tutorials: used to get the available // modes for presentation. if( swapChain->fpGetPhysicalDeviceSurfacePresentModesKHR( swapChain->physicalDevice, swapChain->surface, &presentModeCount, NULL ) != VK_SUCCESS) return FALSE; if( presentModeCount == 0 ) return FALSE; presentModes = NewArray( VkPresentModeKHR, presentModeCount ); if( swapChain->fpGetPhysicalDeviceSurfacePresentModesKHR( swapChain->physicalDevice, swapChain->surface, &presentModeCount, &presentModes[0] ) != VK_SUCCESS ) return FALSE; // When constructing a swap chain we must supply our surface resolution. // Like all things in Vulkan there is a structure for representing this // The way surface capabilities work is rather confusing but width // and height are either both -1 or both not -1. A size of -1 indicates // that the surface size is undefined, which means you can set it to // effectively any size. If the size however is defined, the swap chain // size *MUST* match. if( surfaceCapabilities.currentExtent.width == -1 ) { swapChainExtent.width = *width; swapChainExtent.height = *height; } else { swapChainExtent = surfaceCapabilities.currentExtent; *width = surfaceCapabilities.currentExtent.width; *height = surfaceCapabilities.currentExtent.height; } { // Prefer mailbox mode if present VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; // always supported uint32_t i; for( i = 0; i < presentModeCount; i++ ) { if( presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR ) { presentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } if( presentMode != VK_PRESENT_MODE_MAILBOX_KHR && presentMode != VK_PRESENT_MODE_IMMEDIATE_KHR ) { // The horrible fallback presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } } { // Determine the number of images for our swap chain uint32_t desiredImages = surfaceCapabilities.minImageCount + 1; if( surfaceCapabilities.maxImageCount > 0 && desiredImages > surfaceCapabilities.maxImageCount ) { desiredImages = surfaceCapabilities.maxImageCount; } { // This will be covered in later tutorials VkSurfaceTransformFlagsKHR preTransform = surfaceCapabilities.currentTransform; if( surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ) preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; { VkSwapchainCreateInfoKHR swapChainCreateInfo; // Mandatory fields swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapChainCreateInfo.pNext = NULL; swapChainCreateInfo.surface = swapChain->surface; swapChainCreateInfo.minImageCount = desiredImages; swapChainCreateInfo.imageFormat = swapChain->colorFormat; swapChainCreateInfo.imageColorSpace = swapChain->colorSpace; swapChainCreateInfo.imageExtent.width = swapChainExtent.width; swapChainCreateInfo.imageExtent.height = swapChainExtent.height; // This is literally the same as GL_COLOR_ATTACHMENT0 swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapChainCreateInfo.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform; swapChainCreateInfo.imageArrayLayers = 1; // Only one attachment swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // No sharing swapChainCreateInfo.queueFamilyIndexCount = 0; // Covered in later tutorials swapChainCreateInfo.pQueueFamilyIndices = NULL; // Covered in later tutorials swapChainCreateInfo.presentMode = presentMode; swapChainCreateInfo.clipped = TRUE; // If we want clipping outside the extents // Alpha on the window surface should be opaque: // If it was not we could create transparent regions of our window which // would require support from the Window compositor. You can totally do // that if you wanted though ;) swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; if( swapChain->fpCreateSwapchainKHR( swapChain->device, &swapChainCreateInfo, NULL, &swapChain->swapChain ) != VK_SUCCESS ) return FALSE; } } } } // If an existing swap chain is recreated, destroy the old one. This // also cleans up all presentable images if( oldSwapChain != VK_NULL_HANDLE ) { swapChain->fpDestroySwapchainKHR( swapChain->device, oldSwapChain, NULL ); } { // Now get the presentable images from the swap chain uint32_t imageCount; if( swapChain->fpGetSwapchainImagesKHR( swapChain->device, swapChain->swapChain, &imageCount, NULL ) != VK_SUCCESS ) goto failed; swapChain->images = Reallocate( swapChain->images, sizeof( VkImage) * imageCount ); if( swapChain->fpGetSwapchainImagesKHR( swapChain->device, swapChain->swapChain, &imageCount, &swapChain->images[0] ) != VK_SUCCESS ) { failed: swapChain->fpDestroySwapchainKHR( swapChain->device, swapChain->swapChain, NULL ); return FALSE; } // Create the image views for the swap chain. They will all be single // layer, 2D images, with no mipmaps. // Check the VkImageViewCreateInfo structure to see other views you // can potentially create. swapChain->buffers = Reallocate( swapChain->buffers, sizeof( struct SwapChainBuffer ) * imageCount ); { uint32_t i; for( i = 0; i < imageCount; i++ ) { VkImageViewCreateInfo colorAttachmentView;// = {}; colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; colorAttachmentView.pNext = NULL; colorAttachmentView.format = swapChain->colorFormat; colorAttachmentView.components.r = VK_COMPONENT_SWIZZLE_R; colorAttachmentView.components.g = VK_COMPONENT_SWIZZLE_G; colorAttachmentView.components.b = VK_COMPONENT_SWIZZLE_B; colorAttachmentView.components.a = VK_COMPONENT_SWIZZLE_A; colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; colorAttachmentView.subresourceRange.baseMipLevel = 0; colorAttachmentView.subresourceRange.levelCount = 1; colorAttachmentView.subresourceRange.baseArrayLayer = 0; colorAttachmentView.subresourceRange.layerCount = 1; colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D; colorAttachmentView.flags = 0; // mandatory // Wire them up swapChain->buffers[i].image = swapChain->images[i]; // Transform images from the initial (undefined) layer to // present layout setImageLayout( commandBuffer, swapChain->buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ); colorAttachmentView.image = swapChain->buffers[i].image; // Create the view if( vkCreateImageView( swapChain->device, &colorAttachmentView, NULL, &swapChain->buffers[i].view ) != VK_SUCCESS ) goto failed; } } } return TRUE; }
//============================================================================== // Vulkan初期化 //============================================================================== bool initVulkan(HINSTANCE hinst, HWND wnd) { VkResult result; //================================================== // Vulkanのインスタンス作成 //================================================== VkApplicationInfo applicationInfo = {}; applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; applicationInfo.pApplicationName = APPLICATION_NAME; applicationInfo.pEngineName = APPLICATION_NAME; applicationInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0); std::vector<LPCSTR> enabledExtensionsByInstance = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME }; VkInstanceCreateInfo instanceCreateInfo = {}; instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instanceCreateInfo.pNext = nullptr; instanceCreateInfo.pApplicationInfo = &applicationInfo; if(enabledExtensionsByInstance.empty() == false) { instanceCreateInfo.enabledExtensionCount = enabledExtensionsByInstance.size(); instanceCreateInfo.ppEnabledExtensionNames = enabledExtensionsByInstance.data(); } result = vkCreateInstance(&instanceCreateInfo, nullptr, &g_VulkanInstance); checkVulkanError(result, TEXT("Vulkanインスタンス作成失敗")); //================================================== // 物理デバイス(GPUデバイス) //================================================== // 物理デバイス数を獲得 uint32_t gpuCount = 0; vkEnumeratePhysicalDevices(g_VulkanInstance, &gpuCount, nullptr); assert(gpuCount > 0 && TEXT("物理デバイス数の獲得失敗")); // 物理デバイス数を列挙 std::vector<VkPhysicalDevice> physicalDevices(gpuCount); result = vkEnumeratePhysicalDevices(g_VulkanInstance, &gpuCount, physicalDevices.data()); checkVulkanError(result, TEXT("物理デバイスの列挙に失敗しました")); // すべてのGPU情報を格納 g_GPUs.resize(gpuCount); for(uint32_t i = 0; i < gpuCount; ++i) { g_GPUs[i].device = physicalDevices[i]; // 物理デバイスのプロパティ獲得 vkGetPhysicalDeviceProperties(g_GPUs[i].device, &g_GPUs[i].deviceProperties); // 物理デバイスのメモリプロパティ獲得 vkGetPhysicalDeviceMemoryProperties(g_GPUs[i].device, &g_GPUs[i].deviceMemoryProperties); } // ※このサンプルでは最初に列挙されたGPUデバイスを使用する g_currentGPU = g_GPUs[0]; // グラフィックス操作をサポートするキューを検索 uint32_t queueCount; vkGetPhysicalDeviceQueueFamilyProperties(g_currentGPU.device, &queueCount, nullptr); assert(queueCount >= 1 && TEXT("物理デバイスキューの検索失敗")); std::vector<VkQueueFamilyProperties> queueProps; queueProps.resize(queueCount); vkGetPhysicalDeviceQueueFamilyProperties(g_currentGPU.device, &queueCount, queueProps.data()); uint32_t graphicsQueueIndex = 0; for(graphicsQueueIndex = 0; graphicsQueueIndex < queueCount; ++graphicsQueueIndex) { if(queueProps[graphicsQueueIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) { break; } } assert(graphicsQueueIndex < queueCount && TEXT("グラフィックスをサポートするキューを見つけられませんでした")); //================================================== // Vulkanデバイス作成 //================================================== float queuePrioritie = 0.0f; VkDeviceQueueCreateInfo queueCreateInfo = {}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = graphicsQueueIndex; queueCreateInfo.queueCount = 1; queueCreateInfo.pQueuePriorities = &queuePrioritie; std::vector<LPCSTR> enabledExtensionsByDevice = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; VkDeviceCreateInfo deviceCreateInfo = {}; deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceCreateInfo.pNext = nullptr; deviceCreateInfo.queueCreateInfoCount = 1; deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; deviceCreateInfo.pEnabledFeatures = nullptr; if(enabledExtensionsByDevice.empty() == false) { deviceCreateInfo.enabledExtensionCount = enabledExtensionsByDevice.size(); deviceCreateInfo.ppEnabledExtensionNames = enabledExtensionsByDevice.data(); } result = vkCreateDevice(g_currentGPU.device, &deviceCreateInfo, nullptr, &g_VulkanDevice); checkVulkanError(result, TEXT("Vulkanデバイス作成失敗")); // グラフィックスキュー獲得 vkGetDeviceQueue(g_VulkanDevice, graphicsQueueIndex, 0, &g_VulkanQueue); //================================================== // フェンスオブジェクト作成 //================================================== VkFenceCreateInfo fenceCreateInfo = {}; fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceCreateInfo.pNext = nullptr; fenceCreateInfo.flags = 0; result = vkCreateFence(g_VulkanDevice, &fenceCreateInfo, nullptr, &g_VulkanFence); checkVulkanError(result, TEXT("フェンスオブジェクト作成失敗")); //================================================== // 同期(セマフォ)オブジェクト作成 //================================================== VkSemaphoreCreateInfo semaphoreCreateInfo = {}; semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreCreateInfo.pNext = nullptr; semaphoreCreateInfo.flags = 0; // コマンドバッファ実行用セマフォ作成 result = vkCreateSemaphore(g_VulkanDevice, &semaphoreCreateInfo, nullptr, &g_VulkanSemahoreRenderComplete); checkVulkanError(result, TEXT("コマンドバッファ実行用セマフォ作成失敗")); //================================================== // コマンドプール作製 //================================================== VkCommandPoolCreateInfo cmdPoolInfo = {}; cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; cmdPoolInfo.queueFamilyIndex = 0; cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; result = vkCreateCommandPool(g_VulkanDevice, &cmdPoolInfo, nullptr, &g_VulkanCommandPool); checkVulkanError(result, TEXT("コマンドプール作成失敗")); //================================================== // コマンドバッファ作成 //================================================== // メモリを確保. g_commandBuffers.resize(SWAP_CHAIN_COUNT); VkCommandBufferAllocateInfo commandBufferAllocateInfo = {}; commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; commandBufferAllocateInfo.pNext = nullptr; commandBufferAllocateInfo.commandPool = g_VulkanCommandPool; commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; commandBufferAllocateInfo.commandBufferCount = SWAP_CHAIN_COUNT; result = vkAllocateCommandBuffers(g_VulkanDevice, &commandBufferAllocateInfo, g_commandBuffers.data()); checkVulkanError(result, TEXT("コマンドバッファ作成失敗")); //================================================== // OS(今回はWin32)用のサーフェスを作成する //================================================== VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {}; surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; surfaceCreateInfo.hinstance = hinst; surfaceCreateInfo.hwnd = wnd; result = vkCreateWin32SurfaceKHR(g_VulkanInstance, &surfaceCreateInfo, nullptr, &g_VulkanSurface); checkVulkanError(result, TEXT("サーフェス作成失敗")); //================================================== // スワップチェーンを作成する //================================================== VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM; VkColorSpaceKHR imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; uint32_t surfaceFormatCount = 0; result = vkGetPhysicalDeviceSurfaceFormatsKHR(g_currentGPU.device, g_VulkanSurface, &surfaceFormatCount, nullptr); checkVulkanError(result, TEXT("サポートしているカラーフォーマット数の獲得失敗")); std::vector<VkSurfaceFormatKHR> surfaceFormats; surfaceFormats.resize(surfaceFormatCount); result = vkGetPhysicalDeviceSurfaceFormatsKHR(g_currentGPU.device, g_VulkanSurface, &surfaceFormatCount, surfaceFormats.data()); checkVulkanError(result, TEXT("サポートしているカラーフォーマットの獲得失敗")); // 一致するカラーフォーマットを検索する bool isFind = false; for(const auto& surfaceFormat : surfaceFormats) { if(imageFormat == surfaceFormat.format && imageColorSpace == surfaceFormat.colorSpace) { isFind = true; break; } } if(isFind == false) { imageFormat = surfaceFormats[0].format; imageColorSpace = surfaceFormats[0].colorSpace; } // サーフェスの機能を獲得する VkSurfaceCapabilitiesKHR surfaceCapabilities; VkSurfaceTransformFlagBitsKHR surfaceTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( g_currentGPU.device, g_VulkanSurface, &surfaceCapabilities); checkVulkanError(result, TEXT("サーフェスの機能の獲得失敗")); if((surfaceCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) == 0) { surfaceTransform = surfaceCapabilities.currentTransform; } // プレゼント機能を獲得する VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; uint32_t presentModeCount; result = vkGetPhysicalDeviceSurfacePresentModesKHR( g_currentGPU.device, g_VulkanSurface, &presentModeCount, nullptr); checkVulkanError(result, TEXT("プレゼント機能数の獲得失敗")); std::vector<VkPresentModeKHR> presentModes; presentModes.resize(presentModeCount); result = vkGetPhysicalDeviceSurfacePresentModesKHR( g_currentGPU.device, g_VulkanSurface, &presentModeCount, presentModes.data()); checkVulkanError(result, TEXT("プレゼント機能の獲得失敗")); for(const auto& presentModeInfo : presentModes) { if(presentModeInfo == VK_PRESENT_MODE_MAILBOX_KHR) { presentMode = VK_PRESENT_MODE_MAILBOX_KHR; break; } if(presentModeInfo == VK_PRESENT_MODE_IMMEDIATE_KHR) { presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; } } presentModes.clear(); uint32_t desiredSwapChainImageCount = surfaceCapabilities.minImageCount + 1; if(surfaceCapabilities.maxImageCount > 0 && desiredSwapChainImageCount > surfaceCapabilities.maxImageCount) { desiredSwapChainImageCount = surfaceCapabilities.maxImageCount; } // スワップチェーン作成 VkSwapchainCreateInfoKHR swapchainCreateInfo = {}; swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; swapchainCreateInfo.pNext = nullptr; swapchainCreateInfo.flags = 0; swapchainCreateInfo.surface = g_VulkanSurface; swapchainCreateInfo.minImageCount = desiredSwapChainImageCount; swapchainCreateInfo.imageFormat = imageFormat; swapchainCreateInfo.imageColorSpace = imageColorSpace; swapchainCreateInfo.imageExtent = { SCREEN_WIDTH, SCREEN_HEIGHT }; swapchainCreateInfo.imageArrayLayers = 1; swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapchainCreateInfo.queueFamilyIndexCount = 0; swapchainCreateInfo.pQueueFamilyIndices = nullptr; swapchainCreateInfo.preTransform = surfaceTransform; swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainCreateInfo.presentMode = presentMode; swapchainCreateInfo.clipped = VK_TRUE; swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE; result = vkCreateSwapchainKHR(g_VulkanDevice, &swapchainCreateInfo, nullptr, &g_VulkanSwapChain); checkVulkanError(result, TEXT("サーフェス作成失敗")); //================================================== // イメージの作成 //================================================== uint32_t swapChainCount = 0; result = vkGetSwapchainImagesKHR(g_VulkanDevice, g_VulkanSwapChain, &swapChainCount, nullptr); checkVulkanError(result, TEXT("スワップチェーンイメージ数の獲得失敗")); g_backBuffersTextures.resize(swapChainCount); std::vector<VkImage> images; images.resize(swapChainCount); result = vkGetSwapchainImagesKHR(g_VulkanDevice, g_VulkanSwapChain, &swapChainCount, images.data()); checkVulkanError(result, TEXT("スワップチェーンイメージの獲得失敗")); for(uint32_t i = 0; i < swapChainCount; ++i) { g_backBuffersTextures[i].image = images[i]; } images.clear(); //================================================== // イメージビューの生成 //================================================== for(auto& backBuffer : g_backBuffersTextures) { VkImageViewCreateInfo imageViewCreateInfo = {}; imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageViewCreateInfo.pNext = nullptr; imageViewCreateInfo.flags = 0; imageViewCreateInfo.image = backBuffer.image; imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewCreateInfo.format = imageFormat; imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_R; imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_G; imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_B; imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_A; imageViewCreateInfo.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; result = vkCreateImageView(g_VulkanDevice, &imageViewCreateInfo, nullptr, &backBuffer.view); checkVulkanError(result, TEXT("イメージビューの作成失敗")); setImageLayout( g_VulkanDevice, g_commandBuffers[g_currentBufferIndex], backBuffer.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); } //================================================== // 深度ステンシルバッファの生成 //================================================== VkFormat depthFormat = VK_FORMAT_D24_UNORM_S8_UINT; VkImageTiling imageTiling; VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(g_currentGPU.device, depthFormat, &formatProperties); if(formatProperties.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { imageTiling = VK_IMAGE_TILING_LINEAR; } else if(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) { imageTiling = VK_IMAGE_TILING_OPTIMAL; } else { checkVulkanError(VK_RESULT_MAX_ENUM, TEXT("サポートされていないフォーマットです")); return false; } VkImageCreateInfo imageCreateInfo = {}; imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageCreateInfo.pNext = nullptr; imageCreateInfo.flags = 0; imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; imageCreateInfo.format = depthFormat; imageCreateInfo.extent.width = SCREEN_WIDTH; imageCreateInfo.extent.height = SCREEN_HEIGHT; imageCreateInfo.extent.depth = 1; imageCreateInfo.mipLevels = 1; imageCreateInfo.arrayLayers = 1; imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.tiling = imageTiling; imageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageCreateInfo.queueFamilyIndexCount = 0; imageCreateInfo.pQueueFamilyIndices = nullptr; imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; result = vkCreateImage(g_VulkanDevice, &imageCreateInfo, nullptr, &g_depthBufferTexture.image); checkVulkanError(result, TEXT("深度テクスチャ用イメージビュー作成失敗")); // メモリ要件を獲得 VkMemoryRequirements memoryRequirements; vkGetImageMemoryRequirements(g_VulkanDevice, g_depthBufferTexture.image, &memoryRequirements); VkFlags requirementsMask = 0; uint32_t typeBits = memoryRequirements.memoryTypeBits; uint32_t typeIndex = 0; for(const auto& memoryType : g_currentGPU.deviceMemoryProperties.memoryTypes) { if((typeBits & 0x1) == 1) { if((memoryType.propertyFlags & requirementsMask) == requirementsMask) { break; } } typeBits >>= 1; ++typeIndex; } // メモリ確保 VkMemoryAllocateInfo allocInfo = {}; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.pNext = nullptr; allocInfo.allocationSize = memoryRequirements.size; allocInfo.memoryTypeIndex = typeIndex; result = vkAllocateMemory(g_VulkanDevice, &allocInfo, nullptr, &g_depthBufferTexture.memory); checkVulkanError(result, TEXT("深度テクスチャ用メモリ確保失敗")); result = vkBindImageMemory(g_VulkanDevice, g_depthBufferTexture.image, g_depthBufferTexture.memory, 0); checkVulkanError(result, TEXT("深度テクスチャメモリにバインド失敗")); VkImageViewCreateInfo imageViewCreateInfo = {}; imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageViewCreateInfo.pNext = nullptr; imageViewCreateInfo.image = g_depthBufferTexture.image; imageViewCreateInfo.format = depthFormat; imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_R; imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_G; imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_B; imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_A; imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; imageViewCreateInfo.subresourceRange.baseMipLevel = 0; imageViewCreateInfo.subresourceRange.levelCount = 1; imageViewCreateInfo.subresourceRange.baseArrayLayer = 0; imageViewCreateInfo.subresourceRange.layerCount = 1; imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewCreateInfo.flags = 0; result = vkCreateImageView(g_VulkanDevice, &imageViewCreateInfo, nullptr, &g_depthBufferTexture.view); checkVulkanError(result, TEXT("深度テクスチャイメージビュー作成失敗")); setImageLayout( g_VulkanDevice, g_commandBuffers[g_currentBufferIndex], g_depthBufferTexture.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); //================================================== // フレームバッファの生成 //================================================== VkImageView attachments[2]; // 0=カラーバッファ、1=深度バッファ VkFramebufferCreateInfo frameBufferCreateInfo = {}; frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; frameBufferCreateInfo.pNext = nullptr; frameBufferCreateInfo.flags = 0; frameBufferCreateInfo.renderPass = VK_NULL_HANDLE; frameBufferCreateInfo.attachmentCount = 2; frameBufferCreateInfo.pAttachments = attachments; frameBufferCreateInfo.width = SCREEN_WIDTH; frameBufferCreateInfo.height = SCREEN_HEIGHT; frameBufferCreateInfo.layers = 1; g_frameBuffers.resize(SWAP_CHAIN_COUNT); for(uint32_t i = 0; i < SWAP_CHAIN_COUNT; ++i) { attachments[0] = g_backBuffersTextures[i].view; attachments[1] = g_depthBufferTexture.view; auto result = vkCreateFramebuffer(g_VulkanDevice, &frameBufferCreateInfo, nullptr, &g_frameBuffers[i]); checkVulkanError(result, TEXT("フレームバッファ作成失敗")); } return true; }