Revision control
++ // Copyright (C) 2025 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #ifdef QQ3D_SHADER_META
++ /*{
++ "uniforms": [
++ { "type": "uimage2D", "name": "qt_imgAbuffer" , "imgtype" : "rgba32ui" , "qualifiers": "restrict coherent writeonly" , "condition": "QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST" },
++ { "type": "uimage2D", "name": "qt_imgAux" , "imgtype" : "r32ui" , "qualifiers": "restrict coherent" , "condition": "QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST" },
++ { "type": "uimage2D", "name": "qt_imgCounter" , "imgtype" : "r32ui" , "qualifiers": "restrict" , "condition": "QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST" }
++ ]
++ }*/
++ #endif // QQ3D_SHADER_META
++
++ #include "../effectlib/oitcommon.glsllib"
++
++ ivec2 qt_indexToImageCoord(in uint index, const uint width)
++ {
++ ivec2 uv;
++ uv.y = int(index / width);
++ uv.x = int(index - uv.y * width);
++ return uv;
++ }
++
++ #if QSSG_OIT_METHOD == QSSG_OIT_LINKED_LIST
++
++ vec4 qt_oitLinkedList(const vec4 color, const uint listNodeCount, const uint abufImageWidth, const ivec2 viewSize, const uint viewIndex)
++ {
++ // +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 = imageAtomicAdd(qt_imgCounter, ivec2(0), 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
++ // 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 = imageAtomicExchange(qt_imgAux, coord, newOffset);
++
++ const uvec4 storeValue = uvec4(packUnorm4x8(color),
++ floatBitsToUint(gl_FragCoord.z),
++ oldOffset,
++ 0);
++
++ imageStore(qt_imgAbuffer, qt_indexToImageCoord(newOffset - 1, abufImageWidth), storeValue);
++ } else {
++ ret = color;
++ }
++ return ret;
++ }
++
++ #endif