diff --git a/gfx/drivers/gl_core.c b/gfx/drivers/gl_core.c index 18cd1d3fca..469ffce583 100644 --- a/gfx/drivers/gl_core.c +++ b/gfx/drivers/gl_core.c @@ -34,6 +34,7 @@ #include "../../configuration.h" #include "../../dynamic.h" #include "../../record/record_driver.h" +#include "../../managers/state_manager.h" #include "../../retroarch.h" #include "../../verbosity.h" @@ -1654,6 +1655,7 @@ static bool gl_core_frame(void *data, const void *frame, texture.padded_height = streamed->height; } gl_core_filter_chain_set_frame_count(gl->filter_chain, frame_count); + gl_core_filter_chain_set_frame_direction(gl->filter_chain, state_manager_frame_is_reversed() ? -1 : 1); gl_core_filter_chain_set_input_texture(gl->filter_chain, &texture); gl_core_filter_chain_build_offscreen_passes(gl->filter_chain, &gl->filter_chain_vp); diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 5e76f382c2..edc43d0f13 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -48,6 +48,7 @@ #include "../../driver.h" #include "../../configuration.h" #include "../../record/record_driver.h" +#include "../../managers/state_manager.h" #include "../../retroarch.h" #include "../../verbosity.h" @@ -1751,6 +1752,7 @@ static bool vulkan_frame(void *data, const void *frame, /* Notify filter chain about the new sync index. */ vulkan_filter_chain_notify_sync_index((vulkan_filter_chain_t*)vk->filter_chain, frame_index); vulkan_filter_chain_set_frame_count((vulkan_filter_chain_t*)vk->filter_chain, frame_count); + vulkan_filter_chain_set_frame_direction((vulkan_filter_chain_t*)vk->filter_chain, state_manager_frame_is_reversed() ? -1 : 1); /* Render offscreen filter chain passes. */ { diff --git a/gfx/drivers_shader/shader_gl_core.cpp b/gfx/drivers_shader/shader_gl_core.cpp index 5311314900..087b4328e9 100644 --- a/gfx/drivers_shader/shader_gl_core.cpp +++ b/gfx/drivers_shader/shader_gl_core.cpp @@ -941,6 +941,11 @@ public: frame_count_period = period; } + void set_frame_direction(int32_t direction) + { + frame_direction = direction; + } + void set_name(const char *name) { pass_name = name; @@ -1026,6 +1031,8 @@ private: unsigned width, unsigned height); void build_semantic_uint(uint8_t *data, slang_semantic semantic, uint32_t value); + void build_semantic_int(uint8_t *data, + slang_semantic semantic, int32_t value); void build_semantic_parameter(uint8_t *data, unsigned index, float value); void build_semantic_texture_vec4(uint8_t *data, slang_texture_semantic semantic, @@ -1041,6 +1048,7 @@ private: uint64_t frame_count = 0; unsigned frame_count_period = 0; + int32_t frame_direction = 1; unsigned pass_number = 0; size_t ubo_offset = 0; @@ -1230,6 +1238,7 @@ bool Pass::init_pipeline() reflect_parameter("OutputSize", reflection.semantics[SLANG_SEMANTIC_OUTPUT]); reflect_parameter("FinalViewportSize", reflection.semantics[SLANG_SEMANTIC_FINAL_VIEWPORT]); reflect_parameter("FrameCount", reflection.semantics[SLANG_SEMANTIC_FRAME_COUNT]); + reflect_parameter("FrameDirection", reflection.semantics[SLANG_SEMANTIC_FRAME_DIRECTION]); reflect_parameter("OriginalSize", reflection.semantic_textures[SLANG_TEXTURE_SEMANTIC_ORIGINAL][0]); reflect_parameter("SourceSize", reflection.semantic_textures[SLANG_TEXTURE_SEMANTIC_SOURCE][0]); @@ -1422,6 +1431,38 @@ void Pass::build_semantic_uint(uint8_t *data, slang_semantic semantic, } } +void Pass::build_semantic_int(uint8_t *data, slang_semantic semantic, + int32_t value) +{ + auto &refl = reflection.semantics[semantic]; + + if (data && refl.uniform) + { + if (refl.location.ubo_vertex >= 0 || refl.location.ubo_fragment >= 0) + { + if (refl.location.ubo_vertex >= 0) + glUniform1i(refl.location.ubo_vertex, value); + if (refl.location.ubo_fragment >= 0) + glUniform1i(refl.location.ubo_fragment, value); + } + else + *reinterpret_cast(data + reflection.semantics[semantic].ubo_offset) = value; + } + + if (refl.push_constant) + { + if (refl.location.push_vertex >= 0 || refl.location.push_fragment >= 0) + { + if (refl.location.push_vertex >= 0) + glUniform1i(refl.location.push_vertex, value); + if (refl.location.push_fragment >= 0) + glUniform1i(refl.location.push_fragment, value); + } + else + *reinterpret_cast(push_constant_buffer.data() + refl.push_constant_offset) = value; + } +} + void Pass::build_semantic_texture(uint8_t *buffer, slang_texture_semantic semantic, const Texture &texture) { @@ -1596,6 +1637,9 @@ void Pass::build_semantics(uint8_t *buffer, ? uint32_t(frame_count % frame_count_period) : uint32_t(frame_count)); + build_semantic_int(buffer, SLANG_SEMANTIC_FRAME_DIRECTION, + frame_direction); + /* Standard inputs */ build_semantic_texture(buffer, SLANG_TEXTURE_SEMANTIC_ORIGINAL, original); build_semantic_texture(buffer, SLANG_TEXTURE_SEMANTIC_SOURCE, source); @@ -1761,6 +1805,7 @@ public: void set_frame_count(uint64_t count); void set_frame_count_period(unsigned pass, unsigned period); + void set_frame_direction(int32_t direction); void set_pass_name(unsigned pass, const char *name); void add_static_texture(unique_ptr texture); @@ -2204,6 +2249,13 @@ void gl_core_filter_chain::set_frame_count_period(unsigned pass, unsigned period passes[pass]->set_frame_count_period(period); } +void gl_core_filter_chain::set_frame_direction(int32_t direction) +{ + unsigned i; + for (i = 0; i < passes.size(); i++) + passes[i]->set_frame_direction(direction); +} + void gl_core_filter_chain::set_pass_name(unsigned pass, const char *name) { passes[pass]->set_name(name); @@ -2619,6 +2671,13 @@ void gl_core_filter_chain_set_frame_count( chain->set_frame_count(count); } +void gl_core_filter_chain_set_frame_direction( + gl_core_filter_chain_t *chain, + int32_t direction) +{ + chain->set_frame_direction(direction); +} + void gl_core_filter_chain_set_frame_count_period( gl_core_filter_chain_t *chain, unsigned pass, diff --git a/gfx/drivers_shader/shader_gl_core.h b/gfx/drivers_shader/shader_gl_core.h index 7dbf586ab2..c26c697d2a 100644 --- a/gfx/drivers_shader/shader_gl_core.h +++ b/gfx/drivers_shader/shader_gl_core.h @@ -117,6 +117,9 @@ void gl_core_filter_chain_set_frame_count_period(gl_core_filter_chain_t *chain, unsigned pass, unsigned period); +void gl_core_filter_chain_set_frame_direction(gl_core_filter_chain_t *chain, + int32_t direction); + void gl_core_filter_chain_set_pass_name(gl_core_filter_chain_t *chain, unsigned pass, const char *name); diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 81e2849ab1..c7713a4a44 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -378,6 +378,11 @@ class Pass frame_count_period = period; } + void set_frame_direction(int32_t direction) + { + frame_direction = direction; + } + void set_name(const char *name) { pass_name = name; @@ -476,6 +481,7 @@ class Pass void build_semantic_vec4(uint8_t *data, slang_semantic semantic, unsigned width, unsigned height); void build_semantic_uint(uint8_t *data, slang_semantic semantic, uint32_t value); + void build_semantic_int(uint8_t *data, slang_semantic semantic, int32_t value); void build_semantic_parameter(uint8_t *data, unsigned index, float value); void build_semantic_texture_vec4(uint8_t *data, slang_texture_semantic semantic, @@ -489,6 +495,7 @@ class Pass slang_texture_semantic semantic, unsigned index, const Texture &texture); uint64_t frame_count = 0; + uint32_t frame_direction = 1; unsigned frame_count_period = 0; unsigned pass_number = 0; @@ -548,6 +555,7 @@ struct vulkan_filter_chain void set_frame_count(uint64_t count); void set_frame_count_period(unsigned pass, unsigned period); + void set_frame_direction(int32_t direction); void set_pass_name(unsigned pass, const char *name); void add_static_texture(unique_ptr texture); @@ -1144,6 +1152,13 @@ void vulkan_filter_chain::set_frame_count_period(unsigned pass, unsigned period) passes[pass]->set_frame_count_period(period); } +void vulkan_filter_chain::set_frame_direction(int32_t direction) +{ + unsigned i; + for (i = 0; i < passes.size(); i++) + passes[i]->set_frame_direction(direction); +} + void vulkan_filter_chain::set_pass_name(unsigned pass, const char *name) { passes[pass]->set_name(name); @@ -2127,6 +2142,18 @@ void Pass::build_semantic_uint(uint8_t *data, slang_semantic semantic, *reinterpret_cast(push.buffer.data() + (refl.push_constant_offset >> 2)) = value; } +void Pass::build_semantic_int(uint8_t *data, slang_semantic semantic, + int32_t value) +{ + auto &refl = reflection.semantics[semantic]; + + if (data && refl.uniform) + *reinterpret_cast(data + reflection.semantics[semantic].ubo_offset) = value; + + if (refl.push_constant) + *reinterpret_cast(push.buffer.data() + (refl.push_constant_offset >> 2)) = value; +} + void Pass::build_semantic_texture(VkDescriptorSet set, uint8_t *buffer, slang_texture_semantic semantic, const Texture &texture) { @@ -2180,6 +2207,9 @@ void Pass::build_semantics(VkDescriptorSet set, uint8_t *buffer, ? uint32_t(frame_count % frame_count_period) : uint32_t(frame_count)); + build_semantic_int(buffer, SLANG_SEMANTIC_FRAME_DIRECTION, + frame_direction); + /* Standard inputs */ build_semantic_texture(set, buffer, SLANG_TEXTURE_SEMANTIC_ORIGINAL, original); build_semantic_texture(set, buffer, SLANG_TEXTURE_SEMANTIC_SOURCE, source); @@ -3185,6 +3215,13 @@ void vulkan_filter_chain_set_frame_count_period( chain->set_frame_count_period(pass, period); } +void vulkan_filter_chain_set_frame_direction( + vulkan_filter_chain_t *chain, + int32_t direction) +{ + chain->set_frame_direction(direction); +} + void vulkan_filter_chain_set_pass_name( vulkan_filter_chain_t *chain, unsigned pass, diff --git a/gfx/drivers_shader/shader_vulkan.h b/gfx/drivers_shader/shader_vulkan.h index 93270135e8..60f6c89ebe 100644 --- a/gfx/drivers_shader/shader_vulkan.h +++ b/gfx/drivers_shader/shader_vulkan.h @@ -143,6 +143,9 @@ void vulkan_filter_chain_set_frame_count_period(vulkan_filter_chain_t *chain, unsigned pass, unsigned period); +void vulkan_filter_chain_set_frame_direction(vulkan_filter_chain_t *chain, + int32_t direction); + void vulkan_filter_chain_set_pass_name(vulkan_filter_chain_t *chain, unsigned pass, const char *name); diff --git a/gfx/drivers_shader/slang_process.cpp b/gfx/drivers_shader/slang_process.cpp index a09485162c..2090883dff 100644 --- a/gfx/drivers_shader/slang_process.cpp +++ b/gfx/drivers_shader/slang_process.cpp @@ -72,6 +72,7 @@ get_semantic_name(slang_reflection& reflection, "OutputSize", "FinalViewportSize", "FrameCount", + "FrameDirection", }; if ((int)semantic < sizeof(names) / sizeof(*names)) return std::string(names[semantic]); diff --git a/gfx/drivers_shader/slang_reflection.cpp b/gfx/drivers_shader/slang_reflection.cpp index 90022f6dc3..9cfc5497ef 100644 --- a/gfx/drivers_shader/slang_reflection.cpp +++ b/gfx/drivers_shader/slang_reflection.cpp @@ -49,6 +49,7 @@ static const char *semantic_uniform_names[] = { "OutputSize", "FinalViewportSize", "FrameCount", + "FrameDirection", }; static bool slang_texture_semantic_is_array(slang_texture_semantic sem) @@ -300,6 +301,9 @@ static bool validate_type_for_semantic(const SPIRType &type, slang_semantic sem) /* uint */ case SLANG_SEMANTIC_FRAME_COUNT: return type.basetype == SPIRType::UInt && type.vecsize == 1 && type.columns == 1; + /* int */ + case SLANG_SEMANTIC_FRAME_DIRECTION: + return type.basetype == SPIRType::Int && type.vecsize == 1 && type.columns == 1; /* float */ case SLANG_SEMANTIC_FLOAT_PARAMETER: return type.basetype == SPIRType::Float && type.vecsize == 1 && type.columns == 1; diff --git a/gfx/drivers_shader/slang_reflection.h b/gfx/drivers_shader/slang_reflection.h index 98aa7c3206..515e6e1262 100644 --- a/gfx/drivers_shader/slang_reflection.h +++ b/gfx/drivers_shader/slang_reflection.h @@ -68,10 +68,12 @@ enum slang_semantic SLANG_SEMANTIC_FINAL_VIEWPORT = 2, /* uint, frame count with modulo */ SLANG_SEMANTIC_FRAME_COUNT = 3, + /* int, frame direction */ + SLANG_SEMANTIC_FRAME_DIRECTION = 4, SLANG_NUM_BASE_SEMANTICS, /* float, user defined parameter, arrayed */ - SLANG_SEMANTIC_FLOAT_PARAMETER = 4, + SLANG_SEMANTIC_FLOAT_PARAMETER = 5, SLANG_NUM_SEMANTICS, SLANG_INVALID_SEMANTIC = -1