video_core: Add vulkan shaders (#6619)

This commit is contained in:
GPUCode 2023-06-19 17:02:18 +03:00 committed by GitHub
parent 7c11b9b689
commit 3faddd5e03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 263 additions and 10 deletions

View File

@ -4,13 +4,12 @@
set(SHADER_FILES
format_reinterpreter/d24s8_to_rgba8.frag
format_reinterpreter/fullscreen_quad.vert
format_reinterpreter/rgba4_to_rgb5a1.frag
format_reinterpreter/vulkan_d24s8_to_rgba8.comp
texture_filtering/bicubic.frag
texture_filtering/nearest_neighbor.frag
texture_filtering/refine.frag
texture_filtering/scale_force.frag
texture_filtering/tex_coord.vert
texture_filtering/xbrz_freescale.frag
texture_filtering/mmpx.frag
texture_filtering/x_gradient.frag
@ -20,8 +19,22 @@ set(SHADER_FILES
opengl_present.vert
opengl_present_anaglyph.frag
opengl_present_interlaced.frag
vulkan_depth_to_buffer.comp
vulkan_present.frag
vulkan_present.vert
vulkan_present_anaglyph.frag
vulkan_present_interlaced.frag
vulkan_blit_depth_stencil.frag
)
find_program(GLSLANGVALIDATOR "glslangValidator")
if ("${GLSLANGVALIDATOR}" STREQUAL "GLSLANGVALIDATOR-NOTFOUND")
message(FATAL_ERROR "Required program `glslangValidator` not found.")
endif()
set(MACROS "-Dgl_VertexID=gl_VertexIndex")
set(QUIET_FLAG "--quiet")
set(SHADER_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/include)
set(SHADER_DIR ${SHADER_INCLUDE}/video_core/host_shaders)
set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE)
@ -29,6 +42,23 @@ set(HOST_SHADERS_INCLUDE ${SHADER_INCLUDE} PARENT_SCOPE)
set(INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/source_shader.h.in)
set(HEADER_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/StringShaderHeader.cmake)
# Check if `--quiet` is available on host's glslangValidator version
# glslangValidator prints to STDERR iff an unrecognized flag is passed to it
execute_process(
COMMAND
${GLSLANGVALIDATOR} ${QUIET_FLAG}
ERROR_VARIABLE
GLSLANG_ERROR
# STDOUT variable defined to silence unnecessary output during CMake configuration
OUTPUT_VARIABLE
GLSLANG_OUTPUT
)
if (NOT GLSLANG_ERROR STREQUAL "")
message(WARNING "Refusing to use unavailable flag `${QUIET_FLAG}` on `${GLSLANGVALIDATOR}`")
set(QUIET_FLAG "")
endif()
foreach(FILENAME IN ITEMS ${SHADER_FILES})
string(REPLACE "." "_" SHADER_NAME ${FILENAME})
set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME})
@ -48,6 +78,21 @@ foreach(FILENAME IN ITEMS ${SHADER_FILES})
)
set(SHADER_HEADERS ${SHADER_HEADERS} ${SOURCE_HEADER_FILE})
endif()
# Skip compiling to SPIR-V OpenGL exclusive files
if (NOT ${FILENAME} MATCHES "opengl.*")
get_filename_component(FILE_NAME ${SHADER_NAME} NAME)
string(TOUPPER ${FILE_NAME}_SPV SPIRV_VARIABLE_NAME)
set(SPIRV_HEADER_FILE ${SHADER_DIR}/${SHADER_NAME}_spv.h)
add_custom_command(
OUTPUT
${SPIRV_HEADER_FILE}
COMMAND
${GLSLANGVALIDATOR} --target-env vulkan1.1 --glsl-version 450 ${QUIET_FLAG} ${MACROS} --variable-name ${SPIRV_VARIABLE_NAME} -o ${SPIRV_HEADER_FILE} ${SOURCE_FILE}
MAIN_DEPENDENCY
${SOURCE_FILE}
)
set(SHADER_HEADERS ${SHADER_HEADERS} ${SPIRV_HEADER_FILE})
endif()
endforeach()
set(SHADER_SOURCES ${SHADER_FILES})

View File

@ -0,0 +1,26 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#version 450 core
#extension GL_EXT_samplerless_texture_functions : require
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout(set = 0, binding = 0) uniform highp texture2D depth;
layout(set = 0, binding = 1) uniform lowp utexture2D stencil;
layout(set = 0, binding = 2, rgba8) uniform highp writeonly image2D color;
layout(push_constant, std140) uniform ComputeInfo {
mediump ivec2 src_offset;
mediump ivec2 extent;
};
void main() {
ivec2 tex_coord = src_offset + ivec2(gl_GlobalInvocationID.xy);
highp uint depth_val =
uint(texelFetch(depth, tex_coord, 0).x * (exp2(32.0) - 1.0));
lowp uint stencil_val = texelFetch(stencil, tex_coord, 0).x;
highp uvec4 components =
uvec4(stencil_val, (uvec3(depth_val) >> uvec3(24u, 16u, 8u)) & 0x000000FFu);
imageStore(color, tex_coord, vec4(components) / (exp2(8.0) - 1.0));
}

View File

@ -9,8 +9,20 @@ out gl_PerVertex {
layout(location = 0) out vec2 texcoord;
layout (location = 0) uniform vec2 tex_scale;
layout (location = 1) uniform vec2 tex_offset;
#ifdef VULKAN
#define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants {
#define END_PUSH_CONSTANTS };
#define UNIFORM(n)
#else // if OpenGL
#define BEGIN_PUSH_CONSTANTS
#define END_PUSH_CONSTANTS
#define UNIFORM(n) layout (location = n) uniform
#endif
BEGIN_PUSH_CONSTANTS
UNIFORM(0) vec2 tex_scale;
UNIFORM(1) vec2 tex_offset;
END_PUSH_CONSTANTS
void main() {
float x = float((gl_VertexID & 1) << 2);

View File

@ -9,7 +9,14 @@ layout(location = 0) in vec2 tex_coord;
layout(location = 0) out vec4 frag_color;
layout(binding = 0) uniform sampler2D tex;
layout(location = 2) uniform lowp float scale;
#ifdef VULKAN
layout(push_constant, std140) uniform XbrzInfo {
float scale;
};
#else
layout(location = 2) uniform float scale;
#endif
const int BLEND_NONE = 0;
const int BLEND_NORMAL = 1;

View File

@ -0,0 +1,16 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#version 450 core
#extension GL_ARB_shader_stencil_export : require
layout(binding = 0) uniform sampler2D depth_tex;
layout(binding = 1) uniform usampler2D stencil_tex;
layout(location = 0) in vec2 texcoord;
void main() {
gl_FragDepth = textureLod(depth_tex, texcoord, 0).r;
gl_FragStencilRefARB = int(textureLod(stencil_tex, texcoord, 0).r);
}

View File

@ -0,0 +1,29 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#version 450 core
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout(binding = 0) uniform highp sampler2D depth;
layout(binding = 1) uniform lowp usampler2D stencil;
layout(binding = 2) writeonly buffer OutputBuffer{
uint pixels[];
} staging;
layout(push_constant, std140) uniform ComputeInfo {
mediump ivec2 src_offset;
mediump ivec2 extent;
};
void main() {
ivec2 rect = ivec2(gl_NumWorkGroups.xy) * ivec2(8);
ivec2 dst_coord = ivec2(gl_GlobalInvocationID.xy);
ivec2 tex_icoord = src_offset + dst_coord;
highp vec2 tex_coord = vec2(tex_icoord) / vec2(extent);
highp uint depth_val = uint(texture(depth, tex_coord).x * (exp2(24.0) - 1.0));
lowp uint stencil_val = texture(stencil, tex_coord).x;
highp uint value = stencil_val | (depth_val << 8);
staging.pixels[dst_coord.y * rect.x + dst_coord.x] = value;
}

View File

@ -0,0 +1,25 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#version 450 core
#extension GL_ARB_separate_shader_objects : enable
layout (location = 0) in vec2 frag_tex_coord;
layout (location = 0) out vec4 color;
layout (push_constant, std140) uniform DrawInfo {
mat4 modelview_matrix;
vec4 i_resolution;
vec4 o_resolution;
int screen_id_l;
int screen_id_r;
int layer;
int reverse_interlaced;
};
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
void main() {
color = texture(screen_textures[screen_id_l], frag_tex_coord);
}

View File

@ -0,0 +1,25 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#version 450 core
#extension GL_ARB_separate_shader_objects : enable
layout (location = 0) in vec2 vert_position;
layout (location = 1) in vec2 vert_tex_coord;
layout (location = 0) out vec2 frag_tex_coord;
layout (push_constant, std140) uniform DrawInfo {
mat4 modelview_matrix;
vec4 i_resolution;
vec4 o_resolution;
int screen_id_l;
int screen_id_r;
int layer;
};
void main() {
vec4 position = vec4(vert_position, 0.0, 1.0) * modelview_matrix;
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
frag_tex_coord = vert_tex_coord;
}

View File

@ -0,0 +1,39 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#version 450 core
#extension GL_ARB_separate_shader_objects : enable
layout (location = 0) in vec2 frag_tex_coord;
layout (location = 0) out vec4 color;
// Anaglyph Red-Cyan shader based on Dubois algorithm
// Constants taken from the paper:
// "Conversion of a Stereo Pair to Anaglyph with
// the Least-Squares Projection Method"
// Eric Dubois, March 2009
const mat3 l = mat3( 0.437, 0.449, 0.164,
-0.062,-0.062,-0.024,
-0.048,-0.050,-0.017);
const mat3 r = mat3(-0.011,-0.032,-0.007,
0.377, 0.761, 0.009,
-0.026,-0.093, 1.234);
layout (push_constant, std140) uniform DrawInfo {
mat4 modelview_matrix;
vec4 i_resolution;
vec4 o_resolution;
int screen_id_l;
int screen_id_r;
int layer;
int reverse_interlaced;
};
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
void main() {
vec4 color_tex_l = texture(screen_textures[screen_id_l], frag_tex_coord);
vec4 color_tex_r = texture(screen_textures[screen_id_r], frag_tex_coord);
color = vec4(color_tex_l.rgb*l+color_tex_r.rgb*r, color_tex_l.a);
}

View File

@ -0,0 +1,29 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#version 450 core
#extension GL_ARB_separate_shader_objects : enable
layout (location = 0) in vec2 frag_tex_coord;
layout (location = 0) out vec4 color;
layout (push_constant, std140) uniform DrawInfo {
mat4 modelview_matrix;
vec4 i_resolution;
vec4 o_resolution;
int screen_id_l;
int screen_id_r;
int layer;
int reverse_interlaced;
};
layout (set = 0, binding = 0) uniform sampler2D screen_textures[3];
void main() {
float screen_row = o_resolution.x * frag_tex_coord.x;
if (int(screen_row) % 2 == reverse_interlaced)
color = texture(screen_textures[screen_id_l], frag_tex_coord);
else
color = texture(screen_textures[screen_id_r], frag_tex_coord);
}

View File

@ -1000,7 +1000,7 @@ void RasterizerCache<T>::UploadSurface(Surface& surface, SurfaceInterval interva
}
const BufferTextureCopy upload = {
.buffer_offset = 0,
.buffer_offset = staging.offset,
.buffer_size = staging.size,
.texture_rect = surface.GetSubRect(load_info),
.texture_level = surface.LevelOf(load_info.addr),
@ -1080,7 +1080,7 @@ void RasterizerCache<T>::DownloadSurface(Surface& surface, SurfaceInterval inter
flush_info.width * flush_info.height * surface.GetInternalBytesPerPixel(), false);
const BufferTextureCopy download = {
.buffer_offset = 0,
.buffer_offset = staging.offset,
.buffer_size = staging.size,
.texture_rect = surface.GetSubRect(flush_info),
.texture_level = surface.LevelOf(flush_start),
@ -1137,7 +1137,7 @@ bool RasterizerCache<T>::ValidateByReinterpretation(Surface& surface, SurfacePar
if (reinterpret_id) {
Surface& src_surface = slot_surfaces[reinterpret_id];
const SurfaceInterval copy_interval = src_surface.GetCopyableInterval(params);
if (boost::icl::is_empty(copy_interval)) {
if (boost::icl::is_empty(copy_interval & interval)) {
return false;
}
const PAddr addr = boost::icl::lower(interval);

View File

@ -75,8 +75,8 @@ struct BufferTextureCopy {
struct StagingData {
u32 size;
u32 offset;
std::span<u8> mapped;
u64 buffer_offset;
};
struct TextureCubeConfig {

View File

@ -144,8 +144,8 @@ VideoCore::StagingData TextureRuntime::FindStaging(u32 size, bool upload) {
}
return VideoCore::StagingData{
.size = size,
.offset = 0,
.mapped = std::span{staging_buffer.data(), size},
.buffer_offset = 0,
};
}