#include "XCEngine/RHI/Vulkan/VulkanResourceView.h" #include "XCEngine/RHI/Vulkan/VulkanBuffer.h" #include "XCEngine/RHI/Vulkan/VulkanTexture.h" namespace XCEngine { namespace RHI { VulkanResourceView::~VulkanResourceView() { Shutdown(); } bool VulkanResourceView::InitializeAsRenderTarget(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc) { if (device == VK_NULL_HANDLE || texture == nullptr || texture->GetImage() == VK_NULL_HANDLE) { return false; } m_device = device; m_texture = texture; m_viewType = ResourceViewType::RenderTarget; m_dimension = desc.dimension != ResourceViewDimension::Unknown ? desc.dimension : ResourceViewDimension::Texture2D; m_format = desc.format != 0 ? static_cast(desc.format) : texture->GetFormat(); VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = texture->GetImage(); viewInfo.viewType = ToVulkanImageViewType(m_dimension, texture->GetTextureType()); viewInfo.format = m_format != Format::Unknown ? ToVulkanFormat(m_format) : texture->GetVkFormat(); viewInfo.subresourceRange.aspectMask = GetImageAspectMask(texture->GetFormat()); viewInfo.subresourceRange.baseMipLevel = desc.mipLevel; viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = desc.firstArraySlice; viewInfo.subresourceRange.layerCount = 1; return vkCreateImageView(device, &viewInfo, nullptr, &m_imageView) == VK_SUCCESS; } bool VulkanResourceView::InitializeAsDepthStencil(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc) { if (device == VK_NULL_HANDLE || texture == nullptr || texture->GetImage() == VK_NULL_HANDLE) { return false; } m_device = device; m_texture = texture; m_viewType = ResourceViewType::DepthStencil; m_dimension = desc.dimension != ResourceViewDimension::Unknown ? desc.dimension : ResourceViewDimension::Texture2D; m_format = desc.format != 0 ? static_cast(desc.format) : texture->GetFormat(); VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = texture->GetImage(); viewInfo.viewType = ToVulkanImageViewType(m_dimension, texture->GetTextureType()); viewInfo.format = m_format != Format::Unknown ? ToVulkanFormat(m_format) : texture->GetVkFormat(); viewInfo.subresourceRange.aspectMask = GetImageAspectMask(m_format != Format::Unknown ? m_format : texture->GetFormat()); viewInfo.subresourceRange.baseMipLevel = desc.mipLevel; viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = desc.firstArraySlice; viewInfo.subresourceRange.layerCount = 1; return vkCreateImageView(device, &viewInfo, nullptr, &m_imageView) == VK_SUCCESS; } bool VulkanResourceView::InitializeAsShaderResource(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc) { if (device == VK_NULL_HANDLE || texture == nullptr || texture->GetImage() == VK_NULL_HANDLE) { return false; } m_device = device; m_texture = texture; m_viewType = ResourceViewType::ShaderResource; m_dimension = desc.dimension != ResourceViewDimension::Unknown ? desc.dimension : ResourceViewDimension::Texture2D; m_format = desc.format != 0 ? static_cast(desc.format) : texture->GetFormat(); VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = texture->GetImage(); viewInfo.viewType = ToVulkanImageViewType(m_dimension, texture->GetTextureType()); viewInfo.format = m_format != Format::Unknown ? ToVulkanFormat(m_format) : texture->GetVkFormat(); viewInfo.subresourceRange.aspectMask = GetImageAspectMask(texture->GetFormat()); viewInfo.subresourceRange.baseMipLevel = desc.mipLevel; viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = desc.firstArraySlice; viewInfo.subresourceRange.layerCount = 1; return vkCreateImageView(device, &viewInfo, nullptr, &m_imageView) == VK_SUCCESS; } bool VulkanResourceView::InitializeAsUnorderedAccess(VkDevice device, VulkanTexture* texture, const ResourceViewDesc& desc) { if (device == VK_NULL_HANDLE || texture == nullptr || texture->GetImage() == VK_NULL_HANDLE) { return false; } m_device = device; m_texture = texture; m_viewType = ResourceViewType::UnorderedAccess; m_dimension = desc.dimension != ResourceViewDimension::Unknown ? desc.dimension : ResourceViewDimension::Texture2D; m_format = desc.format != 0 ? static_cast(desc.format) : texture->GetFormat(); VkImageViewCreateInfo viewInfo = {}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = texture->GetImage(); viewInfo.viewType = ToVulkanImageViewType(m_dimension, texture->GetTextureType()); viewInfo.format = m_format != Format::Unknown ? ToVulkanFormat(m_format) : texture->GetVkFormat(); viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.baseMipLevel = desc.mipLevel; viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = desc.firstArraySlice; viewInfo.subresourceRange.layerCount = 1; return vkCreateImageView(device, &viewInfo, nullptr, &m_imageView) == VK_SUCCESS; } bool VulkanResourceView::InitializeAsVertexBuffer(VulkanBuffer* buffer, const ResourceViewDesc& desc) { if (buffer == nullptr || buffer->GetBuffer() == VK_NULL_HANDLE) { return false; } m_viewType = ResourceViewType::VertexBuffer; m_dimension = ResourceViewDimension::Buffer; m_format = Format::Unknown; m_buffer = buffer; m_bufferOffset = desc.bufferLocation; m_bufferSize = static_cast(buffer->GetSize()); m_bufferStride = desc.structureByteStride > 0 ? desc.structureByteStride : buffer->GetStride(); return true; } bool VulkanResourceView::InitializeAsIndexBuffer(VulkanBuffer* buffer, const ResourceViewDesc& desc) { if (buffer == nullptr || buffer->GetBuffer() == VK_NULL_HANDLE) { return false; } m_viewType = ResourceViewType::IndexBuffer; m_dimension = ResourceViewDimension::Buffer; m_format = desc.format != 0 ? static_cast(desc.format) : Format::R32_UInt; m_buffer = buffer; m_bufferOffset = desc.bufferLocation; m_bufferSize = static_cast(buffer->GetSize()); m_bufferStride = buffer->GetStride(); return true; } void* VulkanResourceView::GetNativeHandle() { if (m_imageView != VK_NULL_HANDLE) { return m_imageView; } return m_buffer != nullptr ? m_buffer->GetNativeHandle() : nullptr; } bool VulkanResourceView::IsValid() const { switch (m_viewType) { case ResourceViewType::VertexBuffer: case ResourceViewType::IndexBuffer: return m_buffer != nullptr && m_buffer->GetBuffer() != VK_NULL_HANDLE; case ResourceViewType::RenderTarget: case ResourceViewType::DepthStencil: case ResourceViewType::ShaderResource: case ResourceViewType::UnorderedAccess: return m_imageView != VK_NULL_HANDLE; default: return false; } } VkBuffer VulkanResourceView::GetBuffer() const { return m_buffer != nullptr ? m_buffer->GetBuffer() : VK_NULL_HANDLE; } void VulkanResourceView::Shutdown() { if (m_imageView != VK_NULL_HANDLE && m_device != VK_NULL_HANDLE) { vkDestroyImageView(m_device, m_imageView, nullptr); } m_imageView = VK_NULL_HANDLE; m_device = VK_NULL_HANDLE; m_texture = nullptr; m_buffer = nullptr; m_format = Format::Unknown; m_dimension = ResourceViewDimension::Unknown; m_bufferOffset = 0; m_bufferSize = 0; m_bufferStride = 0; } } // namespace RHI } // namespace XCEngine