mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (MG_Backend/DirectVulkan): implement 3D texture handling
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "VkTextureManager.h"
|
||||
|
||||
#include "MG_State/GLState/Core.h"
|
||||
#include "MG_Util/Converters/MGToStr/TextureEnumConverter.h"
|
||||
#include "MG_Util/Converters/MGToVk/TextureEnumConverter.h"
|
||||
|
||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
@@ -21,6 +22,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Array<Uint8, 4> alphaBytes = {0, 0, 0, 0};
|
||||
};
|
||||
|
||||
struct TextureShapeInfo {
|
||||
VkImageType imageType = VK_IMAGE_TYPE_2D;
|
||||
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
VkImageCreateFlags imageFlags = 0;
|
||||
Uint32 depth = 1;
|
||||
Uint32 arrayLayers = 1;
|
||||
};
|
||||
|
||||
static Bool IsValidSampledImageLayout(VkImageLayout layout) {
|
||||
switch (layout) {
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
@@ -110,6 +119,30 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return components;
|
||||
}
|
||||
|
||||
static Bool TryResolveTextureShapeInfo(const MG_State::GLState::ITextureObject& texture,
|
||||
TextureUploadTarget uploadTarget, const IntVec3& texelSize,
|
||||
TextureShapeInfo& outShape) {
|
||||
switch (uploadTarget) {
|
||||
case TextureUploadTarget::Texture2D:
|
||||
case TextureUploadTarget::ProxyTexture2D:
|
||||
case TextureUploadTarget::TextureRectangle:
|
||||
case TextureUploadTarget::ProxyTextureRectangle:
|
||||
outShape = {};
|
||||
return true;
|
||||
case TextureUploadTarget::Texture3D:
|
||||
case TextureUploadTarget::ProxyTexture3D:
|
||||
MOBILEGL_ASSERT(texelSize.z() > 0,
|
||||
"TryResolveTextureShapeInfo: invalid 3D texture depth=%d for textureId=%d",
|
||||
texelSize.z(), texture.GetExternalIndex());
|
||||
outShape.imageType = VK_IMAGE_TYPE_3D;
|
||||
outShape.viewType = VK_IMAGE_VIEW_TYPE_3D;
|
||||
outShape.depth = static_cast<Uint32>(texelSize.z());
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Bool VkTextureManager::Initialize(const InitInfo& initInfo) {
|
||||
Shutdown();
|
||||
|
||||
@@ -172,7 +205,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return perMipView;
|
||||
}
|
||||
|
||||
perMipView = CreateImageView(resource->image, resource->format, resource->aspect, mipLevel, 1);
|
||||
perMipView = CreateImageView(resource->image, resource->format, resource->aspect, resource->viewType,
|
||||
mipLevel, 1, resource->arrayLayers);
|
||||
if (perMipView == VK_NULL_HANDLE) {
|
||||
MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u", __func__, texture.GetExternalIndex(), mipLevel);
|
||||
return VK_NULL_HANDLE;
|
||||
@@ -198,8 +232,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
const VkComponentMapping sampledComponents = ResolveSampledViewComponents(texture);
|
||||
perMipSampledView = CreateImageView(resource->image, resource->format, resource->aspect, mipLevel, 1,
|
||||
&sampledComponents);
|
||||
perMipSampledView = CreateImageView(resource->image, resource->format, resource->aspect, resource->viewType,
|
||||
mipLevel, 1, resource->arrayLayers, &sampledComponents);
|
||||
if (perMipSampledView == VK_NULL_HANDLE) {
|
||||
MGLOG_D("%s: CreateImageView failed for textureId=%d mipLevel=%u", __func__, texture.GetExternalIndex(),
|
||||
mipLevel);
|
||||
@@ -381,7 +415,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MGLOG_D("%s: no mip levels", __func__);
|
||||
return false;
|
||||
}
|
||||
if (uploadTarget != TextureUploadTarget::Texture2D) {
|
||||
TextureShapeInfo shapeInfo{};
|
||||
const Bool supportedShape = TryResolveTextureShapeInfo(texture, uploadTarget, texelSize, shapeInfo);
|
||||
MOBILEGL_ASSERT(supportedShape,
|
||||
"SyncTextureResource: unsupported uploadTarget=%s textureTarget=%s textureId=%d size=(%d,%d,%d) "
|
||||
"mipLevels=%u vkViewType=%d",
|
||||
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(),
|
||||
MG_Util::ConvertTextureTargetToString(texture.GetTarget()).c_str(),
|
||||
texture.GetExternalIndex(), texelSize.x(), texelSize.y(), texelSize.z(), mipLevels,
|
||||
static_cast<Int>(MG_Util::ConvertTextureUploadTargetToVkEnum(uploadTarget)));
|
||||
if (!supportedShape) {
|
||||
MGLOG_D("%s: not Texture2D, unsupported", __func__);
|
||||
return false;
|
||||
}
|
||||
@@ -389,6 +432,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
const Bool compatible = resource.image != VK_NULL_HANDLE && resource.format == format &&
|
||||
resource.extent.width == static_cast<Uint32>(texelSize.x()) &&
|
||||
resource.extent.height == static_cast<Uint32>(texelSize.y()) &&
|
||||
resource.depth == shapeInfo.depth &&
|
||||
resource.arrayLayers == shapeInfo.arrayLayers &&
|
||||
resource.viewType == shapeInfo.viewType &&
|
||||
resource.mipLevels == mipLevels;
|
||||
if (compatible) {
|
||||
if (resource.perMipViews.size() != mipLevels) {
|
||||
@@ -406,12 +452,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkImageCreateInfo imageInfo{};
|
||||
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageInfo.flags = shapeInfo.imageFlags;
|
||||
imageInfo.imageType = shapeInfo.imageType;
|
||||
imageInfo.extent.width = static_cast<Uint32>(texelSize.x());
|
||||
imageInfo.extent.height = static_cast<Uint32>(texelSize.y());
|
||||
imageInfo.extent.depth = 1;
|
||||
imageInfo.extent.depth = shapeInfo.depth;
|
||||
imageInfo.mipLevels = mipLevels;
|
||||
imageInfo.arrayLayers = 1;
|
||||
imageInfo.arrayLayers = shapeInfo.arrayLayers;
|
||||
imageInfo.format = format;
|
||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
@@ -431,6 +478,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
resource.layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
resource.extent = {static_cast<Uint32>(texelSize.x()), static_cast<Uint32>(texelSize.y())};
|
||||
resource.depth = shapeInfo.depth;
|
||||
resource.arrayLayers = shapeInfo.arrayLayers;
|
||||
resource.mipLevels = mipLevels;
|
||||
resource.perMipViews.assign(mipLevels, VK_NULL_HANDLE);
|
||||
resource.perMipSampledViews.assign(mipLevels, VK_NULL_HANDLE);
|
||||
@@ -438,6 +487,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
resource.sampledLevelCount = mipLevels;
|
||||
resource.format = format;
|
||||
resource.aspect = aspect;
|
||||
resource.viewType = shapeInfo.viewType;
|
||||
resource.syncedTextureParamsVersion = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -464,8 +514,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
const VkComponentMapping sampledComponents = ResolveSampledViewComponents(texture);
|
||||
resource.fullView = CreateImageView(resource.image, resource.format, resource.aspect, baseMipLevel, levelCount,
|
||||
&sampledComponents);
|
||||
resource.fullView = CreateImageView(resource.image, resource.format, resource.aspect, resource.viewType,
|
||||
baseMipLevel, levelCount, resource.arrayLayers, &sampledComponents);
|
||||
if (resource.fullView == VK_NULL_HANDLE) {
|
||||
return false;
|
||||
}
|
||||
@@ -477,12 +527,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
VkImageView VkTextureManager::CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect,
|
||||
Uint32 baseMipLevel, Uint32 levelCount,
|
||||
VkImageViewType viewType, Uint32 baseMipLevel, Uint32 levelCount,
|
||||
Uint32 layerCount,
|
||||
const VkComponentMapping* components) const {
|
||||
VkImageViewCreateInfo viewInfo{};
|
||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
viewInfo.image = image;
|
||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewInfo.viewType = viewType;
|
||||
viewInfo.format = format;
|
||||
viewInfo.components = components != nullptr ?
|
||||
*components :
|
||||
@@ -492,7 +543,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
viewInfo.subresourceRange.baseMipLevel = baseMipLevel;
|
||||
viewInfo.subresourceRange.levelCount = levelCount;
|
||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
viewInfo.subresourceRange.layerCount = 1;
|
||||
viewInfo.subresourceRange.layerCount = layerCount;
|
||||
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VK_VERIFY(vkCreateImageView(m_device, &viewInfo, nullptr, &view), "vkCreateImageView(texture)");
|
||||
@@ -618,7 +669,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
copy.imageSubresource.baseArrayLayer = 0;
|
||||
copy.imageSubresource.layerCount = 1;
|
||||
copy.imageOffset = {0, 0, 0};
|
||||
copy.imageExtent = {static_cast<Uint32>(item.texelSize.x()), static_cast<Uint32>(item.texelSize.y()), 1};
|
||||
copy.imageExtent = {static_cast<Uint32>(item.texelSize.x()), static_cast<Uint32>(item.texelSize.y()),
|
||||
item.texelSize.z() > 0 ? static_cast<Uint32>(item.texelSize.z()) : 1u};
|
||||
vkCmdCopyBufferToImage(commandBuffer, stagingBuffer, outResource.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, ©);
|
||||
}
|
||||
|
||||
@@ -36,11 +36,14 @@ public:
|
||||
Vector<VkImageView> perMipSampledViews;
|
||||
VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkExtent2D extent = {0, 0};
|
||||
Uint32 depth = 1;
|
||||
Uint32 arrayLayers = 1;
|
||||
Uint32 mipLevels = 1;
|
||||
Uint32 sampledBaseMipLevel = 0;
|
||||
Uint32 sampledLevelCount = 1;
|
||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_NONE;
|
||||
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
Uint16 syncedTextureParamsVersion = 0;
|
||||
|
||||
TextureResource() = default;
|
||||
@@ -53,11 +56,14 @@ public:
|
||||
std::swap(this->perMipSampledViews, that.perMipSampledViews);
|
||||
std::swap(this->layout, that.layout);
|
||||
std::swap(this->extent, that.extent);
|
||||
std::swap(this->depth, that.depth);
|
||||
std::swap(this->arrayLayers, that.arrayLayers);
|
||||
std::swap(this->mipLevels, that.mipLevels);
|
||||
std::swap(this->sampledBaseMipLevel, that.sampledBaseMipLevel);
|
||||
std::swap(this->sampledLevelCount, that.sampledLevelCount);
|
||||
std::swap(this->format, that.format);
|
||||
std::swap(this->aspect, that.aspect);
|
||||
std::swap(this->viewType, that.viewType);
|
||||
std::swap(this->syncedTextureParamsVersion, that.syncedTextureParamsVersion);
|
||||
}
|
||||
|
||||
@@ -85,11 +91,14 @@ public:
|
||||
allocation = nullptr;
|
||||
layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
extent = {0, 0};
|
||||
depth = 1;
|
||||
arrayLayers = 1;
|
||||
mipLevels = 1;
|
||||
sampledBaseMipLevel = 0;
|
||||
sampledLevelCount = 1;
|
||||
format = VK_FORMAT_UNDEFINED;
|
||||
aspect = VK_IMAGE_ASPECT_NONE;
|
||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
syncedTextureParamsVersion = 0;
|
||||
}
|
||||
|
||||
@@ -128,7 +137,8 @@ private:
|
||||
TextureResource &resource);
|
||||
Bool SyncTextureViews(const MG_State::GLState::ITextureObject& texture, TextureResource& resource);
|
||||
VkImageView CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect,
|
||||
Uint32 baseMipLevel, Uint32 levelCount,
|
||||
VkImageViewType viewType, Uint32 baseMipLevel, Uint32 levelCount,
|
||||
Uint32 layerCount,
|
||||
const VkComponentMapping* components = nullptr) const;
|
||||
Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
|
||||
TextureUploadTarget uploadTarget,
|
||||
|
||||
Reference in New Issue
Block a user