mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Fix] (DirectVulkan): clear an integer colour buffer with an integer value
glClearBufferiv and glClearBufferuiv flattened their values into the payload's float vector, and every clear was later written into VkClearColorValue::float32. Vulkan reads that union according to the destination image's format rather than converting between its members, so an R8I attachment cleared to -16 received the bit pattern of -16.0f. On top of that, QueueRenderbufferClear copied only the float vector into the pending clear, so even the flattened value was dropped and the attachment kept reading zero - which is what the conformance tests actually observed. The payload now records which of the three entry points supplied the colour and keeps the value in that form, and one helper builds the union member the encoding calls for. GL's rule that a format with no alpha channel reads as one has to be applied in the value's own type, so the "does this format lack alpha" question is now asked separately from the substitution and the helper applies it to whichever member is live. glClear is left on the float path explicitly: ClearFramebufferPayload has no other form. Takes every integer renderbuffer format in direct_state_access.renderbuffers_storage from failing to passing on Magma - 115 reported mismatches down to 20, the rest being the stencil formats Espryt fails too and SRGB8_ALPHA8 - and makes framebuffers_clear pass on both backends.
This commit is contained in:
@@ -24,13 +24,32 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
Uint32 stencil{};
|
||||
};
|
||||
|
||||
// A colour clear reaches us from one of glClear/ClearBufferfv, ClearBufferiv or
|
||||
// ClearBufferuiv, and Vulkan reads VkClearColorValue's union according to the destination
|
||||
// image's format rather than converting between the members - a float written where an
|
||||
// integer format is expected is reinterpreted bit for bit, not rounded. Remember which entry
|
||||
// point supplied the value so the member written when the clear is materialized matches.
|
||||
enum class ClearColorEncoding : Uint8 { Float, Int, Uint };
|
||||
|
||||
struct ClearAttachmentPayload {
|
||||
GLbitfield mask = 0;
|
||||
FloatVec4 color = FloatVec4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
ClearColorEncoding colorEncoding = ClearColorEncoding::Float;
|
||||
IntVec4 colorInt = IntVec4(0, 0, 0, 0);
|
||||
UintVec4 colorUint = UintVec4(0u, 0u, 0u, 0u);
|
||||
Float depth = 1.0f;
|
||||
Uint32 stencil = 0;
|
||||
};
|
||||
|
||||
// Builds the clear value for `payload` in the union member its encoding calls for.
|
||||
// `formatLacksAlpha` applies GL's rule that a format without an alpha channel reads as one,
|
||||
// expressed in whichever type matches (GL 4.6 core 15.2.3).
|
||||
VkClearColorValue MakeVkClearColorValue(const ClearAttachmentPayload& payload, Bool formatLacksAlpha);
|
||||
|
||||
// Applies that same rule in place, for the paths that have to bake it into the payload before
|
||||
// the destination is known.
|
||||
void ForceOpaqueClearAlpha(ClearAttachmentPayload& payload);
|
||||
|
||||
struct PendingClearKey {
|
||||
MG_State::GLState::ITextureObject* texture = nullptr;
|
||||
Uint64 textureLifetimeId = 0;
|
||||
|
||||
Reference in New Issue
Block a user