// This file is generated by the scripts available at https://github.com/hauuau/magpie-prescalers
// Please don't edit this file directly.
// Generated by: ravu-3x.py --target luma --weights-file weights\ravu-3x_weights-r3.py --float-format float16dx --use-magpie --overwrite
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//!MAGPIE EFFECT
//!VERSION 4

//!TEXTURE
Texture2D INPUT;

//!SAMPLER
//!FILTER POINT
SamplerState sam_INPUT;

//!TEXTURE
//!WIDTH  INPUT_WIDTH * 3
//!HEIGHT INPUT_HEIGHT * 3
Texture2D OUTPUT;

//!SAMPLER
//!FILTER LINEAR
SamplerState sam_INPUT_LINEAR;

//!TEXTURE
//!SOURCE ravu_3x_lut3_f16.dds
//!FORMAT R16G16B16A16_FLOAT
Texture2D ravu_3x_lut3;

//!SAMPLER
//!FILTER LINEAR
SamplerState sam_ravu_3x_lut3;

//!COMMON
#include "prescalers.hlsli"

#define LAST_PASS 1

//!PASS 1
//!DESC RAVU-3x (luma, r3)
//!IN INPUT, ravu_3x_lut3
//!OUT OUTPUT
//!BLOCK_SIZE 96, 24
//!NUM_THREADS 32, 8
shared float inp[432];

#define CURRENT_PASS 1

#define GET_SAMPLE(x) dot(x.rgb, rgb2y)
#define imageStore(out_image, pos, val) imageStoreOverride(pos, val.x)
void imageStoreOverride(uint2 pos, float value) {
	float2 UV = mul(rgb2uv, INPUT.SampleLevel(sam_INPUT_LINEAR, HOOKED_map(pos), 0).rgb);
	OUTPUT[pos] = float4(mul(yuv2rgb, float3(value.x, UV)), 1.0);
}

#define INPUT_tex(pos) GET_SAMPLE(vec4(texture(INPUT, pos)))
static const float2 INPUT_size = float2(GetInputSize());
static const float2 INPUT_pt = float2(GetInputPt());

#define ravu_3x_lut3_tex(pos) (vec4(texture(ravu_3x_lut3, pos)))

#define HOOKED_tex(pos) INPUT_tex(pos)
#define HOOKED_size INPUT_size
#define HOOKED_pt INPUT_pt

void Pass1(uint2 blockStart, uint3 threadId) {
	ivec2 group_base = ivec2(gl_WorkGroupID) * ivec2(gl_WorkGroupSize);
	int local_pos = int(gl_LocalInvocationID.x) * 12 + int(gl_LocalInvocationID.y);
	for (int id = int(gl_LocalInvocationIndex); id < 432; id += int(gl_WorkGroupSize.x * gl_WorkGroupSize.y)) {
		uint x = (uint)id / 12, y = (uint)id % 12;
		inp[id] = HOOKED_tex(HOOKED_pt * vec2(float(group_base.x + x) + (-1.5), float(group_base.y + y) + (-1.5))).x;
	}
	barrier();
#if CURRENT_PASS == LAST_PASS
	uint2 destPos = blockStart + threadId.xy * 3;
	uint2 outputSize = GetOutputSize();
	if (destPos.x >= outputSize.x || destPos.y >= outputSize.y) {
		return;
	}
#endif
	float luma0 = inp[local_pos + 0];
	float luma1 = inp[local_pos + 1];
	float luma2 = inp[local_pos + 2];
	float luma3 = inp[local_pos + 3];
	float luma4 = inp[local_pos + 4];
	float luma5 = inp[local_pos + 12];
	float luma6 = inp[local_pos + 13];
	float luma7 = inp[local_pos + 14];
	float luma8 = inp[local_pos + 15];
	float luma9 = inp[local_pos + 16];
	float luma10 = inp[local_pos + 24];
	float luma11 = inp[local_pos + 25];
	float luma12 = inp[local_pos + 26];
	float luma13 = inp[local_pos + 27];
	float luma14 = inp[local_pos + 28];
	float luma15 = inp[local_pos + 36];
	float luma16 = inp[local_pos + 37];
	float luma17 = inp[local_pos + 38];
	float luma18 = inp[local_pos + 39];
	float luma19 = inp[local_pos + 40];
	float luma20 = inp[local_pos + 48];
	float luma21 = inp[local_pos + 49];
	float luma22 = inp[local_pos + 50];
	float luma23 = inp[local_pos + 51];
	float luma24 = inp[local_pos + 52];
	vec3 abd = vec3(0.0, 0.0, 0.0);
	float gx, gy;
	gx = (luma11 - luma1) / 2.0;
	gy = (luma7 - luma5) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.1018680644198163;
	gx = (luma12 - luma2) / 2.0;
	gy = (luma8 - luma6) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.11543163961422666;
	gx = (luma13 - luma3) / 2.0;
	gy = (luma9 - luma7) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.1018680644198163;
	gx = (luma16 - luma6) / 2.0;
	gy = (luma12 - luma10) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.11543163961422666;
	gx = (luma17 - luma7) / 2.0;
	gy = (luma13 - luma11) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.13080118386382833;
	gx = (luma18 - luma8) / 2.0;
	gy = (luma14 - luma12) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.11543163961422666;
	gx = (luma21 - luma11) / 2.0;
	gy = (luma17 - luma15) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.1018680644198163;
	gx = (luma22 - luma12) / 2.0;
	gy = (luma18 - luma16) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.11543163961422666;
	gx = (luma23 - luma13) / 2.0;
	gy = (luma19 - luma17) / 2.0;
	abd += vec3(gx * gx, gx * gy, gy * gy) * 0.1018680644198163;
	float a = abd.x, b = abd.y, d = abd.z;
	float T = a + d, D = a * d - b * b;
	float delta = sqrt(max(T * T / 4.0 - D, 0.0));
	float L1 = T / 2.0 + delta, L2 = T / 2.0 - delta;
	float sqrtL1 = sqrt(L1), sqrtL2 = sqrt(L2);
	float theta = mix(mod(atan(L1 - a, b) + 3.141592653589793, 3.141592653589793), 0.0, abs(b) < 1.192092896e-7);
	float lambda = sqrtL1;
	float mu = mix((sqrtL1 - sqrtL2) / (sqrtL1 + sqrtL2), 0.0, sqrtL1 + sqrtL2 < 1.192092896e-7);
	float angle = floor(theta * 24.0 / 3.141592653589793);
	float strength = mix(mix(0.0, 1.0, lambda >= 0.005), 2.0, lambda >= 0.02);
	float coherence = mix(mix(0.0, 1.0, mu >= 0.25), 2.0, mu >= 0.5);
	float coord_y = ((angle * 3.0 + strength) * 3.0 + coherence + 0.5) / 216.0;
	vec4 res0 = vec4(0.0, 0.0, 0.0, 0.0), res1 = vec4(0.0, 0.0, 0.0, 0.0);
	vec4 w0, w1;
	w0 = texture(ravu_3x_lut3, vec2(0.019230769230769232, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.057692307692307696, coord_y));
	res0 += luma0 * w0 + luma24 * w1.wzyx;
	res1 += luma0 * w1 + luma24 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.09615384615384616, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.1346153846153846, coord_y));
	res0 += luma1 * w0 + luma23 * w1.wzyx;
	res1 += luma1 * w1 + luma23 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.17307692307692307, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.21153846153846154, coord_y));
	res0 += luma2 * w0 + luma22 * w1.wzyx;
	res1 += luma2 * w1 + luma22 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.25, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.28846153846153844, coord_y));
	res0 += luma3 * w0 + luma21 * w1.wzyx;
	res1 += luma3 * w1 + luma21 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.3269230769230769, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.36538461538461536, coord_y));
	res0 += luma4 * w0 + luma20 * w1.wzyx;
	res1 += luma4 * w1 + luma20 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.40384615384615385, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.4423076923076923, coord_y));
	res0 += luma5 * w0 + luma19 * w1.wzyx;
	res1 += luma5 * w1 + luma19 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.4807692307692308, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.5192307692307693, coord_y));
	res0 += luma6 * w0 + luma18 * w1.wzyx;
	res1 += luma6 * w1 + luma18 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.5576923076923077, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.5961538461538461, coord_y));
	res0 += luma7 * w0 + luma17 * w1.wzyx;
	res1 += luma7 * w1 + luma17 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.6346153846153846, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.6730769230769231, coord_y));
	res0 += luma8 * w0 + luma16 * w1.wzyx;
	res1 += luma8 * w1 + luma16 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.7115384615384616, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.75, coord_y));
	res0 += luma9 * w0 + luma15 * w1.wzyx;
	res1 += luma9 * w1 + luma15 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.7884615384615384, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.8269230769230769, coord_y));
	res0 += luma10 * w0 + luma14 * w1.wzyx;
	res1 += luma10 * w1 + luma14 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.8653846153846154, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.9038461538461539, coord_y));
	res0 += luma11 * w0 + luma13 * w1.wzyx;
	res1 += luma11 * w1 + luma13 * w0.wzyx;
	w0 = texture(ravu_3x_lut3, vec2(0.9423076923076923, coord_y));
	w1 = texture(ravu_3x_lut3, vec2(0.9807692307692307, coord_y));
	res0 += luma12 * w0;
	res1 += luma12 * w1;
	res0 = clamp(res0, 0.0, 1.0);
	res1 = clamp(res1, 0.0, 1.0);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(0, 0), res0[0]);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(0, 1), res0[1]);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(0, 2), res0[2]);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(1, 0), res0[3]);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(1, 1), luma12);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(1, 2), res1[0]);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(2, 0), res1[1]);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(2, 1), res1[2]);
	imageStore(out_image, ivec2(gl_GlobalInvocationID) * 3 + ivec2(2, 2), res1[3]);
}
