// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE #pragma anki mutator REDUCTION_TYPE 0 1 // 0: min 1: max #pragma anki mutator MIN_MAX_SAMPLER 0 1 #pragma anki technique comp #include struct Constants { Vec2 m_invSrcTexSize; U32 m_threadGroupCount; U32 m_mipmapCount; }; ANKI_FAST_CONSTANTS(Constants, g_consts) globallycoherent RWStructuredBuffer g_spdCounter : register(u0); globallycoherent RWTexture2D g_dstStorageTextures[kMaxMipsSinglePassDownsamplerCanProduce] : register(u1); Texture2D g_srcTex : register(t0); #if MIN_MAX_SAMPLER SamplerState g_minMaxAnyClampSampler : register(s0); #else SamplerState g_linearAnyClampSampler : register(s0); #endif // Include SPD #define A_GPU 1 #define A_HLSL 1 #include groupshared AU1 s_spdCounter; groupshared AF1 s_spdIntermediateR[16][16]; AF4 SpdLoadSourceImage(AU2 p, AU1 slice) { ANKI_MAYBE_UNUSED(slice); const AF2 uv = p * g_consts.m_invSrcTexSize + g_consts.m_invSrcTexSize; #if MIN_MAX_SAMPLER const F32 f = g_srcTex.SampleLevel(g_minMaxAnyClampSampler, uv, 0.0).r; #else Vec4 samples = g_srcTex.GatherRed(g_linearAnyClampSampler, uv); # if REDUCTION_TYPE == 0 const F32 f = min4(samples); # else const F32 f = max4(samples); # endif #endif return AF4(f, 0.0, 0.0, 0.0); } AF4 SpdLoad(AU2 p, AU1 slice) { ANKI_MAYBE_UNUSED(slice); return AF4(g_dstStorageTextures[5][p].r, 0.0, 0.0, 0.0); } void SpdStore(AU2 p, AF4 value, AU1 mip, AU1 slice) { ANKI_MAYBE_UNUSED(slice); g_dstStorageTextures[mip][p] = Vec4(value.x, 0.0, 0.0, 0.0); } void SpdIncreaseAtomicCounter(AU1 slice) { ANKI_MAYBE_UNUSED(slice); InterlockedAdd(g_spdCounter[0], 1u, s_spdCounter); } AU1 SpdGetAtomicCounter() { return s_spdCounter; } void SpdResetAtomicCounter(AU1 slice) { ANKI_MAYBE_UNUSED(slice); g_spdCounter[0] = 0u; } AF4 SpdLoadIntermediate(AU1 x, AU1 y) { return AF4(s_spdIntermediateR[x][y], 0.0, 0.0, 0.0); } void SpdStoreIntermediate(AU1 x, AU1 y, AF4 value) { s_spdIntermediateR[x][y] = value.x; } AF4 SpdReduce4(AF4 v0, AF4 v1, AF4 v2, AF4 v3) { #if REDUCTION_TYPE == 0 const F32 value = min4(v0.x, v1.x, v2.x, v3.x); #else const F32 value = max4(v0.x, v1.x, v2.x, v3.x); #endif return AF4(value, 0.0, 0.0, 0.0); } #define SPD_LINEAR_SAMPLER 1 #include [numthreads(256, 1, 1)] void main(UVec3 svGroupId : SV_GROUPID, U32 svGroupIndex : SV_GROUPINDEX) { const U32 slice = 0u; const UVec2 offset = UVec2(0, 0); SpdDownsample(AU2(svGroupId.xy), AU1(svGroupIndex), AU1(g_consts.m_mipmapCount), AU1(g_consts.m_threadGroupCount), slice, offset); }