Ejemplo n.º 1
0
	// 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);
	}
Ejemplo n.º 2
0
	// 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);
	}
Ejemplo n.º 3
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
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();
}
Ejemplo n.º 4
0
		// 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);
		}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
	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;
	}
Ejemplo n.º 7
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);
    }
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
//==============================================================================
// 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;
}