diff --git a/dep/reshadefx/include/effect_codegen.hpp b/dep/reshadefx/include/effect_codegen.hpp index 87336891c..6419214a8 100644 --- a/dep/reshadefx/include/effect_codegen.hpp +++ b/dep/reshadefx/include/effect_codegen.hpp @@ -352,12 +352,13 @@ namespace reshadefx /// /// Creates a back-end implementation for GLSL code generation. /// + /// Generate GLSL ES code instead of core OpenGL. /// Generate GLSL for OpenGL or for Vulkan. /// Whether to append debug information like line directives to the generated code. /// Whether to convert uniform variables to specialization constants. /// Use real 16-bit types for the minimum precision types "min16int", "min16uint" and "min16float". /// Insert code to flip the Y component of the output position in vertex shaders. - codegen *create_codegen_glsl(bool vulkan_semantics, bool debug_info, bool uniforms_to_spec_constants, bool enable_16bit_types = false, bool flip_vert_y = false); + codegen *create_codegen_glsl(bool gles, bool vulkan_semantics, bool debug_info, bool uniforms_to_spec_constants, bool enable_16bit_types = false, bool flip_vert_y = false); /// /// Creates a back-end implementation for HLSL code generation. /// diff --git a/dep/reshadefx/src/effect_codegen_glsl.cpp b/dep/reshadefx/src/effect_codegen_glsl.cpp index f8a4d0e41..452312371 100644 --- a/dep/reshadefx/src/effect_codegen_glsl.cpp +++ b/dep/reshadefx/src/effect_codegen_glsl.cpp @@ -13,11 +13,12 @@ using namespace reshadefx; +namespace { class codegen_glsl final : public codegen { public: - codegen_glsl(bool vulkan_semantics, bool debug_info, bool uniforms_to_spec_constants, bool enable_16bit_types, bool flip_vert_y) - : _debug_info(debug_info), _vulkan_semantics(vulkan_semantics), _uniforms_to_spec_constants(uniforms_to_spec_constants), _enable_16bit_types(enable_16bit_types), _flip_vert_y(flip_vert_y) + codegen_glsl(bool gles, bool vulkan_semantics, bool debug_info, bool uniforms_to_spec_constants, bool enable_16bit_types, bool flip_vert_y) + : _gles(gles), _debug_info(debug_info), _vulkan_semantics(vulkan_semantics), _uniforms_to_spec_constants(uniforms_to_spec_constants), _enable_16bit_types(enable_16bit_types), _flip_vert_y(flip_vert_y) { // Create default block and reserve a memory block to avoid frequent reallocations std::string &block = _blocks.emplace(0, std::string()).first->second; @@ -41,6 +42,7 @@ private: std::string _compute_block; std::unordered_map _names; std::unordered_map _blocks; + bool _gles = false; bool _debug_info = false; bool _vulkan_semantics = false; bool _uniforms_to_spec_constants = false; @@ -755,7 +757,7 @@ private: if (!global) code += '\t'; - if (initializer_value != 0 && type.has(type::q_const)) + if (initializer_value != 0 && (type.has(type::q_const) && !_gles)) code += "const "; write_type(code, type); @@ -843,8 +845,8 @@ private: _blocks.at(0) += "#ifdef ENTRY_POINT_" + func.unique_name + '\n'; if (stype == shader_type::cs) _blocks.at(0) += "layout(local_size_x = " + std::to_string(num_threads[0]) + - ", local_size_y = " + std::to_string(num_threads[1]) + - ", local_size_z = " + std::to_string(num_threads[2]) + ") in;\n"; + ", local_size_y = " + std::to_string(num_threads[1]) + + ", local_size_z = " + std::to_string(num_threads[2]) + ") in;\n"; function_info entry_point; entry_point.return_type = { type::t_void }; @@ -1004,7 +1006,7 @@ private: } else { - if (member.type.is_boolean()) + if (member.type.is_boolean() || (_gles && member.type.is_integral())) { write_type(code, member.type); code += '('; @@ -1012,7 +1014,7 @@ private: code += semantic_to_builtin(std::move(in_param_name), member.semantic, stype); - if (member.type.is_boolean()) + if (member.type.is_boolean() || (_gles && member.type.is_integral())) code += ')'; } @@ -1097,7 +1099,7 @@ private: } else { - if (param_type.is_boolean()) + if (param_type.is_boolean() || (_gles && param_type.is_integral())) { write_type(code, param_type); code += '('; @@ -1105,7 +1107,7 @@ private: code += semantic_to_builtin("_in_param" + std::to_string(i), func.parameter_list[i].semantic, stype); - if (param_type.is_boolean()) + if (param_type.is_boolean() || (_gles && param_type.is_integral())) code += ')'; } } @@ -1345,9 +1347,31 @@ private: } else { - expr_code += '.'; - for (unsigned int i = 0; i < 4 && op.swizzle[i] >= 0; ++i) - expr_code += "xyzw"[op.swizzle[i]]; + // can't swizzle scalars + if (_gles && op.from.is_scalar()) + { + // => e.g. vec3(expr, expr, expr).xyz + type.clear(); + write_type(type, op.to); + std::string new_code = type; + new_code += '('; + + const unsigned int components = op.to.components(); + for (unsigned int i = 0; i < components; ++i) + { + if (i > 0) + new_code += ','; + new_code += '(' + expr_code + ')'; + } + new_code += ')'; + expr_code = std::move(new_code); + } + else + { + expr_code += '.'; + for (unsigned int i = 0; i < 4 && op.swizzle[i] >= 0; ++i) + expr_code += "xyzw"[op.swizzle[i]]; + } } break; } @@ -1812,7 +1836,7 @@ private: write_location(code, loc); - if (flags != 0) + if (flags != 0 && !_gles) { _enable_control_flow_attributes = true; @@ -1896,7 +1920,7 @@ private: code += _blocks.at(prev_block); std::string attributes; - if (flags != 0) + if (flags != 0 && !_gles) { _enable_control_flow_attributes = true; @@ -2158,8 +2182,9 @@ private: _blocks.at(0) += "{\n" + _blocks.at(_last_block) + "}\n"; } }; +} // namespace -codegen *reshadefx::create_codegen_glsl(bool vulkan_semantics, bool debug_info, bool uniforms_to_spec_constants, bool enable_16bit_types, bool flip_vert_y) +codegen *reshadefx::create_codegen_glsl(bool gles, bool vulkan_semantics, bool debug_info, bool uniforms_to_spec_constants, bool enable_16bit_types, bool flip_vert_y) { - return new codegen_glsl(vulkan_semantics, debug_info, uniforms_to_spec_constants, enable_16bit_types, flip_vert_y); + return new codegen_glsl(gles, vulkan_semantics, debug_info, uniforms_to_spec_constants, enable_16bit_types, flip_vert_y); } diff --git a/src/util/postprocessing_shader_fx.cpp b/src/util/postprocessing_shader_fx.cpp index 58177d077..e2d463820 100644 --- a/src/util/postprocessing_shader_fx.cpp +++ b/src/util/postprocessing_shader_fx.cpp @@ -81,15 +81,15 @@ static std::unique_ptr CreateRFXCodegen() case RenderAPI::Metal: { return std::unique_ptr(reshadefx::create_codegen_glsl( - true, debug_info, uniforms_to_spec_constants, false, (rapi == RenderAPI::Vulkan))); + false, true, debug_info, uniforms_to_spec_constants, false, (rapi == RenderAPI::Vulkan))); } case RenderAPI::OpenGL: case RenderAPI::OpenGLES: default: { - return std::unique_ptr( - reshadefx::create_codegen_glsl(false, debug_info, uniforms_to_spec_constants, false, true)); + return std::unique_ptr(reshadefx::create_codegen_glsl( + (rapi == RenderAPI::OpenGLES), false, debug_info, uniforms_to_spec_constants, false, true)); } } } @@ -1099,14 +1099,18 @@ bool PostProcessing::ReShadeFXShader::CompilePipeline(GPUTexture::Format format, const std::string_view code(mod.code.data(), mod.code.size()); - auto get_shader = [needs_main_defn, &code](const std::string& name, const std::vector& samplers, - GPUShaderStage stage) { + auto get_shader = [api, needs_main_defn, &code](const std::string& name, const std::vector& samplers, + GPUShaderStage stage) { std::string real_code; if (needs_main_defn) { // dFdx/dFdy are not defined in the vertex shader. const char* defns = (stage == GPUShaderStage::Vertex) ? "#define dFdx(x) x\n#define dFdy(x) x\n" : ""; - real_code = fmt::format("#version 460 core\n#define ENTRY_POINT_{}\n{}\n{}", name, defns, code); + const char* precision = (api == RenderAPI::OpenGLES) ? + "precision highp float;\nprecision highp int;\nprecision highp sampler2D;\n" : + ""; + real_code = fmt::format("#version {}\n#define ENTRY_POINT_{}\n{}\n{}\n{}", + (api == RenderAPI::OpenGLES) ? "320 es" : "460 core", name, defns, precision, code); for (const Sampler& sampler : samplers) {