vulkan中的texture(VkImage、VkImageView、VkSampler、VkDeviceMemory)

在Vulkan中,以下是这几个概念的简要说明以及它们之间的关系:

  1. Texture2D

    • 纹理在vulkan API中并没有一个结构体来表示,它是着色器语言中(比如GLSL)的一种概念。在着色器中, sampler2D 类型的变量表示一个二维纹理。
  2. VkImage

    • 它是Vulkan中表示图像的对象,负责存储图像的元数据(metadata),但不存储像素的具体值,比如宽度、高度、格式等。
    • 类似于 VkBuffer 对象,VkImage 也只是一个句柄(handle),它本身并不包含实际的像素数据。相应地,你需要通过 vkBindImageMemory() 函数将 VkImage 与实际的 VkDeviceMemory 对象关联起来,以便在这块内存中存储图像的像素数据。具体可以参考一下这个文章
    • 一旦完成关联,后续的vkCmdCopyImage等类似的指令,就以该VkImage作为句柄来对该图像数据进行引用了。当然,在事后资源释放时,需要分别销毁vulkan对象(VkDestroyImage)以及释放设备内存(VkFreeMemory)

在 Vulkan 中,对于很多对象(比如 VkBuffer 和 VkImage),数据存储和句柄是分离的,这为开发者提供了更多的灵活性。这样的设计允许你更精细地控制数据的存储位置、布局和访问权限。

  1. VkImageView

    • VkImageView 是对 VkImage 的一个视图或描述。它指定了如何从底层的 VkImage 中读取数据,包括图像的格式、范围等。在Vulkan中,你通常需要使用 VkImageView 来对 VkImage 进行采样操作。
  2. VkSampler

    • VkSampler 是一个对象,用于描述纹理采样的方式。它定义了纹理采样时的过滤方式、边界模式、各向异性过滤等参数。VkSampler 通常与 VkImageView 一起用于纹理采样操作。
  3. VkDeviceMemory

    • VkDeviceMemory 用于表示 Vulkan 设备上的内存对象,它是用于存储 VkImage 或其他 Vulkan 对象数据的实际内存。在 Vulkan 中,你需要显式地为图像数据分配GPU内存,完成数据的写入(从CPU端内存到GPU),然后将该内存绑定到相应的 VkImage 对象上。

关系总结:

  • VkImage 是底层图像数据的表示,它包含像素数据和图像的元数据。
  • VkImageView 是对 VkImage 的描述,它提供了访问图像数据的视图,用于采样等操作。
  • VkSampler 描述了纹理采样的方式,包括过滤方式、边界模式等。
  • VkDeviceMemory 是分配给 VkImage 或其他 Vulkan 对象的实际内存,用于存储底层数据。

在实际使用中,通常流程是:
创建 VkImage 对象 → \to 分配相应的 VkDeviceMemory → \to 创建 VkImageViewVkSampler 以便在着色器中进行纹理采样操作。

一般在游戏引擎里,也会有个Texture2D的类,用来封装一些图像的操作和数据,如:

struct TextureSpecification
{
	ImageFormat Format = ImageFormat::RGBA;
	uint32_t Width = 1;
	uint32_t Height = 1;
	TextureWrap SamplerWrap = TextureWrap::Repeat;
	TextureFilter SamplerFilter = TextureFilter::Linear;
	
	bool GenerateMips = true;
	bool SRGB = false;
	bool Storage = false;
	bool StoreLocally = false;

	std::string DebugName;
};
class VulkanTexture2D : public Texture2D
{
public:
	VulkanTexture2D(const TextureSpecification& specification, const std::filesystem::path& filepath);
	VulkanTexture2D(const TextureSpecification& specification, Buffer data = Buffer());
	~VulkanTexture2D() override;
	
	virtual void Resize(const glm::uvec2& size) override;
	virtual void Resize(uint32_t width, uint32_t height) override;

	void Invalidate();

	virtual ImageFormat GetFormat() const override { return m_Specification.Format; }
	virtual uint32_t GetWidth() const override { return m_Specification.Width; }
	virtual uint32_t GetHeight() const override { return m_Specification.Height; }
	virtual glm::uvec2 GetSize() const override { return { m_Specification.Width, m_Specification.Height }; }

	virtual void Bind(uint32_t slot = 0) const override;

	virtual Ref<Image2D> GetImage() const override { return m_Image; }
	virtual ResourceDescriptorInfo GetDescriptorInfo() const override { return m_Image.As<VulkanImage2D>()->GetDescriptorInfo(); }
	const VkDescriptorImageInfo& GetDescriptorInfoVulkan() const { return *(VkDescriptorImageInfo*)GetDescriptorInfo(); }

	void Lock() override;
	void Unlock() override;

	Buffer GetWriteableBuffer() override;
	bool Loaded() const override { return m_ImageData; }
	const std::filesystem::path& GetPath() const override;
	uint32_t GetMipLevelCount() const override;
	virtual std::pair<uint32_t, uint32_t> GetMipSize(uint32_t mip) const override;

	void GenerateMips();

	virtual uint64_t GetHash() const { return (uint64_t)m_Image.As<VulkanImage2D>()->GetDescriptorInfoVulkan().imageView; }

	void CopyToHostBuffer(Buffer& buffer);
private:
	std::filesystem::path m_Path;
	TextureSpecification m_Specification;

	Buffer m_ImageData; // CPU端内存,存放图像文件中读取的数据

	Ref<Image2D> m_Image;	// Image2D也是自定义的类型看下面
};

VulkanImage2D这又是一层封装,核心内容是

  • VkImage Image = nullptr;
  • VkImageView ImageView = nullptr;
  • VkSampler Sampler = nullptr;
  • VmaAllocation MemoryAlloc = nullptr;

然后是其他的一些相关特性、操作的东西

class VulkanImage2D : public Image2D
{
public:
	VulkanImage2D(const ImageSpecification& specification);
	virtual ~VulkanImage2D() override;

	virtual void Resize(const glm::uvec2& size) override
	{
		Resize(size.x, size.y);
	}
	virtual void Resize(const uint32_t width, const uint32_t height) override
	{
		m_Specification.Width = width;
		m_Specification.Height = height;
		Invalidate();
	}
	virtual void Invalidate() override;
	virtual void Release() override;

	virtual uint32_t GetWidth() const override { return m_Specification.Width; }
	virtual uint32_t GetHeight() const override { return m_Specification.Height; }
	virtual glm::uvec2 GetSize() const override { return { m_Specification.Width, m_Specification.Height };}

	virtual float GetAspectRatio() const override { return (float)m_Specification.Width / (float)m_Specification.Height; }

	virtual ImageSpecification& GetSpecification() override { return m_Specification; }
	virtual const ImageSpecification& GetSpecification() const override { return m_Specification; }

	void RT_Invalidate();

	virtual void CreatePerLayerImageViews() override;
	void RT_CreatePerLayerImageViews();
	void RT_CreatePerSpecificLayerImageViews(const std::vector<uint32_t>& layerIndices);

	virtual VkImageView GetLayerImageView(uint32_t layer)
	{
		HZ_CORE_ASSERT(layer < m_PerLayerImageViews.size());
		return m_PerLayerImageViews[layer];
	}

	VkImageView GetMipImageView(uint32_t mip);
	VkImageView RT_GetMipImageView(uint32_t mip);

	VulkanImageInfo& GetImageInfo() { return m_Info; }
	const VulkanImageInfo& GetImageInfo() const { return m_Info; }

	virtual ResourceDescriptorInfo GetDescriptorInfo() const override { return (ResourceDescriptorInfo)&m_DescriptorImageInfo; }
	const VkDescriptorImageInfo& GetDescriptorInfoVulkan() const { return *(VkDescriptorImageInfo*)GetDescriptorInfo(); }

	virtual Buffer GetBuffer() const override { return m_ImageData; }
	virtual Buffer& GetBuffer() override { return m_ImageData; }

	virtual uint64_t GetHash() const override { return (uint64_t)m_Info.Image; }

	void UpdateDescriptor();

	// Debug
	static const std::map<VkImage, WeakRef<VulkanImage2D>>& GetImageRefs();

	void CopyToHostBuffer(Buffer& buffer);
private:
	ImageSpecification m_Specification;

	Buffer m_ImageData;

	VkImage Image = nullptr;
	VkImageView ImageView = nullptr;
	VkSampler Sampler = nullptr;
	VmaAllocation MemoryAlloc = nullptr;
	VkDeviceSize m_GPUAllocationSize;
	
	std::vector<VkImageView> m_PerLayerImageViews;
	std::map<uint32_t, VkImageView> m_PerMipImageViews;
	VkDescriptorImageInfo m_DescriptorImageInfo = {};
};
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Visual Studio配置Vulkan环境主要涉及安装必要的SDK、设置编译选项和添加Vulkan支持。以下是配置步骤: 1. **安装Vulkan SDK**: - 访问Vulkan官网(https://vulkan.lunarg.com/)下载对应平台的SDK(Windows SDK通常包含预编译库,但如果你需要最新版本,可以从GitHub下载源码并编译)。 - 安装过程,确保选择将Vulkan SDK路径添加到系统的PATH环境变量。 2. **安装Visual Studio插件**: - 如果你使用的是Visual Studio 2019或更高版本,可以在Visual Studio市场(Marketplace)搜索并安装"Vulkan Toolkit for Visual Studio"插件,这将简化Vulkan开发环境的集成。 3. **创建新项目**: - 在Visual Studio,创建一个新项目,选择"空白项目"或"游戏项目"模板,然后勾选"启用C++11标准"和"启用C++14标准"。 4. **添加Vulkan头文件**: - 在项目的`#include`目录,添加Vulkan头文件路径,通常是在Vulkan SDK安装路径下的Include文件夹。 5. **配置项目属性**: - 打开项目属性(Project Properties),在"VC++ Directories",添加Vulkan库目录(Libraries)和包含目录(Include Directories)。 - 在"C/C++" -> "General" -> "Additional Include Directories"添加Vulkan头文件路径。 - 在"Linker" -> "Input" -> "Additional Dependencies"添加Vulkan库,如`vulkan.lib`或`vulkan-1.lib`。 6. **启用Vulkan支持**: - 在项目配置(Project Configuration),确保你的项目配置(如Debug和Release)都启用了Vulkan支持。 7. **编写代码**: - 使用Vulkan API开始编写代码,包括初始化设备、创建交换链等步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宗浩多捞

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值