diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index 790e11b0..ab4bff80 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -12,6 +12,8 @@ #include "MG_State/GLState/Core.h" #include "MG_State/GLState/ErrorState/ErrorInfo.h" #include "MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h" +#include "MG_Util/Converters/GLToMG/TextureEnumConverter.h" +#include "MG_Util/Metrics/TextureMetrics.h" #include "MG_Util/Miscellany/IndexGenerator.h" #include #include @@ -58,6 +60,19 @@ namespace MobileGL::MG_Backend::DirectVulkan { UnorderedMap g_programResourceCaches; + void ClearReadPixelsOutput(GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { + if (!pixels || width <= 0 || height <= 0) { + return; + } + const auto inputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format); + const auto inputType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); + const SizeT size = MG_Util::CalculateInputTextureImageSize(inputFormat, inputType, + IntVec3(width, height, 1)); + if (size > 0) { + std::memset(pixels, 0, size); + } + } + String NormalizeDescriptorName(const SpvReflectDescriptorBinding& binding) { const char* rawName = binding.name; if (binding.type_description != nullptr && binding.type_description->type_name != nullptr) { @@ -1145,8 +1160,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { cache.storageBlocks[storageBlockIndex].binding = storageBlockBinding; } void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { - MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ReadPixels called with null VulkanRenderer"); - MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::ReadPixels called with null GL context"); + if (!pVulkanRenderer || !MG_State::pGLContext) { + // TODO: Route early/default-FBO readbacks through a real DirectVulkan read path instead of returning zeros. + ClearReadPixelsOutput(width, height, format, type, pixels); + return; + } pVulkanRenderer->ReadPixels(x, y, width, height, format, type, pixels); } void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) { @@ -1162,8 +1180,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void Clear(GLbitfield mask) { - MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::Clear called with null VulkanRenderer"); - MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::Clear called with null GL context"); + if (!pVulkanRenderer || !MG_State::pGLContext) { + // TODO: Preserve pending clears issued before the Vulkan renderer/context is fully attached. + return; + } pVulkanRenderer->Clear(mask); } @@ -1277,8 +1297,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::BlitFramebuffer called with null VulkanRenderer"); - MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::BlitFramebuffer called with null GL context"); + if (!pVulkanRenderer || !MG_State::pGLContext) { + // TODO: Support pre-renderer/default-FBO blits instead of dropping them at the DirectVulkan boundary. + return; + } pVulkanRenderer->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index b9dcf229..4cd9e419 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -908,17 +908,6 @@ namespace MobileGL::MG_Backend::DirectVulkan { return false; } - const auto& attachments = framebufferObject.GetAllAttachmentObjects(); - for (SizeT i = 0; i < attachments.size(); ++i) { - const auto attachmentType = static_cast(i); - const auto& attachment = attachments[i]; - if (attachment.IsRenderbuffer() && attachment.IsComplete()) { - if (IsColorAttachment(attachmentType)) { - return true; - } - } - } - const auto& depthAttachment = framebufferObject.GetAttachment(FramebufferAttachmentType::Depth); const auto& stencilAttachment = framebufferObject.GetAttachment(FramebufferAttachmentType::Stencil); if (!depthAttachment.IsComplete() || !stencilAttachment.IsComplete()) { @@ -936,6 +925,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { static Bool IsUnsupportedFramebufferForDirectVulkan( const MG_State::GLState::FramebufferObject& framebufferObject) { + // TODO: Revisit this gate when DirectVulkan has full color renderbuffer render/blit/readback support. return HasDistinctCompleteDepthStencilTextureAttachments(framebufferObject) || HasUnsupportedCompleteRenderbufferAttachment(framebufferObject); } diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp index eeecad6c..bf154453 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp @@ -45,23 +45,10 @@ namespace MobileGL::MG_Impl::GLImpl { depthAttachment.GetTextureLevel() != stencilAttachment.GetTextureLevel(); } - Bool HasCompleteRenderbufferAttachment(const MG_State::GLState::FramebufferObject& framebufferObject) { - if (framebufferObject.GetExternalIndex() == 0) { - return false; - } - - for (const auto& attachment : framebufferObject.GetAllAttachmentObjects()) { - if (attachment.IsRenderbuffer() && attachment.IsComplete()) { - return true; - } - } - return false; - } - Bool IsUnsupportedFramebufferForDirectVulkan( const MG_State::GLState::FramebufferObject& framebufferObject) { - return HasDistinctCompleteDepthStencilTextureAttachments(framebufferObject) || - HasCompleteRenderbufferAttachment(framebufferObject); + // TODO: Keep this in sync with DirectVulkan renderbuffer support as color renderbuffer rendering lands. + return HasDistinctCompleteDepthStencilTextureAttachments(framebufferObject); } Bool HasDefinedAttachment(const MG_State::GLState::FramebufferObject& framebufferObject) {