#include "image.h"
#include "device.h"
#include "buffer.h"
namespace vulkanapi {
	Image::Image(Device& device, string name, const Args& args)
		: mArgs(args)
		, mName(name)
		, mDevice(device)
		, mPtr(nullptr)
	{
		VkImageCreateInfo imageInfo{};
		imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
		imageInfo.imageType = mArgs.Type;
		imageInfo.extent.width = mArgs.Width;
		imageInfo.extent.height = mArgs.Height;
		// 纹理第三个维度的像素数量，如果不是3D纹理应该都是1
		imageInfo.extent.depth = 1;
		imageInfo.mipLevels = mArgs.Levels;
		imageInfo.arrayLayers = mArgs.Layers;
		imageInfo.format = mArgs.Format;
		// VK_IMAGE_TILING_LINEAR: texel以行为主序排列为数组
		// VK_IMAGE_TILING_OPTIMAL: texel按照Vulkan的具体实现来定义的一种顺序排列，以实现最佳访问
		// 这个和layout不一样，一旦设置之后是固定的不能改，如果CPU需要读取这个数据，就设置为VK_IMAGE_TILING_LINEAR
		// 如果只是GPU使用，就设置为VK_IMAGE_TILING_OPTIMAL性能更好
		imageInfo.tiling = mArgs.Tiling;
		// 这里只能填VK_IMAGE_LAYOUT_UNDEFINED或者VK_IMAGE_LAYOUT_PREINITIALIZED
		// VK_IMAGE_LAYOUT_UNDEFINED意味着第一次transition数据的时候数据会被丢弃
		// VK_IMAGE_LAYOUT_PREINITIALIZED是第一次transition数据的时候数据会被保留
		// 不是很懂这个什么意思，如果是一个用来从CPU写入数据，然后transfer到其它VkImage的stagingImage，就要用VK_IMAGE_LAYOUT_PREINITIALIZED
		imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
		imageInfo.usage = mArgs.Usage;
		imageInfo.sharingMode = mArgs.Sharing;
		imageInfo.samples = mArgs.Samples;
		// 这个只影响当作attachments使用的VkImage(自己创建的frame buffer才支持这个，交换链用的那个默认buffer不支持)
		imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;

		Buffer::CreateImage(imageInfo, mPtr, mAllocation, mArgs.Memory);
	}
	Image::Image(Device& device, string name, VkImage ptr, const Args& args)
		: mArgs(args)
		, mName(name)
		, mDevice(device)
		, mPtr(ptr)
	{

	}
	VkImageView Image::View(VkFormat format, VkImageAspectFlags aspectFlags, VkImageViewType viewType)
	{
		VkImageViewCreateInfo createInfo = {};
		createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
		createInfo.image = mPtr;
		createInfo.viewType = viewType;
		createInfo.format = format;

		// components字段允许调整颜色通道的最终的映射逻辑
		// 比如，我们可以将所有颜色通道映射为红色通道，以实现单色纹理，我们也可以将通道映射具体的常量数值0和1
		// 这里用默认的
		createInfo.components.r = VK_COMPONENT_SWIZZLE_R;
		createInfo.components.g = VK_COMPONENT_SWIZZLE_G;
		createInfo.components.b = VK_COMPONENT_SWIZZLE_B;
		createInfo.components.a = VK_COMPONENT_SWIZZLE_A;

		// subresourceRangle字段用于描述图像的使用目标是什么，以及可以被访问的有效区域
		// 这个图像用作填充color还是depth stencil等
		createInfo.subresourceRange.aspectMask = aspectFlags;
		// 默认处理所有Mipmap
		createInfo.subresourceRange.baseMipLevel = 0;
		createInfo.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
		// 默认处理所有Layers
		createInfo.subresourceRange.baseArrayLayer = 0;
		createInfo.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;

		VkImageView imageView;
		vkCreateImageView(mDevice.Ptr(), &createInfo, nullptr, &imageView);
		return imageView;
	}
	Image::Args Image::Make2DArgs(uint32_t width, uint32_t height, VkFormat format, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VmaMemoryUsage memory)
	{
		return Args{
			VK_IMAGE_TYPE_2D,
			width,height,
			1,1,1,
			format,usage,
			VK_IMAGE_TILING_LINEAR,VK_SHARING_MODE_EXCLUSIVE,
			samples,1,memory };
	}
}
