mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 05:08:31 +09:00
[Fix] (DirectVulkan): pass depth/stencil formats through sampled-view resolution so D24S8/D32FS8 samplers stop dropping draws, and memoize per-binding view-format resolution
This commit is contained in:
@@ -298,8 +298,23 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// descriptor valid.
|
||||
const Bool forceNearestFiltering = numericDomain == SamplerNumericDomain::SignedInteger ||
|
||||
numericDomain == SamplerNumericDomain::UnsignedInteger;
|
||||
const VkFormat sampledViewFormat =
|
||||
VkTextureManager::ResolveSampledImageViewFormat(resource->format, numericDomain);
|
||||
SamplerResolveMemo* viewFormatMemo =
|
||||
binding < m_samplerResolveMemo.size() ? &m_samplerResolveMemo[binding] : nullptr;
|
||||
VkFormat sampledViewFormat;
|
||||
if (viewFormatMemo != nullptr && viewFormatMemo->viewFormatValid &&
|
||||
viewFormatMemo->viewFormatSource == resource->format &&
|
||||
viewFormatMemo->viewFormatDomain == numericDomain) {
|
||||
sampledViewFormat = viewFormatMemo->viewFormat;
|
||||
} else {
|
||||
sampledViewFormat =
|
||||
VkTextureManager::ResolveSampledImageViewFormat(resource->format, numericDomain);
|
||||
if (viewFormatMemo != nullptr) {
|
||||
viewFormatMemo->viewFormatSource = resource->format;
|
||||
viewFormatMemo->viewFormatDomain = numericDomain;
|
||||
viewFormatMemo->viewFormat = sampledViewFormat;
|
||||
viewFormatMemo->viewFormatValid = true;
|
||||
}
|
||||
}
|
||||
if (sampledViewFormat == VK_FORMAT_UNDEFINED) {
|
||||
MGLOG_E("ResolveSamplerDescriptor: no compatible sampled view for binding=%u ('%s') "
|
||||
"textureId=%d imageFormat=%d numericDomain=%d",
|
||||
@@ -307,8 +322,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
static_cast<Int>(resource->format), static_cast<Int>(numericDomain));
|
||||
return false;
|
||||
}
|
||||
// No reinterpretation requested: bind the depth-or-color aspect view the sync above
|
||||
// already produced instead of re-entering GetOrCreateSampledImageView's sync path.
|
||||
const VkImageView sampledImageView =
|
||||
m_textureManager->GetOrCreateSampledImageView(*texture, sampledViewFormat);
|
||||
sampledViewFormat == resource->format
|
||||
? resource->sampledView
|
||||
: m_textureManager->GetOrCreateSampledImageView(*texture, sampledViewFormat);
|
||||
if (sampledImageView == VK_NULL_HANDLE) {
|
||||
MGLOG_E("ResolveSamplerDescriptor: failed to resolve sampled view for binding=%u ('%s') "
|
||||
"textureId=%d imageFormat=%d viewFormat=%d numericDomain=%d",
|
||||
|
||||
@@ -176,6 +176,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Uint16 textureParamsVersion = 0;
|
||||
Bool forceNearestFiltering = false;
|
||||
Bool valid = false;
|
||||
// ResolveSampledImageViewFormat is pure in (image format, numeric domain), but a
|
||||
// domain mismatch walks a ~184-entry format table. Memo the resolution per binding
|
||||
// so a reinterpreted sampler pays that scan once, not once per draw.
|
||||
VkFormat viewFormatSource = VK_FORMAT_UNDEFINED;
|
||||
SamplerNumericDomain viewFormatDomain = SamplerNumericDomain::Unknown;
|
||||
VkFormat viewFormat = VK_FORMAT_UNDEFINED;
|
||||
Bool viewFormatValid = false;
|
||||
};
|
||||
mutable Vector<SamplerResolveMemo> m_samplerResolveMemo;
|
||||
};
|
||||
|
||||
@@ -1921,6 +1921,15 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
|
||||
VkFormat VkTextureManager::ResolveSampledImageViewFormat(VkFormat imageFormat,
|
||||
SamplerNumericDomain numericDomain) {
|
||||
// Depth/stencil images always sample through the existing depth-aspect sampledView.
|
||||
// Combined formats (D24S8, D32FS8) are multi-numeric, so vkuFormatIsSampledFloat is
|
||||
// false for them by design, yet their depth aspect reads as float in every GL depth
|
||||
// texture mode; Vulkan also forbids reinterpreting them through color-class views.
|
||||
// Integer domains keep the same view (pre-reinterpretation behavior for stencil-index
|
||||
// style access) rather than failing the draw.
|
||||
if (vkuFormatIsDepthOrStencil(imageFormat)) {
|
||||
return imageFormat;
|
||||
}
|
||||
if (imageFormat == VK_FORMAT_UNDEFINED || numericDomain == SamplerNumericDomain::Unknown ||
|
||||
FormatMatchesSamplerNumericDomain(imageFormat, numericDomain)) {
|
||||
return imageFormat;
|
||||
|
||||
@@ -999,9 +999,27 @@ TEST(DirectVulkanSanity, SampledViewFormatMatchesSamplerNumericDomainWithoutChan
|
||||
EXPECT_EQ(VkTextureManager::ResolveSampledImageViewFormat(
|
||||
VK_FORMAT_B10G11R11_UFLOAT_PACK32, SamplerNumericDomain::UnsignedInteger),
|
||||
VK_FORMAT_UNDEFINED);
|
||||
|
||||
// Depth/stencil formats never resolve through color-class reinterpretation; they pass
|
||||
// through unchanged so the existing depth-aspect sampled view is used. Combined
|
||||
// depth-stencil formats are multi-numeric (vkuFormatIsSampledFloat is false for them),
|
||||
// so without the passthrough a plain sampler2D/sampler2DShadow on GL_DEPTH24_STENCIL8
|
||||
// would resolve to UNDEFINED and the draw would be dropped.
|
||||
EXPECT_EQ(VkTextureManager::ResolveSampledImageViewFormat(
|
||||
VK_FORMAT_D24_UNORM_S8_UINT, SamplerNumericDomain::Float),
|
||||
VK_FORMAT_D24_UNORM_S8_UINT);
|
||||
EXPECT_EQ(VkTextureManager::ResolveSampledImageViewFormat(
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT, SamplerNumericDomain::Float),
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||
EXPECT_EQ(VkTextureManager::ResolveSampledImageViewFormat(
|
||||
VK_FORMAT_D32_SFLOAT, SamplerNumericDomain::Float),
|
||||
VK_FORMAT_D32_SFLOAT);
|
||||
EXPECT_EQ(VkTextureManager::ResolveSampledImageViewFormat(
|
||||
VK_FORMAT_D24_UNORM_S8_UINT, SamplerNumericDomain::UnsignedInteger),
|
||||
VK_FORMAT_D24_UNORM_S8_UINT);
|
||||
EXPECT_EQ(VkTextureManager::ResolveSampledImageViewFormat(
|
||||
VK_FORMAT_D32_SFLOAT, SamplerNumericDomain::UnsignedInteger),
|
||||
VK_FORMAT_UNDEFINED);
|
||||
VK_FORMAT_D32_SFLOAT);
|
||||
|
||||
EXPECT_TRUE(VkTextureManager::AreSampledImageViewFormatsCompatible(
|
||||
VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_UINT));
|
||||
|
||||
Reference in New Issue
Block a user