mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 13:18:31 +09:00
[Feat] (MG_Backend/DirectVulkan): implement multisample texture backend
This commit is contained in:
@@ -46,6 +46,41 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Uint32 arrayLayers = 1;
|
||||
};
|
||||
|
||||
static Bool IsMultisampleTextureUploadTarget(TextureUploadTarget target) {
|
||||
return target == TextureUploadTarget::Texture2DMultisample ||
|
||||
target == TextureUploadTarget::ProxyTexture2DMultisample ||
|
||||
target == TextureUploadTarget::Texture2DMultisampleArray ||
|
||||
target == TextureUploadTarget::ProxyTexture2DMultisampleArray;
|
||||
}
|
||||
|
||||
static Bool TryResolveSampleCountFlagBits(Int requestedSamples, VkSampleCountFlagBits& outSampleCount) {
|
||||
switch (requestedSamples) {
|
||||
case 1:
|
||||
outSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
return true;
|
||||
case 2:
|
||||
outSampleCount = VK_SAMPLE_COUNT_2_BIT;
|
||||
return true;
|
||||
case 4:
|
||||
outSampleCount = VK_SAMPLE_COUNT_4_BIT;
|
||||
return true;
|
||||
case 8:
|
||||
outSampleCount = VK_SAMPLE_COUNT_8_BIT;
|
||||
return true;
|
||||
case 16:
|
||||
outSampleCount = VK_SAMPLE_COUNT_16_BIT;
|
||||
return true;
|
||||
case 32:
|
||||
outSampleCount = VK_SAMPLE_COUNT_32_BIT;
|
||||
return true;
|
||||
case 64:
|
||||
outSampleCount = VK_SAMPLE_COUNT_64_BIT;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static Bool IsCubeMapFaceUploadTarget(TextureUploadTarget target) {
|
||||
return target >= TextureUploadTarget::CubeMapPositiveX &&
|
||||
target <= TextureUploadTarget::CubeMapNegativeZ;
|
||||
@@ -468,6 +503,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
case TextureUploadTarget::ProxyTextureRectangle:
|
||||
outShape = {};
|
||||
return true;
|
||||
case TextureUploadTarget::Texture2DMultisample:
|
||||
case TextureUploadTarget::ProxyTexture2DMultisample:
|
||||
outShape = {};
|
||||
return true;
|
||||
case TextureUploadTarget::Texture2DMultisampleArray:
|
||||
case TextureUploadTarget::ProxyTexture2DMultisampleArray:
|
||||
MOBILEGL_ASSERT(texelSize.z() > 0,
|
||||
"TryResolveTextureShapeInfo: invalid 2D multisample array depth=%d for textureId=%d",
|
||||
texelSize.z(), texture.GetExternalIndex());
|
||||
outShape.imageType = VK_IMAGE_TYPE_2D;
|
||||
outShape.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
outShape.depth = 1;
|
||||
outShape.arrayLayers = static_cast<Uint32>(texelSize.z());
|
||||
return true;
|
||||
case TextureUploadTarget::Texture3D:
|
||||
case TextureUploadTarget::ProxyTexture3D:
|
||||
MOBILEGL_ASSERT(texelSize.z() > 0,
|
||||
@@ -806,6 +855,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
if (resource == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (resource->sampleCount != VK_SAMPLE_COUNT_1_BIT) {
|
||||
MGLOG_D("TransitionTextureForStorageImage: multisample textureId=%d is not exposed as a storage image",
|
||||
texture.GetExternalIndex());
|
||||
return false;
|
||||
}
|
||||
if (resource->layout == VK_IMAGE_LAYOUT_GENERAL) {
|
||||
return true;
|
||||
}
|
||||
@@ -958,7 +1012,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MGLOG_D("%s: no mip levels", __func__);
|
||||
return false;
|
||||
}
|
||||
const Uint32 backingMipLevels = std::max(mipLevels, ComputeFullMipLevelCount(texelSize));
|
||||
const Bool isMultisampleTexture = IsMultisampleTextureUploadTarget(uploadTarget);
|
||||
const Uint32 backingMipLevels =
|
||||
isMultisampleTexture ? 1u : std::max(mipLevels, ComputeFullMipLevelCount(texelSize));
|
||||
TextureShapeInfo shapeInfo{};
|
||||
const Bool supportedShape = TryResolveTextureShapeInfo(texture, uploadTarget, texelSize, shapeInfo);
|
||||
MOBILEGL_ASSERT(supportedShape,
|
||||
@@ -972,6 +1028,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
MGLOG_D("%s: not Texture2D, unsupported", __func__);
|
||||
return false;
|
||||
}
|
||||
VkSampleCountFlagBits resolvedSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
if (isMultisampleTexture &&
|
||||
!TryResolveSampleCountFlagBits(texture.GetSamples(), resolvedSampleCount)) {
|
||||
MGLOG_D("%s: unsupported multisample count=%d for textureId=%d target=%s", __func__,
|
||||
texture.GetSamples(), texture.GetExternalIndex(),
|
||||
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const Bool compatible = resource.image != VK_NULL_HANDLE && resource.format == format &&
|
||||
resource.extent.width == static_cast<Uint32>(texelSize.x()) &&
|
||||
@@ -979,6 +1043,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
resource.depth == shapeInfo.depth &&
|
||||
resource.arrayLayers == shapeInfo.arrayLayers &&
|
||||
resource.viewType == shapeInfo.viewType &&
|
||||
resource.sampleCount == resolvedSampleCount &&
|
||||
resource.mipLevels == backingMipLevels;
|
||||
if (compatible) {
|
||||
if (resource.perMipViews.size() != backingMipLevels) {
|
||||
@@ -998,6 +1063,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
resource.depth == shapeInfo.depth &&
|
||||
resource.arrayLayers == shapeInfo.arrayLayers &&
|
||||
resource.viewType == shapeInfo.viewType &&
|
||||
resource.sampleCount == resolvedSampleCount &&
|
||||
resolvedSampleCount == VK_SAMPLE_COUNT_1_BIT &&
|
||||
resource.mipLevels < backingMipLevels &&
|
||||
resource.layout != VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
@@ -1025,16 +1092,33 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkFormatProperties formatProperties{};
|
||||
vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &formatProperties);
|
||||
const Bool supportsStorageImage =
|
||||
!isMultisampleTexture &&
|
||||
(aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0 &&
|
||||
(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0;
|
||||
imageInfo.usage =
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
||||
(supportsStorageImage ? VK_IMAGE_USAGE_STORAGE_BIT : 0) |
|
||||
((aspect & VK_IMAGE_ASPECT_COLOR_BIT) ?
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
|
||||
((aspect & VK_IMAGE_ASPECT_DEPTH_BIT || aspect & VK_IMAGE_ASPECT_STENCIL_BIT) ?
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
|
||||
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
(supportsStorageImage ? VK_IMAGE_USAGE_STORAGE_BIT : 0) |
|
||||
((aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
|
||||
(((aspect & VK_IMAGE_ASPECT_DEPTH_BIT) || (aspect & VK_IMAGE_ASPECT_STENCIL_BIT)) ?
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :
|
||||
0);
|
||||
if (!isMultisampleTexture) {
|
||||
imageInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
}
|
||||
imageInfo.samples = resolvedSampleCount;
|
||||
if (isMultisampleTexture) {
|
||||
VkImageFormatProperties imageFormatProperties{};
|
||||
const VkResult imageFormatResult = vkGetPhysicalDeviceImageFormatProperties(
|
||||
m_physicalDevice, format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage,
|
||||
imageInfo.flags, &imageFormatProperties);
|
||||
if (imageFormatResult != VK_SUCCESS ||
|
||||
(imageFormatProperties.sampleCounts & resolvedSampleCount) == 0) {
|
||||
MGLOG_D("%s: sampleCount=%d is unsupported for textureId=%d target=%s format=%d usage=0x%x",
|
||||
__func__, texture.GetSamples(), texture.GetExternalIndex(),
|
||||
MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(),
|
||||
static_cast<Int>(format), static_cast<Uint32>(imageInfo.usage));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
VmaAllocationCreateInfo allocationInfo{};
|
||||
allocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||
@@ -1054,6 +1138,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
resource.format = format;
|
||||
resource.aspect = aspect;
|
||||
resource.viewType = shapeInfo.viewType;
|
||||
resource.sampleCount = resolvedSampleCount;
|
||||
resource.syncedTextureParamsVersion = 0;
|
||||
|
||||
if (preservedResource) {
|
||||
|
||||
Reference in New Issue
Block a user