mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 22:28:32 +09:00
[Fix] (MG_Backend/DirectVulkan): use fallback texture in case some
shaderpack failes to properly bind texture
This commit is contained in:
@@ -717,16 +717,18 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
"ProgramFactory::ReflectLayout: sampler binding %u exceeds maxBindings=%u for '%s'",
|
"ProgramFactory::ReflectLayout: sampler binding %u exceeds maxBindings=%u for '%s'",
|
||||||
binding, m_maxBindings, uniformName.c_str());
|
binding, m_maxBindings, uniformName.c_str());
|
||||||
|
|
||||||
|
const Int location = program.GetUniformLocation(uniformName);
|
||||||
|
if (location < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
MOBILEGL_ASSERT(entry.bindingKinds[binding] == DescriptorBindingKind::None ||
|
MOBILEGL_ASSERT(entry.bindingKinds[binding] == DescriptorBindingKind::None ||
|
||||||
entry.bindingKinds[binding] == DescriptorBindingKind::CombinedImageSampler,
|
entry.bindingKinds[binding] == DescriptorBindingKind::CombinedImageSampler,
|
||||||
"ProgramFactory::ReflectLayout: descriptor binding %u has conflicting kinds for sampler '%s'",
|
"ProgramFactory::ReflectLayout: descriptor binding %u has conflicting kinds for sampler '%s'",
|
||||||
binding, uniformName.c_str());
|
binding, uniformName.c_str());
|
||||||
entry.bindingKinds[binding] = DescriptorBindingKind::CombinedImageSampler;
|
entry.bindingKinds[binding] = DescriptorBindingKind::CombinedImageSampler;
|
||||||
|
|
||||||
const Int location = program.GetUniformLocation(uniformName);
|
const TextureTarget target = UniformTypeToTextureTarget(program.GetUniformType(static_cast<Uint>(location)));
|
||||||
const TextureTarget target =
|
|
||||||
location >= 0 ? UniformTypeToTextureTarget(program.GetUniformType(static_cast<Uint>(location)))
|
|
||||||
: ReflectImageTraitsToTextureTarget(sampler->image);
|
|
||||||
MOBILEGL_ASSERT(target != TextureTarget::Unknown,
|
MOBILEGL_ASSERT(target != TextureTarget::Unknown,
|
||||||
"ProgramFactory::ReflectLayout: failed to resolve sampler target for '%s'",
|
"ProgramFactory::ReflectLayout: failed to resolve sampler target for '%s'",
|
||||||
uniformName.c_str());
|
uniformName.c_str());
|
||||||
|
|||||||
@@ -10,10 +10,38 @@
|
|||||||
|
|
||||||
#include "MG_State/GLState/Core.h"
|
#include "MG_State/GLState/Core.h"
|
||||||
#include "MG_State/GLState/ProgramState/ProgramObject.h"
|
#include "MG_State/GLState/ProgramState/ProgramObject.h"
|
||||||
|
#include "MG_State/GLState/TextureState/TextureObject2D.h"
|
||||||
#include "MG_Util/Converters/MGToStr/FramebufferEnumConverter.h"
|
#include "MG_Util/Converters/MGToStr/FramebufferEnumConverter.h"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace MobileGL::MG_Backend::DirectVulkan {
|
namespace MobileGL::MG_Backend::DirectVulkan {
|
||||||
|
namespace {
|
||||||
|
constexpr Uint kFallbackTextureExternalIndexBase = 0xFFFF0000u;
|
||||||
|
|
||||||
|
SharedPtr<MG_State::GLState::ITextureObject> CreateFallbackTexture2D(Uint externalIndex) {
|
||||||
|
static constexpr Array<Uint8, 4> kBlackPixel = {0, 0, 0, 255};
|
||||||
|
|
||||||
|
auto texture = MakeShared<MG_State::GLState::TextureObject2D>(externalIndex);
|
||||||
|
texture->SetInternalFormat(TextureInternalFormat::RGBA8);
|
||||||
|
texture->AllocateStorage(TextureUploadTarget::Texture2D, 0,
|
||||||
|
{.texelSize = {1, 1, 1}, .byteSize = kBlackPixel.size()});
|
||||||
|
texture->UpdateMipmapSubData(TextureUploadTarget::Texture2D, 0,
|
||||||
|
{.data = const_cast<Uint8*>(kBlackPixel.data()),
|
||||||
|
.size = kBlackPixel.size()});
|
||||||
|
texture->SetBaseLevel(0);
|
||||||
|
texture->SetMaxLevel(0);
|
||||||
|
|
||||||
|
const auto& sampler = texture->GetSamplerObject();
|
||||||
|
MOBILEGL_ASSERT(sampler != nullptr, "CreateFallbackTexture2D: texture sampler is null");
|
||||||
|
sampler->SetWrapS(SamplerWrapMode::ClampToEdge);
|
||||||
|
sampler->SetWrapT(SamplerWrapMode::ClampToEdge);
|
||||||
|
sampler->SetMinFilter(SamplerFilterMode::Nearest);
|
||||||
|
sampler->SetMagFilter(SamplerFilterMode::Nearest);
|
||||||
|
sampler->SetMipmapMode(SamplerMipmapMode::None);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Bool FindFramebufferAttachmentForTexture(const MG_State::GLState::FramebufferObject& framebuffer,
|
static Bool FindFramebufferAttachmentForTexture(const MG_State::GLState::FramebufferObject& framebuffer,
|
||||||
const MG_State::GLState::ITextureObject& texture,
|
const MG_State::GLState::ITextureObject& texture,
|
||||||
FramebufferAttachmentType& outAttachment, Int& outLevel) {
|
FramebufferAttachmentType& outAttachment, Int& outLevel) {
|
||||||
@@ -145,6 +173,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
m_peakDescriptorSetsObserved = 0;
|
m_peakDescriptorSetsObserved = 0;
|
||||||
m_textureManager = nullptr;
|
m_textureManager = nullptr;
|
||||||
m_samplerManager = nullptr;
|
m_samplerManager = nullptr;
|
||||||
|
for (auto& fallbackTexture : m_samplerFallbackTextures) {
|
||||||
|
fallbackTexture.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UniformManager::BeginFrame(Uint32 frameIndex) {
|
void UniformManager::BeginFrame(Uint32 frameIndex) {
|
||||||
@@ -292,13 +323,38 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
outTexture = textureUnit.GetBindingSlot(preferredTarget).GetBoundObject();
|
outTexture = textureUnit.GetBindingSlot(preferredTarget).GetBoundObject();
|
||||||
|
|
||||||
if (!outTexture) {
|
if (!outTexture) {
|
||||||
MGLOG_E("ResolveSamplerTexture: no texture bound for sampler binding=%u location=%d unit=%d target=%d",
|
outTexture = GetOrCreateSamplerFallbackTexture(preferredTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outTexture) {
|
||||||
|
MGLOG_E(
|
||||||
|
"ResolveSamplerTexture: no texture bound and no fallback available for sampler binding=%u location=%d unit=%d target=%d",
|
||||||
binding, location, unit, static_cast<Int>(preferredTarget));
|
binding, location, unit, static_cast<Int>(preferredTarget));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return outTexture != nullptr;
|
return outTexture != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedPtr<MG_State::GLState::ITextureObject>
|
||||||
|
UniformManager::GetOrCreateSamplerFallbackTexture(TextureTarget target) const {
|
||||||
|
const SizeT targetIndex = static_cast<SizeT>(target);
|
||||||
|
MOBILEGL_ASSERT(targetIndex < m_samplerFallbackTextures.size(),
|
||||||
|
"GetOrCreateSamplerFallbackTexture: invalid texture target %d", static_cast<Int>(target));
|
||||||
|
|
||||||
|
auto& fallbackTexture = m_samplerFallbackTextures[targetIndex];
|
||||||
|
if (fallbackTexture != nullptr) {
|
||||||
|
return fallbackTexture;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (target) {
|
||||||
|
case TextureTarget::Texture2D:
|
||||||
|
fallbackTexture = CreateFallbackTexture2D(kFallbackTextureExternalIndexBase + static_cast<Uint>(targetIndex));
|
||||||
|
return fallbackTexture;
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Bool UniformManager::CollectSampledTextures(const MG_State::GLState::ProgramObject& program,
|
Bool UniformManager::CollectSampledTextures(const MG_State::GLState::ProgramObject& program,
|
||||||
const ProgramFactory::VkProgramObject& programObj,
|
const ProgramFactory::VkProgramObject& programObj,
|
||||||
Vector<MG_State::GLState::ITextureObject*>& outTextures) {
|
Vector<MG_State::GLState::ITextureObject*>& outTextures) {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Bool ResolveSamplerTexture(const MG_State::GLState::ProgramObject& program,
|
Bool ResolveSamplerTexture(const MG_State::GLState::ProgramObject& program,
|
||||||
const ProgramFactory::VkProgramObject& programObj, Uint32 binding,
|
const ProgramFactory::VkProgramObject& programObj, Uint32 binding,
|
||||||
SharedPtr<MG_State::GLState::ITextureObject>& outTexture) const;
|
SharedPtr<MG_State::GLState::ITextureObject>& outTexture) const;
|
||||||
|
SharedPtr<MG_State::GLState::ITextureObject> GetOrCreateSamplerFallbackTexture(TextureTarget target) const;
|
||||||
Bool ResolveSamplerDescriptor(VkCommandBuffer commandBuffer, const MG_State::GLState::ProgramObject& program,
|
Bool ResolveSamplerDescriptor(VkCommandBuffer commandBuffer, const MG_State::GLState::ProgramObject& program,
|
||||||
const ProgramFactory::VkProgramObject& programObj, Uint32 binding,
|
const ProgramFactory::VkProgramObject& programObj, Uint32 binding,
|
||||||
VkDescriptorImageInfo& outImageInfo) const;
|
VkDescriptorImageInfo& outImageInfo) const;
|
||||||
@@ -90,6 +91,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
Uint32 m_peakDescriptorSetsObserved = 0;
|
Uint32 m_peakDescriptorSetsObserved = 0;
|
||||||
VkTextureManager* m_textureManager = nullptr;
|
VkTextureManager* m_textureManager = nullptr;
|
||||||
VkSamplerManager* m_samplerManager = nullptr;
|
VkSamplerManager* m_samplerManager = nullptr;
|
||||||
|
mutable Array<SharedPtr<MG_State::GLState::ITextureObject>,
|
||||||
|
static_cast<SizeT>(TextureTarget::TextureTargetCount)> m_samplerFallbackTextures{};
|
||||||
};
|
};
|
||||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user