mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Feat] (MG_Backend/DirectVulkan): implement multisample texture backend
This commit is contained in:
@@ -33,6 +33,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.pipelineLayout, sizeof(payload.pipelineLayout)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.pipelineLayout, sizeof(payload.pipelineLayout)));
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.renderPass, sizeof(payload.renderPass)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.renderPass, sizeof(payload.renderPass)));
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.colorAttachmentCount, sizeof(payload.colorAttachmentCount)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.colorAttachmentCount, sizeof(payload.colorAttachmentCount)));
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.rasterizationSamples, sizeof(payload.rasterizationSamples)));
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.subpass, sizeof(payload.subpass)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.subpass, sizeof(payload.subpass)));
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.topology, sizeof(payload.topology)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.topology, sizeof(payload.topology)));
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.cullMode, sizeof(payload.cullMode)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &payload.cullMode, sizeof(payload.cullMode)));
|
||||||
@@ -134,7 +135,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
raster.lineWidth = 1.0f;
|
raster.lineWidth = 1.0f;
|
||||||
|
|
||||||
VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
|
VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO};
|
||||||
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
ms.rasterizationSamples = payload.rasterizationSamples;
|
||||||
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencil{VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
|
VkPipelineDepthStencilStateCreateInfo depthStencil{VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
|
||||||
depthStencil.depthTestEnable = payload.depthTestEnable ? VK_TRUE : VK_FALSE;
|
depthStencil.depthTestEnable = payload.depthTestEnable ? VK_TRUE : VK_FALSE;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
||||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
Uint32 colorAttachmentCount = 1;
|
Uint32 colorAttachmentCount = 1;
|
||||||
|
VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
Uint32 subpass = 0;
|
Uint32 subpass = 0;
|
||||||
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT;
|
VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT;
|
||||||
|
|||||||
@@ -172,6 +172,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
auto* resource = m_textureManager.SyncTextureAndGetDescriptor(*texture);
|
auto* resource = m_textureManager.SyncTextureAndGetDescriptor(*texture);
|
||||||
if (resource != nullptr) {
|
if (resource != nullptr) {
|
||||||
imageIdentity = reinterpret_cast<Uint64>(resource->image);
|
imageIdentity = reinterpret_cast<Uint64>(resource->image);
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &resource->sampleCount, sizeof(resource->sampleCount)));
|
||||||
|
} else {
|
||||||
|
const VkSampleCountFlagBits fallbackSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
XXHASH_VERIFY(XXH64_update(m_hashState, &fallbackSampleCount, sizeof(fallbackSampleCount)));
|
||||||
}
|
}
|
||||||
XXHASH_VERIFY(XXH64_update(m_hashState, &imageIdentity, sizeof(imageIdentity)));
|
XXHASH_VERIFY(XXH64_update(m_hashState, &imageIdentity, sizeof(imageIdentity)));
|
||||||
}
|
}
|
||||||
@@ -289,6 +293,21 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
textureResources.reserve(colorAttachmentSlotCount + 1);
|
textureResources.reserve(colorAttachmentSlotCount + 1);
|
||||||
Vector<VkImageView> attachmentViews;
|
Vector<VkImageView> attachmentViews;
|
||||||
attachmentViews.reserve(colorAttachmentSlotCount + 1);
|
attachmentViews.reserve(colorAttachmentSlotCount + 1);
|
||||||
|
VkSampleCountFlagBits renderPassSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
Bool hasRenderPassSampleCount = false;
|
||||||
|
const auto adoptRenderPassSampleCount = [&](VkSampleCountFlagBits sampleCount,
|
||||||
|
const char* attachmentKind,
|
||||||
|
Int attachmentId) {
|
||||||
|
if (!hasRenderPassSampleCount) {
|
||||||
|
renderPassSampleCount = sampleCount;
|
||||||
|
hasRenderPassSampleCount = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MOBILEGL_ASSERT(renderPassSampleCount == sampleCount,
|
||||||
|
"GetOrCreateRenderPass: mismatched sample count %d on %s attachment %d (expected %d)",
|
||||||
|
static_cast<Int>(sampleCount), attachmentKind, attachmentId,
|
||||||
|
static_cast<Int>(renderPassSampleCount));
|
||||||
|
};
|
||||||
// This should automatically work on default & offscreen FBO
|
// This should automatically work on default & offscreen FBO
|
||||||
// assuming default FBO has the right param
|
// assuming default FBO has the right param
|
||||||
for (Uint32 i = 0; i < colorAttachmentSlotCount; ++i) {
|
for (Uint32 i = 0; i < colorAttachmentSlotCount; ++i) {
|
||||||
@@ -306,15 +325,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
// Color attachment description
|
// Color attachment description
|
||||||
VkAttachmentDescription& desc = attachmentDescriptions.back();
|
VkAttachmentDescription& desc = attachmentDescriptions.back();
|
||||||
switch (textureTarget) {
|
switch (textureTarget) {
|
||||||
case TextureTarget::Texture2D: {
|
case TextureTarget::Texture2D:
|
||||||
auto* texture2d =
|
case TextureTarget::Texture2DMultisample: {
|
||||||
static_cast<MG_State::GLState::TextureObject2D*>(texture);
|
|
||||||
desc.flags = 0;
|
desc.flags = 0;
|
||||||
desc.format = isDefaultFbo ?
|
desc.format = isDefaultFbo ?
|
||||||
m_swapchainObject.GetSurfaceFormat().format :
|
m_swapchainObject.GetSurfaceFormat().format :
|
||||||
MG_Util::ConvertTextureInternalFormatToVkEnum(
|
MG_Util::ConvertTextureInternalFormatToVkEnum(
|
||||||
texture2d->GetFormat());
|
texture->GetFormat());
|
||||||
desc.samples = VK_SAMPLE_COUNT_1_BIT;
|
VkSampleCountFlagBits attachmentSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
ClearAttachmentPayload clearPayload{};
|
ClearAttachmentPayload clearPayload{};
|
||||||
Bool hasClear = m_clearManager.GetPendingClear(att, clearPayload);
|
Bool hasClear = m_clearManager.GetPendingClear(att, clearPayload);
|
||||||
VkImageLayout trackedColorLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
VkImageLayout trackedColorLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
@@ -348,6 +366,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
.swapchainImageIndex = swapchainImageIndex,
|
.swapchainImageIndex = swapchainImageIndex,
|
||||||
.finalLayout = desc.finalLayout,
|
.finalLayout = desc.finalLayout,
|
||||||
});
|
});
|
||||||
|
attachmentSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
textureResources.emplace_back(nullptr);
|
textureResources.emplace_back(nullptr);
|
||||||
attachmentViews.emplace_back(swapchainViews[swapchainImageIndex]);
|
attachmentViews.emplace_back(swapchainViews[swapchainImageIndex]);
|
||||||
} else {
|
} else {
|
||||||
@@ -356,6 +375,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
"GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at color attachment %d", i);
|
"GetOrCreateRenderPass: SyncTextureAndGetDescriptor failed at color attachment %d", i);
|
||||||
textureResources.emplace_back(textureResource);
|
textureResources.emplace_back(textureResource);
|
||||||
desc.format = textureResource->format;
|
desc.format = textureResource->format;
|
||||||
|
attachmentSampleCount = textureResource->sampleCount;
|
||||||
trackedColorLayout = textureResource->layout;
|
trackedColorLayout = textureResource->layout;
|
||||||
trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo {
|
trackedAttachmentLayouts.emplace_back(TrackedAttachmentLayoutInfo {
|
||||||
.target = TrackedAttachmentTarget::Texture,
|
.target = TrackedAttachmentTarget::Texture,
|
||||||
@@ -372,6 +392,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MOBILEGL_ASSERT(attachmentViews.back() != VK_NULL_HANDLE,
|
MOBILEGL_ASSERT(attachmentViews.back() != VK_NULL_HANDLE,
|
||||||
"GetOrCreateRenderPass: GetOrCreateAttachmentView failed at color attachment %d", i);
|
"GetOrCreateRenderPass: GetOrCreateAttachmentView failed at color attachment %d", i);
|
||||||
}
|
}
|
||||||
|
desc.samples = attachmentSampleCount;
|
||||||
|
adoptRenderPassSampleCount(attachmentSampleCount, "color", texture->GetExternalIndex());
|
||||||
|
|
||||||
if (!hasClear && trackedColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
|
if (!hasClear && trackedColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
|
||||||
MGLOG_W("GetOrCreateRenderPass: color attachment textureId=%d starts with undefined layout and no clear; "
|
MGLOG_W("GetOrCreateRenderPass: color attachment textureId=%d starts with undefined layout and no clear; "
|
||||||
@@ -439,10 +461,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
depthAttachmentDescription.format = isDefaultFbo ?
|
depthAttachmentDescription.format = isDefaultFbo ?
|
||||||
m_swapchainObject.GetDepthStencilFormat() :
|
m_swapchainObject.GetDepthStencilFormat() :
|
||||||
MG_Util::ConvertTextureInternalFormatToVkEnum(texture.GetFormat());
|
MG_Util::ConvertTextureInternalFormatToVkEnum(texture.GetFormat());
|
||||||
|
VkSampleCountFlagBits depthAttachmentSampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
if (!isDefaultFbo) {
|
if (!isDefaultFbo) {
|
||||||
depthAttachmentDescription.format = depthTextureResource->format;
|
depthAttachmentDescription.format = depthTextureResource->format;
|
||||||
|
depthAttachmentSampleCount = depthTextureResource->sampleCount;
|
||||||
}
|
}
|
||||||
depthAttachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
|
depthAttachmentDescription.samples = depthAttachmentSampleCount;
|
||||||
|
adoptRenderPassSampleCount(depthAttachmentSampleCount, "depth/stencil", texture.GetExternalIndex());
|
||||||
const auto loadInfo =
|
const auto loadInfo =
|
||||||
ResolveDepthStencilAttachmentLoadInfo(trackedDepthLayout, clearDepth, clearStencil);
|
ResolveDepthStencilAttachmentLoadInfo(trackedDepthLayout, clearDepth, clearStencil);
|
||||||
depthAttachmentDescription.loadOp = loadInfo.depthLoadOp;
|
depthAttachmentDescription.loadOp = loadInfo.depthLoadOp;
|
||||||
@@ -556,13 +581,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
static_cast<Uint32>(attachmentViews.size()),
|
static_cast<Uint32>(attachmentViews.size()),
|
||||||
static_cast<Uint32>(colorAttachmentRefs.size()),
|
static_cast<Uint32>(colorAttachmentRefs.size()),
|
||||||
hasDepthStencilAttachment,
|
hasDepthStencilAttachment,
|
||||||
|
renderPassSampleCount,
|
||||||
extent,
|
extent,
|
||||||
1 };
|
1 };
|
||||||
MGLOG_D("VkRenderPassManager::GetOrCreateRenderPass: hash=0x%llx compatibilityHash=0x%llx attachmentCount=%u colorAttachmentCount=%u extent=%dx%d",
|
MGLOG_D("VkRenderPassManager::GetOrCreateRenderPass: hash=0x%llx compatibilityHash=0x%llx attachmentCount=%u colorAttachmentCount=%u samples=%d extent=%dx%d",
|
||||||
static_cast<unsigned long long>(hash),
|
static_cast<unsigned long long>(hash),
|
||||||
static_cast<unsigned long long>(compatibilityHash),
|
static_cast<unsigned long long>(compatibilityHash),
|
||||||
renderPassEntry.attachmentCount,
|
renderPassEntry.attachmentCount,
|
||||||
renderPassEntry.colorAttachmentCount,
|
renderPassEntry.colorAttachmentCount,
|
||||||
|
static_cast<Int>(renderPassEntry.sampleCount),
|
||||||
extent.x(),
|
extent.x(),
|
||||||
extent.y());
|
extent.y());
|
||||||
auto [insertedIt, _] = m_renderPasses.emplace(hash, Move(renderPassEntry));
|
auto [insertedIt, _] = m_renderPasses.emplace(hash, Move(renderPassEntry));
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Uint32 attachmentCount = 0;
|
Uint32 attachmentCount = 0;
|
||||||
Uint32 colorAttachmentCount = 0;
|
Uint32 colorAttachmentCount = 0;
|
||||||
Bool hasDepthStencilAttachment = false;
|
Bool hasDepthStencilAttachment = false;
|
||||||
|
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
IntVec2 extent = {0, 0};
|
IntVec2 extent = {0, 0};
|
||||||
Uint32 subpass = 0;
|
Uint32 subpass = 0;
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
std::swap(attachmentCount, that.attachmentCount);
|
std::swap(attachmentCount, that.attachmentCount);
|
||||||
std::swap(colorAttachmentCount, that.colorAttachmentCount);
|
std::swap(colorAttachmentCount, that.colorAttachmentCount);
|
||||||
std::swap(hasDepthStencilAttachment, that.hasDepthStencilAttachment);
|
std::swap(hasDepthStencilAttachment, that.hasDepthStencilAttachment);
|
||||||
|
std::swap(sampleCount, that.sampleCount);
|
||||||
std::swap(extent, that.extent);
|
std::swap(extent, that.extent);
|
||||||
std::swap(subpass, that.subpass);
|
std::swap(subpass, that.subpass);
|
||||||
}
|
}
|
||||||
@@ -86,6 +88,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Uint32 attachmentCount,
|
Uint32 attachmentCount,
|
||||||
Uint32 colorAttachmentCount,
|
Uint32 colorAttachmentCount,
|
||||||
Bool hasDepthStencilAttachment,
|
Bool hasDepthStencilAttachment,
|
||||||
|
VkSampleCountFlagBits sampleCount,
|
||||||
IntVec2 extent, int subpass):
|
IntVec2 extent, int subpass):
|
||||||
hash(hash),
|
hash(hash),
|
||||||
renderPass(renderpass),
|
renderPass(renderpass),
|
||||||
@@ -96,6 +99,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
attachmentCount(attachmentCount),
|
attachmentCount(attachmentCount),
|
||||||
colorAttachmentCount(colorAttachmentCount),
|
colorAttachmentCount(colorAttachmentCount),
|
||||||
hasDepthStencilAttachment(hasDepthStencilAttachment),
|
hasDepthStencilAttachment(hasDepthStencilAttachment),
|
||||||
|
sampleCount(sampleCount),
|
||||||
extent(extent),
|
extent(extent),
|
||||||
subpass(subpass)
|
subpass(subpass)
|
||||||
{}
|
{}
|
||||||
|
|||||||
@@ -46,6 +46,41 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Uint32 arrayLayers = 1;
|
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) {
|
static Bool IsCubeMapFaceUploadTarget(TextureUploadTarget target) {
|
||||||
return target >= TextureUploadTarget::CubeMapPositiveX &&
|
return target >= TextureUploadTarget::CubeMapPositiveX &&
|
||||||
target <= TextureUploadTarget::CubeMapNegativeZ;
|
target <= TextureUploadTarget::CubeMapNegativeZ;
|
||||||
@@ -468,6 +503,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
case TextureUploadTarget::ProxyTextureRectangle:
|
case TextureUploadTarget::ProxyTextureRectangle:
|
||||||
outShape = {};
|
outShape = {};
|
||||||
return true;
|
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::Texture3D:
|
||||||
case TextureUploadTarget::ProxyTexture3D:
|
case TextureUploadTarget::ProxyTexture3D:
|
||||||
MOBILEGL_ASSERT(texelSize.z() > 0,
|
MOBILEGL_ASSERT(texelSize.z() > 0,
|
||||||
@@ -806,6 +855,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
if (resource == nullptr) {
|
if (resource == nullptr) {
|
||||||
return false;
|
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) {
|
if (resource->layout == VK_IMAGE_LAYOUT_GENERAL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -958,7 +1012,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MGLOG_D("%s: no mip levels", __func__);
|
MGLOG_D("%s: no mip levels", __func__);
|
||||||
return false;
|
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{};
|
TextureShapeInfo shapeInfo{};
|
||||||
const Bool supportedShape = TryResolveTextureShapeInfo(texture, uploadTarget, texelSize, shapeInfo);
|
const Bool supportedShape = TryResolveTextureShapeInfo(texture, uploadTarget, texelSize, shapeInfo);
|
||||||
MOBILEGL_ASSERT(supportedShape,
|
MOBILEGL_ASSERT(supportedShape,
|
||||||
@@ -972,6 +1028,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MGLOG_D("%s: not Texture2D, unsupported", __func__);
|
MGLOG_D("%s: not Texture2D, unsupported", __func__);
|
||||||
return false;
|
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 &&
|
const Bool compatible = resource.image != VK_NULL_HANDLE && resource.format == format &&
|
||||||
resource.extent.width == static_cast<Uint32>(texelSize.x()) &&
|
resource.extent.width == static_cast<Uint32>(texelSize.x()) &&
|
||||||
@@ -979,6 +1043,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
resource.depth == shapeInfo.depth &&
|
resource.depth == shapeInfo.depth &&
|
||||||
resource.arrayLayers == shapeInfo.arrayLayers &&
|
resource.arrayLayers == shapeInfo.arrayLayers &&
|
||||||
resource.viewType == shapeInfo.viewType &&
|
resource.viewType == shapeInfo.viewType &&
|
||||||
|
resource.sampleCount == resolvedSampleCount &&
|
||||||
resource.mipLevels == backingMipLevels;
|
resource.mipLevels == backingMipLevels;
|
||||||
if (compatible) {
|
if (compatible) {
|
||||||
if (resource.perMipViews.size() != backingMipLevels) {
|
if (resource.perMipViews.size() != backingMipLevels) {
|
||||||
@@ -998,6 +1063,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
resource.depth == shapeInfo.depth &&
|
resource.depth == shapeInfo.depth &&
|
||||||
resource.arrayLayers == shapeInfo.arrayLayers &&
|
resource.arrayLayers == shapeInfo.arrayLayers &&
|
||||||
resource.viewType == shapeInfo.viewType &&
|
resource.viewType == shapeInfo.viewType &&
|
||||||
|
resource.sampleCount == resolvedSampleCount &&
|
||||||
|
resolvedSampleCount == VK_SAMPLE_COUNT_1_BIT &&
|
||||||
resource.mipLevels < backingMipLevels &&
|
resource.mipLevels < backingMipLevels &&
|
||||||
resource.layout != VK_IMAGE_LAYOUT_UNDEFINED;
|
resource.layout != VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
@@ -1025,16 +1092,33 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkFormatProperties formatProperties{};
|
VkFormatProperties formatProperties{};
|
||||||
vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &formatProperties);
|
vkGetPhysicalDeviceFormatProperties(m_physicalDevice, format, &formatProperties);
|
||||||
const Bool supportsStorageImage =
|
const Bool supportsStorageImage =
|
||||||
|
!isMultisampleTexture &&
|
||||||
(aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0 &&
|
(aspect & VK_IMAGE_ASPECT_COLOR_BIT) != 0 &&
|
||||||
(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0;
|
(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) != 0;
|
||||||
imageInfo.usage =
|
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
|
|
||||||
(supportsStorageImage ? VK_IMAGE_USAGE_STORAGE_BIT : 0) |
|
(supportsStorageImage ? VK_IMAGE_USAGE_STORAGE_BIT : 0) |
|
||||||
((aspect & VK_IMAGE_ASPECT_COLOR_BIT) ?
|
((aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
|
(((aspect & VK_IMAGE_ASPECT_DEPTH_BIT) || (aspect & VK_IMAGE_ASPECT_STENCIL_BIT)) ?
|
||||||
((aspect & VK_IMAGE_ASPECT_DEPTH_BIT || aspect & VK_IMAGE_ASPECT_STENCIL_BIT) ?
|
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :
|
||||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
|
0);
|
||||||
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
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;
|
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
VmaAllocationCreateInfo allocationInfo{};
|
VmaAllocationCreateInfo allocationInfo{};
|
||||||
allocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
allocationInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
|
||||||
@@ -1054,6 +1138,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
resource.format = format;
|
resource.format = format;
|
||||||
resource.aspect = aspect;
|
resource.aspect = aspect;
|
||||||
resource.viewType = shapeInfo.viewType;
|
resource.viewType = shapeInfo.viewType;
|
||||||
|
resource.sampleCount = resolvedSampleCount;
|
||||||
resource.syncedTextureParamsVersion = 0;
|
resource.syncedTextureParamsVersion = 0;
|
||||||
|
|
||||||
if (preservedResource) {
|
if (preservedResource) {
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public:
|
|||||||
VkFormat format = VK_FORMAT_UNDEFINED;
|
VkFormat format = VK_FORMAT_UNDEFINED;
|
||||||
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_NONE;
|
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_NONE;
|
||||||
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
|
VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
Uint16 syncedTextureParamsVersion = 0;
|
Uint16 syncedTextureParamsVersion = 0;
|
||||||
|
|
||||||
TextureResource() = default;
|
TextureResource() = default;
|
||||||
@@ -94,6 +95,7 @@ public:
|
|||||||
std::swap(this->format, that.format);
|
std::swap(this->format, that.format);
|
||||||
std::swap(this->aspect, that.aspect);
|
std::swap(this->aspect, that.aspect);
|
||||||
std::swap(this->viewType, that.viewType);
|
std::swap(this->viewType, that.viewType);
|
||||||
|
std::swap(this->sampleCount, that.sampleCount);
|
||||||
std::swap(this->syncedTextureParamsVersion, that.syncedTextureParamsVersion);
|
std::swap(this->syncedTextureParamsVersion, that.syncedTextureParamsVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +141,7 @@ public:
|
|||||||
format = VK_FORMAT_UNDEFINED;
|
format = VK_FORMAT_UNDEFINED;
|
||||||
aspect = VK_IMAGE_ASPECT_NONE;
|
aspect = VK_IMAGE_ASPECT_NONE;
|
||||||
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||||
syncedTextureParamsVersion = 0;
|
syncedTextureParamsVersion = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2167,6 +2167,7 @@ void main() {
|
|||||||
.pipelineLayout = programObj.pipelineLayout,
|
.pipelineLayout = programObj.pipelineLayout,
|
||||||
.renderPass = renderPassEntry.renderPass,
|
.renderPass = renderPassEntry.renderPass,
|
||||||
.colorAttachmentCount = renderPassEntry.colorAttachmentCount,
|
.colorAttachmentCount = renderPassEntry.colorAttachmentCount,
|
||||||
|
.rasterizationSamples = renderPassEntry.sampleCount,
|
||||||
.subpass = 0,
|
.subpass = 0,
|
||||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||||
.cullMode = VK_CULL_MODE_NONE,
|
.cullMode = VK_CULL_MODE_NONE,
|
||||||
@@ -2633,6 +2634,7 @@ void main() {
|
|||||||
.pipelineLayout = programObj.pipelineLayout,
|
.pipelineLayout = programObj.pipelineLayout,
|
||||||
.renderPass = renderPassEntry.renderPass,
|
.renderPass = renderPassEntry.renderPass,
|
||||||
.colorAttachmentCount = renderPassEntry.colorAttachmentCount,
|
.colorAttachmentCount = renderPassEntry.colorAttachmentCount,
|
||||||
|
.rasterizationSamples = renderPassEntry.sampleCount,
|
||||||
.subpass = 0,
|
.subpass = 0,
|
||||||
.topology = MG_Util::ConvertPrimitiveModeToVkEnum(mode),
|
.topology = MG_Util::ConvertPrimitiveModeToVkEnum(mode),
|
||||||
.cullMode = cullFaceEnabled
|
.cullMode = cullFaceEnabled
|
||||||
|
|||||||
Reference in New Issue
Block a user