/** * MojoShader; generate shader programs from bytecode of compiled * Direct3D shaders. * * Please see the file LICENSE.txt in the source's root directory. * * This file written by Ryan C. Gordon. */ #ifndef MOJOSHADER_PROFILE_H #define MOJOSHADER_PROFILE_H #include "../mojoshader_internal.h" typedef struct ConstantsList { MOJOSHADER_constant constant; struct ConstantsList *next; } ConstantsList; typedef struct VariableList { MOJOSHADER_uniformType type; int index; int count; ConstantsList *constant; int used; int emit_position; // used in some profiles. struct VariableList *next; } VariableList; typedef struct RegisterList { RegisterType regtype; int regnum; MOJOSHADER_usage usage; unsigned int index; int writemask; int misc; int written; const VariableList *array; struct RegisterList *next; } RegisterList; typedef struct { const uint32 *token; // this is the unmolested token in the stream. int regnum; int swizzle; // xyzw (all four, not split out). int swizzle_x; int swizzle_y; int swizzle_z; int swizzle_w; SourceMod src_mod; RegisterType regtype; int relative; RegisterType relative_regtype; int relative_regnum; int relative_component; const VariableList *relative_array; } SourceArgInfo; struct Profile; // predeclare. typedef struct CtabData { int have_ctab; int symbol_count; MOJOSHADER_symbol *symbols; } CtabData; // Context...this is state that changes as we parse through a shader... typedef struct Context { int isfail; int out_of_memory; MOJOSHADER_malloc malloc; MOJOSHADER_free free; void *malloc_data; int current_position; const uint32 *orig_tokens; const uint32 *tokens; uint32 tokencount; int know_shader_size; const MOJOSHADER_swizzle *swizzles; unsigned int swizzles_count; const MOJOSHADER_samplerMap *samplermap; unsigned int samplermap_count; Buffer *output; Buffer *preflight; Buffer *globals; Buffer *inputs; Buffer *outputs; Buffer *helpers; Buffer *subroutines; Buffer *mainline_intro; Buffer *mainline_arguments; Buffer *mainline_top; Buffer *mainline; Buffer *postflight; Buffer *ignore; Buffer *output_stack[3]; int indent_stack[3]; int output_stack_len; int indent; const char *shader_type_str; const char *endline; const char *mainfn; int endline_len; int profileid; const struct Profile *profile; MOJOSHADER_shaderType shader_type; uint8 major_ver; uint8 minor_ver; DestArgInfo dest_arg; SourceArgInfo source_args[5]; SourceArgInfo predicate_arg; // for predicated instructions. uint32 dwords[4]; uint32 version_token; int instruction_count; uint32 instruction_controls; uint32 previous_opcode; int coissue; int loops; int reps; int max_reps; int cmps; int scratch_registers; int max_scratch_registers; int branch_labels_stack_index; int branch_labels_stack[32]; int assigned_branch_labels; int assigned_vertex_attributes; int last_address_reg_component; RegisterList used_registers; RegisterList defined_registers; ErrorList *errors; int constant_count; ConstantsList *constants; int uniform_count; int uniform_float4_count; int uniform_int4_count; int uniform_bool_count; RegisterList uniforms; int attribute_count; RegisterList attributes; int sampler_count; RegisterList samplers; VariableList *variables; // variables to register mapping. int centroid_allowed; CtabData ctab; int have_relative_input_registers; int have_multi_color_outputs; int determined_constants_arrays; int predicated; int uses_pointsize; int uses_fog; // !!! FIXME: move these into SUPPORT_PROFILE sections. int glsl_generated_lit_helper; int glsl_generated_texlod_setup; int glsl_generated_texm3x3spec_helper; int glsl_need_max_float; int arb1_wrote_position; // !!! FIXME: move these into SUPPORT_PROFILE sections. int have_preshader; int ignores_ctab; int reset_texmpad; int texm3x2pad_dst0; int texm3x2pad_src0; int texm3x3pad_dst0; int texm3x3pad_src0; int texm3x3pad_dst1; int texm3x3pad_src1; MOJOSHADER_preshader *preshader; #if SUPPORT_PROFILE_ARB1_NV int profile_supports_nv2; int profile_supports_nv3; int profile_supports_nv4; #endif #if SUPPORT_PROFILE_GLSL120 int profile_supports_glsl120; #endif #if SUPPORT_PROFILE_GLSLES int profile_supports_glsles; #endif #if SUPPORT_PROFILE_METAL int metal_need_header_common; int metal_need_header_math; int metal_need_header_relational; int metal_need_header_geometric; int metal_need_header_graphics; int metal_need_header_texture; #endif } Context; // Use these macros so we can remove all bits of these profiles from the build. #if SUPPORT_PROFILE_ARB1_NV #define support_nv2(ctx) ((ctx)->profile_supports_nv2) #define support_nv3(ctx) ((ctx)->profile_supports_nv3) #define support_nv4(ctx) ((ctx)->profile_supports_nv4) #else #define support_nv2(ctx) (0) #define support_nv3(ctx) (0) #define support_nv4(ctx) (0) #endif #if SUPPORT_PROFILE_GLSL120 #define support_glsl120(ctx) ((ctx)->profile_supports_glsl120) #else #define support_glsl120(ctx) (0) #endif #if SUPPORT_PROFILE_GLSLES #define support_glsles(ctx) ((ctx)->profile_supports_glsles) #else #define support_glsles(ctx) (0) #endif // Profile entry points... // one emit function for each opcode in each profile. typedef void (*emit_function)(Context *ctx); // one emit function for starting output in each profile. typedef void (*emit_start)(Context *ctx, const char *profilestr); // one emit function for ending output in each profile. typedef void (*emit_end)(Context *ctx); // one emit function for phase opcode output in each profile. typedef void (*emit_phase)(Context *ctx); // one emit function for finalizing output in each profile. typedef void (*emit_finalize)(Context *ctx); // one emit function for global definitions in each profile. typedef void (*emit_global)(Context *ctx, RegisterType regtype, int regnum); // one emit function for relative uniform arrays in each profile. typedef void (*emit_array)(Context *ctx, VariableList *var); // one emit function for relative constants arrays in each profile. typedef void (*emit_const_array)(Context *ctx, const struct ConstantsList *constslist, int base, int size); // one emit function for uniforms in each profile. typedef void (*emit_uniform)(Context *ctx, RegisterType regtype, int regnum, const VariableList *var); // one emit function for samplers in each profile. typedef void (*emit_sampler)(Context *ctx, int stage, TextureType ttype, int texbem); // one emit function for attributes in each profile. typedef void (*emit_attribute)(Context *ctx, RegisterType regtype, int regnum, MOJOSHADER_usage usage, int index, int wmask, int flags); // one args function for each possible sequence of opcode arguments. typedef int (*args_function)(Context *ctx); // one state function for each opcode where we have state machine updates. typedef void (*state_function)(Context *ctx); // one function for varnames in each profile. typedef const char *(*varname_function)(Context *c, RegisterType t, int num); // one function for const var array in each profile. typedef const char *(*const_array_varname_function)(Context *c, int base, int size); typedef struct Profile { const char *name; emit_start start_emitter; emit_end end_emitter; emit_phase phase_emitter; emit_global global_emitter; emit_array array_emitter; emit_const_array const_array_emitter; emit_uniform uniform_emitter; emit_sampler sampler_emitter; emit_attribute attribute_emitter; emit_finalize finalize_emitter; varname_function get_varname; const_array_varname_function get_const_array_varname; } Profile; // Common utilities... void out_of_memory(Context *ctx); void *Malloc(Context *ctx, const size_t len); char *StrDup(Context *ctx, const char *str); void Free(Context *ctx, void *ptr); void * MOJOSHADERCALL MallocBridge(int bytes, void *data); void MOJOSHADERCALL FreeBridge(void *ptr, void *data); int set_output(Context *ctx, Buffer **section); void push_output(Context *ctx, Buffer **section); void pop_output(Context *ctx); uint32 ver_ui32(const uint8 major, const uint8 minor); int shader_version_supported(const uint8 maj, const uint8 min); int shader_version_atleast(const Context *ctx, const uint8 maj, const uint8 min); int shader_version_exactly(const Context *ctx, const uint8 maj, const uint8 min); int shader_is_pixel(const Context *ctx); int shader_is_vertex(const Context *ctx); int isfail(const Context *ctx); void failf(Context *ctx, const char *fmt, ...); void fail(Context *ctx, const char *reason); void output_line(Context *ctx, const char *fmt, ...); void output_blank_line(Context *ctx); void floatstr(Context *ctx, char *buf, size_t bufsize, float f, int leavedecimal); RegisterList *reglist_insert(Context *ctx, RegisterList *prev, const RegisterType regtype, const int regnum); RegisterList *reglist_find(const RegisterList *prev, const RegisterType rtype, const int regnum); RegisterList *set_used_register(Context *ctx, const RegisterType regtype, const int regnum, const int written); void set_defined_register(Context *ctx, const RegisterType rtype, const int regnum); int writemask_xyzw(const int writemask); int writemask_xyz(const int writemask); int writemask_xy(const int writemask); int writemask_x(const int writemask); int writemask_y(const int writemask); int replicate_swizzle(const int swizzle); int no_swizzle(const int swizzle); int vecsize_from_writemask(const int m); void set_dstarg_writemask(DestArgInfo *dst, const int mask); int isscalar(Context *ctx, const MOJOSHADER_shaderType shader_type, const RegisterType rtype, const int rnum); static const char swizzle_channels[] = { 'x', 'y', 'z', 'w' }; const char *get_D3D_register_string(Context *ctx, RegisterType regtype, int regnum, char *regnum_str, size_t regnum_size); // !!! FIXME: These should stay in the mojoshader_profile_d3d file // !!! FIXME: but ARB1 relies on them, so we have to move them here. // !!! FIXME: If/when we kill off ARB1, we can move these back. const char *get_D3D_varname_in_buf(Context *ctx, RegisterType rt, int regnum, char *buf, const size_t len); const char *get_D3D_varname(Context *ctx, RegisterType rt, int regnum); #endif