1#version 460 core 2#extension GL_ARB_separate_shader_objects : enable 3#extension GL_ARB_shading_language_420pack : enable 4 5// Lume Super Resolution 6// Create new locks mask 7 8// includes 9#include "render/shaders/common/render_color_conversion_common.h" 10#include "render/shaders/common/render_post_process_structs_common.h" 11 12#include "common/bloom_common.h" 13 14// camera data 15struct DefaultCameraMatrixStruct { 16 mat4 view; 17 mat4 proj; 18 mat4 viewProj; 19 20 mat4 viewInv; 21 mat4 projInv; 22 mat4 viewProjInv; 23 24 mat4 viewPrevFrame; 25 mat4 projPrevFrame; 26 mat4 viewProjPrevFrame; 27 28 mat4 shadowViewProj; 29 mat4 shadowViewProjInv; 30 31 // .xy = jitter offset, .zw = jitter offset with baked screen size 32 vec4 jitter; 33 vec4 jitterPrevFrame; 34 35 // .xy = unique id (64-bit), .zw = layer mask (64 bit) 36 uvec4 indices; 37 // .x multi-view camera additional layer count, .yzw 3 multi-view camera indices 38 // yzw are packed, use unpack functions 39 uvec4 multiViewIndices; 40 41 vec4 frustumPlanes[2]; 42 43 // .x environment count 44 uvec4 counts; 45 // padding to 256 46 uvec4 pad0; 47 mat4 matPad0; 48 mat4 matPad1; 49}; 50 51struct LockPassPushConstant { 52 vec4 renderSizeInvSize; 53 vec4 displaySizeInvSize; 54}; 55 56// sets 57 58layout(set = 0, binding = 0) uniform texture2D lockInputLumaTex; 59layout(set = 0, binding = 1, r8) uniform writeonly image2D newLocksTex; 60layout(set = 0, binding = 3, r32ui) uniform writeonly uimage2D prevDepthTex; 61layout(set = 0, binding = 2) uniform sampler uSampler; 62 63layout(push_constant, std430) uniform uPushConstantBlock 64{ 65 LockPassPushConstant uPc; 66}; 67 68layout(set = 0, binding = 12, std140) uniform uCameraMatrices 69{ 70 DefaultCameraMatrixStruct uCameras[16]; 71}; 72 73layout(constant_id = 0) const uint CORE_POST_PROCESS_FLAGS = 0; 74 75// Constants 76const float cSimilarThreshold = 1.05f; 77 78//---------------- Utility Functions ------------------// 79 80ivec2 RenderSize() { 81 return ivec2(uPc.renderSizeInvSize.x, uPc.renderSizeInvSize.y); 82} 83 84ivec2 DisplaySize() { 85 return ivec2(uPc.displaySizeInvSize.x, uPc.displaySizeInvSize.y); 86} 87 88vec2 RenderSizeVec2() { return uPc.renderSizeInvSize.xy; } 89vec2 DisplaySizeVec2() { return uPc.displaySizeInvSize.xy; } 90 91bool OnScreen(ivec2 pos, ivec2 size) { 92 return (pos.x >= 0 && pos.y >= 0 && pos.x < size.x && pos.y < size.y); 93} 94 95vec2 JitterPixels() { return uCameras[0].jitter.xy; } 96//vec2 JitterPixels() { return vec2(0); } 97 98// Load Luma from the input texture calculated in the Dilate/Reconstruct pass 99float LoadLockInputLuma(ivec2 px) 100{ 101 ivec2 sz = RenderSize(); 102 px = clamp(px, ivec2(0), sz - ivec2(1)); 103 return texelFetch(sampler2D(lockInputLumaTex, uSampler), px, 0).r; 104} 105 106ivec2 HrPosFromLrPos(vec2 iPxLrPos) 107{ 108 vec2 fSrcJitteredPos = vec2(iPxLrPos) + 0.5f - JitterPixels(); 109 vec2 fLrPosInHr = (fSrcJitteredPos / RenderSizeVec2()) * DisplaySizeVec2(); 110 ivec2 iPxHrPos = ivec2(floor(fLrPosInHr)); 111 return iPxHrPos; 112} 113 114void StoreNewLocks(ivec2 coord, float lockValue) { 115 imageStore(newLocksTex, coord, vec4(lockValue, 0, 0, 0)); 116} 117 118 119void GatherLockInputLumaRQuad(vec2 baseUv, 120 out float col00, 121 out float col10, 122 out float col01, 123 out float col11) 124{ 125 vec4 g = textureGather(sampler2D(lockInputLumaTex, uSampler), baseUv, 0); 126 127 col01 = g.w; 128 col11 = g.z; 129 col10 = g.y; 130 col00 = g.x; 131} 132 133bool ComputeThinFeatureConfidence(ivec2 pos) 134{ 135 const float kSimilarThreshold = 1.05; 136 const float kFp16Max = 65504.0; 137 const uint kSetBit4 = 1u << 4; 138 139 const uint rejectionMasks[4] = { 140 (1u<<0)|(1u<<1)|(1u<<3)|(1u<<4), // upper-left 2�2 141 (1u<<1)|(1u<<2)|(1u<<4)|(1u<<5), // upper-right 2�2 142 (1u<<3)|(1u<<4)|(1u<<6)|(1u<<7), // lower-left 2�2 143 (1u<<4)|(1u<<5)|(1u<<7)|(1u<<8) // lower-right 2�2 144 }; 145 146 147 float nucleusLuma = LoadLockInputLuma(pos); 148 float dissimMin = kFp16Max; 149 float dissimMax = 0.0; 150 uint similarityMask = kSetBit4; 151 152 //------------------------------------------------------------------ 153 // sample neighbourhood 0 1 2 154 // 3 4 5 155 // 6 7 8 156 //------------------------------------------------------------------ 157 float luma[9]; 158 float dummy; 159 160 vec2 invInputSize = 1.0 / vec2(RenderSize()); 161 vec2 baseUv = vec2(pos) * invInputSize; 162 vec2 unitUv = invInputSize; // (1 px, 1 px) in UV 163 164 GatherLockInputLumaRQuad(baseUv, 165 luma[0], luma[1], 166 luma[3], luma[4]); 167 GatherLockInputLumaRQuad(baseUv + unitUv, 168 dummy, 169 luma[5], 170 luma[7], luma[8]); 171 172 luma[2] = LoadLockInputLuma(pos + ivec2( 1,-1)); 173 luma[6] = LoadLockInputLuma(pos + ivec2(-1, 1)); 174 175 int idx = 0; 176 for (int y =-1; y <= 1; ++y) 177 for (int x =-1; x <= 1; ++x, ++idx) 178 { 179 if (x==0 && y==0) continue; 180 181 float s = luma[idx]; 182 float ratio = max(s, nucleusLuma) / min(s, nucleusLuma); 183 184 if (ratio < kSimilarThreshold) 185 { 186 similarityMask |= 1u << idx; 187 } 188 else 189 { 190 dissimMin = min(dissimMin, s); 191 dissimMax = max(dissimMax, s); 192 } 193 } 194 195 bool isRidge = (nucleusLuma > dissimMax) || (nucleusLuma < dissimMin); 196 if (!isRidge) return false; 197 198 199 for (int i = 0; i < 4; ++i) 200 if ((similarityMask & rejectionMasks[i]) == rejectionMasks[i]) 201 return false; 202 203 return true; 204} 205 206#define cTgs 8 207 208layout(local_size_x = 32, local_size_y = 8, local_size_z = 1) in; 209void main() 210{ 211 const ivec2 gid = ivec2(gl_GlobalInvocationID.xy); 212 const ivec2 size = RenderSize(); 213 214 if (gid.x >= size.x || gid.y >= size.y) { 215 return; 216 } 217 218 if(ComputeThinFeatureConfidence(gid)) 219 { 220 StoreNewLocks(HrPosFromLrPos(gid), 1U); 221 } 222 223 // Clear depth map for next frame 224 uint farPlaneBits = floatBitsToUint(1.0); 225 imageStore(prevDepthTex, gid, uvec4(farPlaneBits, 0, 0, 0)); 226} 227