| /************************************************************************** |
| * |
| * Copyright 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, sub license, 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 (including the |
| * next paragraph) 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 NON-INFRINGEMENT. |
| * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS 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 TGSI_UREG_H |
| #define TGSI_UREG_H |
| |
| #include "pipe/p_defines.h" |
| #include "pipe/p_format.h" |
| #include "pipe/p_compiler.h" |
| #include "pipe/p_shader_tokens.h" |
| #include "util/u_debug.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| struct pipe_screen; |
| struct ureg_program; |
| struct pipe_stream_output_info; |
| struct shader_info; |
| |
| /* Almost a tgsi_src_register, but we need to pull in the Absolute |
| * flag from the _ext token. Indirect flag always implies ADDR[0]. |
| */ |
| struct ureg_src |
| { |
| unsigned File : 4; /* TGSI_FILE_ */ |
| unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */ |
| unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */ |
| unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */ |
| unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */ |
| unsigned Indirect : 1; /* BOOL */ |
| unsigned DimIndirect : 1; /* BOOL */ |
| unsigned Dimension : 1; /* BOOL */ |
| unsigned Absolute : 1; /* BOOL */ |
| unsigned Negate : 1; /* BOOL */ |
| unsigned IndirectFile : 4; /* TGSI_FILE_ */ |
| unsigned IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ |
| unsigned DimIndFile : 4; /* TGSI_FILE_ */ |
| unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */ |
| int Index : 16; /* SINT */ |
| int IndirectIndex : 16; /* SINT */ |
| int DimensionIndex : 16; /* SINT */ |
| int DimIndIndex : 16; /* SINT */ |
| unsigned ArrayID : 10; /* UINT */ |
| }; |
| |
| /* Very similar to a tgsi_dst_register, removing unsupported fields |
| * and adding a Saturate flag. It's easier to push saturate into the |
| * destination register than to try and create a _SAT variant of each |
| * instruction function. |
| */ |
| struct ureg_dst |
| { |
| unsigned File : 4; /* TGSI_FILE_ */ |
| unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */ |
| unsigned Indirect : 1; /* BOOL */ |
| unsigned DimIndirect : 1; /* BOOL */ |
| unsigned Dimension : 1; /* BOOL */ |
| unsigned Saturate : 1; /* BOOL */ |
| unsigned Invariant : 1; /* BOOL */ |
| int Index : 16; /* SINT */ |
| int IndirectIndex : 16; /* SINT */ |
| unsigned IndirectFile : 4; /* TGSI_FILE_ */ |
| int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ |
| unsigned DimIndFile : 4; /* TGSI_FILE_ */ |
| unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */ |
| int DimensionIndex : 16; /* SINT */ |
| int DimIndIndex : 16; /* SINT */ |
| unsigned ArrayID : 10; /* UINT */ |
| }; |
| |
| struct pipe_context; |
| |
| struct ureg_program * |
| ureg_create(enum pipe_shader_type processor); |
| |
| struct ureg_program * |
| ureg_create_with_screen(enum pipe_shader_type processor, |
| struct pipe_screen *screen); |
| |
| const struct tgsi_token * |
| ureg_finalize( struct ureg_program * ); |
| |
| /* Create and return a shader: |
| */ |
| void * |
| ureg_create_shader( struct ureg_program *, |
| struct pipe_context *pipe, |
| const struct pipe_stream_output_info *so ); |
| |
| void |
| ureg_set_next_shader_processor(struct ureg_program *ureg, unsigned processor); |
| |
| /* Alternately, return the built token stream and hand ownership of |
| * that memory to the caller: |
| */ |
| const struct tgsi_token * |
| ureg_get_tokens( struct ureg_program *ureg, |
| unsigned *nr_tokens ); |
| |
| /* |
| * Returns the number of currently declared outputs. |
| */ |
| unsigned |
| ureg_get_nr_outputs( const struct ureg_program *ureg ); |
| |
| |
| /* Free the tokens created by ureg_get_tokens() */ |
| void ureg_free_tokens( const struct tgsi_token *tokens ); |
| |
| |
| void |
| ureg_destroy( struct ureg_program * ); |
| |
| void ureg_set_precise( struct ureg_program *ureg, bool precise ); |
| |
| /*********************************************************************** |
| * Convenience routine: |
| */ |
| static inline void * |
| ureg_create_shader_with_so_and_destroy( struct ureg_program *p, |
| struct pipe_context *pipe, |
| const struct pipe_stream_output_info *so ) |
| { |
| void *result = ureg_create_shader( p, pipe, so ); |
| ureg_destroy( p ); |
| return result; |
| } |
| |
| static inline void * |
| ureg_create_shader_and_destroy( struct ureg_program *p, |
| struct pipe_context *pipe ) |
| { |
| return ureg_create_shader_with_so_and_destroy(p, pipe, NULL); |
| } |
| |
| |
| /*********************************************************************** |
| * Build shader properties: |
| */ |
| |
| void |
| ureg_property(struct ureg_program *ureg, unsigned name, unsigned value); |
| |
| |
| /*********************************************************************** |
| * Build shader declarations: |
| */ |
| |
| struct ureg_src |
| ureg_DECL_fs_input_centroid_layout(struct ureg_program *, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index, |
| enum tgsi_interpolate_mode interp_mode, |
| enum tgsi_interpolate_loc interp_location, |
| unsigned index, |
| unsigned usage_mask, |
| unsigned array_id, |
| unsigned array_size); |
| |
| struct ureg_src |
| ureg_DECL_fs_input_centroid(struct ureg_program *, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index, |
| enum tgsi_interpolate_mode interp_mode, |
| enum tgsi_interpolate_loc interp_location, |
| unsigned array_id, |
| unsigned array_size); |
| |
| static inline struct ureg_src |
| ureg_DECL_fs_input(struct ureg_program *ureg, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index, |
| enum tgsi_interpolate_mode interp_mode) |
| { |
| return ureg_DECL_fs_input_centroid(ureg, |
| semantic_name, |
| semantic_index, |
| interp_mode, |
| TGSI_INTERPOLATE_LOC_CENTER, 0, 1); |
| } |
| |
| struct ureg_src |
| ureg_DECL_vs_input( struct ureg_program *, |
| unsigned index ); |
| |
| struct ureg_src |
| ureg_DECL_input_layout(struct ureg_program *, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index, |
| unsigned index, |
| unsigned usage_mask, |
| unsigned array_id, |
| unsigned array_size); |
| |
| struct ureg_src |
| ureg_DECL_input(struct ureg_program *, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index, |
| unsigned array_id, |
| unsigned array_size); |
| |
| struct ureg_src |
| ureg_DECL_system_value(struct ureg_program *, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index); |
| |
| struct ureg_dst |
| ureg_DECL_output_layout(struct ureg_program *, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index, |
| unsigned streams, |
| unsigned index, |
| unsigned usage_mask, |
| unsigned array_id, |
| unsigned array_size, |
| boolean invariant); |
| |
| struct ureg_dst |
| ureg_DECL_output_masked(struct ureg_program *, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index, |
| unsigned usage_mask, |
| unsigned array_id, |
| unsigned array_size); |
| |
| struct ureg_dst |
| ureg_DECL_output(struct ureg_program *, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index); |
| |
| struct ureg_dst |
| ureg_DECL_output_array(struct ureg_program *ureg, |
| enum tgsi_semantic semantic_name, |
| unsigned semantic_index, |
| unsigned array_id, |
| unsigned array_size); |
| |
| struct ureg_src |
| ureg_DECL_immediate( struct ureg_program *, |
| const float *v, |
| unsigned nr ); |
| |
| struct ureg_src |
| ureg_DECL_immediate_f64( struct ureg_program *, |
| const double *v, |
| unsigned nr ); |
| |
| struct ureg_src |
| ureg_DECL_immediate_uint( struct ureg_program *, |
| const unsigned *v, |
| unsigned nr ); |
| |
| struct ureg_src |
| ureg_DECL_immediate_block_uint( struct ureg_program *, |
| const unsigned *v, |
| unsigned nr ); |
| |
| struct ureg_src |
| ureg_DECL_immediate_int( struct ureg_program *, |
| const int *v, |
| unsigned nr ); |
| |
| struct ureg_src |
| ureg_DECL_immediate_uint64( struct ureg_program *, |
| const uint64_t *v, |
| unsigned nr ); |
| |
| struct ureg_src |
| ureg_DECL_immediate_int64( struct ureg_program *, |
| const int64_t *v, |
| unsigned nr ); |
| |
| void |
| ureg_DECL_constant2D(struct ureg_program *ureg, |
| unsigned first, |
| unsigned last, |
| unsigned index2D); |
| |
| struct ureg_src |
| ureg_DECL_constant( struct ureg_program *, |
| unsigned index ); |
| |
| void |
| ureg_DECL_hw_atomic(struct ureg_program *ureg, |
| unsigned first, |
| unsigned last, |
| unsigned buffer_id, |
| unsigned array_id); |
| |
| struct ureg_dst |
| ureg_DECL_temporary( struct ureg_program * ); |
| |
| /** |
| * Emit a temporary with the LOCAL declaration flag set. For use when |
| * the register value is not required to be preserved across |
| * subroutine boundaries. |
| */ |
| struct ureg_dst |
| ureg_DECL_local_temporary( struct ureg_program * ); |
| |
| /** |
| * Declare "size" continuous temporary registers. |
| */ |
| struct ureg_dst |
| ureg_DECL_array_temporary( struct ureg_program *, |
| unsigned size, |
| boolean local ); |
| |
| void |
| ureg_release_temporary( struct ureg_program *ureg, |
| struct ureg_dst tmp ); |
| |
| struct ureg_dst |
| ureg_DECL_address( struct ureg_program * ); |
| |
| /* Supply an index to the sampler declaration as this is the hook to |
| * the external pipe_sampler state. Users of this function probably |
| * don't want just any sampler, but a specific one which they've set |
| * up state for in the context. |
| */ |
| struct ureg_src |
| ureg_DECL_sampler( struct ureg_program *, |
| unsigned index ); |
| |
| struct ureg_src |
| ureg_DECL_sampler_view(struct ureg_program *, |
| unsigned index, |
| enum tgsi_texture_type target, |
| enum tgsi_return_type return_type_x, |
| enum tgsi_return_type return_type_y, |
| enum tgsi_return_type return_type_z, |
| enum tgsi_return_type return_type_w ); |
| |
| struct ureg_src |
| ureg_DECL_image(struct ureg_program *ureg, |
| unsigned index, |
| enum tgsi_texture_type target, |
| enum pipe_format format, |
| boolean wr, |
| boolean raw); |
| |
| struct ureg_src |
| ureg_DECL_buffer(struct ureg_program *ureg, unsigned nr, bool atomic); |
| |
| struct ureg_src |
| ureg_DECL_memory(struct ureg_program *ureg, unsigned memory_type); |
| |
| static inline struct ureg_src |
| ureg_imm4f( struct ureg_program *ureg, |
| float a, float b, |
| float c, float d) |
| { |
| float v[4]; |
| v[0] = a; |
| v[1] = b; |
| v[2] = c; |
| v[3] = d; |
| return ureg_DECL_immediate( ureg, v, 4 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm3f( struct ureg_program *ureg, |
| float a, float b, |
| float c) |
| { |
| float v[3]; |
| v[0] = a; |
| v[1] = b; |
| v[2] = c; |
| return ureg_DECL_immediate( ureg, v, 3 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm2f( struct ureg_program *ureg, |
| float a, float b) |
| { |
| float v[2]; |
| v[0] = a; |
| v[1] = b; |
| return ureg_DECL_immediate( ureg, v, 2 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm1f( struct ureg_program *ureg, |
| float a) |
| { |
| float v[1]; |
| v[0] = a; |
| return ureg_DECL_immediate( ureg, v, 1 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm4u( struct ureg_program *ureg, |
| unsigned a, unsigned b, |
| unsigned c, unsigned d) |
| { |
| unsigned v[4]; |
| v[0] = a; |
| v[1] = b; |
| v[2] = c; |
| v[3] = d; |
| return ureg_DECL_immediate_uint( ureg, v, 4 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm3u( struct ureg_program *ureg, |
| unsigned a, unsigned b, |
| unsigned c) |
| { |
| unsigned v[3]; |
| v[0] = a; |
| v[1] = b; |
| v[2] = c; |
| return ureg_DECL_immediate_uint( ureg, v, 3 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm2u( struct ureg_program *ureg, |
| unsigned a, unsigned b) |
| { |
| unsigned v[2]; |
| v[0] = a; |
| v[1] = b; |
| return ureg_DECL_immediate_uint( ureg, v, 2 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm1u( struct ureg_program *ureg, |
| unsigned a) |
| { |
| return ureg_DECL_immediate_uint( ureg, &a, 1 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm4i( struct ureg_program *ureg, |
| int a, int b, |
| int c, int d) |
| { |
| int v[4]; |
| v[0] = a; |
| v[1] = b; |
| v[2] = c; |
| v[3] = d; |
| return ureg_DECL_immediate_int( ureg, v, 4 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm3i( struct ureg_program *ureg, |
| int a, int b, |
| int c) |
| { |
| int v[3]; |
| v[0] = a; |
| v[1] = b; |
| v[2] = c; |
| return ureg_DECL_immediate_int( ureg, v, 3 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm2i( struct ureg_program *ureg, |
| int a, int b) |
| { |
| int v[2]; |
| v[0] = a; |
| v[1] = b; |
| return ureg_DECL_immediate_int( ureg, v, 2 ); |
| } |
| |
| static inline struct ureg_src |
| ureg_imm1i( struct ureg_program *ureg, |
| int a) |
| { |
| return ureg_DECL_immediate_int( ureg, &a, 1 ); |
| } |
| |
| /* Where the destination register has a valid file, but an empty |
| * writemask. |
| */ |
| static inline boolean |
| ureg_dst_is_empty( struct ureg_dst dst ) |
| { |
| return dst.File != TGSI_FILE_NULL && |
| dst.WriteMask == 0; |
| } |
| |
| /*********************************************************************** |
| * Functions for patching up labels |
| */ |
| |
| |
| /* Will return a number which can be used in a label to point to the |
| * next instruction to be emitted. |
| */ |
| unsigned |
| ureg_get_instruction_number( struct ureg_program *ureg ); |
| |
| |
| /* Patch a given label (expressed as a token number) to point to a |
| * given instruction (expressed as an instruction number). |
| * |
| * Labels are obtained from instruction emitters, eg ureg_CAL(). |
| * Instruction numbers are obtained from ureg_get_instruction_number(), |
| * above. |
| */ |
| void |
| ureg_fixup_label(struct ureg_program *ureg, |
| unsigned label_token, |
| unsigned instruction_number ); |
| |
| |
| /* Generic instruction emitter. Use if you need to pass the opcode as |
| * a parameter, rather than using the emit_OP() variants below. |
| */ |
| void |
| ureg_insn(struct ureg_program *ureg, |
| enum tgsi_opcode opcode, |
| const struct ureg_dst *dst, |
| unsigned nr_dst, |
| const struct ureg_src *src, |
| unsigned nr_src, |
| unsigned precise ); |
| |
| |
| void |
| ureg_tex_insn(struct ureg_program *ureg, |
| enum tgsi_opcode opcode, |
| const struct ureg_dst *dst, |
| unsigned nr_dst, |
| enum tgsi_texture_type target, |
| enum tgsi_return_type return_type, |
| const struct tgsi_texture_offset *texoffsets, |
| unsigned nr_offset, |
| const struct ureg_src *src, |
| unsigned nr_src ); |
| |
| |
| void |
| ureg_memory_insn(struct ureg_program *ureg, |
| enum tgsi_opcode opcode, |
| const struct ureg_dst *dst, |
| unsigned nr_dst, |
| const struct ureg_src *src, |
| unsigned nr_src, |
| unsigned qualifier, |
| enum tgsi_texture_type texture, |
| enum pipe_format format); |
| |
| /*********************************************************************** |
| * Internal instruction helpers, don't call these directly: |
| */ |
| |
| struct ureg_emit_insn_result { |
| unsigned insn_token; /*< Used to fixup insn size. */ |
| unsigned extended_token; /*< Used to set the Extended bit, usually the same as insn_token. */ |
| }; |
| |
| struct ureg_emit_insn_result |
| ureg_emit_insn(struct ureg_program *ureg, |
| enum tgsi_opcode opcode, |
| boolean saturate, |
| unsigned precise, |
| unsigned num_dst, |
| unsigned num_src); |
| |
| void |
| ureg_emit_label(struct ureg_program *ureg, |
| unsigned insn_token, |
| unsigned *label_token ); |
| |
| void |
| ureg_emit_texture(struct ureg_program *ureg, |
| unsigned insn_token, |
| enum tgsi_texture_type target, |
| enum tgsi_return_type return_type, |
| unsigned num_offsets); |
| |
| void |
| ureg_emit_texture_offset(struct ureg_program *ureg, |
| const struct tgsi_texture_offset *offset); |
| |
| void |
| ureg_emit_memory(struct ureg_program *ureg, |
| unsigned insn_token, |
| unsigned qualifier, |
| enum tgsi_texture_type texture, |
| enum pipe_format format); |
| |
| void |
| ureg_emit_dst( struct ureg_program *ureg, |
| struct ureg_dst dst ); |
| |
| void |
| ureg_emit_src( struct ureg_program *ureg, |
| struct ureg_src src ); |
| |
| void |
| ureg_fixup_insn_size(struct ureg_program *ureg, |
| unsigned insn ); |
| |
| |
| #define OP00( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| FALSE, \ |
| 0, \ |
| 0, \ |
| 0); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP01( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_src src ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| FALSE, \ |
| 0, \ |
| 0, \ |
| 1); \ |
| ureg_emit_src( ureg, src ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP00_LBL( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| unsigned *label_token ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| FALSE, \ |
| 0, \ |
| 0, \ |
| 0); \ |
| ureg_emit_label( ureg, insn.extended_token, label_token ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP01_LBL( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_src src, \ |
| unsigned *label_token ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| FALSE, \ |
| 0, \ |
| 0, \ |
| 1); \ |
| ureg_emit_label( ureg, insn.extended_token, label_token ); \ |
| ureg_emit_src( ureg, src ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP10( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_dst dst ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| if (ureg_dst_is_empty(dst)) \ |
| return; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| dst.Saturate, \ |
| 0, \ |
| 1, \ |
| 0); \ |
| ureg_emit_dst( ureg, dst ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| |
| #define OP11( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_dst dst, \ |
| struct ureg_src src ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| if (ureg_dst_is_empty(dst)) \ |
| return; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| dst.Saturate, \ |
| 0, \ |
| 1, \ |
| 1); \ |
| ureg_emit_dst( ureg, dst ); \ |
| ureg_emit_src( ureg, src ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP12( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_dst dst, \ |
| struct ureg_src src0, \ |
| struct ureg_src src1 ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| if (ureg_dst_is_empty(dst)) \ |
| return; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| dst.Saturate, \ |
| 0, \ |
| 1, \ |
| 2); \ |
| ureg_emit_dst( ureg, dst ); \ |
| ureg_emit_src( ureg, src0 ); \ |
| ureg_emit_src( ureg, src1 ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP12_TEX( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_dst dst, \ |
| enum tgsi_texture_type target, \ |
| struct ureg_src src0, \ |
| struct ureg_src src1 ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| enum tgsi_return_type return_type = TGSI_RETURN_TYPE_UNKNOWN; \ |
| struct ureg_emit_insn_result insn; \ |
| if (ureg_dst_is_empty(dst)) \ |
| return; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| dst.Saturate, \ |
| 0, \ |
| 1, \ |
| 2); \ |
| ureg_emit_texture( ureg, insn.extended_token, target, \ |
| return_type, 0 ); \ |
| ureg_emit_dst( ureg, dst ); \ |
| ureg_emit_src( ureg, src0 ); \ |
| ureg_emit_src( ureg, src1 ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP13( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_dst dst, \ |
| struct ureg_src src0, \ |
| struct ureg_src src1, \ |
| struct ureg_src src2 ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| if (ureg_dst_is_empty(dst)) \ |
| return; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| dst.Saturate, \ |
| 0, \ |
| 1, \ |
| 3); \ |
| ureg_emit_dst( ureg, dst ); \ |
| ureg_emit_src( ureg, src0 ); \ |
| ureg_emit_src( ureg, src1 ); \ |
| ureg_emit_src( ureg, src2 ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP14( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_dst dst, \ |
| struct ureg_src src0, \ |
| struct ureg_src src1, \ |
| struct ureg_src src2, \ |
| struct ureg_src src3 ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| struct ureg_emit_insn_result insn; \ |
| if (ureg_dst_is_empty(dst)) \ |
| return; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| dst.Saturate, \ |
| 0, \ |
| 1, \ |
| 4); \ |
| ureg_emit_dst( ureg, dst ); \ |
| ureg_emit_src( ureg, src0 ); \ |
| ureg_emit_src( ureg, src1 ); \ |
| ureg_emit_src( ureg, src2 ); \ |
| ureg_emit_src( ureg, src3 ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| #define OP14_TEX( op ) \ |
| static inline void ureg_##op( struct ureg_program *ureg, \ |
| struct ureg_dst dst, \ |
| enum tgsi_texture_type target, \ |
| struct ureg_src src0, \ |
| struct ureg_src src1, \ |
| struct ureg_src src2, \ |
| struct ureg_src src3 ) \ |
| { \ |
| enum tgsi_opcode opcode = TGSI_OPCODE_##op; \ |
| enum tgsi_return_type return_type = TGSI_RETURN_TYPE_UNKNOWN; \ |
| struct ureg_emit_insn_result insn; \ |
| if (ureg_dst_is_empty(dst)) \ |
| return; \ |
| insn = ureg_emit_insn(ureg, \ |
| opcode, \ |
| dst.Saturate, \ |
| 0, \ |
| 1, \ |
| 4); \ |
| ureg_emit_texture( ureg, insn.extended_token, target, \ |
| return_type, 0 ); \ |
| ureg_emit_dst( ureg, dst ); \ |
| ureg_emit_src( ureg, src0 ); \ |
| ureg_emit_src( ureg, src1 ); \ |
| ureg_emit_src( ureg, src2 ); \ |
| ureg_emit_src( ureg, src3 ); \ |
| ureg_fixup_insn_size( ureg, insn.insn_token ); \ |
| } |
| |
| /* Use a template include to generate a correctly-typed ureg_OP() |
| * function for each TGSI opcode: |
| */ |
| #include "tgsi_opcode_tmp.h" |
| |
| |
| /*********************************************************************** |
| * Inline helpers for manipulating register structs: |
| */ |
| static inline struct ureg_src |
| ureg_negate( struct ureg_src reg ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Negate ^= 1; |
| return reg; |
| } |
| |
| static inline struct ureg_src |
| ureg_abs( struct ureg_src reg ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Absolute = 1; |
| reg.Negate = 0; |
| return reg; |
| } |
| |
| static inline struct ureg_src |
| ureg_swizzle( struct ureg_src reg, |
| int x, int y, int z, int w ) |
| { |
| unsigned swz = ( (reg.SwizzleX << 0) | |
| (reg.SwizzleY << 2) | |
| (reg.SwizzleZ << 4) | |
| (reg.SwizzleW << 6)); |
| |
| assert(reg.File != TGSI_FILE_NULL); |
| assert(x < 4); |
| assert(y < 4); |
| assert(z < 4); |
| assert(w < 4); |
| |
| reg.SwizzleX = (swz >> (x*2)) & 0x3; |
| reg.SwizzleY = (swz >> (y*2)) & 0x3; |
| reg.SwizzleZ = (swz >> (z*2)) & 0x3; |
| reg.SwizzleW = (swz >> (w*2)) & 0x3; |
| return reg; |
| } |
| |
| static inline struct ureg_src |
| ureg_scalar( struct ureg_src reg, int x ) |
| { |
| return ureg_swizzle(reg, x, x, x, x); |
| } |
| |
| static inline struct ureg_dst |
| ureg_writemask( struct ureg_dst reg, |
| unsigned writemask ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.WriteMask &= writemask; |
| return reg; |
| } |
| |
| static inline struct ureg_dst |
| ureg_saturate( struct ureg_dst reg ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Saturate = 1; |
| return reg; |
| } |
| |
| static inline struct ureg_dst |
| ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Indirect = 1; |
| reg.IndirectFile = addr.File; |
| reg.IndirectIndex = addr.Index; |
| reg.IndirectSwizzle = addr.SwizzleX; |
| return reg; |
| } |
| |
| static inline struct ureg_src |
| ureg_src_indirect( struct ureg_src reg, struct ureg_src addr ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Indirect = 1; |
| reg.IndirectFile = addr.File; |
| reg.IndirectIndex = addr.Index; |
| reg.IndirectSwizzle = addr.SwizzleX; |
| return reg; |
| } |
| |
| static inline struct ureg_dst |
| ureg_dst_dimension( struct ureg_dst reg, int index ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Dimension = 1; |
| reg.DimIndirect = 0; |
| reg.DimensionIndex = index; |
| return reg; |
| } |
| |
| static inline struct ureg_src |
| ureg_src_dimension( struct ureg_src reg, int index ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Dimension = 1; |
| reg.DimIndirect = 0; |
| reg.DimensionIndex = index; |
| return reg; |
| } |
| |
| static inline struct ureg_dst |
| ureg_dst_dimension_indirect( struct ureg_dst reg, struct ureg_src addr, |
| int index ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Dimension = 1; |
| reg.DimIndirect = 1; |
| reg.DimensionIndex = index; |
| reg.DimIndFile = addr.File; |
| reg.DimIndIndex = addr.Index; |
| reg.DimIndSwizzle = addr.SwizzleX; |
| return reg; |
| } |
| |
| static inline struct ureg_src |
| ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr, |
| int index ) |
| { |
| assert(reg.File != TGSI_FILE_NULL); |
| reg.Dimension = 1; |
| reg.DimIndirect = 1; |
| reg.DimensionIndex = index; |
| reg.DimIndFile = addr.File; |
| reg.DimIndIndex = addr.Index; |
| reg.DimIndSwizzle = addr.SwizzleX; |
| return reg; |
| } |
| |
| static inline struct ureg_src |
| ureg_src_array_offset(struct ureg_src reg, int offset) |
| { |
| reg.Index += offset; |
| return reg; |
| } |
| |
| static inline struct ureg_dst |
| ureg_dst_array_offset( struct ureg_dst reg, int offset ) |
| { |
| reg.Index += offset; |
| return reg; |
| } |
| |
| static inline struct ureg_dst |
| ureg_dst_array_register(unsigned file, |
| unsigned index, |
| unsigned array_id) |
| { |
| struct ureg_dst dst; |
| |
| dst.File = file; |
| dst.WriteMask = TGSI_WRITEMASK_XYZW; |
| dst.Indirect = 0; |
| dst.IndirectFile = TGSI_FILE_NULL; |
| dst.IndirectIndex = 0; |
| dst.IndirectSwizzle = 0; |
| dst.Saturate = 0; |
| dst.Index = index; |
| dst.Dimension = 0; |
| dst.DimensionIndex = 0; |
| dst.DimIndirect = 0; |
| dst.DimIndFile = TGSI_FILE_NULL; |
| dst.DimIndIndex = 0; |
| dst.DimIndSwizzle = 0; |
| dst.ArrayID = array_id; |
| dst.Invariant = 0; |
| |
| return dst; |
| } |
| |
| static inline struct ureg_dst |
| ureg_dst_register(unsigned file, |
| unsigned index) |
| { |
| return ureg_dst_array_register(file, index, 0); |
| } |
| |
| static inline struct ureg_dst |
| ureg_dst( struct ureg_src src ) |
| { |
| struct ureg_dst dst; |
| |
| dst.File = src.File; |
| dst.WriteMask = TGSI_WRITEMASK_XYZW; |
| dst.IndirectFile = src.IndirectFile; |
| dst.Indirect = src.Indirect; |
| dst.IndirectIndex = src.IndirectIndex; |
| dst.IndirectSwizzle = src.IndirectSwizzle; |
| dst.Saturate = 0; |
| dst.Index = src.Index; |
| dst.Dimension = src.Dimension; |
| dst.DimensionIndex = src.DimensionIndex; |
| dst.DimIndirect = src.DimIndirect; |
| dst.DimIndFile = src.DimIndFile; |
| dst.DimIndIndex = src.DimIndIndex; |
| dst.DimIndSwizzle = src.DimIndSwizzle; |
| dst.ArrayID = src.ArrayID; |
| dst.Invariant = 0; |
| |
| return dst; |
| } |
| |
| static inline struct ureg_src |
| ureg_src_array_register(unsigned file, |
| unsigned index, |
| unsigned array_id) |
| { |
| struct ureg_src src; |
| |
| src.File = file; |
| src.SwizzleX = TGSI_SWIZZLE_X; |
| src.SwizzleY = TGSI_SWIZZLE_Y; |
| src.SwizzleZ = TGSI_SWIZZLE_Z; |
| src.SwizzleW = TGSI_SWIZZLE_W; |
| src.Indirect = 0; |
| src.IndirectFile = TGSI_FILE_NULL; |
| src.IndirectIndex = 0; |
| src.IndirectSwizzle = 0; |
| src.Absolute = 0; |
| src.Index = index; |
| src.Negate = 0; |
| src.Dimension = 0; |
| src.DimensionIndex = 0; |
| src.DimIndirect = 0; |
| src.DimIndFile = TGSI_FILE_NULL; |
| src.DimIndIndex = 0; |
| src.DimIndSwizzle = 0; |
| src.ArrayID = array_id; |
| |
| return src; |
| } |
| |
| static inline struct ureg_src |
| ureg_src_register(unsigned file, |
| unsigned index) |
| { |
| return ureg_src_array_register(file, index, 0); |
| } |
| |
| static inline struct ureg_src |
| ureg_src( struct ureg_dst dst ) |
| { |
| struct ureg_src src; |
| |
| src.File = dst.File; |
| src.SwizzleX = TGSI_SWIZZLE_X; |
| src.SwizzleY = TGSI_SWIZZLE_Y; |
| src.SwizzleZ = TGSI_SWIZZLE_Z; |
| src.SwizzleW = TGSI_SWIZZLE_W; |
| src.Indirect = dst.Indirect; |
| src.IndirectFile = dst.IndirectFile; |
| src.IndirectIndex = dst.IndirectIndex; |
| src.IndirectSwizzle = dst.IndirectSwizzle; |
| src.Absolute = 0; |
| src.Index = dst.Index; |
| src.Negate = 0; |
| src.Dimension = dst.Dimension; |
| src.DimensionIndex = dst.DimensionIndex; |
| src.DimIndirect = dst.DimIndirect; |
| src.DimIndFile = dst.DimIndFile; |
| src.DimIndIndex = dst.DimIndIndex; |
| src.DimIndSwizzle = dst.DimIndSwizzle; |
| src.ArrayID = dst.ArrayID; |
| |
| return src; |
| } |
| |
| |
| |
| static inline struct ureg_dst |
| ureg_dst_undef( void ) |
| { |
| struct ureg_dst dst; |
| |
| dst.File = TGSI_FILE_NULL; |
| dst.WriteMask = 0; |
| dst.Indirect = 0; |
| dst.IndirectFile = TGSI_FILE_NULL; |
| dst.IndirectIndex = 0; |
| dst.IndirectSwizzle = 0; |
| dst.Saturate = 0; |
| dst.Index = 0; |
| dst.Dimension = 0; |
| dst.DimensionIndex = 0; |
| dst.DimIndirect = 0; |
| dst.DimIndFile = TGSI_FILE_NULL; |
| dst.DimIndIndex = 0; |
| dst.DimIndSwizzle = 0; |
| dst.ArrayID = 0; |
| dst.Invariant = 0; |
| |
| return dst; |
| } |
| |
| static inline struct ureg_src |
| ureg_src_undef( void ) |
| { |
| struct ureg_src src; |
| |
| src.File = TGSI_FILE_NULL; |
| src.SwizzleX = 0; |
| src.SwizzleY = 0; |
| src.SwizzleZ = 0; |
| src.SwizzleW = 0; |
| src.Indirect = 0; |
| src.IndirectFile = TGSI_FILE_NULL; |
| src.IndirectIndex = 0; |
| src.IndirectSwizzle = 0; |
| src.Absolute = 0; |
| src.Index = 0; |
| src.Negate = 0; |
| src.Dimension = 0; |
| src.DimensionIndex = 0; |
| src.DimIndirect = 0; |
| src.DimIndFile = TGSI_FILE_NULL; |
| src.DimIndIndex = 0; |
| src.DimIndSwizzle = 0; |
| src.ArrayID = 0; |
| |
| return src; |
| } |
| |
| static inline boolean |
| ureg_src_is_undef( struct ureg_src src ) |
| { |
| return src.File == TGSI_FILE_NULL; |
| } |
| |
| static inline boolean |
| ureg_dst_is_undef( struct ureg_dst dst ) |
| { |
| return dst.File == TGSI_FILE_NULL; |
| } |
| |
| void |
| ureg_setup_shader_info(struct ureg_program *ureg, |
| const struct shader_info *info); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif |