mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-14 21:55:46 -04:00
dep: Add reshadefx
This commit is contained in:
377
dep/reshadefx/include/effect_codegen.hpp
Normal file
377
dep/reshadefx/include/effect_codegen.hpp
Normal file
@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Patrick Mours
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect_module.hpp"
|
||||
#include <memory> // std::unique_ptr
|
||||
#include <algorithm> // std::find_if
|
||||
|
||||
namespace reshadefx
|
||||
{
|
||||
/// <summary>
|
||||
/// A SSA code generation back-end interface for the parser to call into.
|
||||
/// </summary>
|
||||
class codegen
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Virtual destructor to guarantee that memory of the implementations deriving from this interface is properly destroyed.
|
||||
/// </summary>
|
||||
virtual ~codegen() {}
|
||||
|
||||
/// <summary>
|
||||
/// Writes result of the code generation to the specified <paramref name="module"/>.
|
||||
/// </summary>
|
||||
/// <param name="module">Target module to fill.</param>
|
||||
virtual void write_result(module &module) = 0;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// An opaque ID referring to a SSA value or basic block.
|
||||
/// </summary>
|
||||
using id = uint32_t;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a new struct type.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this definition (for debugging).</param>
|
||||
/// <param name="info">Description of the type.</param>
|
||||
/// <returns>New SSA ID of the type.</returns>
|
||||
virtual id define_struct(const location &loc, struct_info &info) = 0;
|
||||
/// <summary>
|
||||
/// Defines a new texture binding.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this definition (for debugging).</param>
|
||||
/// <param name="info">Description of the texture object.</param>
|
||||
/// <returns>New SSA ID of the binding.</returns>
|
||||
virtual id define_texture(const location &loc, texture_info &info) = 0;
|
||||
/// <summary>
|
||||
/// Defines a new sampler binding.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this definition (for debugging).</param>
|
||||
/// <param name="tex_info">Description of the texture this sampler object references.</param>
|
||||
/// <param name="info">Description of the sampler object.</param>
|
||||
/// <returns>New SSA ID of the binding.</returns>
|
||||
virtual id define_sampler(const location &loc, const texture_info &tex_info, sampler_info &info) = 0;
|
||||
/// <summary>
|
||||
/// Defines a new storage binding.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this definition (for debugging).</param>
|
||||
/// <param name="tex_info">Description of the texture this storage object references.</param>
|
||||
/// <param name="info">Description of the storage object.</param>
|
||||
/// <returns>New SSA ID of the binding.</returns>
|
||||
virtual id define_storage(const location &loc, const texture_info &tex_info, storage_info &info) = 0;
|
||||
/// <summary>
|
||||
/// Defines a new uniform variable.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this definition (for debugging).</param>
|
||||
/// <param name="info">Description of the uniform variable.</param>
|
||||
/// <returns>New SSA ID of the variable.</returns>
|
||||
virtual id define_uniform(const location &loc, uniform_info &info) = 0;
|
||||
/// <summary>
|
||||
/// Defines a new variable.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this definition (for debugging).</param>
|
||||
/// <param name="type">Data type of the variable.</param>
|
||||
/// <param name="name">Name of the variable.</param>
|
||||
/// <param name="global"><c>true</c> if this variable is in global scope, <c>false</c> otherwise.</param>
|
||||
/// <param name="initializer_value">SSA ID of an optional initializer value.</param>
|
||||
/// <returns>New SSA ID of the variable.</returns>
|
||||
virtual id define_variable(const location &loc, const type &type, std::string name = std::string(), bool global = false, id initializer_value = 0) = 0;
|
||||
/// <summary>
|
||||
/// Defines a new function and its function parameters and make it current. Any code added after this call is added to this function.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this definition (for debugging).</param>
|
||||
/// <param name="info">Description of the function.</param>
|
||||
/// <returns>New SSA ID of the function.</returns>
|
||||
virtual id define_function(const location &loc, function_info &info) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a new effect technique.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this definition (for debugging).</param>
|
||||
/// <param name="info">Description of the technique.</param>
|
||||
void define_technique(technique_info &&info) { _module.techniques.push_back(std::move(info)); }
|
||||
/// <summary>
|
||||
/// Makes a function a shader entry point.
|
||||
/// </summary>
|
||||
/// <param name="function">Function to use as entry point. May be overwritten to point to a new unique function for this entry point.</param>
|
||||
/// <param name="type">Shader type (vertex, pixel or compute shader).</param>
|
||||
/// <param name="num_threads">Number of local threads it this is a compute entry point.</param>
|
||||
virtual void define_entry_point(function_info &function, shader_type type, int num_threads[3] = nullptr) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the access chain and add a load operation to the output.
|
||||
/// </summary>
|
||||
/// <param name="chain">Access chain pointing to the variable to load from.</param>
|
||||
/// <param name="force_new_id">Set to <see langword="true"/> to force this to return a new SSA ID for l-value loads.</param>
|
||||
/// <returns>New SSA ID with the loaded value.</returns>
|
||||
virtual id emit_load(const expression &chain, bool force_new_id = false) = 0;
|
||||
/// <summary>
|
||||
/// Resolves the access chain and add a store operation to the output.
|
||||
/// </summary>
|
||||
/// <param name="chain">Access chain pointing to the variable to store to.</param>
|
||||
/// <param name="value">SSA ID of the value to store.</param>
|
||||
virtual void emit_store(const expression &chain, id value) = 0;
|
||||
/// <summary>
|
||||
/// Resolves the access chain, but do not add a load operation. This returns a pointer instead.
|
||||
/// </summary>
|
||||
/// <param name="chain">Access chain pointing to the variable to resolve.</param>
|
||||
/// <param name="chain_index">Output value which is set to the index in the access chain up to which the access chain went.</param>
|
||||
/// <returns>New SSA ID with a pointer to the value.</returns>
|
||||
virtual id emit_access_chain(const expression &chain, size_t &chain_index) { chain_index = chain.chain.size(); return emit_load(chain); }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a SSA constant value.
|
||||
/// </summary>
|
||||
/// <param name="type">Data type of the constant.</param>
|
||||
/// <param name="data">Actual constant data to convert into a SSA ID.</param>
|
||||
/// <returns>New SSA ID with the constant value.</returns>
|
||||
virtual id emit_constant(const type &type, const constant &data) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Adds an unary operation to the output (built-in operation with one argument).
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this operation (for debugging).</param>
|
||||
/// <param name="op">Unary operator to use.</param>
|
||||
/// <param name="type">Data type of the input value.</param>
|
||||
/// <param name="val">SSA ID of value to perform the operation on.</param>
|
||||
/// <returns>New SSA ID with the result of the operation.</returns>
|
||||
virtual id emit_unary_op(const location &loc, tokenid op, const type &type, id val) = 0;
|
||||
/// <summary>
|
||||
/// Adds a binary operation to the output (built-in operation with two arguments).
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this operation (for debugging).</param>
|
||||
/// <param name="op">Binary operator to use.</param>
|
||||
/// <param name="res_type">Data type of the result.</param>
|
||||
/// <param name="type">Data type of the input values.</param>
|
||||
/// <param name="lhs">SSA ID of the value on the left-hand side of the binary operation.</param>
|
||||
/// <param name="rhs">SSA ID of the value on the right-hand side of the binary operation.</param>
|
||||
/// <returns>New SSA ID with the result of the operation.</returns>
|
||||
virtual id emit_binary_op(const location &loc, tokenid op, const type &res_type, const type &type, id lhs, id rhs) = 0;
|
||||
id emit_binary_op(const location &loc, tokenid op, const type &type, id lhs, id rhs) { return emit_binary_op(loc, op, type, type, lhs, rhs); }
|
||||
/// <summary>
|
||||
/// Adds a ternary operation to the output (built-in operation with three arguments).
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this operation (for debugging).</param>
|
||||
/// <param name="op">Ternary operator to use.</param>
|
||||
/// <param name="type">Data type of the input values.</param>
|
||||
/// <param name="condition">SSA ID of the condition value of the ternary operation.</param>
|
||||
/// <param name="true_value">SSA ID of the first value of the ternary operation.</param>
|
||||
/// <param name="false_value">SSA ID of the second value of the ternary operation.</param>
|
||||
/// <returns>New SSA ID with the result of the operation.</returns>
|
||||
virtual id emit_ternary_op(const location &loc, tokenid op, const type &type, id condition, id true_value, id false_value) = 0;
|
||||
/// <summary>
|
||||
/// Adds a function call to the output.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this operation (for debugging).</param>
|
||||
/// <param name="function">SSA ID of the function to call.</param>
|
||||
/// <param name="res_type">Data type of the call result.</param>
|
||||
/// <param name="args">List of SSA IDs representing the call arguments.</param>
|
||||
/// <returns>New SSA ID with the result of the function call.</returns>
|
||||
virtual id emit_call(const location &loc, id function, const type &res_type, const std::vector<expression> &args) = 0;
|
||||
/// <summary>
|
||||
/// Adds an intrinsic function call to the output.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this operation (for debugging).</param>
|
||||
/// <param name="function">Intrinsic to call.</param>
|
||||
/// <param name="res_type">Data type of the call result.</param>
|
||||
/// <param name="args">List of SSA IDs representing the call arguments.</param>
|
||||
/// <returns>New SSA ID with the result of the function call.</returns>
|
||||
virtual id emit_call_intrinsic(const location &loc, id function, const type &res_type, const std::vector<expression> &args) = 0;
|
||||
/// <summary>
|
||||
/// Adds a type constructor call to the output.
|
||||
/// </summary>
|
||||
/// <param name="type">Data type to construct.</param>
|
||||
/// <param name="args">List of SSA IDs representing the scalar constructor arguments.</param>
|
||||
/// <returns>New SSA ID with the constructed value.</returns>
|
||||
virtual id emit_construct(const location &loc, const type &type, const std::vector<expression> &args) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a structured branch control flow to the output.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this branch (for debugging).</param>
|
||||
/// <param name="flags">0 - default, 1 - flatten, 2 - do not flatten</param>
|
||||
virtual void emit_if(const location &loc, id condition_value, id condition_block, id true_statement_block, id false_statement_block, unsigned int flags) = 0;
|
||||
/// <summary>
|
||||
/// Adds a branch control flow with a SSA phi operation to the output.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this branch (for debugging).</param>
|
||||
/// <returns>New SSA ID with the result of the phi operation.</returns>
|
||||
virtual id emit_phi(const location &loc, id condition_value, id condition_block, id true_value, id true_statement_block, id false_value, id false_statement_block, const type &type) = 0;
|
||||
/// <summary>
|
||||
/// Adds a structured loop control flow to the output.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this loop (for debugging).</param>
|
||||
/// <param name="flags">0 - default, 1 - unroll, 2 - do not unroll</param>
|
||||
virtual void emit_loop(const location &loc, id condition_value, id prev_block, id header_block, id condition_block, id loop_block, id continue_block, unsigned int flags) = 0;
|
||||
/// <summary>
|
||||
/// Adds a structured switch control flow to the output.
|
||||
/// </summary>
|
||||
/// <param name="loc">Source location matching this switch (for debugging).</param>
|
||||
/// <param name="flags">0 - default, 1 - flatten, 2 - do not flatten</param>
|
||||
virtual void emit_switch(const location &loc, id selector_value, id selector_block, id default_label, id default_block, const std::vector<id> &case_literal_and_labels, const std::vector<id> &case_blocks, unsigned int flags) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true"/> if code is currently added to a basic block.
|
||||
/// </summary>
|
||||
bool is_in_block() const { return _current_block != 0; }
|
||||
/// <summary>
|
||||
/// Returns <see langword="true"/> if code is currently added to a function.
|
||||
/// </summary>
|
||||
virtual bool is_in_function() const { return is_in_block(); }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new basic block.
|
||||
/// </summary>
|
||||
/// <returns>New ID of the basic block.</returns>
|
||||
virtual id create_block() { return make_id(); }
|
||||
/// <summary>
|
||||
/// Overwrites the current block ID.
|
||||
/// </summary>
|
||||
/// <param name="id">ID of the block to make current.</param>
|
||||
/// <returns>ID of the previous basic block.</returns>
|
||||
virtual id set_block(id id) = 0;
|
||||
/// <summary>
|
||||
/// Creates a new basic block and make it current.
|
||||
/// </summary>
|
||||
/// <param name="id">ID of the basic block to create and make current.</param>
|
||||
virtual void enter_block(id id) = 0;
|
||||
/// <summary>
|
||||
/// Returns from the current basic block and kill the shader invocation.
|
||||
/// </summary>
|
||||
/// <returns>ID of the current basic block.</returns>
|
||||
virtual id leave_block_and_kill() = 0;
|
||||
/// <summary>
|
||||
/// Returns from the current basic block and hand control flow over to the function call side.
|
||||
/// </summary>
|
||||
/// <param name="value">Optional SSA ID of a return value.</param>
|
||||
/// <returns>ID of the current basic block.</returns>
|
||||
virtual id leave_block_and_return(id value = 0) = 0;
|
||||
/// <summary>
|
||||
/// Diverges the current control flow and enter a switch.
|
||||
/// </summary>
|
||||
/// <param name="value">SSA ID of the selector value to decide the switch path.</param>
|
||||
/// <returns>ID of the current basic block.</returns>
|
||||
virtual id leave_block_and_switch(id value, id default_target) = 0;
|
||||
/// <summary>
|
||||
/// Diverges the current control flow and jump to the specified target block.
|
||||
/// </summary>
|
||||
/// <param name="target">ID of the basic block to jump to.</param>
|
||||
/// <param name="is_continue">Set to <see langword="true"/> if this corresponds to a loop continue statement.</param>
|
||||
/// <returns>ID of the current basic block.</returns>
|
||||
virtual id leave_block_and_branch(id target, unsigned int loop_flow = 0) = 0;
|
||||
/// <summary>
|
||||
/// Diverges the current control flow and jump to one of the specified target blocks, depending on the condition.
|
||||
/// </summary>
|
||||
/// <param name="condition">SSA ID of a value used to choose which path to take.</param>
|
||||
/// <param name="true_target">ID of the basic block to jump to when the condition is true.</param>
|
||||
/// <param name="false_target">ID of the basic block to jump to when the condition is false.</param>
|
||||
/// <returns>ID of the current basic block.</returns>
|
||||
virtual id leave_block_and_branch_conditional(id condition, id true_target, id false_target) = 0;
|
||||
/// <summary>
|
||||
/// Leaves the current function. Any code added after this call is added in the global scope.
|
||||
/// </summary>
|
||||
virtual void leave_function() = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Looks up an existing struct type.
|
||||
/// </summary>
|
||||
/// <param name="id">SSA ID of the type to find.</param>
|
||||
/// <returns>Reference to the struct description.</returns>
|
||||
const struct_info &get_struct(id id) const
|
||||
{
|
||||
return *std::find_if(_structs.begin(), _structs.end(),
|
||||
[id](const auto &it) { return it.definition == id; });
|
||||
}
|
||||
/// <summary>
|
||||
/// Looks up an existing texture binding.
|
||||
/// </summary>
|
||||
/// <param name="id">SSA ID of the texture binding to find.</param>
|
||||
/// <returns>Reference to the texture description.</returns>
|
||||
texture_info &get_texture(id id)
|
||||
{
|
||||
return *std::find_if(_module.textures.begin(), _module.textures.end(),
|
||||
[id](const auto &it) { return it.id == id; });
|
||||
}
|
||||
/// <summary>
|
||||
/// Looks up an existing sampler binding.
|
||||
/// </summary>
|
||||
/// <param name="id">SSA ID of the sampler binding to find.</param>
|
||||
/// <returns>Reference to the sampler description.</returns>
|
||||
const sampler_info &get_sampler(id id) const
|
||||
{
|
||||
return *std::find_if(_module.samplers.begin(), _module.samplers.end(),
|
||||
[id](const auto &it) { return it.id == id; });
|
||||
}
|
||||
/// <summary>
|
||||
/// Looks up an existing storage binding.
|
||||
/// </summary>
|
||||
/// <param name="id">SSA ID of the storage binding to find.</param>
|
||||
/// <returns>Reference to the storage description.</returns>
|
||||
const storage_info &get_storage(id id) const
|
||||
{
|
||||
return *std::find_if(_module.storages.begin(), _module.storages.end(),
|
||||
[id](const auto &it) { return it.id == id; });
|
||||
}
|
||||
/// <summary>
|
||||
/// Looks up an existing function definition.
|
||||
/// </summary>
|
||||
/// <param name="id">SSA ID of the function variable to find.</param>
|
||||
/// <returns>Reference to the function description.</returns>
|
||||
function_info &get_function(id id)
|
||||
{
|
||||
return *std::find_if(_functions.begin(), _functions.end(),
|
||||
[id](const auto &it) { return it->definition == id; })->get();
|
||||
}
|
||||
|
||||
protected:
|
||||
id make_id() { return _next_id++; }
|
||||
|
||||
static uint32_t align_up(uint32_t size, uint32_t alignment)
|
||||
{
|
||||
alignment -= 1;
|
||||
return ((size + alignment) & ~alignment);
|
||||
}
|
||||
static uint32_t align_up(uint32_t size, uint32_t alignment, uint32_t elements)
|
||||
{
|
||||
return align_up(size, alignment) * (elements - 1) + size;
|
||||
}
|
||||
|
||||
reshadefx::module _module;
|
||||
std::vector<struct_info> _structs;
|
||||
std::vector<std::unique_ptr<function_info>> _functions;
|
||||
id _next_id = 1;
|
||||
id _last_block = 0;
|
||||
id _current_block = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Creates a back-end implementation for GLSL code generation.
|
||||
/// </summary>
|
||||
/// <param name="vulkan_semantics">Generate GLSL for OpenGL or for Vulkan.</param>
|
||||
/// <param name="debug_info">Whether to append debug information like line directives to the generated code.</param>
|
||||
/// <param name="uniforms_to_spec_constants">Whether to convert uniform variables to specialization constants.</param>
|
||||
/// <param name="enable_16bit_types">Use real 16-bit types for the minimum precision types "min16int", "min16uint" and "min16float".</param>
|
||||
/// <param name="flip_vert_y">Insert code to flip the Y component of the output position in vertex shaders.</param>
|
||||
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);
|
||||
/// <summary>
|
||||
/// Creates a back-end implementation for HLSL code generation.
|
||||
/// </summary>
|
||||
/// <param name="shader_model">The HLSL shader model version (e.g. 30, 41, 50, 60, ...)</param>
|
||||
/// <param name="debug_info">Whether to append debug information like line directives to the generated code.</param>
|
||||
/// <param name="uniforms_to_spec_constants">Whether to convert uniform variables to specialization constants.</param>
|
||||
codegen *create_codegen_hlsl(unsigned int shader_model, bool debug_info, bool uniforms_to_spec_constants);
|
||||
/// <summary>
|
||||
/// Creates a back-end implementation for SPIR-V code generation.
|
||||
/// </summary>
|
||||
/// <param name="vulkan_semantics">Generate SPIR-V for OpenGL or for Vulkan.</param>
|
||||
/// <param name="debug_info">Whether to append debug information like line directives to the generated code.</param>
|
||||
/// <param name="uniforms_to_spec_constants">Whether to convert uniform variables to specialization constants.</param>
|
||||
/// <param name="enable_16bit_types">Use real 16-bit types for the minimum precision types "min16int", "min16uint" and "min16float".</param>
|
||||
/// <param name="flip_vert_y">Insert code to flip the Y component of the output position in vertex shaders.</param>
|
||||
codegen *create_codegen_spirv(bool vulkan_semantics, bool debug_info, bool uniforms_to_spec_constants, bool enable_16bit_types = false, bool flip_vert_y = false);
|
||||
}
|
249
dep/reshadefx/include/effect_expression.hpp
Normal file
249
dep/reshadefx/include/effect_expression.hpp
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Patrick Mours
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect_token.hpp"
|
||||
|
||||
namespace reshadefx
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure which encapsulates a parsed value type
|
||||
/// </summary>
|
||||
struct type
|
||||
{
|
||||
enum datatype : uint8_t
|
||||
{
|
||||
t_void,
|
||||
t_bool,
|
||||
t_min16int,
|
||||
t_int,
|
||||
t_min16uint,
|
||||
t_uint,
|
||||
t_min16float,
|
||||
t_float,
|
||||
t_string,
|
||||
t_struct,
|
||||
t_texture1d,
|
||||
t_texture2d,
|
||||
t_texture3d,
|
||||
t_sampler1d_int,
|
||||
t_sampler2d_int,
|
||||
t_sampler3d_int,
|
||||
t_sampler1d_uint,
|
||||
t_sampler2d_uint,
|
||||
t_sampler3d_uint,
|
||||
t_sampler1d_float,
|
||||
t_sampler2d_float,
|
||||
t_sampler3d_float,
|
||||
t_storage1d_int,
|
||||
t_storage2d_int,
|
||||
t_storage3d_int,
|
||||
t_storage1d_uint,
|
||||
t_storage2d_uint,
|
||||
t_storage3d_uint,
|
||||
t_storage1d_float,
|
||||
t_storage2d_float,
|
||||
t_storage3d_float,
|
||||
t_function,
|
||||
};
|
||||
enum qualifier : uint32_t
|
||||
{
|
||||
q_extern = 1 << 0,
|
||||
q_static = 1 << 1,
|
||||
q_uniform = 1 << 2,
|
||||
q_volatile = 1 << 3,
|
||||
q_precise = 1 << 4,
|
||||
q_groupshared = 1 << 14,
|
||||
q_in = 1 << 5,
|
||||
q_out = 1 << 6,
|
||||
q_inout = q_in | q_out,
|
||||
q_const = 1 << 8,
|
||||
q_linear = 1 << 10,
|
||||
q_noperspective = 1 << 11,
|
||||
q_centroid = 1 << 12,
|
||||
q_nointerpolation = 1 << 13,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets the result type of an operation involving the two input types.
|
||||
/// </summary>
|
||||
static type merge(const type &lhs, const type &rhs);
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the ranking between two types which can be used to select the best matching function overload. The higher the rank, the better the match. A value of zero indicates that the types are not compatible.
|
||||
/// </summary>
|
||||
static unsigned int rank(const type &src, const type &dst);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a human-readable description of this type definition.
|
||||
/// </summary>
|
||||
std::string description() const;
|
||||
|
||||
bool has(qualifier x) const { return (qualifiers & x) == x; }
|
||||
|
||||
bool is_void() const { return base == t_void; }
|
||||
bool is_boolean() const { return base == t_bool; }
|
||||
bool is_numeric() const { return base >= t_bool && base <= t_float; }
|
||||
bool is_integral() const { return (base >= t_bool && base <= t_uint) || (base >= t_sampler1d_int && base <= t_sampler3d_uint) || (base >= t_storage1d_int && base <= t_storage3d_uint); }
|
||||
bool is_floating_point() const { return base == t_min16float || base == t_float || (base >= t_sampler1d_float && base <= t_sampler3d_float) || (base >= t_storage1d_float && base <= t_storage3d_float); }
|
||||
bool is_signed() const { return base == t_min16int || base == t_int || (base >= t_sampler1d_int && base <= t_sampler3d_int) || (base >= t_storage1d_int && base <= t_storage3d_int) || is_floating_point(); }
|
||||
bool is_unsigned() const { return base == t_min16uint || base == t_uint || (base >= t_sampler1d_uint && base <= t_sampler3d_uint) || (base >= t_storage1d_uint && base <= t_storage3d_uint); }
|
||||
|
||||
bool is_struct() const { return base == t_struct; }
|
||||
bool is_object() const { return is_texture() || is_sampler() || is_storage(); }
|
||||
bool is_texture() const { return base >= t_texture1d && base <= t_texture3d; }
|
||||
bool is_sampler() const { return base >= t_sampler1d_int && base <= t_sampler3d_float; }
|
||||
bool is_storage() const { return base >= t_storage1d_int && base <= t_storage3d_float; }
|
||||
bool is_function() const { return base == t_function; }
|
||||
|
||||
bool is_array() const { return array_length != 0; }
|
||||
bool is_scalar() const { return is_numeric() && !is_matrix() && !is_vector() && !is_array(); }
|
||||
bool is_vector() const { return is_numeric() && rows > 1 && cols == 1; }
|
||||
bool is_matrix() const { return is_numeric() && rows >= 1 && cols > 1; }
|
||||
|
||||
unsigned int precision() const { return base == t_min16int || base == t_min16uint || base == t_min16float ? 16 : 32; }
|
||||
unsigned int components() const { return rows * cols; }
|
||||
unsigned int texture_dimension() const { return base >= t_texture1d && base <= t_storage3d_float ? ((base - t_texture1d) % 3) + 1 : 0; }
|
||||
|
||||
friend inline bool operator==(const type &lhs, const type &rhs)
|
||||
{
|
||||
return lhs.base == rhs.base && lhs.rows == rhs.rows && lhs.cols == rhs.cols && lhs.array_length == rhs.array_length && lhs.definition == rhs.definition;
|
||||
}
|
||||
friend inline bool operator!=(const type &lhs, const type &rhs)
|
||||
{
|
||||
return !operator==(lhs, rhs);
|
||||
}
|
||||
|
||||
// Underlying base type ('int', 'float', ...)
|
||||
datatype base = t_void;
|
||||
// Number of rows if this is a vector type
|
||||
unsigned int rows = 0;
|
||||
// Number of columns if this is a matrix type
|
||||
unsigned int cols = 0;
|
||||
// Bit mask of all the qualifiers decorating the type
|
||||
unsigned int qualifiers = 0;
|
||||
// Negative if an unsized array, otherwise the number of elements if this is an array type
|
||||
int array_length = 0;
|
||||
// ID of the matching struct if this is a struct type
|
||||
uint32_t definition = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Structure which encapsulates a parsed constant value
|
||||
/// </summary>
|
||||
struct constant
|
||||
{
|
||||
union
|
||||
{
|
||||
float as_float[16];
|
||||
int32_t as_int[16];
|
||||
uint32_t as_uint[16];
|
||||
};
|
||||
|
||||
// Optional string associated with this constant
|
||||
std::string string_data;
|
||||
// Optional additional elements if this is an array constant
|
||||
std::vector<constant> array_data;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Structures which keeps track of the access chain of an expression
|
||||
/// </summary>
|
||||
struct expression
|
||||
{
|
||||
struct operation
|
||||
{
|
||||
enum op_type
|
||||
{
|
||||
op_cast,
|
||||
op_member,
|
||||
op_dynamic_index,
|
||||
op_constant_index,
|
||||
op_swizzle,
|
||||
};
|
||||
|
||||
op_type op;
|
||||
reshadefx::type from, to;
|
||||
uint32_t index = 0;
|
||||
signed char swizzle[4] = {};
|
||||
};
|
||||
|
||||
uint32_t base = 0;
|
||||
reshadefx::type type = {};
|
||||
reshadefx::constant constant = {};
|
||||
bool is_lvalue = false;
|
||||
bool is_constant = false;
|
||||
reshadefx::location location;
|
||||
std::vector<operation> chain;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the expression to a l-value.
|
||||
/// </summary>
|
||||
/// <param name="loc">Code location of the expression.</param>
|
||||
/// <param name="base">SSA ID of the l-value.</param>
|
||||
/// <param name="type">Value type of the expression result.</param>
|
||||
void reset_to_lvalue(const reshadefx::location &loc, uint32_t base, const reshadefx::type &type);
|
||||
/// <summary>
|
||||
/// Initializes the expression to a r-value.
|
||||
/// </summary>
|
||||
/// <param name="loc">Code location of the expression.</param>
|
||||
/// <param name="base">SSA ID of the r-value.</param>
|
||||
/// <param name="type">Value type of the expression result.</param>
|
||||
void reset_to_rvalue(const reshadefx::location &loc, uint32_t base, const reshadefx::type &type);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the expression to a constant value.
|
||||
/// </summary>
|
||||
/// <param name="loc">Code location of the constant expression.</param>
|
||||
/// <param name="data">Constant value to initialize to.</param>
|
||||
void reset_to_rvalue_constant(const reshadefx::location &loc, bool data);
|
||||
void reset_to_rvalue_constant(const reshadefx::location &loc, float data);
|
||||
void reset_to_rvalue_constant(const reshadefx::location &loc, int32_t data);
|
||||
void reset_to_rvalue_constant(const reshadefx::location &loc, uint32_t data);
|
||||
void reset_to_rvalue_constant(const reshadefx::location &loc, std::string data);
|
||||
void reset_to_rvalue_constant(const reshadefx::location &loc, reshadefx::constant data, const reshadefx::type &type);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a cast operation to the current access chain.
|
||||
/// </summary>
|
||||
/// <param name="type">Type to cast the expression to.</param>
|
||||
void add_cast_operation(const reshadefx::type &type);
|
||||
/// <summary>
|
||||
/// Adds a structure member lookup to the current access chain.
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the member to dereference.</param>
|
||||
/// <param name="type">Value type of the member.</param>
|
||||
void add_member_access(unsigned int index, const reshadefx::type &type);
|
||||
/// <summary>
|
||||
/// Adds an index operation to the current access chain.
|
||||
/// </summary>
|
||||
/// <param name="index_expression">SSA ID of the indexing value.</param>
|
||||
void add_dynamic_index_access(uint32_t index_expression);
|
||||
/// <summary>
|
||||
/// Adds an constant index operation to the current access chain.
|
||||
/// </summary>
|
||||
/// <param name="index">Constant indexing value.</param>
|
||||
void add_constant_index_access(unsigned int index);
|
||||
/// <summary>
|
||||
/// Adds a swizzle operation to the current access chain.
|
||||
/// </summary>
|
||||
/// <param name="swizzle">Swizzle for each component. -1 = unused, 0 = x, 1 = y, 2 = z, 3 = w.</param>
|
||||
/// <param name="length">Number of components in the swizzle. The maximum is 4.</param>
|
||||
void add_swizzle_access(const signed char swizzle[4], unsigned int length);
|
||||
|
||||
/// <summary>
|
||||
/// Applies an unary operation to this constant expression.
|
||||
/// </summary>
|
||||
/// <param name="op">Unary operator to apply.</param>
|
||||
bool evaluate_constant_expression(reshadefx::tokenid op);
|
||||
/// <summary>
|
||||
/// Applies a binary operation to this constant expression.
|
||||
/// </summary>
|
||||
/// <param name="op">Binary operator to apply.</param>
|
||||
/// <param name="rhs">Constant value to use as right-hand side of the binary operation.</param>
|
||||
bool evaluate_constant_expression(reshadefx::tokenid op, const reshadefx::constant &rhs);
|
||||
};
|
||||
}
|
112
dep/reshadefx/include/effect_lexer.hpp
Normal file
112
dep/reshadefx/include/effect_lexer.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Patrick Mours
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect_token.hpp"
|
||||
|
||||
namespace reshadefx
|
||||
{
|
||||
/// <summary>
|
||||
/// A lexical analyzer for C-like languages.
|
||||
/// </summary>
|
||||
class lexer
|
||||
{
|
||||
public:
|
||||
explicit lexer(
|
||||
std::string input,
|
||||
bool ignore_comments = true,
|
||||
bool ignore_whitespace = true,
|
||||
bool ignore_pp_directives = true,
|
||||
bool ignore_line_directives = false,
|
||||
bool ignore_keywords = false,
|
||||
bool escape_string_literals = true,
|
||||
const location &start_location = location()) :
|
||||
_input(std::move(input)),
|
||||
_cur_location(start_location),
|
||||
_ignore_comments(ignore_comments),
|
||||
_ignore_whitespace(ignore_whitespace),
|
||||
_ignore_pp_directives(ignore_pp_directives),
|
||||
_ignore_line_directives(ignore_line_directives),
|
||||
_ignore_keywords(ignore_keywords),
|
||||
_escape_string_literals(escape_string_literals)
|
||||
{
|
||||
_cur = _input.data();
|
||||
_end = _cur + _input.size();
|
||||
}
|
||||
|
||||
lexer(const lexer &lexer) { operator=(lexer); }
|
||||
lexer &operator=(const lexer &lexer)
|
||||
{
|
||||
_input = lexer._input;
|
||||
_cur_location = lexer._cur_location;
|
||||
reset_to_offset(lexer._cur - lexer._input.data());
|
||||
_end = _input.data() + _input.size();
|
||||
_ignore_comments = lexer._ignore_comments;
|
||||
_ignore_whitespace = lexer._ignore_whitespace;
|
||||
_ignore_pp_directives = lexer._ignore_pp_directives;
|
||||
_ignore_keywords = lexer._ignore_keywords;
|
||||
_escape_string_literals = lexer._escape_string_literals;
|
||||
_ignore_line_directives = lexer._ignore_line_directives;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current position in the input string.
|
||||
/// </summary>
|
||||
size_t input_offset() const { return _cur - _input.data(); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the input string this lexical analyzer works on.
|
||||
/// </summary>
|
||||
/// <returns>Constant reference to the input string.</returns>
|
||||
const std::string &input_string() const { return _input; }
|
||||
|
||||
/// <summary>
|
||||
/// Performs lexical analysis on the input string and return the next token in sequence.
|
||||
/// </summary>
|
||||
/// <returns>Next token from the input string.</returns>
|
||||
token lex();
|
||||
|
||||
/// <summary>
|
||||
/// Advances to the next token that is not whitespace.
|
||||
/// </summary>
|
||||
void skip_space();
|
||||
/// <summary>
|
||||
/// Advances to the next new line, ignoring all tokens.
|
||||
/// </summary>
|
||||
void skip_to_next_line();
|
||||
|
||||
/// <summary>
|
||||
/// Resets position to the specified <paramref name="offset"/>.
|
||||
/// </summary>
|
||||
/// <param name="offset">Offset in characters from the start of the input string.</param>
|
||||
void reset_to_offset(size_t offset);
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Skips an arbitrary amount of characters in the input string.
|
||||
/// </summary>
|
||||
/// <param name="length">Number of input characters to skip.</param>
|
||||
void skip(size_t length);
|
||||
|
||||
void parse_identifier(token &tok) const;
|
||||
bool parse_pp_directive(token &tok);
|
||||
void parse_string_literal(token &tok, bool escape);
|
||||
void parse_numeric_literal(token &tok) const;
|
||||
|
||||
std::string _input;
|
||||
location _cur_location;
|
||||
const std::string::value_type *_cur, *_end;
|
||||
|
||||
bool _ignore_comments;
|
||||
bool _ignore_whitespace;
|
||||
bool _ignore_pp_directives;
|
||||
bool _ignore_line_directives;
|
||||
bool _ignore_keywords;
|
||||
bool _escape_string_literals;
|
||||
};
|
||||
}
|
350
dep/reshadefx/include/effect_module.hpp
Normal file
350
dep/reshadefx/include/effect_module.hpp
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Patrick Mours
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect_expression.hpp"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace reshadefx
|
||||
{
|
||||
/// <summary>
|
||||
/// A list of supported texture types.
|
||||
/// </summary>
|
||||
enum class texture_type
|
||||
{
|
||||
texture_1d = 1,
|
||||
texture_2d = 2,
|
||||
texture_3d = 3
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A list of supported texture formats.
|
||||
/// </summary>
|
||||
enum class texture_format
|
||||
{
|
||||
unknown,
|
||||
|
||||
r8,
|
||||
r16,
|
||||
r16f,
|
||||
r32i,
|
||||
r32u,
|
||||
r32f,
|
||||
rg8,
|
||||
rg16,
|
||||
rg16f,
|
||||
rg32f,
|
||||
rgba8,
|
||||
rgba16,
|
||||
rgba16f,
|
||||
rgba32f,
|
||||
rgb10a2
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A filtering type used for texture lookups.
|
||||
/// </summary>
|
||||
enum class filter_mode
|
||||
{
|
||||
min_mag_mip_point = 0,
|
||||
min_mag_point_mip_linear = 0x1,
|
||||
min_point_mag_linear_mip_point = 0x4,
|
||||
min_point_mag_mip_linear = 0x5,
|
||||
min_linear_mag_mip_point = 0x10,
|
||||
min_linear_mag_point_mip_linear = 0x11,
|
||||
min_mag_linear_mip_point = 0x14,
|
||||
min_mag_mip_linear = 0x15
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Specifies behavior of sampling with texture coordinates outside an image.
|
||||
/// </summary>
|
||||
enum class texture_address_mode
|
||||
{
|
||||
wrap = 1,
|
||||
mirror = 2,
|
||||
clamp = 3,
|
||||
border = 4
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Specifies RGB or alpha blending operations.
|
||||
/// </summary>
|
||||
enum class pass_blend_op : uint8_t
|
||||
{
|
||||
add = 1,
|
||||
subtract,
|
||||
reverse_subtract,
|
||||
min,
|
||||
max
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Specifies blend factors, which modulate values between the pixel shader output and render target.
|
||||
/// </summary>
|
||||
enum class pass_blend_factor : uint8_t
|
||||
{
|
||||
zero = 0,
|
||||
one = 1,
|
||||
source_color,
|
||||
one_minus_source_color,
|
||||
dest_color,
|
||||
one_minus_dest_color,
|
||||
source_alpha,
|
||||
one_minus_source_alpha,
|
||||
dest_alpha,
|
||||
one_minus_dest_alpha
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the stencil operations that can be performed during depth-stencil testing.
|
||||
/// </summary>
|
||||
enum class pass_stencil_op : uint8_t
|
||||
{
|
||||
zero = 0,
|
||||
keep,
|
||||
replace,
|
||||
increment_saturate,
|
||||
decrement_saturate,
|
||||
invert,
|
||||
increment,
|
||||
decrement
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Specifies comparison options for depth-stencil testing.
|
||||
/// </summary>
|
||||
enum class pass_stencil_func : uint8_t
|
||||
{
|
||||
never,
|
||||
less,
|
||||
equal,
|
||||
less_equal,
|
||||
greater,
|
||||
not_equal,
|
||||
greater_equal,
|
||||
always
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the possible primitives.
|
||||
/// </summary>
|
||||
enum class primitive_topology : uint8_t
|
||||
{
|
||||
point_list = 1,
|
||||
line_list,
|
||||
line_strip,
|
||||
triangle_list,
|
||||
triangle_strip
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A struct type defined in the effect code.
|
||||
/// </summary>
|
||||
struct struct_info
|
||||
{
|
||||
std::string name;
|
||||
std::string unique_name;
|
||||
std::vector<struct struct_member_info> member_list;
|
||||
uint32_t definition = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A struct field defined in the effect code.
|
||||
/// </summary>
|
||||
struct struct_member_info
|
||||
{
|
||||
reshadefx::type type;
|
||||
std::string name;
|
||||
std::string semantic;
|
||||
reshadefx::location location;
|
||||
uint32_t definition = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// An annotation attached to a variable.
|
||||
/// </summary>
|
||||
struct annotation
|
||||
{
|
||||
reshadefx::type type;
|
||||
std::string name;
|
||||
reshadefx::constant value;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A texture defined in the effect code.
|
||||
/// </summary>
|
||||
struct texture_info
|
||||
{
|
||||
uint32_t id = 0;
|
||||
uint32_t binding = 0;
|
||||
std::string name;
|
||||
std::string semantic;
|
||||
std::string unique_name;
|
||||
std::vector<annotation> annotations;
|
||||
texture_type type = texture_type::texture_2d;
|
||||
uint32_t width = 1;
|
||||
uint32_t height = 1;
|
||||
uint16_t depth = 1;
|
||||
uint16_t levels = 1;
|
||||
texture_format format = texture_format::rgba8;
|
||||
bool render_target = false;
|
||||
bool storage_access = false;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A texture sampler defined in the effect code.
|
||||
/// </summary>
|
||||
struct sampler_info
|
||||
{
|
||||
uint32_t id = 0;
|
||||
uint32_t binding = 0;
|
||||
uint32_t texture_binding = 0;
|
||||
std::string name;
|
||||
reshadefx::type type;
|
||||
std::string unique_name;
|
||||
std::string texture_name;
|
||||
std::vector<annotation> annotations;
|
||||
filter_mode filter = filter_mode::min_mag_mip_linear;
|
||||
texture_address_mode address_u = texture_address_mode::clamp;
|
||||
texture_address_mode address_v = texture_address_mode::clamp;
|
||||
texture_address_mode address_w = texture_address_mode::clamp;
|
||||
float min_lod = -3.402823466e+38f;
|
||||
float max_lod = +3.402823466e+38f; // FLT_MAX
|
||||
float lod_bias = 0.0f;
|
||||
uint8_t srgb = false;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A texture storage object defined in the effect code.
|
||||
/// </summary>
|
||||
struct storage_info
|
||||
{
|
||||
uint32_t id = 0;
|
||||
uint32_t binding = 0;
|
||||
std::string name;
|
||||
reshadefx::type type;
|
||||
std::string unique_name;
|
||||
std::string texture_name;
|
||||
uint16_t level = 0;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// An uniform variable defined in the effect code.
|
||||
/// </summary>
|
||||
struct uniform_info
|
||||
{
|
||||
std::string name;
|
||||
reshadefx::type type;
|
||||
uint32_t size = 0;
|
||||
uint32_t offset = 0;
|
||||
std::vector<annotation> annotations;
|
||||
bool has_initializer_value = false;
|
||||
reshadefx::constant initializer_value;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Type of a shader entry point.
|
||||
/// </summary>
|
||||
enum class shader_type
|
||||
{
|
||||
vs,
|
||||
ps,
|
||||
cs,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A shader entry point function.
|
||||
/// </summary>
|
||||
struct entry_point
|
||||
{
|
||||
std::string name;
|
||||
shader_type type;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A function defined in the effect code.
|
||||
/// </summary>
|
||||
struct function_info
|
||||
{
|
||||
uint32_t definition;
|
||||
std::string name;
|
||||
std::string unique_name;
|
||||
reshadefx::type return_type;
|
||||
std::string return_semantic;
|
||||
std::vector<struct_member_info> parameter_list;
|
||||
std::unordered_set<uint32_t> referenced_samplers;
|
||||
std::unordered_set<uint32_t> referenced_storages;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A render pass with all its state info.
|
||||
/// </summary>
|
||||
struct pass_info
|
||||
{
|
||||
std::string name;
|
||||
std::string render_target_names[8] = {};
|
||||
std::string vs_entry_point;
|
||||
std::string ps_entry_point;
|
||||
std::string cs_entry_point;
|
||||
uint8_t generate_mipmaps = true;
|
||||
uint8_t clear_render_targets = false;
|
||||
uint8_t srgb_write_enable = false;
|
||||
uint8_t blend_enable[8] = { false, false, false, false, false, false, false, false };
|
||||
uint8_t stencil_enable = false;
|
||||
uint8_t color_write_mask[8] = { 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF };
|
||||
uint8_t stencil_read_mask = 0xFF;
|
||||
uint8_t stencil_write_mask = 0xFF;
|
||||
pass_blend_op blend_op[8] = { pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add };
|
||||
pass_blend_op blend_op_alpha[8] = { pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add, pass_blend_op::add };
|
||||
pass_blend_factor src_blend[8] = { pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one };
|
||||
pass_blend_factor dest_blend[8] = { pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero };
|
||||
pass_blend_factor src_blend_alpha[8] = { pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one, pass_blend_factor::one };
|
||||
pass_blend_factor dest_blend_alpha[8] = { pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero, pass_blend_factor::zero };
|
||||
pass_stencil_func stencil_comparison_func = pass_stencil_func::always;
|
||||
uint32_t stencil_reference_value = 0;
|
||||
pass_stencil_op stencil_op_pass = pass_stencil_op::keep;
|
||||
pass_stencil_op stencil_op_fail = pass_stencil_op::keep;
|
||||
pass_stencil_op stencil_op_depth_fail = pass_stencil_op::keep;
|
||||
uint32_t num_vertices = 3;
|
||||
primitive_topology topology = primitive_topology::triangle_list;
|
||||
uint32_t viewport_width = 0;
|
||||
uint32_t viewport_height = 0;
|
||||
uint32_t viewport_dispatch_z = 1;
|
||||
std::vector<sampler_info> samplers;
|
||||
std::vector<storage_info> storages;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A collection of passes that make up an effect.
|
||||
/// </summary>
|
||||
struct technique_info
|
||||
{
|
||||
std::string name;
|
||||
std::vector<pass_info> passes;
|
||||
std::vector<annotation> annotations;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// In-memory representation of an effect file.
|
||||
/// </summary>
|
||||
struct module
|
||||
{
|
||||
std::vector<char> code;
|
||||
|
||||
std::vector<entry_point> entry_points;
|
||||
std::vector<texture_info> textures;
|
||||
std::vector<sampler_info> samplers;
|
||||
std::vector<storage_info> storages;
|
||||
std::vector<uniform_info> uniforms, spec_constants;
|
||||
std::vector<technique_info> techniques;
|
||||
|
||||
uint32_t total_uniform_size = 0;
|
||||
uint32_t num_texture_bindings = 0;
|
||||
uint32_t num_sampler_bindings = 0;
|
||||
uint32_t num_storage_bindings = 0;
|
||||
};
|
||||
}
|
88
dep/reshadefx/include/effect_parser.hpp
Normal file
88
dep/reshadefx/include/effect_parser.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Patrick Mours
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect_symbol_table.hpp"
|
||||
#include <memory> // std::unique_ptr
|
||||
|
||||
namespace reshadefx
|
||||
{
|
||||
/// <summary>
|
||||
/// A parser for the ReShade FX shader language.
|
||||
/// </summary>
|
||||
class parser : symbol_table
|
||||
{
|
||||
public:
|
||||
// Define constructor explicitly because lexer class is not included here
|
||||
parser();
|
||||
~parser();
|
||||
|
||||
/// <summary>
|
||||
/// Parses the provided input string.
|
||||
/// </summary>
|
||||
/// <param name="source">String to analyze.</param>
|
||||
/// <param name="backend">Code generation implementation to use.</param>
|
||||
/// <returns><see langword="true"/> if parsing was successfull, <see langword="false"/> otherwise.</returns>
|
||||
bool parse(std::string source, class codegen *backend);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of error messages.
|
||||
/// </summary>
|
||||
const std::string &errors() const { return _errors; }
|
||||
|
||||
private:
|
||||
void error(const location &location, unsigned int code, const std::string &message);
|
||||
void warning(const location &location, unsigned int code, const std::string &message);
|
||||
|
||||
void backup();
|
||||
void restore();
|
||||
|
||||
bool peek(char tok) const { return _token_next.id == static_cast<tokenid>(tok); }
|
||||
bool peek(tokenid tokid) const { return _token_next.id == tokid; }
|
||||
void consume();
|
||||
void consume_until(char tok) { return consume_until(static_cast<tokenid>(tok)); }
|
||||
void consume_until(tokenid tokid);
|
||||
bool accept(char tok) { return accept(static_cast<tokenid>(tok)); }
|
||||
bool accept(tokenid tokid);
|
||||
bool expect(char tok) { return expect(static_cast<tokenid>(tok)); }
|
||||
bool expect(tokenid tokid);
|
||||
|
||||
bool accept_symbol(std::string &identifier, scoped_symbol &symbol);
|
||||
bool accept_type_class(type &type);
|
||||
bool accept_type_qualifiers(type &type);
|
||||
bool accept_unary_op();
|
||||
bool accept_postfix_op();
|
||||
bool peek_multary_op(unsigned int &precedence) const;
|
||||
bool accept_assignment_op();
|
||||
|
||||
void parse_top(bool &parse_success);
|
||||
bool parse_struct();
|
||||
bool parse_function(type type, std::string name);
|
||||
bool parse_variable(type type, std::string name, bool global = false);
|
||||
bool parse_technique();
|
||||
bool parse_technique_pass(pass_info &info);
|
||||
bool parse_type(type &type);
|
||||
bool parse_array_size(type &type);
|
||||
bool parse_expression(expression &expression);
|
||||
bool parse_expression_unary(expression &expression);
|
||||
bool parse_expression_multary(expression &expression, unsigned int precedence = 0);
|
||||
bool parse_expression_assignment(expression &expression);
|
||||
bool parse_annotations(std::vector<annotation> &annotations);
|
||||
bool parse_statement(bool scoped);
|
||||
bool parse_statement_block(bool scoped);
|
||||
|
||||
codegen *_codegen = nullptr;
|
||||
std::string _errors;
|
||||
|
||||
token _token, _token_next, _token_backup;
|
||||
std::unique_ptr<class lexer> _lexer;
|
||||
size_t _lexer_backup_offset = 0;
|
||||
|
||||
std::vector<uint32_t> _loop_break_target_stack;
|
||||
std::vector<uint32_t> _loop_continue_target_stack;
|
||||
reshadefx::function_info *_current_function = nullptr;
|
||||
};
|
||||
}
|
166
dep/reshadefx/include/effect_preprocessor.hpp
Normal file
166
dep/reshadefx/include/effect_preprocessor.hpp
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Patrick Mours
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect_token.hpp"
|
||||
#include <memory> // std::unique_ptr
|
||||
#include <filesystem>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace reshadefx
|
||||
{
|
||||
/// <summary>
|
||||
/// A C-style preprocessor implementation.
|
||||
/// </summary>
|
||||
class preprocessor
|
||||
{
|
||||
public:
|
||||
struct macro
|
||||
{
|
||||
std::string replacement_list;
|
||||
std::vector<std::string> parameters;
|
||||
bool is_predefined = false;
|
||||
bool is_variadic = false;
|
||||
bool is_function_like = false;
|
||||
};
|
||||
|
||||
// Define constructor explicitly because lexer class is not included here
|
||||
preprocessor();
|
||||
~preprocessor();
|
||||
|
||||
/// <summary>
|
||||
/// Adds an include directory to the list of search paths used when resolving #include directives.
|
||||
/// </summary>
|
||||
/// <param name="path">Path to the directory to add.</param>
|
||||
void add_include_path(const std::filesystem::path &path);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new macro definition. This is equal to appending '#define name macro' to this preprocessor instance.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the macro to define.</param>
|
||||
/// <param name="macro">Definition of the macro function or value.</param>
|
||||
/// <returns></returns>
|
||||
bool add_macro_definition(const std::string &name, const macro ¯o);
|
||||
/// <summary>
|
||||
/// Adds a new macro value definition. This is equal to appending '#define name macro' to this preprocessor instance.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the macro to define.</param>
|
||||
/// <param name="value">Value to define that macro to.</param>
|
||||
/// <returns></returns>
|
||||
bool add_macro_definition(const std::string &name, std::string value = "1")
|
||||
{
|
||||
return add_macro_definition(name, macro { std::move(value), {}, true });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified file, parses its contents and appends them to the output.
|
||||
/// </summary>
|
||||
/// <param name="path">Path to the file to parse.</param>
|
||||
/// <returns><see langword="true"/> if parsing was successful, <see langword="false"/> otherwise.</returns>
|
||||
bool append_file(const std::filesystem::path &path);
|
||||
/// <summary>
|
||||
/// Parses the specified string and appends it to the output.
|
||||
/// </summary>
|
||||
/// <param name="source_code">String to parse.</param>
|
||||
/// <param name="path">Optional file path to identify this string with.</param>
|
||||
/// <returns><see langword="true"/> if parsing was successful, <see langword="false"/> otherwise.</returns>
|
||||
bool append_string(std::string source_code, const std::filesystem::path &path = std::filesystem::path());
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of error messages.
|
||||
/// </summary>
|
||||
const std::string &errors() const { return _errors; }
|
||||
/// <summary>
|
||||
/// Gets the current pre-processed output string.
|
||||
/// </summary>
|
||||
const std::string &output() const { return _output; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all included files.
|
||||
/// </summary>
|
||||
std::vector<std::filesystem::path> included_files() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all defines that were used in #ifdef and #ifndef lines.
|
||||
/// </summary>
|
||||
std::vector<std::pair<std::string, std::string>> used_macro_definitions() const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of pragma directives that occured.
|
||||
/// </summary>
|
||||
std::vector<std::pair<std::string, std::string>> used_pragma_directives() const { return _used_pragmas; }
|
||||
|
||||
private:
|
||||
struct if_level
|
||||
{
|
||||
bool value;
|
||||
bool skipping;
|
||||
token pp_token;
|
||||
size_t input_index;
|
||||
};
|
||||
struct input_level
|
||||
{
|
||||
std::string name;
|
||||
std::unique_ptr<class lexer> lexer;
|
||||
token next_token;
|
||||
std::unordered_set<std::string> hidden_macros;
|
||||
};
|
||||
|
||||
void error(const location &location, const std::string &message);
|
||||
void warning(const location &location, const std::string &message);
|
||||
|
||||
void push(std::string input, const std::string &name = std::string());
|
||||
|
||||
bool peek(tokenid tokid) const;
|
||||
void consume();
|
||||
void consume_until(tokenid tokid);
|
||||
bool accept(tokenid tokid, bool ignore_whitespace = true);
|
||||
bool expect(tokenid tokid);
|
||||
|
||||
void parse();
|
||||
void parse_def();
|
||||
void parse_undef();
|
||||
void parse_if();
|
||||
void parse_ifdef();
|
||||
void parse_ifndef();
|
||||
void parse_elif();
|
||||
void parse_else();
|
||||
void parse_endif();
|
||||
void parse_error();
|
||||
void parse_warning();
|
||||
void parse_pragma();
|
||||
void parse_include();
|
||||
|
||||
bool evaluate_expression();
|
||||
bool evaluate_identifier_as_macro();
|
||||
|
||||
bool is_defined(const std::string &name) const;
|
||||
void expand_macro(const std::string &name, const macro ¯o, const std::vector<std::string> &arguments);
|
||||
void create_macro_replacement_list(macro ¯o);
|
||||
|
||||
bool _success = true;
|
||||
std::string _output, _errors;
|
||||
|
||||
std::string _current_token_raw_data;
|
||||
reshadefx::token _token;
|
||||
location _output_location;
|
||||
std::vector<input_level> _input_stack;
|
||||
size_t _next_input_index = 0;
|
||||
size_t _current_input_index = 0;
|
||||
|
||||
std::vector<if_level> _if_stack;
|
||||
|
||||
unsigned short _recursion_count = 0;
|
||||
std::unordered_set<std::string> _used_macros;
|
||||
std::unordered_map<std::string, macro> _macros;
|
||||
|
||||
std::vector<std::filesystem::path> _include_paths;
|
||||
std::unordered_map<std::string, std::string> _file_cache;
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> _used_pragmas;
|
||||
};
|
||||
}
|
103
dep/reshadefx/include/effect_symbol_table.hpp
Normal file
103
dep/reshadefx/include/effect_symbol_table.hpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Patrick Mours
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "effect_module.hpp"
|
||||
#include <unordered_map> // Used for symbol lookup table
|
||||
|
||||
namespace reshadefx
|
||||
{
|
||||
/// <summary>
|
||||
/// A scope encapsulating symbols.
|
||||
/// </summary>
|
||||
struct scope
|
||||
{
|
||||
std::string name;
|
||||
uint32_t level, namespace_level;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Enumeration of all possible symbol types.
|
||||
/// </summary>
|
||||
enum class symbol_type
|
||||
{
|
||||
invalid,
|
||||
variable,
|
||||
constant,
|
||||
function,
|
||||
intrinsic,
|
||||
structure,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A single symbol in the symbol table.
|
||||
/// </summary>
|
||||
struct symbol
|
||||
{
|
||||
symbol_type op = symbol_type::invalid;
|
||||
uint32_t id = 0;
|
||||
reshadefx::type type = {};
|
||||
reshadefx::constant constant = {};
|
||||
const reshadefx::function_info *function = nullptr;
|
||||
};
|
||||
struct scoped_symbol : symbol
|
||||
{
|
||||
struct scope scope; // Store scope together with symbol data
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A symbol table managing a list of scopes and symbols.
|
||||
/// </summary>
|
||||
class symbol_table
|
||||
{
|
||||
public:
|
||||
symbol_table();
|
||||
|
||||
/// <summary>
|
||||
/// Enters a new scope as child of the current one.
|
||||
/// </summary>
|
||||
void enter_scope();
|
||||
/// <summary>
|
||||
/// Enters a new namespace as child of the current one.
|
||||
/// </summary>
|
||||
void enter_namespace(const std::string &name);
|
||||
/// <summary>
|
||||
/// Leaves the current scope and enter the parent one.
|
||||
/// </summary>
|
||||
void leave_scope();
|
||||
/// <summary>
|
||||
/// Leaves the current namespace and enter the parent one.
|
||||
/// </summary>
|
||||
void leave_namespace();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current scope the symbol table operates in.
|
||||
/// </summary>
|
||||
const scope ¤t_scope() const { return _current_scope; }
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an new symbol in the symbol table.
|
||||
/// Returns <see langword="false"/> if a symbol by that name and type already exists.
|
||||
/// </summary>
|
||||
bool insert_symbol(const std::string &name, const symbol &symbol, bool global = false);
|
||||
|
||||
/// <summary>
|
||||
/// Looks for an existing symbol with the specified <paramref name="name"/>.
|
||||
/// </summary>
|
||||
scoped_symbol find_symbol(const std::string &name) const;
|
||||
scoped_symbol find_symbol(const std::string &name, const scope &scope, bool exclusive) const;
|
||||
|
||||
/// <summary>
|
||||
/// Searches for the best function or intrinsic overload matching the argument list.
|
||||
/// </summary>
|
||||
bool resolve_function_call(const std::string &name, const std::vector<expression> &args, const scope &scope, symbol &data, bool &ambiguous) const;
|
||||
|
||||
private:
|
||||
scope _current_scope;
|
||||
// Lookup table from name to matching symbols
|
||||
std::unordered_map<std::string, std::vector<scoped_symbol>> _symbol_stack;
|
||||
};
|
||||
}
|
252
dep/reshadefx/include/effect_token.hpp
Normal file
252
dep/reshadefx/include/effect_token.hpp
Normal file
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Patrick Mours
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace reshadefx
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure which keeps track of a code location.
|
||||
/// </summary>
|
||||
struct location
|
||||
{
|
||||
location() : line(1), column(1) {}
|
||||
explicit location(uint32_t line, uint32_t column = 1) : line(line), column(column) {}
|
||||
explicit location(std::string source, uint32_t line, uint32_t column = 1) : source(std::move(source)), line(line), column(column) {}
|
||||
|
||||
std::string source;
|
||||
uint32_t line, column;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A collection of identifiers for various possible tokens.
|
||||
/// </summary>
|
||||
enum class tokenid
|
||||
{
|
||||
unknown = -1,
|
||||
end_of_file = 0,
|
||||
end_of_line = '\n',
|
||||
|
||||
// operators
|
||||
space = ' ',
|
||||
exclaim = '!',
|
||||
hash = '#',
|
||||
dollar = '$',
|
||||
percent = '%',
|
||||
ampersand = '&',
|
||||
parenthesis_open = '(',
|
||||
parenthesis_close = ')',
|
||||
star = '*',
|
||||
plus = '+',
|
||||
comma = ',',
|
||||
minus = '-',
|
||||
dot = '.',
|
||||
slash = '/',
|
||||
colon = ':',
|
||||
semicolon = ';',
|
||||
less = '<',
|
||||
equal = '=',
|
||||
greater = '>',
|
||||
question = '?',
|
||||
at = '@',
|
||||
bracket_open = '[',
|
||||
backslash = '\\',
|
||||
bracket_close = ']',
|
||||
caret = '^',
|
||||
brace_open = '{',
|
||||
pipe = '|',
|
||||
brace_close = '}',
|
||||
tilde = '~',
|
||||
exclaim_equal = 256 /* != */,
|
||||
percent_equal /* %= */,
|
||||
ampersand_ampersand /* && */,
|
||||
ampersand_equal /* &= */,
|
||||
star_equal /* *= */,
|
||||
plus_plus /* ++*/,
|
||||
plus_equal /* += */,
|
||||
minus_minus /* -- */,
|
||||
minus_equal /* -= */,
|
||||
arrow /* -> */,
|
||||
ellipsis /* ... */,
|
||||
slash_equal /* /= */,
|
||||
colon_colon /* :: */,
|
||||
less_less_equal /* <<= */,
|
||||
less_less /* << */,
|
||||
less_equal /* <= */,
|
||||
equal_equal /* == */,
|
||||
greater_greater_equal /* >>= */,
|
||||
greater_greater /* >> */,
|
||||
greater_equal /* >= */,
|
||||
caret_equal /* ^= */,
|
||||
pipe_equal /* |= */,
|
||||
pipe_pipe /* || */,
|
||||
|
||||
// identifiers
|
||||
reserved,
|
||||
identifier,
|
||||
|
||||
// literals
|
||||
true_literal,
|
||||
false_literal,
|
||||
int_literal,
|
||||
uint_literal,
|
||||
float_literal,
|
||||
double_literal,
|
||||
string_literal,
|
||||
|
||||
// keywords
|
||||
namespace_,
|
||||
struct_,
|
||||
technique,
|
||||
pass,
|
||||
for_,
|
||||
while_,
|
||||
do_,
|
||||
if_,
|
||||
else_,
|
||||
switch_,
|
||||
case_,
|
||||
default_,
|
||||
break_,
|
||||
continue_,
|
||||
return_,
|
||||
discard_,
|
||||
extern_,
|
||||
static_,
|
||||
uniform_,
|
||||
volatile_,
|
||||
precise,
|
||||
groupshared,
|
||||
in,
|
||||
out,
|
||||
inout,
|
||||
const_,
|
||||
linear,
|
||||
noperspective,
|
||||
centroid,
|
||||
nointerpolation,
|
||||
|
||||
void_,
|
||||
bool_,
|
||||
bool2,
|
||||
bool3,
|
||||
bool4,
|
||||
bool2x2,
|
||||
bool2x3,
|
||||
bool2x4,
|
||||
bool3x2,
|
||||
bool3x3,
|
||||
bool3x4,
|
||||
bool4x2,
|
||||
bool4x3,
|
||||
bool4x4,
|
||||
int_,
|
||||
int2,
|
||||
int3,
|
||||
int4,
|
||||
int2x2,
|
||||
int2x3,
|
||||
int2x4,
|
||||
int3x2,
|
||||
int3x3,
|
||||
int3x4,
|
||||
int4x2,
|
||||
int4x3,
|
||||
int4x4,
|
||||
min16int,
|
||||
min16int2,
|
||||
min16int3,
|
||||
min16int4,
|
||||
uint_,
|
||||
uint2,
|
||||
uint3,
|
||||
uint4,
|
||||
uint2x2,
|
||||
uint2x3,
|
||||
uint2x4,
|
||||
uint3x2,
|
||||
uint3x3,
|
||||
uint3x4,
|
||||
uint4x2,
|
||||
uint4x3,
|
||||
uint4x4,
|
||||
min16uint,
|
||||
min16uint2,
|
||||
min16uint3,
|
||||
min16uint4,
|
||||
float_,
|
||||
float2,
|
||||
float3,
|
||||
float4,
|
||||
float2x2,
|
||||
float2x3,
|
||||
float2x4,
|
||||
float3x2,
|
||||
float3x3,
|
||||
float3x4,
|
||||
float4x2,
|
||||
float4x3,
|
||||
float4x4,
|
||||
min16float,
|
||||
min16float2,
|
||||
min16float3,
|
||||
min16float4,
|
||||
vector,
|
||||
matrix,
|
||||
string_,
|
||||
texture1d,
|
||||
texture2d,
|
||||
texture3d,
|
||||
sampler1d,
|
||||
sampler2d,
|
||||
sampler3d,
|
||||
storage1d,
|
||||
storage2d,
|
||||
storage3d,
|
||||
|
||||
// preprocessor directives
|
||||
hash_def,
|
||||
hash_undef,
|
||||
hash_if,
|
||||
hash_ifdef,
|
||||
hash_ifndef,
|
||||
hash_else,
|
||||
hash_elif,
|
||||
hash_endif,
|
||||
hash_error,
|
||||
hash_warning,
|
||||
hash_pragma,
|
||||
hash_include,
|
||||
hash_unknown,
|
||||
|
||||
single_line_comment,
|
||||
multi_line_comment,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A structure describing a single token in the input string.
|
||||
/// </summary>
|
||||
struct token
|
||||
{
|
||||
tokenid id;
|
||||
reshadefx::location location;
|
||||
size_t offset, length;
|
||||
union
|
||||
{
|
||||
int literal_as_int;
|
||||
unsigned int literal_as_uint;
|
||||
float literal_as_float;
|
||||
double literal_as_double;
|
||||
};
|
||||
std::string literal_as_string;
|
||||
|
||||
inline operator tokenid() const { return id; }
|
||||
|
||||
static std::string id_to_name(tokenid id);
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user