blob: 053b3228b22688d91964cc276cc5772eebf425bf [file] [log] [blame]
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ConvertIndexIndirectLineloop.comp: Convert lineloop to linelist with primitive restart
// (if enabled). Will also output a new "command" buffer with adjusted index values.
//
// The following defines tweak the functionality, and a different shader is built based on these.
//
// - Flags:
// * Is32Bit: Process 32-bit indices, otherwise process 16-bit.
//
#version 450 core
layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
layout (set = 0, binding = 0) buffer dst
{
// Shader invocation outputs linelist(s) here.
uint dstData[];
};
layout (set = 0, binding = 1) readonly buffer src
{
// Source index buffer
uint srcData[];
};
layout (set = 0, binding = 2) readonly buffer cmd
{
// Shader invocations read the cmd data to determine what indices to convert
// Command data at offset cmdOffset of buffer
uint cmdData[];
};
layout (set = 0, binding = 3) buffer dstCmd
{
// Shader outputs updated indirect buffer here.
uint dstCmdData[];
};
layout (push_constant) uniform PushConstants
{
// Read offset in bytes into the cmdData array, divided by four.
uint cmdOffsetDiv4;
// Dst command offset in bytes into the cmdData array, divided by four.
uint dstCmdOffsetDiv4;
// Write offset in bytes into the dstData array, divided by four.
uint dstOffsetDiv4;
// Maximum size of the read buffer. The highest index value we will convert.
uint isRestartEnabled;
};
// Structure of command data loaded at offset cmdOffsetDiv4 of the cmdData buffer
// struct VkDrawIndexedIndirectCommand {
// uint32_t indexCount;
// uint32_t instanceCount;
// uint32_t firstIndex;
// int32_t vertexOffset;
// uint32_t firstInstance;
// };
uint GetIndexValue(uint index)
{
#ifdef Is32Bit
return srcData[index];
#else
// srcData points to 32bit words, get the word with our index value
uint srcBlock = srcData[index >> 1];
// Compute the shift necessary to access desired index value
uint srcShift = (index & 0x1) << 4;
// Only want 16bits
uint srcMask = 0xffff;
// unpacking correct 16bit index value from the 32bit word
uint value = (srcBlock >> srcShift) & srcMask;
return value;
#endif
}
void PutIndexValue(uint index, uint value)
{
#ifdef Is32Bit
dstData[dstOffsetDiv4 + index] = value;
return;
#else
// Compute index into dstData for our index value
uint dstIndex = dstOffsetDiv4 + (index >> 1);
// Get dest index value
uint srcBlock = dstData[dstIndex];
// Compute the shift for our index value
uint srcShift = (index & 0x1) << 4;
uint srcMask = 0xffff;
// Clear appropriate 16bits of 32bit word
srcBlock &= ~(srcMask << srcShift);
// Shift value to pack 16bit value into 32bit word
srcBlock |= value << srcShift;
// Store updated value in destination
dstData[dstIndex] = srcBlock;
#endif
}
void main()
{
// Load the relevant command info from cmdData
uint indexCount = cmdData[cmdOffsetDiv4];
uint firstIndex = cmdData[cmdOffsetDiv4 + 2];
uint endIndex = firstIndex + indexCount;
// Only first invocation does the work
if (gl_GlobalInvocationID.x >= 1)
return;
uint workingCount = 0;
uint srcIdx = firstIndex;
uint indicesRemaining = indexCount;
uint lineSize = 0;
uint firstIndexValue = 0;
while (indicesRemaining > 0)
{
uint indexValue;
#ifdef Is32Bit
uint restartValue = 0xffffffff;
#else
uint restartValue = 0xffff;
#endif
indexValue = GetIndexValue(srcIdx++);
if (lineSize == 0)
{
firstIndexValue = indexValue;
}
indicesRemaining--;
if ((isRestartEnabled == 1) && (indexValue == restartValue))
{
// We have a primitive restart, close the loop
if (lineSize > 1)
{
PutIndexValue(workingCount++, firstIndexValue);
}
if (lineSize > 0)
{
PutIndexValue(workingCount++, restartValue);
}
lineSize = 0;
} else {
PutIndexValue(workingCount, indexValue);
workingCount++;
lineSize++;
}
}
if (lineSize > 1)
{
PutIndexValue(workingCount, firstIndexValue);
workingCount++;
}
// Update new command buffer
dstCmdData[dstCmdOffsetDiv4] = workingCount;
dstCmdData[dstCmdOffsetDiv4 + 1] = cmdData[cmdOffsetDiv4 + 1];
dstCmdData[dstCmdOffsetDiv4 + 2] = 0;
dstCmdData[dstCmdOffsetDiv4 + 3] = cmdData[cmdOffsetDiv4 + 3];
dstCmdData[dstCmdOffsetDiv4 + 4] = cmdData[cmdOffsetDiv4 + 4];
}