diff options
| author | 2021-01-10 22:09:56 -0700 | |
|---|---|---|
| committer | 2021-01-10 22:09:56 -0700 | |
| commit | 7a3c884e39fccfbb498b855080bffabc9ce2e7f1 (patch) | |
| tree | 5056f9406dec188439cb0deb87603498243a9412 /src/video_core/host_shaders | |
| parent | More forgetting... duh (diff) | |
| parent | Merge pull request #5229 from Morph1984/fullscreen-opt (diff) | |
| download | yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.gz yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.xz yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.zip | |
Merge remote-tracking branch 'upstream/master' into int-flags
Diffstat (limited to 'src/video_core/host_shaders')
18 files changed, 674 insertions, 21 deletions
diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index aa62363a7..4c7399d5a 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt | |||
| @@ -1,18 +1,29 @@ | |||
| 1 | set(SHADER_FILES | 1 | set(SHADER_FILES |
| 2 | block_linear_unswizzle_2d.comp | ||
| 3 | block_linear_unswizzle_3d.comp | ||
| 4 | convert_depth_to_float.frag | ||
| 5 | convert_float_to_depth.frag | ||
| 6 | full_screen_triangle.vert | ||
| 7 | opengl_copy_bc4.comp | ||
| 2 | opengl_present.frag | 8 | opengl_present.frag |
| 3 | opengl_present.vert | 9 | opengl_present.vert |
| 10 | pitch_unswizzle.comp | ||
| 11 | vulkan_blit_color_float.frag | ||
| 12 | vulkan_blit_depth_stencil.frag | ||
| 13 | vulkan_present.frag | ||
| 14 | vulkan_present.vert | ||
| 15 | vulkan_quad_array.comp | ||
| 16 | vulkan_quad_indexed.comp | ||
| 17 | vulkan_uint8.comp | ||
| 4 | ) | 18 | ) |
| 5 | 19 | ||
| 6 | set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include) | 20 | find_program(GLSLANGVALIDATOR "glslangValidator" REQUIRED) |
| 7 | set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE) | 21 | |
| 22 | set(GLSL_FLAGS "") | ||
| 8 | 23 | ||
| 24 | set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include) | ||
| 9 | set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders) | 25 | set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders) |
| 10 | add_custom_command( | 26 | set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE) |
| 11 | OUTPUT | ||
| 12 | ${SHADER_DIR} | ||
| 13 | COMMAND | ||
| 14 | ${CMAKE_COMMAND} -E make_directory ${SHADER_DIR} | ||
| 15 | ) | ||
| 16 | 27 | ||
| 17 | set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) | 28 | set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in) |
| 18 | set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) | 29 | set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) |
| @@ -20,19 +31,36 @@ set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake) | |||
| 20 | foreach(FILENAME IN ITEMS ${SHADER_FILES}) | 31 | foreach(FILENAME IN ITEMS ${SHADER_FILES}) |
| 21 | string(REPLACE "." "_" SHADER_NAME ${FILENAME}) | 32 | string(REPLACE "." "_" SHADER_NAME ${FILENAME}) |
| 22 | set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}) | 33 | set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}) |
| 23 | set(HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}.h) | 34 | # Skip generating source headers on Vulkan exclusive files |
| 24 | add_custom_command( | 35 | if (NOT ${FILENAME} MATCHES "vulkan.*") |
| 25 | OUTPUT | 36 | set(SOURCE_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}.h) |
| 26 | ${HEADER_FILE} | 37 | add_custom_command( |
| 27 | COMMAND | 38 | OUTPUT |
| 28 | ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${HEADER_FILE} ${INPUT_FILE} | 39 | ${SOURCE_HEADER_FILE} |
| 29 | MAIN_DEPENDENCY | 40 | COMMAND |
| 30 | ${SOURCE_FILE} | 41 | ${CMAKE_COMMAND} -P ${HEADER_GENERATOR} ${SOURCE_FILE} ${SOURCE_HEADER_FILE} ${INPUT_FILE} |
| 31 | DEPENDS | 42 | MAIN_DEPENDENCY |
| 32 | ${HEADER_GENERATOR} | 43 | ${SOURCE_FILE} |
| 33 | ${INPUT_FILE} | 44 | DEPENDS |
| 34 | ) | 45 | ${INPUT_FILE} |
| 35 | set(SHADER_HEADERS ${SHADER_HEADERS} ${HEADER_FILE}) | 46 | # HEADER_GENERATOR should be included here but msbuild seems to assume it's always modified |
| 47 | ) | ||
| 48 | set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE}) | ||
| 49 | endif() | ||
| 50 | # Skip compiling to SPIR-V OpenGL exclusive files | ||
| 51 | if (NOT ${FILENAME} MATCHES "opengl.*") | ||
| 52 | string(TOUPPER ${SHADER_NAME}_SPV SPIRV_VARIABLE_NAME) | ||
| 53 | set(SPIRV_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}_spv.h) | ||
| 54 | add_custom_command( | ||
| 55 | OUTPUT | ||
| 56 | ${SPIRV_HEADER_FILE} | ||
| 57 | COMMAND | ||
| 58 | ${GLSLANGVALIDATOR} -V ${GLSL_FLAGS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE} | ||
| 59 | MAIN_DEPENDENCY | ||
| 60 | ${SOURCE_FILE} | ||
| 61 | ) | ||
| 62 | set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE}) | ||
| 63 | endif() | ||
| 36 | endforeach() | 64 | endforeach() |
| 37 | 65 | ||
| 38 | add_custom_target(host_shaders | 66 | add_custom_target(host_shaders |
diff --git a/src/video_core/host_shaders/StringShaderHeader.cmake b/src/video_core/host_shaders/StringShaderHeader.cmake index 368bce0ed..c0fc49768 100644 --- a/src/video_core/host_shaders/StringShaderHeader.cmake +++ b/src/video_core/host_shaders/StringShaderHeader.cmake | |||
| @@ -8,4 +8,6 @@ string(TOUPPER ${CONTENTS_NAME} CONTENTS_NAME) | |||
| 8 | 8 | ||
| 9 | file(READ ${SOURCE_FILE} CONTENTS) | 9 | file(READ ${SOURCE_FILE} CONTENTS) |
| 10 | 10 | ||
| 11 | get_filename_component(OUTPUT_DIR ${HEADER_FILE} DIRECTORY) | ||
| 12 | make_directory(${OUTPUT_DIR}) | ||
| 11 | configure_file(${INPUT_FILE} ${HEADER_FILE} @ONLY) | 13 | configure_file(${INPUT_FILE} ${HEADER_FILE} @ONLY) |
diff --git a/src/video_core/host_shaders/block_linear_unswizzle_2d.comp b/src/video_core/host_shaders/block_linear_unswizzle_2d.comp new file mode 100644 index 000000000..a131be79e --- /dev/null +++ b/src/video_core/host_shaders/block_linear_unswizzle_2d.comp | |||
| @@ -0,0 +1,122 @@ | |||
| 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 | ||
| 6 | |||
| 7 | #ifdef VULKAN | ||
| 8 | |||
| 9 | #extension GL_EXT_shader_16bit_storage : require | ||
| 10 | #extension GL_EXT_shader_8bit_storage : require | ||
| 11 | #define HAS_EXTENDED_TYPES 1 | ||
| 12 | #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { | ||
| 13 | #define END_PUSH_CONSTANTS }; | ||
| 14 | #define UNIFORM(n) | ||
| 15 | #define BINDING_SWIZZLE_BUFFER 0 | ||
| 16 | #define BINDING_INPUT_BUFFER 1 | ||
| 17 | #define BINDING_OUTPUT_IMAGE 2 | ||
| 18 | |||
| 19 | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||
| 20 | |||
| 21 | #extension GL_NV_gpu_shader5 : enable | ||
| 22 | #ifdef GL_NV_gpu_shader5 | ||
| 23 | #define HAS_EXTENDED_TYPES 1 | ||
| 24 | #else | ||
| 25 | #define HAS_EXTENDED_TYPES 0 | ||
| 26 | #endif | ||
| 27 | #define BEGIN_PUSH_CONSTANTS | ||
| 28 | #define END_PUSH_CONSTANTS | ||
| 29 | #define UNIFORM(n) layout (location = n) uniform | ||
| 30 | #define BINDING_SWIZZLE_BUFFER 0 | ||
| 31 | #define BINDING_INPUT_BUFFER 1 | ||
| 32 | #define BINDING_OUTPUT_IMAGE 0 | ||
| 33 | |||
| 34 | #endif | ||
| 35 | |||
| 36 | BEGIN_PUSH_CONSTANTS | ||
| 37 | UNIFORM(0) uvec3 origin; | ||
| 38 | UNIFORM(1) ivec3 destination; | ||
| 39 | UNIFORM(2) uint bytes_per_block_log2; | ||
| 40 | UNIFORM(3) uint layer_stride; | ||
| 41 | UNIFORM(4) uint block_size; | ||
| 42 | UNIFORM(5) uint x_shift; | ||
| 43 | UNIFORM(6) uint block_height; | ||
| 44 | UNIFORM(7) uint block_height_mask; | ||
| 45 | END_PUSH_CONSTANTS | ||
| 46 | |||
| 47 | layout(binding = BINDING_SWIZZLE_BUFFER, std430) readonly buffer SwizzleTable { | ||
| 48 | uint swizzle_table[]; | ||
| 49 | }; | ||
| 50 | |||
| 51 | #if HAS_EXTENDED_TYPES | ||
| 52 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU8 { uint8_t u8data[]; }; | ||
| 53 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU16 { uint16_t u16data[]; }; | ||
| 54 | #endif | ||
| 55 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU32 { uint u32data[]; }; | ||
| 56 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU64 { uvec2 u64data[]; }; | ||
| 57 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU128 { uvec4 u128data[]; }; | ||
| 58 | |||
| 59 | layout(binding = BINDING_OUTPUT_IMAGE) uniform writeonly uimage2DArray output_image; | ||
| 60 | |||
| 61 | layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; | ||
| 62 | |||
| 63 | const uint GOB_SIZE_X = 64; | ||
| 64 | const uint GOB_SIZE_Y = 8; | ||
| 65 | const uint GOB_SIZE_Z = 1; | ||
| 66 | const uint GOB_SIZE = GOB_SIZE_X * GOB_SIZE_Y * GOB_SIZE_Z; | ||
| 67 | |||
| 68 | const uint GOB_SIZE_X_SHIFT = 6; | ||
| 69 | const uint GOB_SIZE_Y_SHIFT = 3; | ||
| 70 | const uint GOB_SIZE_Z_SHIFT = 0; | ||
| 71 | const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_SHIFT; | ||
| 72 | |||
| 73 | const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1, GOB_SIZE_Y - 1); | ||
| 74 | |||
| 75 | uint SwizzleOffset(uvec2 pos) { | ||
| 76 | pos = pos & SWIZZLE_MASK; | ||
| 77 | return swizzle_table[pos.y * 64 + pos.x]; | ||
| 78 | } | ||
| 79 | |||
| 80 | uvec4 ReadTexel(uint offset) { | ||
| 81 | switch (bytes_per_block_log2) { | ||
| 82 | #if HAS_EXTENDED_TYPES | ||
| 83 | case 0: | ||
| 84 | return uvec4(u8data[offset], 0, 0, 0); | ||
| 85 | case 1: | ||
| 86 | return uvec4(u16data[offset / 2], 0, 0, 0); | ||
| 87 | #else | ||
| 88 | case 0: | ||
| 89 | return uvec4(bitfieldExtract(u32data[offset / 4], int((offset * 8) & 24), 8), 0, 0, 0); | ||
| 90 | case 1: | ||
| 91 | return uvec4(bitfieldExtract(u32data[offset / 4], int((offset * 8) & 16), 16), 0, 0, 0); | ||
| 92 | #endif | ||
| 93 | case 2: | ||
| 94 | return uvec4(u32data[offset / 4], 0, 0, 0); | ||
| 95 | case 3: | ||
| 96 | return uvec4(u64data[offset / 8], 0, 0); | ||
| 97 | case 4: | ||
| 98 | return u128data[offset / 16]; | ||
| 99 | } | ||
| 100 | return uvec4(0); | ||
| 101 | } | ||
| 102 | |||
| 103 | void main() { | ||
| 104 | uvec3 pos = gl_GlobalInvocationID + origin; | ||
| 105 | pos.x <<= bytes_per_block_log2; | ||
| 106 | |||
| 107 | // Read as soon as possible due to its latency | ||
| 108 | const uint swizzle = SwizzleOffset(pos.xy); | ||
| 109 | |||
| 110 | const uint block_y = pos.y >> GOB_SIZE_Y_SHIFT; | ||
| 111 | |||
| 112 | uint offset = 0; | ||
| 113 | offset += pos.z * layer_stride; | ||
| 114 | offset += (block_y >> block_height) * block_size; | ||
| 115 | offset += (block_y & block_height_mask) << GOB_SIZE_SHIFT; | ||
| 116 | offset += (pos.x >> GOB_SIZE_X_SHIFT) << x_shift; | ||
| 117 | offset += swizzle; | ||
| 118 | |||
| 119 | const uvec4 texel = ReadTexel(offset); | ||
| 120 | const ivec3 coord = ivec3(gl_GlobalInvocationID) + destination; | ||
| 121 | imageStore(output_image, coord, texel); | ||
| 122 | } | ||
diff --git a/src/video_core/host_shaders/block_linear_unswizzle_3d.comp b/src/video_core/host_shaders/block_linear_unswizzle_3d.comp new file mode 100644 index 000000000..bb6872e6b --- /dev/null +++ b/src/video_core/host_shaders/block_linear_unswizzle_3d.comp | |||
| @@ -0,0 +1,125 @@ | |||
| 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 | ||
| 6 | |||
| 7 | #ifdef VULKAN | ||
| 8 | |||
| 9 | #extension GL_EXT_shader_16bit_storage : require | ||
| 10 | #extension GL_EXT_shader_8bit_storage : require | ||
| 11 | #define HAS_EXTENDED_TYPES 1 | ||
| 12 | #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { | ||
| 13 | #define END_PUSH_CONSTANTS }; | ||
| 14 | #define UNIFORM(n) | ||
| 15 | #define BINDING_SWIZZLE_BUFFER 0 | ||
| 16 | #define BINDING_INPUT_BUFFER 1 | ||
| 17 | #define BINDING_OUTPUT_IMAGE 2 | ||
| 18 | |||
| 19 | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||
| 20 | |||
| 21 | #extension GL_NV_gpu_shader5 : enable | ||
| 22 | #ifdef GL_NV_gpu_shader5 | ||
| 23 | #define HAS_EXTENDED_TYPES 1 | ||
| 24 | #else | ||
| 25 | #define HAS_EXTENDED_TYPES 0 | ||
| 26 | #endif | ||
| 27 | #define BEGIN_PUSH_CONSTANTS | ||
| 28 | #define END_PUSH_CONSTANTS | ||
| 29 | #define UNIFORM(n) layout (location = n) uniform | ||
| 30 | #define BINDING_SWIZZLE_BUFFER 0 | ||
| 31 | #define BINDING_INPUT_BUFFER 1 | ||
| 32 | #define BINDING_OUTPUT_IMAGE 0 | ||
| 33 | |||
| 34 | #endif | ||
| 35 | |||
| 36 | BEGIN_PUSH_CONSTANTS | ||
| 37 | UNIFORM(0) uvec3 origin; | ||
| 38 | UNIFORM(1) ivec3 destination; | ||
| 39 | UNIFORM(2) uint bytes_per_block_log2; | ||
| 40 | UNIFORM(3) uint slice_size; | ||
| 41 | UNIFORM(4) uint block_size; | ||
| 42 | UNIFORM(5) uint x_shift; | ||
| 43 | UNIFORM(6) uint block_height; | ||
| 44 | UNIFORM(7) uint block_height_mask; | ||
| 45 | UNIFORM(8) uint block_depth; | ||
| 46 | UNIFORM(9) uint block_depth_mask; | ||
| 47 | END_PUSH_CONSTANTS | ||
| 48 | |||
| 49 | layout(binding = BINDING_SWIZZLE_BUFFER, std430) readonly buffer SwizzleTable { | ||
| 50 | uint swizzle_table[]; | ||
| 51 | }; | ||
| 52 | |||
| 53 | #if HAS_EXTENDED_TYPES | ||
| 54 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU8 { uint8_t u8data[]; }; | ||
| 55 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU16 { uint16_t u16data[]; }; | ||
| 56 | #endif | ||
| 57 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU32 { uint u32data[]; }; | ||
| 58 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU64 { uvec2 u64data[]; }; | ||
| 59 | layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU128 { uvec4 u128data[]; }; | ||
| 60 | |||
| 61 | layout(binding = BINDING_OUTPUT_IMAGE) uniform writeonly uimage3D output_image; | ||
| 62 | |||
| 63 | layout(local_size_x = 16, local_size_y = 8, local_size_z = 8) in; | ||
| 64 | |||
| 65 | const uint GOB_SIZE_X = 64; | ||
| 66 | const uint GOB_SIZE_Y = 8; | ||
| 67 | const uint GOB_SIZE_Z = 1; | ||
| 68 | const uint GOB_SIZE = GOB_SIZE_X * GOB_SIZE_Y * GOB_SIZE_Z; | ||
| 69 | |||
| 70 | const uint GOB_SIZE_X_SHIFT = 6; | ||
| 71 | const uint GOB_SIZE_Y_SHIFT = 3; | ||
| 72 | const uint GOB_SIZE_Z_SHIFT = 0; | ||
| 73 | const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_SHIFT; | ||
| 74 | |||
| 75 | const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1, GOB_SIZE_Y - 1); | ||
| 76 | |||
| 77 | uint SwizzleOffset(uvec2 pos) { | ||
| 78 | pos = pos & SWIZZLE_MASK; | ||
| 79 | return swizzle_table[pos.y * 64 + pos.x]; | ||
| 80 | } | ||
| 81 | |||
| 82 | uvec4 ReadTexel(uint offset) { | ||
| 83 | switch (bytes_per_block_log2) { | ||
| 84 | #if HAS_EXTENDED_TYPES | ||
| 85 | case 0: | ||
| 86 | return uvec4(u8data[offset], 0, 0, 0); | ||
| 87 | case 1: | ||
| 88 | return uvec4(u16data[offset / 2], 0, 0, 0); | ||
| 89 | #else | ||
| 90 | case 0: | ||
| 91 | return uvec4(bitfieldExtract(u32data[offset / 4], int((offset * 8) & 24), 8), 0, 0, 0); | ||
| 92 | case 1: | ||
| 93 | return uvec4(bitfieldExtract(u32data[offset / 4], int((offset * 8) & 16), 16), 0, 0, 0); | ||
| 94 | #endif | ||
| 95 | case 2: | ||
| 96 | return uvec4(u32data[offset / 4], 0, 0, 0); | ||
| 97 | case 3: | ||
| 98 | return uvec4(u64data[offset / 8], 0, 0); | ||
| 99 | case 4: | ||
| 100 | return u128data[offset / 16]; | ||
| 101 | } | ||
| 102 | return uvec4(0); | ||
| 103 | } | ||
| 104 | |||
| 105 | void main() { | ||
| 106 | uvec3 pos = gl_GlobalInvocationID + origin; | ||
| 107 | pos.x <<= bytes_per_block_log2; | ||
| 108 | |||
| 109 | // Read as soon as possible due to its latency | ||
| 110 | const uint swizzle = SwizzleOffset(pos.xy); | ||
| 111 | |||
| 112 | const uint block_y = pos.y >> GOB_SIZE_Y_SHIFT; | ||
| 113 | |||
| 114 | uint offset = 0; | ||
| 115 | offset += (pos.z >> block_depth) * slice_size; | ||
| 116 | offset += (pos.z & block_depth_mask) << (GOB_SIZE_SHIFT + block_height); | ||
| 117 | offset += (block_y >> block_height) * block_size; | ||
| 118 | offset += (block_y & block_height_mask) << GOB_SIZE_SHIFT; | ||
| 119 | offset += (pos.x >> GOB_SIZE_X_SHIFT) << x_shift; | ||
| 120 | offset += swizzle; | ||
| 121 | |||
| 122 | const uvec4 texel = ReadTexel(offset); | ||
| 123 | const ivec3 coord = ivec3(gl_GlobalInvocationID) + destination; | ||
| 124 | imageStore(output_image, coord, texel); | ||
| 125 | } | ||
diff --git a/src/video_core/host_shaders/convert_depth_to_float.frag b/src/video_core/host_shaders/convert_depth_to_float.frag new file mode 100644 index 000000000..624c58509 --- /dev/null +++ b/src/video_core/host_shaders/convert_depth_to_float.frag | |||
| @@ -0,0 +1,13 @@ | |||
| 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 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D depth_texture; | ||
| 8 | layout(location = 0) out float output_color; | ||
| 9 | |||
| 10 | void main() { | ||
| 11 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 12 | output_color = texelFetch(depth_texture, coord, 0).r; | ||
| 13 | } | ||
diff --git a/src/video_core/host_shaders/convert_float_to_depth.frag b/src/video_core/host_shaders/convert_float_to_depth.frag new file mode 100644 index 000000000..d86c795f4 --- /dev/null +++ b/src/video_core/host_shaders/convert_float_to_depth.frag | |||
| @@ -0,0 +1,13 @@ | |||
| 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 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D color_texture; | ||
| 8 | |||
| 9 | void main() { | ||
| 10 | ivec2 coord = ivec2(gl_FragCoord.xy); | ||
| 11 | float color = texelFetch(color_texture, coord, 0).r; | ||
| 12 | gl_FragDepth = color; | ||
| 13 | } | ||
diff --git a/src/video_core/host_shaders/full_screen_triangle.vert b/src/video_core/host_shaders/full_screen_triangle.vert new file mode 100644 index 000000000..452ad6502 --- /dev/null +++ b/src/video_core/host_shaders/full_screen_triangle.vert | |||
| @@ -0,0 +1,29 @@ | |||
| 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 450 | ||
| 6 | |||
| 7 | #ifdef VULKAN | ||
| 8 | #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { | ||
| 9 | #define END_PUSH_CONSTANTS }; | ||
| 10 | #define UNIFORM(n) | ||
| 11 | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||
| 12 | #define BEGIN_PUSH_CONSTANTS | ||
| 13 | #define END_PUSH_CONSTANTS | ||
| 14 | #define UNIFORM(n) layout (location = n) uniform | ||
| 15 | #endif | ||
| 16 | |||
| 17 | BEGIN_PUSH_CONSTANTS | ||
| 18 | UNIFORM(0) vec2 tex_scale; | ||
| 19 | UNIFORM(1) vec2 tex_offset; | ||
| 20 | END_PUSH_CONSTANTS | ||
| 21 | |||
| 22 | layout(location = 0) out vec2 texcoord; | ||
| 23 | |||
| 24 | void main() { | ||
| 25 | float x = float((gl_VertexIndex & 1) << 2); | ||
| 26 | float y = float((gl_VertexIndex & 2) << 1); | ||
| 27 | gl_Position = vec4(x - 1.0, y - 1.0, 0.0, 1.0); | ||
| 28 | texcoord = fma(vec2(x, y) / 2.0, tex_scale, tex_offset); | ||
| 29 | } | ||
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 | |||
| 8 | layout (local_size_x = 4, local_size_y = 4) in; | ||
| 9 | |||
| 10 | layout(binding = 0, rg32ui) readonly uniform uimage3D bc4_input; | ||
| 11 | layout(binding = 1, rgba8ui) writeonly uniform uimage3D bc4_output; | ||
| 12 | |||
| 13 | layout(location = 0) uniform uvec3 src_offset; | ||
| 14 | layout(location = 1) uniform uvec3 dst_offset; | ||
| 15 | |||
| 16 | // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_rgtc.txt | ||
| 17 | uint 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 | |||
| 64 | void 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 | } | ||
diff --git a/src/video_core/host_shaders/opengl_present.frag b/src/video_core/host_shaders/opengl_present.frag index 8a4cb024b..84b818227 100644 --- a/src/video_core/host_shaders/opengl_present.frag +++ b/src/video_core/host_shaders/opengl_present.frag | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 1 | #version 430 core | 5 | #version 430 core |
| 2 | 6 | ||
| 3 | layout (location = 0) in vec2 frag_tex_coord; | 7 | layout (location = 0) in vec2 frag_tex_coord; |
diff --git a/src/video_core/host_shaders/opengl_present.vert b/src/video_core/host_shaders/opengl_present.vert index 2235d31a4..c3b5adbba 100644 --- a/src/video_core/host_shaders/opengl_present.vert +++ b/src/video_core/host_shaders/opengl_present.vert | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 1 | #version 430 core | 5 | #version 430 core |
| 2 | 6 | ||
| 3 | out gl_PerVertex { | 7 | out gl_PerVertex { |
diff --git a/src/video_core/host_shaders/pitch_unswizzle.comp b/src/video_core/host_shaders/pitch_unswizzle.comp new file mode 100644 index 000000000..cb48ec170 --- /dev/null +++ b/src/video_core/host_shaders/pitch_unswizzle.comp | |||
| @@ -0,0 +1,86 @@ | |||
| 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 | ||
| 6 | |||
| 7 | #ifdef VULKAN | ||
| 8 | |||
| 9 | #extension GL_EXT_shader_16bit_storage : require | ||
| 10 | #extension GL_EXT_shader_8bit_storage : require | ||
| 11 | #define HAS_EXTENDED_TYPES 1 | ||
| 12 | #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { | ||
| 13 | #define END_PUSH_CONSTANTS }; | ||
| 14 | #define UNIFORM(n) | ||
| 15 | #define BINDING_INPUT_BUFFER 0 | ||
| 16 | #define BINDING_OUTPUT_IMAGE 1 | ||
| 17 | |||
| 18 | #else // ^^^ Vulkan ^^^ // vvv OpenGL vvv | ||
| 19 | |||
| 20 | #extension GL_NV_gpu_shader5 : enable | ||
| 21 | #ifdef GL_NV_gpu_shader5 | ||
| 22 | #define HAS_EXTENDED_TYPES 1 | ||
| 23 | #else | ||
| 24 | #define HAS_EXTENDED_TYPES 0 | ||
| 25 | #endif | ||
| 26 | #define BEGIN_PUSH_CONSTANTS | ||
| 27 | #define END_PUSH_CONSTANTS | ||
| 28 | #define UNIFORM(n) layout (location = n) uniform | ||
| 29 | #define BINDING_INPUT_BUFFER 0 | ||
| 30 | #define BINDING_OUTPUT_IMAGE 0 | ||
| 31 | |||
| 32 | #endif | ||
| 33 | |||
| 34 | BEGIN_PUSH_CONSTANTS | ||
| 35 | UNIFORM(0) uvec2 origin; | ||
| 36 | UNIFORM(1) ivec2 destination; | ||
| 37 | UNIFORM(2) uint bytes_per_block; | ||
| 38 | UNIFORM(3) uint pitch; | ||
| 39 | END_PUSH_CONSTANTS | ||
| 40 | |||
| 41 | #if HAS_EXTENDED_TYPES | ||
| 42 | layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU8 { uint8_t u8data[]; }; | ||
| 43 | layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU16 { uint16_t u16data[]; }; | ||
| 44 | #endif | ||
| 45 | layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU32 { uint u32data[]; }; | ||
| 46 | layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU64 { uvec2 u64data[]; }; | ||
| 47 | layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU128 { uvec4 u128data[]; }; | ||
| 48 | |||
| 49 | layout(binding = BINDING_OUTPUT_IMAGE) writeonly uniform uimage2D output_image; | ||
| 50 | |||
| 51 | layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in; | ||
| 52 | |||
| 53 | uvec4 ReadTexel(uint offset) { | ||
| 54 | switch (bytes_per_block) { | ||
| 55 | #if HAS_EXTENDED_TYPES | ||
| 56 | case 1: | ||
| 57 | return uvec4(u8data[offset], 0, 0, 0); | ||
| 58 | case 2: | ||
| 59 | return uvec4(u16data[offset / 2], 0, 0, 0); | ||
| 60 | #else | ||
| 61 | case 1: | ||
| 62 | return uvec4(bitfieldExtract(u32data[offset / 4], int((offset * 8) & 24), 8), 0, 0, 0); | ||
| 63 | case 2: | ||
| 64 | return uvec4(bitfieldExtract(u32data[offset / 4], int((offset * 8) & 16), 16), 0, 0, 0); | ||
| 65 | #endif | ||
| 66 | case 4: | ||
| 67 | return uvec4(u32data[offset / 4], 0, 0, 0); | ||
| 68 | case 8: | ||
| 69 | return uvec4(u64data[offset / 8], 0, 0); | ||
| 70 | case 16: | ||
| 71 | return u128data[offset / 16]; | ||
| 72 | } | ||
| 73 | return uvec4(0); | ||
| 74 | } | ||
| 75 | |||
| 76 | void main() { | ||
| 77 | uvec2 pos = gl_GlobalInvocationID.xy + origin; | ||
| 78 | |||
| 79 | uint offset = 0; | ||
| 80 | offset += pos.x * bytes_per_block; | ||
| 81 | offset += pos.y * pitch; | ||
| 82 | |||
| 83 | const uvec4 texel = ReadTexel(offset); | ||
| 84 | const ivec2 coord = ivec2(gl_GlobalInvocationID.xy) + destination; | ||
| 85 | imageStore(output_image, coord, texel); | ||
| 86 | } | ||
diff --git a/src/video_core/host_shaders/vulkan_blit_color_float.frag b/src/video_core/host_shaders/vulkan_blit_color_float.frag new file mode 100644 index 000000000..4a6aae410 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_blit_color_float.frag | |||
| @@ -0,0 +1,14 @@ | |||
| 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 450 | ||
| 6 | |||
| 7 | layout(binding = 0) uniform sampler2D tex; | ||
| 8 | |||
| 9 | layout(location = 0) in vec2 texcoord; | ||
| 10 | layout(location = 0) out vec4 color; | ||
| 11 | |||
| 12 | void main() { | ||
| 13 | color = textureLod(tex, texcoord, 0); | ||
| 14 | } | ||
diff --git a/src/video_core/host_shaders/vulkan_blit_depth_stencil.frag b/src/video_core/host_shaders/vulkan_blit_depth_stencil.frag new file mode 100644 index 000000000..19bb23a5a --- /dev/null +++ b/src/video_core/host_shaders/vulkan_blit_depth_stencil.frag | |||
| @@ -0,0 +1,16 @@ | |||
| 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 450 | ||
| 6 | #extension GL_ARB_shader_stencil_export : require | ||
| 7 | |||
| 8 | layout(binding = 0) uniform sampler2D depth_tex; | ||
| 9 | layout(binding = 1) uniform isampler2D stencil_tex; | ||
| 10 | |||
| 11 | layout(location = 0) in vec2 texcoord; | ||
| 12 | |||
| 13 | void main() { | ||
| 14 | gl_FragDepth = textureLod(depth_tex, texcoord, 0).r; | ||
| 15 | gl_FragStencilRefARB = textureLod(stencil_tex, texcoord, 0).r; | ||
| 16 | } | ||
diff --git a/src/video_core/host_shaders/vulkan_present.frag b/src/video_core/host_shaders/vulkan_present.frag new file mode 100644 index 000000000..0979ff3e6 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_present.frag | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 460 core | ||
| 6 | |||
| 7 | layout (location = 0) in vec2 frag_tex_coord; | ||
| 8 | |||
| 9 | layout (location = 0) out vec4 color; | ||
| 10 | |||
| 11 | layout (binding = 1) uniform sampler2D color_texture; | ||
| 12 | |||
| 13 | void main() { | ||
| 14 | color = texture(color_texture, frag_tex_coord); | ||
| 15 | } | ||
diff --git a/src/video_core/host_shaders/vulkan_present.vert b/src/video_core/host_shaders/vulkan_present.vert new file mode 100644 index 000000000..00b868958 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_present.vert | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 460 core | ||
| 6 | |||
| 7 | layout (location = 0) in vec2 vert_position; | ||
| 8 | layout (location = 1) in vec2 vert_tex_coord; | ||
| 9 | |||
| 10 | layout (location = 0) out vec2 frag_tex_coord; | ||
| 11 | |||
| 12 | layout (set = 0, binding = 0) uniform MatrixBlock { | ||
| 13 | mat4 modelview_matrix; | ||
| 14 | }; | ||
| 15 | |||
| 16 | void main() { | ||
| 17 | gl_Position = modelview_matrix * vec4(vert_position, 0.0, 1.0); | ||
| 18 | frag_tex_coord = vert_tex_coord; | ||
| 19 | } | ||
diff --git a/src/video_core/host_shaders/vulkan_quad_array.comp b/src/video_core/host_shaders/vulkan_quad_array.comp new file mode 100644 index 000000000..212f4e998 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_quad_array.comp | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 460 core | ||
| 6 | |||
| 7 | layout (local_size_x = 1024) in; | ||
| 8 | |||
| 9 | layout (std430, set = 0, binding = 0) buffer OutputBuffer { | ||
| 10 | uint output_indexes[]; | ||
| 11 | }; | ||
| 12 | |||
| 13 | layout (push_constant) uniform PushConstants { | ||
| 14 | uint first; | ||
| 15 | }; | ||
| 16 | |||
| 17 | void main() { | ||
| 18 | uint primitive = gl_GlobalInvocationID.x; | ||
| 19 | if (primitive * 6 >= output_indexes.length()) { | ||
| 20 | return; | ||
| 21 | } | ||
| 22 | |||
| 23 | const uint quad_map[6] = uint[](0, 1, 2, 0, 2, 3); | ||
| 24 | for (uint vertex = 0; vertex < 6; ++vertex) { | ||
| 25 | uint index = first + primitive * 4 + quad_map[vertex]; | ||
| 26 | output_indexes[primitive * 6 + vertex] = index; | ||
| 27 | } | ||
| 28 | } | ||
diff --git a/src/video_core/host_shaders/vulkan_quad_indexed.comp b/src/video_core/host_shaders/vulkan_quad_indexed.comp new file mode 100644 index 000000000..8655591d0 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_quad_indexed.comp | |||
| @@ -0,0 +1,41 @@ | |||
| 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 460 core | ||
| 6 | |||
| 7 | layout (local_size_x = 1024) in; | ||
| 8 | |||
| 9 | layout (std430, set = 0, binding = 0) readonly buffer InputBuffer { | ||
| 10 | uint input_indexes[]; | ||
| 11 | }; | ||
| 12 | |||
| 13 | layout (std430, set = 0, binding = 1) writeonly buffer OutputBuffer { | ||
| 14 | uint output_indexes[]; | ||
| 15 | }; | ||
| 16 | |||
| 17 | layout (push_constant) uniform PushConstants { | ||
| 18 | uint base_vertex; | ||
| 19 | int index_shift; // 0: uint8, 1: uint16, 2: uint32 | ||
| 20 | }; | ||
| 21 | |||
| 22 | void main() { | ||
| 23 | int primitive = int(gl_GlobalInvocationID.x); | ||
| 24 | if (primitive * 6 >= output_indexes.length()) { | ||
| 25 | return; | ||
| 26 | } | ||
| 27 | |||
| 28 | int index_size = 8 << index_shift; | ||
| 29 | int flipped_shift = 2 - index_shift; | ||
| 30 | int mask = (1 << flipped_shift) - 1; | ||
| 31 | |||
| 32 | const int quad_swizzle[6] = int[](0, 1, 2, 0, 2, 3); | ||
| 33 | for (uint vertex = 0; vertex < 6; ++vertex) { | ||
| 34 | int offset = primitive * 4 + quad_swizzle[vertex]; | ||
| 35 | int int_offset = offset >> flipped_shift; | ||
| 36 | int bit_offset = (offset & mask) * index_size; | ||
| 37 | uint packed_input = input_indexes[int_offset]; | ||
| 38 | uint index = bitfieldExtract(packed_input, bit_offset, index_size); | ||
| 39 | output_indexes[primitive * 6 + vertex] = index + base_vertex; | ||
| 40 | } | ||
| 41 | } | ||
diff --git a/src/video_core/host_shaders/vulkan_uint8.comp b/src/video_core/host_shaders/vulkan_uint8.comp new file mode 100644 index 000000000..ad74d7af9 --- /dev/null +++ b/src/video_core/host_shaders/vulkan_uint8.comp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #version 460 core | ||
| 6 | #extension GL_EXT_shader_16bit_storage : require | ||
| 7 | #extension GL_EXT_shader_8bit_storage : require | ||
| 8 | |||
| 9 | layout (local_size_x = 1024) in; | ||
| 10 | |||
| 11 | layout (std430, set = 0, binding = 0) readonly buffer InputBuffer { | ||
| 12 | uint8_t input_indexes[]; | ||
| 13 | }; | ||
| 14 | |||
| 15 | layout (std430, set = 0, binding = 1) writeonly buffer OutputBuffer { | ||
| 16 | uint16_t output_indexes[]; | ||
| 17 | }; | ||
| 18 | |||
| 19 | void main() { | ||
| 20 | uint id = gl_GlobalInvocationID.x; | ||
| 21 | if (id < input_indexes.length()) { | ||
| 22 | output_indexes[id] = uint16_t(input_indexes[id]); | ||
| 23 | } | ||
| 24 | } | ||