2
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
6
// ConvertIndex.comp: Convert UINT_8 indices into UINT_16 using a compute shader.
8
// The following defines tweak the functionality, and a different shader is built based on these.
11
// * IsPrimitiveRestartEnabled: enables conversion from 0xFF to 0xFFFF,
12
// the restart indices for 8-bit and 16-bit indices.
13
// * IsIndirect: Use indirect buffer for index info
18
layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
20
layout (set = 0, binding = 0) buffer dst
22
// Shader invocations output one packed 32-bit value with up to two 16-bit indices.
26
layout (set = 0, binding = 1) readonly buffer src
28
// Shader invocations read at most 16 bits of one packed 32-bit value. (Two 8-bit indices.)
33
layout (set = 0, binding = 2) readonly buffer srcIndirect
35
// Shader invocations read from the srcIndirectBuf buffer to determine what indices to convert
36
// The command data starts at offset srcIndirectOffsetDiv4 of the srcIndirectBuf buffer.
37
uint srcIndirectBuf[];
40
layout (set = 0, binding = 3) buffer dstIndirect
42
// output indirect buffer data, data starts at dstIndirectBufOffsetDiv4
43
uint dstIndirectBuf[];
46
layout (push_constant) uniform PushConstants
48
// Read offset in bytes into the srcIndirectBuf array, divided by four.
49
uint srcIndirectOffsetDiv4;
50
// Write offset in bytes into the dstIndexBuf array, divided by four.
51
uint dstIndexBufOffsetDiv4;
52
// Maximum size of the read buffer. The highest index value we will convert.
54
// Write offset in bytes/4 of destinatio indirect buffer
55
uint dstIndirectBufOffsetDiv4;
60
layout (push_constant) uniform PushConstants
62
// Read offset in bytes into the srcIndexBuf array.
64
// Write offset in bytes into the dstIndexBuf array, divided by four.
65
uint dstIndexBufOffsetDiv4;
66
// Maximum size of the read buffer. The highest index value we will convert.
68
// Not used in the shader. Kept to pad "PushConstants" to the size of a vec4.
73
uint PullIndex(uint index)
76
uint srcIndex = index;
78
uint srcIndex = index + srcIndexOffset;
80
uint srcBlock = srcIndexBuf[srcIndex >> 2];
81
uint srcComponent = (srcIndex & 3);
83
uint value = (srcBlock >> (srcComponent << 3)) & 0xFF;
84
#if IsPrimitiveRestartEnabled
85
// convert 0xFF (restart value for 8-bit indices)
86
// to 0xFFFF (restart value for 16-bit indices).
93
void PackIndexValue(uint srcValue, uint indexIndex, inout uint dstValue)
95
// Pack 16-byte index into the 32-byte destination.
96
dstValue |= srcValue << (indexIndex << 4);
102
uint indexCount = srcIndirectBuf[srcIndirectOffsetDiv4];
103
uint firstIndex = srcIndirectBuf[srcIndirectOffsetDiv4 + 2];
104
uint endIndex = firstIndex + indexCount;
107
uint endIndex = firstIndex + maxIndex;
110
// The element index is invocation ID times two plus
111
// the firstIndex / 2.
112
// This way the first indexCount/2 invocations will transform
113
// the data and any additional invocations will be a no-op
114
uint index = ((gl_GlobalInvocationID.x + (firstIndex >> 1)) << 1);
116
// Don't write anything to dest if we're entirely past the end of the buffer.
117
// We assume buffer size is uint-aligned.
118
if (index >= endIndex)
123
// Skip packing the first index if we're before the first element.
124
if (index >= firstIndex)
126
uint srcValue = PullIndex(index);
127
PackIndexValue(srcValue, 0, dstValue);
130
// Skip packing the second index if we're after the last element.
131
if (index + 1 < endIndex)
133
uint srcValue = PullIndex(index + 1);
134
PackIndexValue(srcValue, 1, dstValue);
137
dstIndexBuf[dstIndexBufOffsetDiv4 + gl_GlobalInvocationID.x] = dstValue;
140
// Copy the source indirect draw info (DrawElementsIndirectCommand) to the destination
141
// indirect draw buffer adjusting the firstIndex to account for the offset into dstIndirectBuf
144
// uint instanceCount;
147
// uint reservedMustBeZero;
148
// } DrawElementsIndirectCommand;
149
if (gl_GlobalInvocationID.x == 0)
151
dstIndirectBuf[dstIndirectBufOffsetDiv4] = srcIndirectBuf[srcIndirectOffsetDiv4]; // count
153
dstIndirectBuf[dstIndirectBufOffsetDiv4 + 1] = srcIndirectBuf[srcIndirectOffsetDiv4 + 1];
154
// ANGLE will supply dstIndexBufOffset when binding the index buffer so don't
155
// need to worry about that as part of firstIndex for the new indirect buffer command.
156
// firstIndex can be in 2nd half of word so add one if incoming firstIndex is odd
157
dstIndirectBuf[dstIndirectBufOffsetDiv4 + 2] = firstIndex & 1; // firstIndex
159
dstIndirectBuf[dstIndirectBufOffsetDiv4 + 3] = srcIndirectBuf[srcIndirectOffsetDiv4 + 3];
160
dstIndirectBuf[dstIndirectBufOffsetDiv4 + 4] = 0; // reservedMustBeZero