[Feat] (MG_Backend/DirectVulkan): TextureManager mipmap completeness check

This commit is contained in:
2026-02-25 11:04:28 +08:00
parent db58f4c214
commit b4be1292b8
2 changed files with 47 additions and 29 deletions
@@ -68,10 +68,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
Bool VkTextureManager::SyncTexture(MG_State::GLState::ITextureObject &texture, Bool VkTextureManager::SyncTexture(MG_State::GLState::ITextureObject &texture,
TextureResource &outResource) { TextureResource &outResource) {
TextureUploadTarget level0Target = TextureUploadTarget::Unknown; TextureUploadTarget uploadTarget = TextureUploadTarget::Unknown;
IntVec3 texelSize{0, 0, 0}; IntVec3 texelSize{0, 0, 0};
SizeT byteSize = 0; SizeT byteSize = 0;
if (!CheckLevel0Completeness(texture, level0Target, texelSize, byteSize)) { Uint32 mipLevelCount = 0;
if (!CheckMipmapCompleteness(texture, uploadTarget, texelSize, byteSize, mipLevelCount)) {
return false; return false;
} }
@@ -80,18 +81,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return false; return false;
} }
const Uint32 mipLevelCount = GetUploadMipLevelCount(*mipTexture, level0Target); if (!SyncTextureResource(texture, uploadTarget, texelSize, byteSize, mipLevelCount, outResource)) {
if (mipLevelCount == 0) {
return false;
}
if (!SyncTextureResource(texture, level0Target, texelSize, byteSize, mipLevelCount, outResource)) {
return false; return false;
} }
Bool hasDirtyMipLevel = false; Bool hasDirtyMipLevel = false;
for (Uint32 level = 0; level < mipLevelCount; ++level) { for (Uint32 level = 0; level < mipLevelCount; ++level) {
if (mipTexture->IsStorageDirty(level0Target, level)) { if (mipTexture->IsStorageDirty(uploadTarget, level)) {
hasDirtyMipLevel = true; hasDirtyMipLevel = true;
break; break;
} }
@@ -100,14 +96,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true; return true;
} }
if (!UploadDirtyMipLevels(*mipTexture, level0Target, outResource)) { if (!UploadDirtyMipLevels(*mipTexture, uploadTarget, outResource)) {
return false; return false;
} }
return true; return true;
} }
Bool VkTextureManager::SyncTextureResource(const MG_State::GLState::ITextureObject &texture, Bool VkTextureManager::SyncTextureResource(const MG_State::GLState::ITextureObject &texture,
TextureUploadTarget level0Target, TextureUploadTarget uploadTarget,
const IntVec3 &texelSize, SizeT byteSize, Uint32 mipLevels, const IntVec3 &texelSize, SizeT byteSize, Uint32 mipLevels,
TextureResource &resource) { TextureResource &resource) {
const VkFormat format = GetVkFormat(texture.GetFormat()); const VkFormat format = GetVkFormat(texture.GetFormat());
@@ -120,7 +116,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (mipLevels == 0) { if (mipLevels == 0) {
return false; return false;
} }
if (level0Target != TextureUploadTarget::Texture2D) { if (uploadTarget != TextureUploadTarget::Texture2D) {
return false; return false;
} }
@@ -175,7 +171,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
Bool VkTextureManager::UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture, Bool VkTextureManager::UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
TextureUploadTarget level0Target, TextureUploadTarget uploadTarget,
TextureResource &outResource) { TextureResource &outResource) {
struct UploadItem { struct UploadItem {
Uint32 level = 0; Uint32 level = 0;
@@ -190,18 +186,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkDeviceSize stagingSize = 0; VkDeviceSize stagingSize = 0;
for (Uint32 level = 0; level < outResource.mipLevels; ++level) { for (Uint32 level = 0; level < outResource.mipLevels; ++level) {
if (!mipmapTexture.IsStorageDirty(level0Target, level)) { if (!mipmapTexture.IsStorageDirty(uploadTarget, level)) {
continue; continue;
} }
const auto texelSize = mipmapTexture.GetMipmapTexelSize(level0Target, level); const auto texelSize = mipmapTexture.GetMipmapTexelSize(uploadTarget, level);
const auto byteSize = mipmapTexture.GetMipmapByteSize(level0Target, level); const auto byteSize = mipmapTexture.GetMipmapByteSize(uploadTarget, level);
if (texelSize.x() <= 0 || texelSize.y() <= 0 || byteSize == 0) { if (texelSize.x() <= 0 || texelSize.y() <= 0 || byteSize == 0) {
mipmapTexture.MarkStorageDirty(level0Target, level, false); mipmapTexture.MarkStorageDirty(uploadTarget, level, false);
continue; continue;
} }
const void* source = mipmapTexture.MapMipmapData(level0Target, level); const void* source = mipmapTexture.MapMipmapData(uploadTarget, level);
if (source == nullptr) { if (source == nullptr) {
return false; return false;
} }
@@ -298,7 +294,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return false; return false;
} }
for (const auto& item : uploadItems) { for (const auto& item : uploadItems) {
mipmapTexture.MarkStorageDirty(level0Target, item.level, false); mipmapTexture.MarkStorageDirty(uploadTarget, item.level, false);
} }
outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
return true; return true;
@@ -350,8 +346,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
resource.format = VK_FORMAT_UNDEFINED; resource.format = VK_FORMAT_UNDEFINED;
} }
Bool VkTextureManager::CheckLevel0Completeness(const MG_State::GLState::ITextureObject& texture, TextureUploadTarget& outTarget, Bool VkTextureManager::CheckMipmapCompleteness(const MG_State::GLState::ITextureObject& texture,
IntVec3& outTexelSize, SizeT& outByteSize) { TextureUploadTarget& outTarget,
IntVec3& outTexelSize,
SizeT& outByteSize,
Uint32& outMipLevelCount) {
const auto* mipTexture = dynamic_cast<const MG_State::GLState::TextureObjectMipmap*>(&texture); const auto* mipTexture = dynamic_cast<const MG_State::GLState::TextureObjectMipmap*>(&texture);
if (!mipTexture) { if (!mipTexture) {
return false; return false;
@@ -360,10 +359,26 @@ namespace MobileGL::MG_Backend::DirectVulkan {
if (targets.empty()) { if (targets.empty()) {
return false; return false;
} }
outTarget = targets.front();
outTexelSize = mipTexture->GetMipmapTexelSize(outTarget, 0); for (const auto target : targets) {
outByteSize = mipTexture->GetMipmapByteSize(outTarget, 0); const Uint32 mipLevelCount = GetUploadMipLevelCount(*mipTexture, target);
return outTexelSize.x() > 0 && outTexelSize.y() > 0 && outByteSize > 0; if (mipLevelCount == 0) {
continue;
}
const auto level0TexelSize = mipTexture->GetMipmapTexelSize(target, 0);
const auto level0ByteSize = mipTexture->GetMipmapByteSize(target, 0);
if (level0TexelSize.x() <= 0 || level0TexelSize.y() <= 0 || level0ByteSize == 0) {
continue;
}
outTarget = target;
outTexelSize = level0TexelSize;
outByteSize = level0ByteSize;
outMipLevelCount = mipLevelCount;
return true;
}
return false;
} }
Uint32 VkTextureManager::GetUploadMipLevelCount(const MG_State::GLState::TextureObjectMipmap& texture, Uint32 VkTextureManager::GetUploadMipLevelCount(const MG_State::GLState::TextureObjectMipmap& texture,
@@ -48,16 +48,19 @@ private:
Bool SyncTexture(MG_State::GLState::ITextureObject &texture, Bool SyncTexture(MG_State::GLState::ITextureObject &texture,
TextureResource &outResource); TextureResource &outResource);
Bool SyncTextureResource(const MG_State::GLState::ITextureObject &texture, Bool SyncTextureResource(const MG_State::GLState::ITextureObject &texture,
TextureUploadTarget level0Target, TextureUploadTarget uploadTarget,
const IntVec3 &texelSize, SizeT byteSize, Uint32 mipLevels, const IntVec3 &texelSize, SizeT byteSize, Uint32 mipLevels,
TextureResource &resource); TextureResource &resource);
Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture, Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
TextureUploadTarget level0Target, TextureUploadTarget uploadTarget,
TextureResource &outResource); TextureResource &outResource);
Bool ExecuteCmdBufImmediate(const std::function<void(VkCommandBuffer)>& recorder) const; Bool ExecuteCmdBufImmediate(const std::function<void(VkCommandBuffer)>& recorder) const;
void DestroyTextureResource(TextureResource& resource) const; void DestroyTextureResource(TextureResource& resource) const;
static Bool CheckLevel0Completeness(const MG_State::GLState::ITextureObject& texture, TextureUploadTarget& outTarget, static Bool CheckMipmapCompleteness(const MG_State::GLState::ITextureObject& texture,
IntVec3& outTexelSize, SizeT& outByteSize); TextureUploadTarget& outTarget,
IntVec3& outTexelSize,
SizeT& outByteSize,
Uint32& outMipLevelCount);
static Uint32 GetUploadMipLevelCount(const MG_State::GLState::TextureObjectMipmap& texture, TextureUploadTarget target); static Uint32 GetUploadMipLevelCount(const MG_State::GLState::TextureObjectMipmap& texture, TextureUploadTarget target);
static VkFormat GetVkFormat(TextureInternalFormat format); static VkFormat GetVkFormat(TextureInternalFormat format);