video_core: Add vulkan shaders (#6619)
This commit is contained in:
parent
7c11b9b689
commit
3faddd5e03
13 changed files with 263 additions and 10 deletions
|
@ -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})
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
16
src/video_core/host_shaders/vulkan_blit_depth_stencil.frag
Normal file
16
src/video_core/host_shaders/vulkan_blit_depth_stencil.frag
Normal 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);
|
||||
}
|
29
src/video_core/host_shaders/vulkan_depth_to_buffer.comp
Normal file
29
src/video_core/host_shaders/vulkan_depth_to_buffer.comp
Normal 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;
|
||||
}
|
25
src/video_core/host_shaders/vulkan_present.frag
Normal file
25
src/video_core/host_shaders/vulkan_present.frag
Normal 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);
|
||||
}
|
25
src/video_core/host_shaders/vulkan_present.vert
Normal file
25
src/video_core/host_shaders/vulkan_present.vert
Normal 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;
|
||||
}
|
39
src/video_core/host_shaders/vulkan_present_anaglyph.frag
Normal file
39
src/video_core/host_shaders/vulkan_present_anaglyph.frag
Normal 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);
|
||||
}
|
29
src/video_core/host_shaders/vulkan_present_interlaced.frag
Normal file
29
src/video_core/host_shaders/vulkan_present_interlaced.frag
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -75,8 +75,8 @@ struct BufferTextureCopy {
|
|||
|
||||
struct StagingData {
|
||||
u32 size;
|
||||
u32 offset;
|
||||
std::span<u8> mapped;
|
||||
u64 buffer_offset;
|
||||
};
|
||||
|
||||
struct TextureCubeConfig {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue