pathfinder/resources/shaders/gl4/d3d11/bin.cs.glsl

260 lines
7.0 KiB
Plaintext
Raw Normal View History

2020-06-23 15:35:57 -04:00
#version {{version}}
// Automatically generated from files in pathfinder/shaders/. Do not edit!
#extension GL_GOOGLE_include_directive : enable
precision highp float;
layout(local_size_x = 64)in;
uniform int uMicrolineCount;
uniform int uMaxFillCount;
layout(std430, binding = 0)buffer bMicrolines {
restrict readonly uvec4 iMicrolines[];
};
layout(std430, binding = 1)buffer bMetadata {
restrict readonly ivec4 iMetadata[];
};
layout(std430, binding = 2)buffer bIndirectDrawParams {
restrict uint iIndirectDrawParams[];
};
layout(std430, binding = 3)buffer bFills {
restrict writeonly uint iFills[];
};
layout(std430, binding = 4)buffer bTiles {
restrict uint iTiles[];
};
layout(std430, binding = 5)buffer bBackdrops {
restrict uint iBackdrops[];
};
uint computeTileIndexNoCheck(ivec2 tileCoords, ivec4 pathTileRect, uint pathTileOffset){
ivec2 offsetCoords = tileCoords - pathTileRect . xy;
return pathTileOffset + offsetCoords . x + offsetCoords . y *(pathTileRect . z - pathTileRect . x);
}
bvec4 computeTileOutcodes(ivec2 tileCoords, ivec4 pathTileRect){
return bvec4(lessThan(tileCoords, pathTileRect . xy),
greaterThanEqual(tileCoords, pathTileRect . zw));
}
bool computeTileIndex(ivec2 tileCoords,
ivec4 pathTileRect,
uint pathTileOffset,
out uint outTileIndex){
outTileIndex = computeTileIndexNoCheck(tileCoords, pathTileRect, pathTileOffset);
return ! any(computeTileOutcodes(tileCoords, pathTileRect));
}
void addFill(vec4 lineSegment, ivec2 tileCoords, ivec4 pathTileRect, uint pathTileOffset){
uint tileIndex;
if(! computeTileIndex(tileCoords, pathTileRect, pathTileOffset, tileIndex)){
return;
}
uvec4 scaledLocalLine = uvec4((lineSegment - vec4(tileCoords . xyxy * ivec4(16)))* vec4(256.0));
if(scaledLocalLine . x == scaledLocalLine . z)
return;
uint fillIndex = atomicAdd(iIndirectDrawParams[1], 1);
uint fillLink = atomicExchange(iTiles[tileIndex * 4 + 1],
int(fillIndex));
if(fillIndex < uMaxFillCount){
iFills[fillIndex * 3 + 0]= scaledLocalLine . x |(scaledLocalLine . y << 16);
iFills[fillIndex * 3 + 1]= scaledLocalLine . z |(scaledLocalLine . w << 16);
iFills[fillIndex * 3 + 2]= fillLink;
}
}
void adjustBackdrop(int backdropDelta,
ivec2 tileCoords,
ivec4 pathTileRect,
uint pathTileOffset,
uint pathBackdropOffset){
bvec4 outcodes = computeTileOutcodes(tileCoords, pathTileRect);
if(any(outcodes)){
if(! outcodes . x && outcodes . y && ! outcodes . z){
uint backdropIndex = pathBackdropOffset + uint(tileCoords . x - pathTileRect . x);
atomicAdd(iBackdrops[backdropIndex * 3], backdropDelta);
}
} else {
uint tileIndex = computeTileIndexNoCheck(tileCoords, pathTileRect, pathTileOffset);
atomicAdd(iTiles[tileIndex * 4 + 2],
uint(backdropDelta)<< 24);
}
}
vec4 unpackMicroline(uvec4 packedMicroline, out uint outPathIndex){
outPathIndex = packedMicroline . w;
ivec4 signedMicroline = ivec4(packedMicroline);
return vec4((signedMicroline . x << 16)>> 16, signedMicroline . x >> 16,
(signedMicroline . y << 16)>> 16, signedMicroline . y >> 16)+
vec4(signedMicroline . z & 0xff,(signedMicroline . z >> 8)& 0xff,
(signedMicroline . z >> 16)& 0xff,(signedMicroline . z >> 24)& 0xff)/ 256.0;
}
void main(){
uint segmentIndex = gl_GlobalInvocationID . x;
if(segmentIndex >= uMicrolineCount)
return;
uint pathIndex;
vec4 lineSegment = unpackMicroline(iMicrolines[segmentIndex], pathIndex);
ivec4 pathTileRect = iMetadata[pathIndex * 3 + 0];
uint pathTileOffset = uint(iMetadata[pathIndex * 3 + 1]. x);
uint pathBackdropOffset = uint(iMetadata[pathIndex * 3 + 2]. x);
ivec2 tileSize = ivec2(16);
ivec4 tileLineSegment = ivec4(floor(lineSegment / vec4(tileSize . xyxy)));
ivec2 fromTileCoords = tileLineSegment . xy, toTileCoords = tileLineSegment . zw;
vec2 vector = lineSegment . zw - lineSegment . xy;
vec2 vectorIsNegative = vec2(vector . x < 0.0 ? - 1.0 : 0.0, vector . y < 0.0 ? - 1.0 : 0.0);
ivec2 tileStep = ivec2(vector . x < 0.0 ? - 1 : 1, vector . y < 0.0 ? - 1 : 1);
vec2 firstTileCrossing = vec2((fromTileCoords + ivec2(vector . x >= 0.0 ? 1 : 0,
vector . y >= 0.0 ? 1 : 0))* tileSize);
vec2 tMax =(firstTileCrossing - lineSegment . xy)/ vector;
vec2 tDelta = abs(tileSize / vector);
vec2 currentPosition = lineSegment . xy;
ivec2 tileCoords = fromTileCoords;
int lastStepDirection = 0;
uint iteration = 0;
while(iteration < 1024u){
int nextStepDirection;
if(tMax . x < tMax . y)
nextStepDirection = 1;
else if(tMax . x > tMax . y)
nextStepDirection = 2;
else if(tileStep . x > 0.0)
nextStepDirection = 1;
else
nextStepDirection = 2;
float nextT = min(nextStepDirection == 1 ? tMax . x : tMax . y, 1.0);
if(tileCoords == toTileCoords)
nextStepDirection = 0;
vec2 nextPosition = mix(lineSegment . xy, lineSegment . zw, nextT);
vec4 clippedLineSegment = vec4(currentPosition, nextPosition);
addFill(clippedLineSegment, tileCoords, pathTileRect, pathTileOffset);
vec4 auxiliarySegment;
bool haveAuxiliarySegment = false;
if(tileStep . y < 0 && nextStepDirection == 2){
auxiliarySegment = vec4(clippedLineSegment . zw, vec2(tileCoords * tileSize));
haveAuxiliarySegment = true;
} else if(tileStep . y > 0 && lastStepDirection == 2){
auxiliarySegment = vec4(vec2(tileCoords * tileSize), clippedLineSegment . xy);
haveAuxiliarySegment = true;
}
if(haveAuxiliarySegment)
addFill(auxiliarySegment, tileCoords, pathTileRect, pathTileOffset);
if(tileStep . x < 0 && lastStepDirection == 1){
adjustBackdrop(1,
tileCoords,
pathTileRect,
pathTileOffset,
pathBackdropOffset);
} else if(tileStep . x > 0 && nextStepDirection == 1){
adjustBackdrop(- 1,
tileCoords,
pathTileRect,
pathTileOffset,
pathBackdropOffset);
}
if(nextStepDirection == 1){
tMax . x += tDelta . x;
tileCoords . x += tileStep . x;
} else if(nextStepDirection == 2){
tMax . y += tDelta . y;
tileCoords . y += tileStep . y;
} else if(nextStepDirection == 0){
break;
}
currentPosition = nextPosition;
lastStepDirection = nextStepDirection;
iteration ++;
}
}