summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/host_shaders/CMakeLists.txt1
-rw-r--r--src/video_core/host_shaders/opengl_copy_bc4.comp70
2 files changed, 71 insertions, 0 deletions
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt
index 5770c4761..338bf9eec 100644
--- a/src/video_core/host_shaders/CMakeLists.txt
+++ b/src/video_core/host_shaders/CMakeLists.txt
@@ -2,6 +2,7 @@ set(SHADER_FILES
2 block_linear_unswizzle_2d.comp 2 block_linear_unswizzle_2d.comp
3 block_linear_unswizzle_3d.comp 3 block_linear_unswizzle_3d.comp
4 full_screen_triangle.vert 4 full_screen_triangle.vert
5 opengl_copy_bc4.comp
5 opengl_present.frag 6 opengl_present.frag
6 opengl_present.vert 7 opengl_present.vert
7 pitch_unswizzle.comp 8 pitch_unswizzle.comp
diff --git a/src/video_core/host_shaders/opengl_copy_bc4.comp b/src/video_core/host_shaders/opengl_copy_bc4.comp
new file mode 100644
index 000000000..7b8e20fbe
--- /dev/null
+++ b/src/video_core/host_shaders/opengl_copy_bc4.comp
@@ -0,0 +1,70 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#version 430 core
6#extension GL_ARB_gpu_shader_int64 : require
7
8layout (local_size_x = 4, local_size_y = 4) in;
9
10layout(binding = 0, rg32ui) readonly uniform uimage3D bc4_input;
11layout(binding = 1, rgba8ui) writeonly uniform uimage3D bc4_output;
12
13layout(location = 0) uniform uvec3 src_offset;
14layout(location = 1) uniform uvec3 dst_offset;
15
16// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_rgtc.txt
17uint DecompressBlock(uint64_t bits, uvec2 coord) {
18 const uint code_offset = 16 + 3 * (4 * coord.y + coord.x);
19 const uint code = uint(bits >> code_offset) & 7;
20 const uint red0 = uint(bits >> 0) & 0xff;
21 const uint red1 = uint(bits >> 8) & 0xff;
22 if (red0 > red1) {
23 switch (code) {
24 case 0:
25 return red0;
26 case 1:
27 return red1;
28 case 2:
29 return (6 * red0 + 1 * red1) / 7;
30 case 3:
31 return (5 * red0 + 2 * red1) / 7;
32 case 4:
33 return (4 * red0 + 3 * red1) / 7;
34 case 5:
35 return (3 * red0 + 4 * red1) / 7;
36 case 6:
37 return (2 * red0 + 5 * red1) / 7;
38 case 7:
39 return (1 * red0 + 6 * red1) / 7;
40 }
41 } else {
42 switch (code) {
43 case 0:
44 return red0;
45 case 1:
46 return red1;
47 case 2:
48 return (4 * red0 + 1 * red1) / 5;
49 case 3:
50 return (3 * red0 + 2 * red1) / 5;
51 case 4:
52 return (2 * red0 + 3 * red1) / 5;
53 case 5:
54 return (1 * red0 + 4 * red1) / 5;
55 case 6:
56 return 0;
57 case 7:
58 return 0xff;
59 }
60 }
61 return 0;
62}
63
64void main() {
65 uvec2 packed_bits = imageLoad(bc4_input, ivec3(gl_WorkGroupID + src_offset)).rg;
66 uint64_t bits = packUint2x32(packed_bits);
67 uint red = DecompressBlock(bits, gl_LocalInvocationID.xy);
68 uvec4 color = uvec4(red & 0xff, 0, 0, 0xff);
69 imageStore(bc4_output, ivec3(gl_GlobalInvocationID + dst_offset), color);
70}