Revision control
Copy as Markdown
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "../effectlib/oitcommon.glsllib"
#if QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST
layout(std430, binding = 3) restrict coherent writeonly buffer qt_imgABuffer
{
uvec4 abufData[];
};
layout(std430, binding = 4) restrict coherent buffer qt_imgAux
{
uint auxData[];
};
layout(std430, binding = 5) restrict buffer qt_imgCounter
{
uint counter;
};
vec4 qt_oitLinkedList(const vec4 color, const uint listNodeCount, const uint abufImageWidth, const ivec2 viewSize, const uint viewIndex, const uint samples)
{
// +1 as 0 is used as a list terminator. Adds 1 to imgCounter[0,0] and
// returns the original value.
if (color.a <= 0.000001)
return vec4(0);
const uint newOffset = atomicAdd(counter, 1) + 1;
vec4 ret = vec4(0.0);
if(newOffset < listNodeCount) {
#if QSHADER_VIEW_COUNT >= 2
ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y + viewIndex * viewSize.y);
#else
ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y);
#endif
#if QSSG_MULTISAMPLE == 1
coord.x += gl_SampleID * viewSize.x;
#endif
uint index = coord.x + coord.y * viewSize.x * samples;
// Note that this is indeed thread-safe! The order in which threads
// reach this line determines the order of the fragments in the linked list.
const uint oldOffset = atomicExchange(auxData[index], newOffset);
const uvec4 storeValue = uvec4(packUnorm4x8(color),
floatBitsToUint(gl_FragCoord.z),
oldOffset,
0);
abufData[newOffset - 1] = storeValue;
} else {
ret = color;
}
return ret;
}
#endif