/********************************************************** * Copyright 2008-2009 VMware, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * **********************************************************/ #ifndef SVGA_TGSI_EMIT_H #define SVGA_TGSI_EMIT_H #include "tgsi/tgsi_scan.h" #include "svga_hw_reg.h" #include "svga_tgsi.h" #include "svga3d_shaderdefs.h" struct src_register { SVGA3dShaderSrcToken base; SVGA3dShaderSrcToken indirect; }; struct svga_arl_consts { int number; int idx; int swizzle; int arl_num; }; /* Internal functions: */ struct svga_shader_emitter { unsigned size; char *buf; char *ptr; struct svga_compile_key key; struct tgsi_shader_info info; int unit; int imm_start; int nr_hw_float_const; int nr_hw_int_const; int nr_hw_temp; int insn_offset; int internal_temp_count; int internal_imm_count; int internal_color_idx[2]; /* diffuse, specular */ int internal_color_count; boolean emitted_vface; boolean emit_frontface; int internal_frontface_idx; int ps30_input_count; int vs30_output_count; int dynamic_branching_level; boolean in_main_func; boolean created_zero_immediate; int zero_immediate_idx; boolean created_loop_const; int loop_const_idx; unsigned inverted_texcoords; /**< bitmask of which texcoords are flipped */ struct src_register ps_true_texcoord[PIPE_MAX_ATTRIBS]; struct src_register ps_inverted_texcoord[PIPE_MAX_ATTRIBS]; unsigned ps_inverted_texcoord_input[PIPE_MAX_ATTRIBS]; unsigned label[32]; unsigned nr_labels; struct src_register input_map[PIPE_MAX_ATTRIBS]; SVGA3dShaderDestToken output_map[PIPE_MAX_ATTRIBS]; boolean ps_reads_pos; boolean emitted_depth_fog; struct src_register ps_true_pos; struct src_register ps_depth_pos; SVGA3dShaderDestToken ps_temp_pos; /* shared input for depth and fog */ struct src_register ps_depth_fog; struct src_register imm_0055; SVGA3dShaderDestToken temp_pos; SVGA3dShaderDestToken true_pos; SVGA3dShaderDestToken depth_pos; /* shared output for depth and fog */ SVGA3dShaderDestToken vs_depth_fog; SVGA3dShaderDestToken temp_col[PIPE_MAX_COLOR_BUFS]; SVGA3dShaderDestToken true_col[PIPE_MAX_COLOR_BUFS]; SVGA3dShaderDestToken temp_psiz; SVGA3dShaderDestToken true_psiz; struct svga_arl_consts arl_consts[12]; int num_arl_consts; int current_arl; }; boolean svga_shader_emit_dword( struct svga_shader_emitter *emit, unsigned dword ); boolean svga_shader_emit_dwords( struct svga_shader_emitter *emit, const unsigned *dwords, unsigned nr ); boolean svga_shader_emit_opcode( struct svga_shader_emitter *emit, unsigned opcode ); boolean svga_shader_emit_instructions( struct svga_shader_emitter *emit, const struct tgsi_token *tokens ); boolean svga_translate_decl_sm30( struct svga_shader_emitter *emit, const struct tgsi_full_declaration *decl ); static INLINE boolean emit_dst( struct svga_shader_emitter *emit, SVGA3dShaderDestToken dest ) { assert(dest.reserved0); assert(dest.mask); return svga_shader_emit_dword( emit, dest.value ); } static INLINE boolean emit_src( struct svga_shader_emitter *emit, const struct src_register src ) { if (src.base.relAddr) { assert(src.base.reserved0); assert(src.indirect.reserved0); return (svga_shader_emit_dword( emit, src.base.value ) && svga_shader_emit_dword( emit, src.indirect.value )); } else { assert(src.base.reserved0); return svga_shader_emit_dword( emit, src.base.value ); } } static INLINE boolean emit_instruction( struct svga_shader_emitter *emit, SVGA3dShaderInstToken opcode ) { return svga_shader_emit_opcode( emit, opcode.value ); } static INLINE boolean emit_op1( struct svga_shader_emitter *emit, SVGA3dShaderInstToken inst, SVGA3dShaderDestToken dest, struct src_register src0 ) { return (emit_instruction( emit, inst ) && emit_dst( emit, dest ) && emit_src( emit, src0 )); } static INLINE boolean emit_op2( struct svga_shader_emitter *emit, SVGA3dShaderInstToken inst, SVGA3dShaderDestToken dest, struct src_register src0, struct src_register src1 ) { return (emit_instruction( emit, inst ) && emit_dst( emit, dest ) && emit_src( emit, src0 ) && emit_src( emit, src1 )); } static INLINE boolean emit_op3( struct svga_shader_emitter *emit, SVGA3dShaderInstToken inst, SVGA3dShaderDestToken dest, struct src_register src0, struct src_register src1, struct src_register src2 ) { return (emit_instruction( emit, inst ) && emit_dst( emit, dest ) && emit_src( emit, src0 ) && emit_src( emit, src1 ) && emit_src( emit, src2 )); } static INLINE boolean emit_op4( struct svga_shader_emitter *emit, SVGA3dShaderInstToken inst, SVGA3dShaderDestToken dest, struct src_register src0, struct src_register src1, struct src_register src2, struct src_register src3) { return (emit_instruction( emit, inst ) && emit_dst( emit, dest ) && emit_src( emit, src0 ) && emit_src( emit, src1 ) && emit_src( emit, src2 ) && emit_src( emit, src3 )); } #define TRANSLATE_SWIZZLE(x,y,z,w) ((x) | ((y) << 2) | ((z) << 4) | ((w) << 6)) #define SWIZZLE_XYZW \ TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_W) #define SWIZZLE_XXXX \ TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_X,TGSI_SWIZZLE_X,TGSI_SWIZZLE_X) #define SWIZZLE_YYYY \ TRANSLATE_SWIZZLE(TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y) #define SWIZZLE_ZZZZ \ TRANSLATE_SWIZZLE(TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z) #define SWIZZLE_WWWW \ TRANSLATE_SWIZZLE(TGSI_SWIZZLE_W,TGSI_SWIZZLE_W,TGSI_SWIZZLE_W,TGSI_SWIZZLE_W) static INLINE SVGA3dShaderInstToken inst_token( unsigned opcode ) { SVGA3dShaderInstToken inst; inst.value = 0; inst.op = opcode; return inst; } /** * Create an instance of a SVGA3dShaderDestToken. * Note that this function is used to create tokens for output registers, * temp registers AND constants (see emit_def_const()). */ static INLINE SVGA3dShaderDestToken dst_register( unsigned file, int number ) { SVGA3dShaderDestToken dest; /* check values against bitfield sizes */ assert(number < (1 << 11)); assert(file <= SVGA3DREG_PREDICATE); dest.value = 0; dest.num = number; dest.type_upper = file >> 3; dest.relAddr = 0; dest.reserved1 = 0; dest.mask = 0xf; dest.dstMod = 0; dest.shfScale = 0; dest.type_lower = file & 0x7; dest.reserved0 = 1; /* is_reg */ return dest; } static INLINE SVGA3dShaderDestToken writemask( SVGA3dShaderDestToken dest, unsigned mask ) { assert(dest.mask & mask); dest.mask &= mask; return dest; } static INLINE SVGA3dShaderSrcToken src_token( unsigned file, int number ) { SVGA3dShaderSrcToken src; /* check values against bitfield sizes */ assert(number < (1 << 11)); assert(file <= SVGA3DREG_PREDICATE); src.value = 0; src.num = number; src.type_upper = file >> 3; src.relAddr = 0; src.reserved1 = 0; src.swizzle = SWIZZLE_XYZW; src.srcMod = 0; src.type_lower = file & 0x7; src.reserved0 = 1; /* is_reg */ return src; } static INLINE struct src_register absolute( struct src_register src ) { src.base.srcMod = SVGA3DSRCMOD_ABS; return src; } static INLINE struct src_register negate( struct src_register src ) { switch (src.base.srcMod) { case SVGA3DSRCMOD_ABS: src.base.srcMod = SVGA3DSRCMOD_ABSNEG; break; case SVGA3DSRCMOD_ABSNEG: src.base.srcMod = SVGA3DSRCMOD_ABS; break; case SVGA3DSRCMOD_NEG: src.base.srcMod = SVGA3DSRCMOD_NONE; break; case SVGA3DSRCMOD_NONE: src.base.srcMod = SVGA3DSRCMOD_NEG; break; } return src; } static INLINE struct src_register src_register( unsigned file, int number ) { struct src_register src; src.base = src_token( file, number ); src.indirect.value = 0; return src; } static INLINE SVGA3dShaderDestToken dst( struct src_register src ) { return dst_register( SVGA3dShaderGetRegType( src.base.value ), src.base.num ); } static INLINE struct src_register src( SVGA3dShaderDestToken dst ) { return src_register( SVGA3dShaderGetRegType( dst.value ), dst.num ); } static INLINE ubyte svga_tgsi_sampler_type( struct svga_shader_emitter *emit, int idx ) { switch (emit->key.fkey.tex[idx].texture_target) { case PIPE_TEXTURE_1D: return SVGA3DSAMP_2D; case PIPE_TEXTURE_2D: case PIPE_TEXTURE_RECT: return SVGA3DSAMP_2D; case PIPE_TEXTURE_3D: return SVGA3DSAMP_VOLUME; case PIPE_TEXTURE_CUBE: return SVGA3DSAMP_CUBE; } return SVGA3DSAMP_UNKNOWN; } #endif