diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2019-10-16 09:26:38 -0700 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2019-10-30 09:22:32 -0700 |
commit | 5176b7a54d5ed4c512590f8390774a28d654c89e (patch) | |
tree | 06535f83ab23c2dc2290e7cff3c13f1c1cada225 /shaders | |
parent | 2e377edaae300e5d72474c19a0fa955e95656698 (diff) |
shaders: Add Chromium's CMAA shader
Generated in Chromium by the code in
https://github.com/chromium/chromium/blob/master/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc.
Reviewed by: Dylann Baker <dylan@pnwbakers.com>
Diffstat (limited to 'shaders')
-rw-r--r-- | shaders/chromium/85.shader_test | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/shaders/chromium/85.shader_test b/shaders/chromium/85.shader_test new file mode 100644 index 0000000..bbd0c90 --- /dev/null +++ b/shaders/chromium/85.shader_test @@ -0,0 +1,167 @@ +[require] +GLSL ES >= 3.10 + +[vertex shader] +#version 310 es +#extension GL_NV_image_formats : require +#define SUPPORTS_USAMPLER2D +#define EDGE_READ_FORMAT r8 +#define DETECT_EDGES2 + +precision highp float; void main() { float x = -1.0 + float((gl_VertexID & 1) << 2); float y = -1.0 + float((gl_VertexID & 2) << 1); gl_Position = vec4(x, y, 0.0, 1.0); } +[fragment shader] +#version 310 es +#extension GL_NV_image_formats : require +#define SUPPORTS_USAMPLER2D +#define EDGE_READ_FORMAT r8 +#define DETECT_EDGES2 + +precision highp float; precision highp int; +#define SETTINGS_ALLOW_SHORT_Zs 1 + +#define EDGE_DETECT_THRESHOLD 13.0f + +#define saturate(x) clamp((x), 0.0, 1.0) + layout(location = 0) uniform vec2 g_OneOverScreenSize; +#ifndef EDGE_DETECT_THRESHOLD + layout(location = 1) uniform float g_ColorThreshold; +#endif + +#ifdef DETECT_EDGES1 + layout(location = 2) uniform int g_DoCopy; +#endif + +#ifdef SUPPORTS_USAMPLER2D + +#define USAMPLER usampler2D + +#define UVEC4 uvec4 + +#define LOAD_UINT(arg) arg + +#define STORE_UVEC4(arg) arg + +#else + +#define USAMPLER sampler2D + +#define UVEC4 vec4 + +#define LOAD_UINT(arg) uint(arg * 255.0f) + +#define STORE_UVEC4(arg) vec4(float(arg.x) / 255.0f, float(arg.y) / 255.0f, float(arg.z) / 255.0f, float(arg.w) / 255.0f) + +#endif + layout(binding = 0) uniform highp sampler2D g_screenTexture; layout(binding = 1) uniform highp sampler2D g_src0TextureFlt; layout(binding = 1) uniform highp USAMPLER g_src0Texture4Uint; +#ifdef GL_ES + layout(binding = 0, EDGE_READ_FORMAT) restrict writeonly uniform highp image2D g_resultEdgeTexture; layout(binding = 1, rgba8) restrict writeonly uniform highp image2D g_resultRGBATextureSlot1; layout(binding = 2, rgba8) restrict writeonly uniform highp image2D g_targetTextureSlot2; +#else + layout(EDGE_READ_FORMAT) restrict writeonly uniform highp image2D g_resultEdgeTexture; layout(rgba8) restrict writeonly uniform highp image2D g_resultRGBATextureSlot1; layout(rgba8) restrict writeonly uniform highp image2D g_targetTextureSlot2; +#endif + const vec4 c_lumWeights = vec4(0.2126f, 0.7152f, 0.0722f, 0.0000f); +#ifdef EDGE_DETECT_THRESHOLD + const float c_ColorThreshold = 1.0f / EDGE_DETECT_THRESHOLD; +#endif + const int c_maxLineLength = 64; const vec4 c_edgeDebugColours[5] = vec4[5](vec4(0.5, 0.5, 0.5, 0.4), vec4(1.0, 0.1, 1.0, 0.8), vec4(0.9, 0.0, 0.0, 0.8), vec4(0.0, 0.9, 0.0, 0.8), vec4(0.0, 0.0, 0.9, 0.8)); +#ifdef IN_GAMMA_CORRECT_MODE + float D3DX_FLOAT_to_SRGB(float val) { if (val < 0.0031308f) val *= 12.92f; else { val = 1.055f * pow(val, 1.0f / 2.4f) - 0.055f; } return val; } vec3 D3DX_FLOAT3_to_SRGB(vec3 val) { vec3 outVal; outVal.x = D3DX_FLOAT_to_SRGB(val.x); outVal.y = D3DX_FLOAT_to_SRGB(val.y); outVal.z = D3DX_FLOAT_to_SRGB(val.z); return outVal; } +#endif + uint PackEdge(uvec4 edges) { return (edges.x << 0u) | (edges.y << 1u) | (edges.z << 2u) | (edges.w << 3u); } uvec4 UnpackEdge(uint value) { uvec4 ret; ret.x = (value & 0x01u) != 0u ? 1u : 0u; ret.y = (value & 0x02u) != 0u ? 1u : 0u; ret.z = (value & 0x04u) != 0u ? 1u : 0u; ret.w = (value & 0x08u) != 0u ? 1u : 0u; return ret; } vec4 PackBlurAAInfo(ivec2 pixelPos, uint shapeType) { uint packedEdges = uint( texelFetch(g_src0TextureFlt, pixelPos, 0).r * 255.5); float retval = float(packedEdges + (shapeType << 4u)); return vec4(retval / 255.0); } void UnpackBlurAAInfo(float packedValue, out uint edges, out uint shapeType) { uint packedValueInt = uint(packedValue * 255.5); edges = packedValueInt & 0xFu; shapeType = packedValueInt >> 4u; } float EdgeDetectColorCalcDiff(vec3 colorA, vec3 colorB) { +#ifdef IN_BGR_MODE + vec3 LumWeights = c_lumWeights.bgr; +#else + vec3 LumWeights = c_lumWeights.rgb; +#endif + return dot(abs(colorA.rgb - colorB.rgb), LumWeights); } bool EdgeDetectColor(vec3 colorA, vec3 colorB) { +#ifdef EDGE_DETECT_THRESHOLD + return EdgeDetectColorCalcDiff(colorA, colorB) > c_ColorThreshold; +#else + return EdgeDetectColorCalcDiff(colorA, colorB) > g_ColorThreshold; +#endif + } void FindLineLength(out int lineLengthLeft, out int lineLengthRight, ivec2 screenPos, const bool horizontal, const bool invertedZShape, const ivec2 stepRight) { uint maskLeft = uint(0); uint bitsContinueLeft = uint(0); uint maskRight = uint(0); uint bitsContinueRight = uint(0); { uint maskTraceLeft = uint(0); uint maskTraceRight = uint(0); uint maskStopLeft = uint(0); uint maskStopRight = uint(0); if (horizontal) { if (invertedZShape) { maskTraceLeft = 0x08u; maskTraceRight = 0x02u; } else { maskTraceLeft = 0x02u; maskTraceRight = 0x08u; } maskStopLeft = 0x01u; maskStopRight = 0x04u; } else { if (invertedZShape) { maskTraceLeft = 0x01u; maskTraceRight = 0x04u; } else { maskTraceLeft = 0x04u; maskTraceRight = 0x01u; } maskStopLeft = 0x02u; maskStopRight = 0x08u; } maskLeft = maskTraceLeft | maskStopLeft; bitsContinueLeft = maskTraceLeft; maskRight = maskTraceRight | maskStopRight; bitsContinueRight = maskTraceRight; } +#ifdef SETTINGS_ALLOW_SHORT_Zs + int i = 1; +#else + int i = 2; +#endif + for (; i < c_maxLineLength; i++) { uint edgeLeft = uint( texelFetch(g_src0TextureFlt, ivec2(screenPos.xy - stepRight * i), 0).r * 255.5); uint edgeRight = uint( texelFetch(g_src0TextureFlt, ivec2(screenPos.xy + stepRight * (i + 1)), 0).r * 255.5); int stopLeft = (edgeLeft & maskLeft) != bitsContinueLeft ? 1 : 0; int stopRight = (edgeRight & maskRight) != bitsContinueRight ? 1 : 0; if (bool(stopLeft) || bool(stopRight)) { lineLengthLeft = 1 + i - stopLeft; lineLengthRight = 1 + i - stopRight; return; } } lineLengthLeft = lineLengthRight = i; return; } void ProcessDetectedZ(ivec2 screenPos, bool horizontal, bool invertedZShape) { int lineLengthLeft = 0; int lineLengthRight = 0; ivec2 stepRight = (horizontal) ? (ivec2(1, 0)) : (ivec2(0, 1)); vec2 blendDir = (horizontal) ? (vec2(0, -1)) : (vec2(1, 0)); FindLineLength(lineLengthLeft, lineLengthRight, screenPos, horizontal, invertedZShape, stepRight); vec2 pixelSize = g_OneOverScreenSize; float leftOdd = 0.15 * float(lineLengthLeft % 2); float rightOdd = 0.15 * float(lineLengthRight % 2); int loopFrom = -int((lineLengthLeft + 1) / 2) + 1; int loopTo = int((lineLengthRight + 1) / 2); float totalLength = float(loopTo - loopFrom) + 1.0 - leftOdd - rightOdd; for (int i = loopFrom; i <= loopTo; i++) { highp ivec2 pixelPos = screenPos + stepRight * i; vec2 pixelPosFlt = vec2(float(pixelPos.x) + 0.5, float(pixelPos.y) + 0.5); +#ifdef DEBUG_OUTPUT_AAINFO + imageStore(g_resultEdgeTexture, pixelPos, PackBlurAAInfo(pixelPos, 1u)); +#endif + float m = (float(i) + 0.5 - leftOdd - float(loopFrom)) / totalLength; m = saturate(m); float k = m - ((i > 0) ? 1.0 : 0.0); k = (invertedZShape) ? (k) : (-k); vec4 color = textureLod(g_screenTexture, (pixelPosFlt + blendDir * k) * pixelSize, 0.0); +#ifdef IN_GAMMA_CORRECT_MODE + color.rgb = D3DX_FLOAT3_to_SRGB(color.rgb); +#endif + imageStore(g_resultRGBATextureSlot1, pixelPos, color); } } vec4 CalcDbgDisplayColor(const vec4 blurMap) { vec3 pixelC = vec3(0.0, 0.0, 0.0); vec3 pixelL = vec3(0.0, 0.0, 1.0); vec3 pixelT = vec3(1.0, 0.0, 0.0); vec3 pixelR = vec3(0.0, 1.0, 0.0); vec3 pixelB = vec3(0.8, 0.8, 0.0); const float centerWeight = 1.0; float fromBelowWeight = (1.0 / (1.0 - blurMap.x)) - 1.0; float fromAboveWeight = (1.0 / (1.0 - blurMap.y)) - 1.0; float fromRightWeight = (1.0 / (1.0 - blurMap.z)) - 1.0; float fromLeftWeight = (1.0 / (1.0 - blurMap.w)) - 1.0; float weightSum = centerWeight + dot(vec4(fromBelowWeight, fromAboveWeight, fromRightWeight, fromLeftWeight), vec4(1, 1, 1, 1)); vec4 pixel; pixel.rgb = pixelC.rgb + fromAboveWeight * pixelT + fromBelowWeight * pixelB + fromLeftWeight * pixelL + fromRightWeight * pixelR; pixel.rgb /= weightSum; pixel.a = dot(pixel.rgb, vec3(1, 1, 1)) * 100.0; return saturate(pixel); } +#ifdef DETECT_EDGES1 + layout(location = 0) out UVEC4 outEdges; void DetectEdges1() { uvec4 outputEdges; ivec2 screenPosI = ivec2(gl_FragCoord.xy) * ivec2(2, 2); vec4 pixel00 = texelFetch(g_screenTexture, screenPosI.xy, 0); vec4 pixel10 = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(1, 0)); vec4 pixel20 = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(2, 0)); vec4 pixel01 = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(0, 1)); vec4 pixel11 = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(1, 1)); vec4 pixel21 = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(2, 1)); vec4 pixel02 = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(0, 2)); vec4 pixel12 = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(1, 2)); if (g_DoCopy == 1) { imageStore(g_targetTextureSlot2, screenPosI.xy + ivec2(0, 0), pixel00); imageStore(g_targetTextureSlot2, screenPosI.xy + ivec2(1, 0), pixel10); imageStore(g_targetTextureSlot2, screenPosI.xy + ivec2(0, 1), pixel01); imageStore(g_targetTextureSlot2, screenPosI.xy + ivec2(1, 1), pixel11); } float storeFlagPixel00 = 0.0; float storeFlagPixel10 = 0.0; float storeFlagPixel20 = 0.0; float storeFlagPixel01 = 0.0; float storeFlagPixel11 = 0.0; float storeFlagPixel21 = 0.0; float storeFlagPixel02 = 0.0; float storeFlagPixel12 = 0.0; vec2 et; +#ifdef EDGE_DETECT_THRESHOLD + float threshold = c_ColorThreshold; +#else + float threshold = g_ColorThreshold; +#endif + { et.x = EdgeDetectColorCalcDiff(pixel00.rgb, pixel10.rgb); et.y = EdgeDetectColorCalcDiff(pixel00.rgb, pixel01.rgb); et = saturate(et - threshold); ivec2 eti = ivec2(et * 15.0 + 0.99); outputEdges.x = uint(eti.x | (eti.y << 4)); storeFlagPixel00 += et.x; storeFlagPixel00 += et.y; storeFlagPixel10 += et.x; storeFlagPixel01 += et.y; } { et.x = EdgeDetectColorCalcDiff(pixel10.rgb, pixel20.rgb); et.y = EdgeDetectColorCalcDiff(pixel10.rgb, pixel11.rgb); et = saturate(et - threshold); ivec2 eti = ivec2(et * 15.0 + 0.99); outputEdges.y = uint(eti.x | (eti.y << 4)); storeFlagPixel10 += et.x; storeFlagPixel10 += et.y; storeFlagPixel20 += et.x; storeFlagPixel11 += et.y; } { et.x = EdgeDetectColorCalcDiff(pixel01.rgb, pixel11.rgb); et.y = EdgeDetectColorCalcDiff(pixel01.rgb, pixel02.rgb); et = saturate(et - threshold); ivec2 eti = ivec2(et * 15.0 + 0.99); outputEdges.z = uint(eti.x | (eti.y << 4)); storeFlagPixel01 += et.x; storeFlagPixel01 += et.y; storeFlagPixel11 += et.x; storeFlagPixel02 += et.y; } { et.x = EdgeDetectColorCalcDiff(pixel11.rgb, pixel21.rgb); et.y = EdgeDetectColorCalcDiff(pixel11.rgb, pixel12.rgb); et = saturate(et - threshold); ivec2 eti = ivec2(et * 15.0 + 0.99); outputEdges.w = uint(eti.x | (eti.y << 4)); storeFlagPixel11 += et.x; storeFlagPixel11 += et.y; storeFlagPixel21 += et.x; storeFlagPixel12 += et.y; } gl_FragDepth = any(bvec4(outputEdges)) ? 1.0 : 0.0; if (gl_FragDepth != 0.0) { if (storeFlagPixel00 != 0.0) imageStore(g_resultRGBATextureSlot1, screenPosI.xy + ivec2(0, 0), pixel00); if (storeFlagPixel10 != 0.0) imageStore(g_resultRGBATextureSlot1, screenPosI.xy + ivec2(1, 0), pixel10); if (storeFlagPixel20 != 0.0) imageStore(g_resultRGBATextureSlot1, screenPosI.xy + ivec2(2, 0), pixel20); if (storeFlagPixel01 != 0.0) imageStore(g_resultRGBATextureSlot1, screenPosI.xy + ivec2(0, 1), pixel01); if (storeFlagPixel02 != 0.0) imageStore(g_resultRGBATextureSlot1, screenPosI.xy + ivec2(0, 2), pixel02); if (storeFlagPixel11 != 0.0) imageStore(g_resultRGBATextureSlot1, screenPosI.xy + ivec2(1, 1), pixel11); if (storeFlagPixel21 != 0.0) imageStore(g_resultRGBATextureSlot1, screenPosI.xy + ivec2(2, 1), pixel21); if (storeFlagPixel12 != 0.0) imageStore(g_resultRGBATextureSlot1, screenPosI.xy + ivec2(1, 2), pixel12); } outEdges = STORE_UVEC4(outputEdges); } +#endif + vec2 UnpackThresholds(uint val) { return vec2(val & 0x0Fu, val >> 4u) / 15.0f; } uvec4 PruneNonDominantEdges(vec4 edges[3]) { vec4 maxE4 = vec4(0.0, 0.0, 0.0, 0.0); float avg = 0.0; for (int i = 0; i < 3; i++) { maxE4 = max(maxE4, edges[i]); avg = dot(edges[i], vec4(1, 1, 1, 1) / (3.0 * 4.0)); } vec2 maxE2 = max(maxE4.xy, maxE4.zw); float maxE = max(maxE2.x, maxE2.y); float threshold = avg * 0.65 + maxE * 0.35; uint cx = edges[0].x >= threshold ? 1u : 0u; uint cy = edges[0].y >= threshold ? 1u : 0u; return uvec4(cx, cy, 0, 0); } void CollectEdges(int offX, int offY, out vec4 edges[3], const uint packedVals[6 * 6]) { vec2 pixelP0P0 = UnpackThresholds(packedVals[(offX)*6+(offY)]); vec2 pixelP1P0 = UnpackThresholds(packedVals[(offX+1)*6+(offY)]); vec2 pixelP0P1 = UnpackThresholds(packedVals[(offX)*6+(offY+1)]); vec2 pixelM1P0 = UnpackThresholds(packedVals[(offX-1)*6 +(offY)]); vec2 pixelP0M1 = UnpackThresholds(packedVals[(offX)*6+(offY-1)]); vec2 pixelP1M1 = UnpackThresholds(packedVals[(offX+1)*6 +(offY-1)]); vec2 pixelM1P1 = UnpackThresholds(packedVals[(offX-1)*6+(offY+1)]); edges[0].x = pixelP0P0.x; edges[0].y = pixelP0P0.y; edges[0].z = pixelP1P0.x; edges[0].w = pixelP1P0.y; edges[1].x = pixelP0P1.x; edges[1].y = pixelP0P1.y; edges[1].z = pixelM1P0.x; edges[1].w = pixelM1P0.y; edges[2].x = pixelP0M1.x; edges[2].y = pixelP0M1.y; edges[2].z = pixelP1M1.y; edges[2].w = pixelM1P1.x; } +#ifdef DETECT_EDGES2 + layout(early_fragment_tests) in; void DetectEdges2() { ivec2 screenPosI = ivec2(gl_FragCoord.xy); uvec2 notTopRight = uvec2(notEqual((screenPosI + 1), textureSize(g_src0Texture4Uint, 0))); uint packedVals[6 * 6]; UVEC4 packedQ4 = texelFetch(g_src0Texture4Uint, screenPosI.xy, 0); packedVals[(2) * 6 + (2)] = LOAD_UINT(packedQ4.x); packedVals[(3) * 6 + (2)] = LOAD_UINT(packedQ4.y); packedVals[(2) * 6 + (3)] = LOAD_UINT(packedQ4.z); packedVals[(3) * 6 + (3)] = LOAD_UINT(packedQ4.w); vec4 edges[3]; if (bool(packedVals[(2) * 6 + (2)]) || bool(packedVals[(3) * 6 + (2)])) { UVEC4 packedQ1 = texelFetchOffset(g_src0Texture4Uint, screenPosI.xy, 0, ivec2(0, -1)); packedVals[(2) * 6 + (0)] = LOAD_UINT(packedQ1.x); packedVals[(3) * 6 + (0)] = LOAD_UINT(packedQ1.y); packedVals[(2) * 6 + (1)] = LOAD_UINT(packedQ1.z); packedVals[(3) * 6 + (1)] = LOAD_UINT(packedQ1.w); } if (bool(packedVals[(2) * 6 + (2)]) || bool(packedVals[(2) * 6 + (3)])) { UVEC4 packedQ3 = texelFetchOffset(g_src0Texture4Uint, screenPosI.xy, 0, ivec2(-1, 0)); packedVals[(0) * 6 + (2)] = LOAD_UINT(packedQ3.x); packedVals[(1) * 6 + (2)] = LOAD_UINT(packedQ3.y); packedVals[(0) * 6 + (3)] = LOAD_UINT(packedQ3.z); packedVals[(1) * 6 + (3)] = LOAD_UINT(packedQ3.w); } if (bool(packedVals[(2) * 6 + (2)])) { CollectEdges(2, 2, edges, packedVals); uint pe = PackEdge(PruneNonDominantEdges(edges)); if (pe != 0u) { imageStore(g_resultEdgeTexture, 2 * screenPosI.xy + ivec2(0, 0), vec4(float(0x80u | pe) / 255.0, 0, 0, 0)); } } if (bool(packedVals[(3) * 6 + (2)]) || bool(packedVals[(3) * 6 + (3)])) { UVEC4 packedQ5 = texelFetchOffset(g_src0Texture4Uint, screenPosI.xy, 0, ivec2(1, 0)); packedVals[(4) * 6 + (2)] = LOAD_UINT(packedQ5.x); packedVals[(5) * 6 + (2)] = LOAD_UINT(packedQ5.y); packedVals[(4) * 6 + (3)] = LOAD_UINT(packedQ5.z); packedVals[(5) * 6 + (3)] = LOAD_UINT(packedQ5.w); } if (bool(packedVals[(3) * 6 + (2)])) { UVEC4 packedQ2 = texelFetchOffset(g_src0Texture4Uint, screenPosI.xy, 0, ivec2(1, -1)); packedVals[(4) * 6 + (0)] = LOAD_UINT(packedQ2.x); packedVals[(5) * 6 + (0)] = LOAD_UINT(packedQ2.y); packedVals[(4) * 6 + (1)] = LOAD_UINT(packedQ2.z); packedVals[(5) * 6 + (1)] = LOAD_UINT(packedQ2.w); CollectEdges(3, 2, edges, packedVals); uvec4 dominant_edges = PruneNonDominantEdges(edges); uint pe = PackEdge(dominant_edges * uvec4(notTopRight.x, 1, 1, 1)); if (pe != 0u) { imageStore(g_resultEdgeTexture, 2 * screenPosI.xy + ivec2(1, 0), vec4(float(0x80u | pe) / 255.0, 0, 0, 0)); } } if (bool(packedVals[(2) * 6 + (3)]) || bool(packedVals[(3) * 6 + (3)])) { UVEC4 packedQ7 = texelFetchOffset(g_src0Texture4Uint, screenPosI.xy, 0, ivec2(0, 1)); packedVals[(2) * 6 + (4)] = LOAD_UINT(packedQ7.x); packedVals[(3) * 6 + (4)] = LOAD_UINT(packedQ7.y); packedVals[(2) * 6 + (5)] = LOAD_UINT(packedQ7.z); packedVals[(3) * 6 + (5)] = LOAD_UINT(packedQ7.w); } if (bool(packedVals[(2) * 6 + (3)])) { UVEC4 packedQ6 = texelFetchOffset(g_src0Texture4Uint, screenPosI.xy, 0, ivec2(-1, -1)); packedVals[(0) * 6 + (4)] = LOAD_UINT(packedQ6.x); packedVals[(1) * 6 + (4)] = LOAD_UINT(packedQ6.y); packedVals[(0) * 6 + (5)] = LOAD_UINT(packedQ6.z); packedVals[(1) * 6 + (5)] = LOAD_UINT(packedQ6.w); CollectEdges(2, 3, edges, packedVals); uvec4 dominant_edges = PruneNonDominantEdges(edges); uint pe = PackEdge(dominant_edges * uvec4(1, notTopRight.y, 1, 1)); if (pe != 0u) { imageStore(g_resultEdgeTexture, 2 * screenPosI.xy + ivec2(0, 1), vec4(float(0x80u | pe) / 255.0, 0, 0, 0)); } } if (bool(packedVals[(3) * 6 + (3)])) { CollectEdges(3, 3, edges, packedVals); uvec4 dominant_edges = PruneNonDominantEdges(edges); uint pe = PackEdge(dominant_edges * uvec4(notTopRight, 1, 1)); if (pe != 0u) { imageStore(g_resultEdgeTexture, 2 * screenPosI.xy + ivec2(1, 1), vec4(float(0x80u | pe) / 255.0, 0, 0, 0)); } } } +#endif + +#ifdef COMBINE_EDGES + void CombineEdges() { ivec3 screenPosIBase = ivec3(ivec2(gl_FragCoord.xy) * 2, 0); vec3 screenPosBase = vec3(screenPosIBase); uvec2 notBottomLeft = uvec2(notEqual(screenPosIBase.xy, ivec2(0, 0))); uint packedEdgesArray[3 * 3]; uvec4 sampA = uvec4( textureGatherOffset(g_src0TextureFlt, screenPosBase.xy * g_OneOverScreenSize, ivec2(1, 0)) * 255.0 - 127.5); uvec4 sampB = uvec4( textureGatherOffset(g_src0TextureFlt, screenPosBase.xy * g_OneOverScreenSize, ivec2(0, 1)) * 255.0 - 127.5); uint sampC = uint( texelFetchOffset(g_src0TextureFlt, screenPosIBase.xy, 0, ivec2(1, 1)).r * 255.0 - 127.5); packedEdgesArray[(0) * 3 + (0)] = 0u; packedEdgesArray[(1) * 3 + (0)] = sampA.w * notBottomLeft.y; packedEdgesArray[(2) * 3 + (0)] = sampA.z * notBottomLeft.y; packedEdgesArray[(1) * 3 + (1)] = sampA.x; packedEdgesArray[(2) * 3 + (1)] = sampA.y; packedEdgesArray[(0) * 3 + (1)] = sampB.w * notBottomLeft.x; packedEdgesArray[(0) * 3 + (2)] = sampB.x * notBottomLeft.x; packedEdgesArray[(1) * 3 + (2)] = sampB.y; packedEdgesArray[(2) * 3 + (2)] = sampC; uvec4 pixelsC = uvec4(packedEdgesArray[(1 + 0) * 3 + (1 + 0)], packedEdgesArray[(1 + 1) * 3 + (1 + 0)], packedEdgesArray[(1 + 0) * 3 + (1 + 1)], packedEdgesArray[(1 + 1) * 3 + (1 + 1)]); uvec4 pixelsL = uvec4(packedEdgesArray[(0 + 0) * 3 + (1 + 0)], packedEdgesArray[(0 + 1) * 3 + (1 + 0)], packedEdgesArray[(0 + 0) * 3 + (1 + 1)], packedEdgesArray[(0 + 1) * 3 + (1 + 1)]); uvec4 pixelsU = uvec4(packedEdgesArray[(1 + 0) * 3 + (0 + 0)], packedEdgesArray[(1 + 1) * 3 + (0 + 0)], packedEdgesArray[(1 + 0) * 3 + (0 + 1)], packedEdgesArray[(1 + 1) * 3 + (0 + 1)]); uvec4 outEdge4 = pixelsC | ((pixelsL & 0x01u) << 2u) | ((pixelsU & 0x02u) << 2u); vec4 outEdge4Flt = vec4(outEdge4) / 255.0; imageStore(g_resultEdgeTexture, screenPosIBase.xy + ivec2(0, 0), outEdge4Flt.xxxx); imageStore(g_resultEdgeTexture, screenPosIBase.xy + ivec2(1, 0), outEdge4Flt.yyyy); imageStore(g_resultEdgeTexture, screenPosIBase.xy + ivec2(0, 1), outEdge4Flt.zzzz); imageStore(g_resultEdgeTexture, screenPosIBase.xy + ivec2(1, 1), outEdge4Flt.wwww); gl_FragDepth = any(greaterThan(outEdge4, uvec4(1))) ? 1.0 : 0.0; } +#endif + +#ifdef BLUR_EDGES + layout(early_fragment_tests) in; void BlurEdges() { ivec3 screenPosIBase = ivec3(ivec2(gl_FragCoord.xy) * 2, 0); vec3 screenPosBase = vec3(screenPosIBase); uvec2 notBottomLeft = uvec2(notEqual(screenPosIBase.xy, ivec2(0, 0))); uvec2 notTopRight = uvec2( notEqual((screenPosIBase.xy + 2), textureSize(g_src0TextureFlt, 0))); uint forFollowUpCount = 0u; ivec4 forFollowUpCoords[4]; uint packedEdgesArray[4 * 4]; uvec4 sampA = uvec4( textureGatherOffset(g_src0TextureFlt, screenPosBase.xy * g_OneOverScreenSize, ivec2(0, 0)) *255.5); uvec4 sampB = uvec4( textureGatherOffset(g_src0TextureFlt, screenPosBase.xy * g_OneOverScreenSize, ivec2(2, 0)) *255.5); uvec4 sampC = uvec4( textureGatherOffset(g_src0TextureFlt, screenPosBase.xy * g_OneOverScreenSize, ivec2(0, 2)) *255.5); uvec4 sampD = uvec4( textureGatherOffset(g_src0TextureFlt, screenPosBase.xy * g_OneOverScreenSize, ivec2(2, 2)) *255.5); packedEdgesArray[(0) * 4 + (0)] = sampA.w * notBottomLeft.x * notBottomLeft.y; packedEdgesArray[(1) * 4 + (0)] = sampA.z * notBottomLeft.y; packedEdgesArray[(0) * 4 + (1)] = sampA.x * notBottomLeft.x; packedEdgesArray[(1) * 4 + (1)] = sampA.y; packedEdgesArray[(2) * 4 + (0)] = sampB.w * notBottomLeft.y; packedEdgesArray[(3) * 4 + (0)] = sampB.z * notBottomLeft.y * notTopRight.x; packedEdgesArray[(2) * 4 + (1)] = sampB.x; packedEdgesArray[(3) * 4 + (1)] = sampB.y * notTopRight.x; packedEdgesArray[(0) * 4 + (2)] = sampC.w * notBottomLeft.x; packedEdgesArray[(1) * 4 + (2)] = sampC.z; packedEdgesArray[(0) * 4 + (3)] = sampC.x * notBottomLeft.x * notTopRight.y; packedEdgesArray[(1) * 4 + (3)] = sampC.y * notTopRight.y; packedEdgesArray[(2) * 4 + (2)] = sampD.w; packedEdgesArray[(3) * 4 + (2)] = sampD.z * notTopRight.x; packedEdgesArray[(2) * 4 + (3)] = sampD.x * notTopRight.y; packedEdgesArray[(3) * 4 + (3)] = sampD.y * notTopRight.x * notTopRight.y; for (int _i = 0; _i < 4; _i++) { int _x = _i % 2; int _y = _i / 2; ivec3 screenPosI = screenPosIBase + ivec3(_x, _y, 0); uint packedEdgesC = packedEdgesArray[(1 + _x) * 4 + (1 + _y)]; uvec4 edges = UnpackEdge(packedEdgesC); uint numberOfEdges = edges.x + edges.y + edges.z + edges.w; if (numberOfEdges <= 1u) continue; vec4 edgesFlt = vec4(edges); float fromRight = edgesFlt.r; float fromAbove = edgesFlt.g; float fromLeft = edgesFlt.b; float fromBelow = edgesFlt.a; vec4 xFroms = vec4(fromBelow, fromAbove, fromRight, fromLeft); float blurCoeff = 0.0; if (numberOfEdges == 2u) { blurCoeff = 0.15; blurCoeff *= (1.0 - fromBelow * fromAbove) * (1.0 - fromRight * fromLeft); if (blurCoeff == 0.0) continue; uint packedEdgesL = packedEdgesArray[(0 + _x) * 4 + (1 + _y)]; uint packedEdgesB = packedEdgesArray[(1 + _x) * 4 + (0 + _y)]; uint packedEdgesR = packedEdgesArray[(2 + _x) * 4 + (1 + _y)]; uint packedEdgesT = packedEdgesArray[(1 + _x) * 4 + (2 + _y)]; bool large_l1 = (packedEdgesC == (0x01u | 0x02u)) && bool(packedEdgesL & 0x02u) && bool(packedEdgesB & 0x01u); bool large_l2 = (packedEdgesC == (0x01u | 0x08u)) && bool(packedEdgesL & 0x08u) && bool(packedEdgesT & 0x01u); bool large_l3 = (packedEdgesC == (0x04u | 0x08u)) && bool(packedEdgesR & 0x08u) && bool(packedEdgesT & 0x04u); bool large_l4 = (packedEdgesC == (0x02u | 0x04u)) && bool(packedEdgesR & 0x02u) && bool(packedEdgesB & 0x04u); if (large_l1 || large_l2 || large_l3 || large_l4) continue; bool isolated_l1 = (packedEdgesC == (0x01u | 0x02u)) && bool((packedEdgesL & 0x02u) == 0x00u) && bool((packedEdgesT & 0x04u) == 0x00u) && bool((packedEdgesR & 0x08u) == 0x00u) && bool((packedEdgesB & 0x01u) == 0x00u); bool isolated_l2 = (packedEdgesC == (0x01u | 0x08u)) && bool((packedEdgesL & 0x08u) == 0x00u) && bool((packedEdgesT & 0x01u) == 0x00u) && bool((packedEdgesR & 0x02u) == 0x00u) && bool((packedEdgesB & 0x04u) == 0x00u); bool isolated_l3 = (packedEdgesC == (0x04u | 0x08u)) && bool((packedEdgesL & 0x02u) == 0x00u) && bool((packedEdgesT & 0x04u) == 0x00u) && bool((packedEdgesR & 0x08u) == 0x00u) && bool((packedEdgesB & 0x01u) == 0x00u); bool isolated_l4 = (packedEdgesC == (0x02u | 0x04u)) && bool((packedEdgesL & 0x08u) == 0x00u) && bool((packedEdgesT & 0x01u) == 0x00u) && bool((packedEdgesR & 0x02u) == 0x00u) && bool((packedEdgesB & 0x04u) == 0x00u); if (isolated_l1 || isolated_l2 || isolated_l3 || isolated_l4) continue; } if (numberOfEdges == 3u) { blurCoeff = 0.13; } if (numberOfEdges == 4u) { blurCoeff = 0.07; } vec4 blurMap = xFroms * blurCoeff; vec4 pixelC = texelFetch(g_screenTexture, screenPosI.xy, 0); const float centerWeight = 1.0; float fromBelowWeight = blurMap.x; float fromAboveWeight = blurMap.y; float fromRightWeight = blurMap.z; float fromLeftWeight = blurMap.w; float fourWeightSum = dot(blurMap, vec4(1, 1, 1, 1)); float allWeightSum = centerWeight + fourWeightSum; vec4 color = vec4(0, 0, 0, 0); if (fromLeftWeight > 0.0) { vec4 pixelL = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(-1, 0)); color += fromLeftWeight * pixelL; } if (fromAboveWeight > 0.0) { vec4 pixelT = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(0, 1)); color += fromAboveWeight * pixelT; } if (fromRightWeight > 0.0) { vec4 pixelR = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(1, 0)); color += fromRightWeight * pixelR; } if (fromBelowWeight > 0.0) { vec4 pixelB = texelFetchOffset(g_screenTexture, screenPosI.xy, 0, ivec2(0, -1)); color += fromBelowWeight * pixelB; } color /= fourWeightSum + 0.0001; color = mix(color, pixelC, centerWeight / allWeightSum); +#ifdef IN_GAMMA_CORRECT_MODE + color.rgb = D3DX_FLOAT3_to_SRGB(color.rgb); +#endif + +#ifdef DEBUG_OUTPUT_AAINFO + imageStore(g_resultEdgeTexture, screenPosI.xy, PackBlurAAInfo(screenPosI.xy, numberOfEdges)); +#endif + imageStore(g_resultRGBATextureSlot1, screenPosI.xy, color); if (numberOfEdges == 2u) { uint packedEdgesL = packedEdgesArray[(0 + _x) * 4 + (1 + _y)]; uint packedEdgesB = packedEdgesArray[(1 + _x) * 4 + (0 + _y)]; uint packedEdgesR = packedEdgesArray[(2 + _x) * 4 + (1 + _y)]; uint packedEdgesT = packedEdgesArray[(1 + _x) * 4 + (2 + _y)]; bool isHorizontalA = ((packedEdgesC) == (0x01u | 0x02u)) && ((packedEdgesR & 0x08u) == 0x08u); bool isHorizontalB = ((packedEdgesC) == (0x01u | 0x08u)) && ((packedEdgesR & 0x02u) == 0x02u); bool isHCandidate = isHorizontalA || isHorizontalB; bool isVerticalA = ((packedEdgesC) == (0x02u | 0x04u)) && ((packedEdgesT & 0x01u) == 0x01u); bool isVerticalB = ((packedEdgesC) == (0x01u | 0x02u)) && ((packedEdgesT & 0x04u) == 0x04u); bool isVCandidate = isVerticalA || isVerticalB; bool isCandidate = isHCandidate || isVCandidate; if (!isCandidate) continue; bool horizontal = isHCandidate; if (isHCandidate && isVCandidate) horizontal = (isHorizontalA && ((packedEdgesL & 0x02u) == 0x02u)) || (isHorizontalB && ((packedEdgesL & 0x08u) == 0x08u)); ivec2 offsetC; uint packedEdgesM1P0; uint packedEdgesP1P0; if (horizontal) { packedEdgesM1P0 = packedEdgesL; packedEdgesP1P0 = packedEdgesR; offsetC = ivec2(2, 0); } else { packedEdgesM1P0 = packedEdgesB; packedEdgesP1P0 = packedEdgesT; offsetC = ivec2(0, 2); } uvec4 edgesM1P0 = UnpackEdge(packedEdgesM1P0); uvec4 edgesP1P0 = UnpackEdge(packedEdgesP1P0); uvec4 edgesP2P0 = UnpackEdge(uint(texelFetch( g_src0TextureFlt, screenPosI.xy + offsetC, 0).r * 255.5)); uvec4 arg0; uvec4 arg1; uvec4 arg2; uvec4 arg3; bool arg4; if (horizontal) { arg0 = uvec4(edges); arg1 = edgesM1P0; arg2 = edgesP1P0; arg3 = edgesP2P0; arg4 = true; } else { arg0 = uvec4(edges.gbar); arg1 = edgesM1P0.gbar; arg2 = edgesP1P0.gbar; arg3 = edgesP2P0.gbar; arg4 = false; } { ivec2 screenPos = screenPosI.xy; uvec4 _edges = arg0; uvec4 _edgesM1P0 = arg1; uvec4 _edgesP1P0 = arg2; uvec4 _edgesP2P0 = arg3; bool horizontal = arg4; bool isInvertedZ = false; bool isNormalZ = false; { +#ifndef SETTINGS_ALLOW_SHORT_Zs + uint isZShape = _edges.r * _edges.g * _edgesM1P0.g * _edgesP1P0.a *_edgesP2P0.a * (1u - _edges.b) * (1u - _edgesP1P0.r) * (1u - _edges.a) * (1u - _edgesP1P0.g); +#else + uint isZShape = _edges.r * _edges.g * _edgesP1P0.a * (1u - _edges.b) * (1u - _edgesP1P0.r) * (1u - _edges.a) * (1u - _edgesP1P0.g); isZShape *= (_edgesM1P0.g + _edgesP2P0.a); +#endif + if (isZShape > 0u) { isNormalZ = true; } } { +#ifndef SETTINGS_ALLOW_SHORT_Zs + uint isZShape = _edges.r * _edges.a * _edgesM1P0.a * _edgesP1P0.g * _edgesP2P0.g * (1u - _edges.b) * (1u - _edgesP1P0.r) * (1u - _edges.g) * (1u - _edgesP1P0.a); +#else + uint isZShape = _edges.r * _edges.a * _edgesP1P0.g * (1u - _edges.b) * (1u - _edgesP1P0.r) * (1u - _edges.g) * (1u - _edgesP1P0.a); isZShape *= (_edgesM1P0.a + _edgesP2P0.g); +#endif + if (isZShape > 0u) { isInvertedZ = true; } } bool isZ = isInvertedZ || isNormalZ; if (isZ) { forFollowUpCoords[forFollowUpCount++] = ivec4(screenPosI.xy, horizontal, isInvertedZ); } } } } for (uint _i = 0u; _i < forFollowUpCount; _i++) { ivec4 data = forFollowUpCoords[_i]; ProcessDetectedZ(data.xy, bool(data.z), bool(data.w)); } } +#endif + +#ifdef DISPLAY_EDGES + layout(location = 0) out vec4 color; layout(location = 1) out vec4 hasEdges; void DisplayEdges() { ivec2 screenPosI = ivec2(gl_FragCoord.xy); uint packedEdges = uint(0); uint shapeType = uint(0); UnpackBlurAAInfo(texelFetch(g_src0TextureFlt, screenPosI, 0).r, packedEdges, shapeType); vec4 edges = vec4(UnpackEdge(packedEdges)); if (any(greaterThan(edges.xyzw, vec4(0)))) { +#ifdef IN_BGR_MODE + color = c_edgeDebugColours[shapeType].bgra; +#else + color = c_edgeDebugColours[shapeType]; +#endif + hasEdges = vec4(1.0); } else { color = vec4(0); hasEdges = vec4(0.0); } } +#endif + void main() { +#ifdef DETECT_EDGES1 + DetectEdges1(); +#endif + +#if defined DETECT_EDGES2 + DetectEdges2(); +#endif + +#if defined COMBINE_EDGES + CombineEdges(); +#endif + +#if defined BLUR_EDGES + BlurEdges(); +#endif + +#if defined DISPLAY_EDGES + DisplayEdges(); +#endif + } |