1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h" 28bf215546Sopenharmony_ci#include "tgsi/tgsi_dump.h" 29bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h" 30bf215546Sopenharmony_ci#include "util/u_memory.h" 31bf215546Sopenharmony_ci#include "util/u_math.h" 32bf215546Sopenharmony_ci#include "util/u_pstipple.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "svga_tgsi_emit.h" 35bf215546Sopenharmony_ci#include "svga_context.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cistatic boolean emit_vs_postamble( struct svga_shader_emitter *emit ); 39bf215546Sopenharmony_cistatic boolean emit_ps_postamble( struct svga_shader_emitter *emit ); 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_cistatic SVGA3dShaderOpCodeType 43bf215546Sopenharmony_citranslate_opcode(enum tgsi_opcode opcode) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci switch (opcode) { 46bf215546Sopenharmony_ci case TGSI_OPCODE_ADD: return SVGA3DOP_ADD; 47bf215546Sopenharmony_ci case TGSI_OPCODE_DP3: return SVGA3DOP_DP3; 48bf215546Sopenharmony_ci case TGSI_OPCODE_DP4: return SVGA3DOP_DP4; 49bf215546Sopenharmony_ci case TGSI_OPCODE_FRC: return SVGA3DOP_FRC; 50bf215546Sopenharmony_ci case TGSI_OPCODE_MAD: return SVGA3DOP_MAD; 51bf215546Sopenharmony_ci case TGSI_OPCODE_MAX: return SVGA3DOP_MAX; 52bf215546Sopenharmony_ci case TGSI_OPCODE_MIN: return SVGA3DOP_MIN; 53bf215546Sopenharmony_ci case TGSI_OPCODE_MOV: return SVGA3DOP_MOV; 54bf215546Sopenharmony_ci case TGSI_OPCODE_MUL: return SVGA3DOP_MUL; 55bf215546Sopenharmony_ci case TGSI_OPCODE_NOP: return SVGA3DOP_NOP; 56bf215546Sopenharmony_ci default: 57bf215546Sopenharmony_ci assert(!"svga: unexpected opcode in translate_opcode()"); 58bf215546Sopenharmony_ci return SVGA3DOP_LAST_INST; 59bf215546Sopenharmony_ci } 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_cistatic SVGA3dShaderRegType 64bf215546Sopenharmony_citranslate_file(enum tgsi_file_type file) 65bf215546Sopenharmony_ci{ 66bf215546Sopenharmony_ci switch (file) { 67bf215546Sopenharmony_ci case TGSI_FILE_TEMPORARY: return SVGA3DREG_TEMP; 68bf215546Sopenharmony_ci case TGSI_FILE_INPUT: return SVGA3DREG_INPUT; 69bf215546Sopenharmony_ci case TGSI_FILE_OUTPUT: return SVGA3DREG_OUTPUT; /* VS3.0+ only */ 70bf215546Sopenharmony_ci case TGSI_FILE_IMMEDIATE: return SVGA3DREG_CONST; 71bf215546Sopenharmony_ci case TGSI_FILE_CONSTANT: return SVGA3DREG_CONST; 72bf215546Sopenharmony_ci case TGSI_FILE_SAMPLER: return SVGA3DREG_SAMPLER; 73bf215546Sopenharmony_ci case TGSI_FILE_ADDRESS: return SVGA3DREG_ADDR; 74bf215546Sopenharmony_ci default: 75bf215546Sopenharmony_ci assert(!"svga: unexpected register file in translate_file()"); 76bf215546Sopenharmony_ci return SVGA3DREG_TEMP; 77bf215546Sopenharmony_ci } 78bf215546Sopenharmony_ci} 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci/** 82bf215546Sopenharmony_ci * Translate a TGSI destination register to an SVGA3DShaderDestToken. 83bf215546Sopenharmony_ci * \param insn the TGSI instruction 84bf215546Sopenharmony_ci * \param idx which TGSI dest register to translate (usually (always?) zero) 85bf215546Sopenharmony_ci */ 86bf215546Sopenharmony_cistatic SVGA3dShaderDestToken 87bf215546Sopenharmony_citranslate_dst_register( struct svga_shader_emitter *emit, 88bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn, 89bf215546Sopenharmony_ci unsigned idx ) 90bf215546Sopenharmony_ci{ 91bf215546Sopenharmony_ci const struct tgsi_full_dst_register *reg = &insn->Dst[idx]; 92bf215546Sopenharmony_ci SVGA3dShaderDestToken dest; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci switch (reg->Register.File) { 95bf215546Sopenharmony_ci case TGSI_FILE_OUTPUT: 96bf215546Sopenharmony_ci /* Output registers encode semantic information in their name. 97bf215546Sopenharmony_ci * Need to lookup a table built at decl time: 98bf215546Sopenharmony_ci */ 99bf215546Sopenharmony_ci dest = emit->output_map[reg->Register.Index]; 100bf215546Sopenharmony_ci emit->num_output_writes++; 101bf215546Sopenharmony_ci break; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci default: 104bf215546Sopenharmony_ci { 105bf215546Sopenharmony_ci unsigned index = reg->Register.Index; 106bf215546Sopenharmony_ci assert(index < SVGA3D_TEMPREG_MAX); 107bf215546Sopenharmony_ci index = MIN2(index, SVGA3D_TEMPREG_MAX - 1); 108bf215546Sopenharmony_ci dest = dst_register(translate_file(reg->Register.File), index); 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci break; 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (reg->Register.Indirect) { 114bf215546Sopenharmony_ci debug_warning("Indirect indexing of dest registers is not supported!\n"); 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci dest.mask = reg->Register.WriteMask; 118bf215546Sopenharmony_ci assert(dest.mask); 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci if (insn->Instruction.Saturate) 121bf215546Sopenharmony_ci dest.dstMod = SVGA3DDSTMOD_SATURATE; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci return dest; 124bf215546Sopenharmony_ci} 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci/** 128bf215546Sopenharmony_ci * Apply a swizzle to a src_register, returning a new src_register 129bf215546Sopenharmony_ci * Ex: swizzle(SRC.ZZYY, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_X, SWIZZLE_Y) 130bf215546Sopenharmony_ci * would return SRC.YYZZ 131bf215546Sopenharmony_ci */ 132bf215546Sopenharmony_cistatic struct src_register 133bf215546Sopenharmony_ciswizzle(struct src_register src, 134bf215546Sopenharmony_ci unsigned x, unsigned y, unsigned z, unsigned w) 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci assert(x < 4); 137bf215546Sopenharmony_ci assert(y < 4); 138bf215546Sopenharmony_ci assert(z < 4); 139bf215546Sopenharmony_ci assert(w < 4); 140bf215546Sopenharmony_ci x = (src.base.swizzle >> (x * 2)) & 0x3; 141bf215546Sopenharmony_ci y = (src.base.swizzle >> (y * 2)) & 0x3; 142bf215546Sopenharmony_ci z = (src.base.swizzle >> (z * 2)) & 0x3; 143bf215546Sopenharmony_ci w = (src.base.swizzle >> (w * 2)) & 0x3; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci src.base.swizzle = TRANSLATE_SWIZZLE(x, y, z, w); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci return src; 148bf215546Sopenharmony_ci} 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci/** 152bf215546Sopenharmony_ci * Apply a "scalar" swizzle to a src_register returning a new 153bf215546Sopenharmony_ci * src_register where all the swizzle terms are the same. 154bf215546Sopenharmony_ci * Ex: scalar(SRC.WZYX, SWIZZLE_Y) would return SRC.ZZZZ 155bf215546Sopenharmony_ci */ 156bf215546Sopenharmony_cistatic struct src_register 157bf215546Sopenharmony_ciscalar(struct src_register src, unsigned comp) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci assert(comp < 4); 160bf215546Sopenharmony_ci return swizzle( src, comp, comp, comp, comp ); 161bf215546Sopenharmony_ci} 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_cistatic boolean 165bf215546Sopenharmony_cisvga_arl_needs_adjustment( const struct svga_shader_emitter *emit ) 166bf215546Sopenharmony_ci{ 167bf215546Sopenharmony_ci unsigned i; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci for (i = 0; i < emit->num_arl_consts; ++i) { 170bf215546Sopenharmony_ci if (emit->arl_consts[i].arl_num == emit->current_arl) 171bf215546Sopenharmony_ci return TRUE; 172bf215546Sopenharmony_ci } 173bf215546Sopenharmony_ci return FALSE; 174bf215546Sopenharmony_ci} 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_cistatic int 178bf215546Sopenharmony_cisvga_arl_adjustment( const struct svga_shader_emitter *emit ) 179bf215546Sopenharmony_ci{ 180bf215546Sopenharmony_ci unsigned i; 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci for (i = 0; i < emit->num_arl_consts; ++i) { 183bf215546Sopenharmony_ci if (emit->arl_consts[i].arl_num == emit->current_arl) 184bf215546Sopenharmony_ci return emit->arl_consts[i].number; 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci return 0; 187bf215546Sopenharmony_ci} 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci/** 191bf215546Sopenharmony_ci * Translate a TGSI src register to a src_register. 192bf215546Sopenharmony_ci */ 193bf215546Sopenharmony_cistatic struct src_register 194bf215546Sopenharmony_citranslate_src_register( const struct svga_shader_emitter *emit, 195bf215546Sopenharmony_ci const struct tgsi_full_src_register *reg ) 196bf215546Sopenharmony_ci{ 197bf215546Sopenharmony_ci struct src_register src; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci switch (reg->Register.File) { 200bf215546Sopenharmony_ci case TGSI_FILE_INPUT: 201bf215546Sopenharmony_ci /* Input registers are referred to by their semantic name rather 202bf215546Sopenharmony_ci * than by index. Use the mapping build up from the decls: 203bf215546Sopenharmony_ci */ 204bf215546Sopenharmony_ci src = emit->input_map[reg->Register.Index]; 205bf215546Sopenharmony_ci break; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci case TGSI_FILE_IMMEDIATE: 208bf215546Sopenharmony_ci /* Immediates are appended after TGSI constants in the D3D 209bf215546Sopenharmony_ci * constant buffer. 210bf215546Sopenharmony_ci */ 211bf215546Sopenharmony_ci src = src_register( translate_file( reg->Register.File ), 212bf215546Sopenharmony_ci reg->Register.Index + emit->imm_start ); 213bf215546Sopenharmony_ci break; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci default: 216bf215546Sopenharmony_ci src = src_register( translate_file( reg->Register.File ), 217bf215546Sopenharmony_ci reg->Register.Index ); 218bf215546Sopenharmony_ci break; 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci /* Indirect addressing. 222bf215546Sopenharmony_ci */ 223bf215546Sopenharmony_ci if (reg->Register.Indirect) { 224bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_FRAGMENT) { 225bf215546Sopenharmony_ci /* Pixel shaders have only loop registers for relative 226bf215546Sopenharmony_ci * addressing into inputs. Ignore the redundant address 227bf215546Sopenharmony_ci * register, the contents of aL should be in sync with it. 228bf215546Sopenharmony_ci */ 229bf215546Sopenharmony_ci if (reg->Register.File == TGSI_FILE_INPUT) { 230bf215546Sopenharmony_ci src.base.relAddr = 1; 231bf215546Sopenharmony_ci src.indirect = src_token(SVGA3DREG_LOOP, 0); 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci else { 235bf215546Sopenharmony_ci /* Constant buffers only. 236bf215546Sopenharmony_ci */ 237bf215546Sopenharmony_ci if (reg->Register.File == TGSI_FILE_CONSTANT) { 238bf215546Sopenharmony_ci /* we shift the offset towards the minimum */ 239bf215546Sopenharmony_ci if (svga_arl_needs_adjustment( emit )) { 240bf215546Sopenharmony_ci src.base.num -= svga_arl_adjustment( emit ); 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci src.base.relAddr = 1; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci /* Not really sure what should go in the second token: 245bf215546Sopenharmony_ci */ 246bf215546Sopenharmony_ci src.indirect = src_token( SVGA3DREG_ADDR, 247bf215546Sopenharmony_ci reg->Indirect.Index ); 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci src.indirect.swizzle = SWIZZLE_XXXX; 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci } 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci src = swizzle( src, 255bf215546Sopenharmony_ci reg->Register.SwizzleX, 256bf215546Sopenharmony_ci reg->Register.SwizzleY, 257bf215546Sopenharmony_ci reg->Register.SwizzleZ, 258bf215546Sopenharmony_ci reg->Register.SwizzleW ); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci /* src.mod isn't a bitfield, unfortunately */ 261bf215546Sopenharmony_ci if (reg->Register.Absolute) { 262bf215546Sopenharmony_ci if (reg->Register.Negate) 263bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_ABSNEG; 264bf215546Sopenharmony_ci else 265bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_ABS; 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci else { 268bf215546Sopenharmony_ci if (reg->Register.Negate) 269bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_NEG; 270bf215546Sopenharmony_ci else 271bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_NONE; 272bf215546Sopenharmony_ci } 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci return src; 275bf215546Sopenharmony_ci} 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci/* 279bf215546Sopenharmony_ci * Get a temporary register. 280bf215546Sopenharmony_ci * Note: if we exceed the temporary register limit we just use 281bf215546Sopenharmony_ci * register SVGA3D_TEMPREG_MAX - 1. 282bf215546Sopenharmony_ci */ 283bf215546Sopenharmony_cistatic SVGA3dShaderDestToken 284bf215546Sopenharmony_ciget_temp( struct svga_shader_emitter *emit ) 285bf215546Sopenharmony_ci{ 286bf215546Sopenharmony_ci int i = emit->nr_hw_temp + emit->internal_temp_count++; 287bf215546Sopenharmony_ci if (i >= SVGA3D_TEMPREG_MAX) { 288bf215546Sopenharmony_ci debug_warn_once("svga: Too many temporary registers used in shader\n"); 289bf215546Sopenharmony_ci i = SVGA3D_TEMPREG_MAX - 1; 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci return dst_register( SVGA3DREG_TEMP, i ); 292bf215546Sopenharmony_ci} 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci/** 296bf215546Sopenharmony_ci * Release a single temp. Currently only effective if it was the last 297bf215546Sopenharmony_ci * allocated temp, otherwise release will be delayed until the next 298bf215546Sopenharmony_ci * call to reset_temp_regs(). 299bf215546Sopenharmony_ci */ 300bf215546Sopenharmony_cistatic void 301bf215546Sopenharmony_cirelease_temp( struct svga_shader_emitter *emit, 302bf215546Sopenharmony_ci SVGA3dShaderDestToken temp ) 303bf215546Sopenharmony_ci{ 304bf215546Sopenharmony_ci if (temp.num == emit->internal_temp_count - 1) 305bf215546Sopenharmony_ci emit->internal_temp_count--; 306bf215546Sopenharmony_ci} 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci/** 310bf215546Sopenharmony_ci * Release all temps. 311bf215546Sopenharmony_ci */ 312bf215546Sopenharmony_cistatic void 313bf215546Sopenharmony_cireset_temp_regs(struct svga_shader_emitter *emit) 314bf215546Sopenharmony_ci{ 315bf215546Sopenharmony_ci emit->internal_temp_count = 0; 316bf215546Sopenharmony_ci} 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci/** Emit bytecode for a src_register */ 320bf215546Sopenharmony_cistatic boolean 321bf215546Sopenharmony_ciemit_src(struct svga_shader_emitter *emit, const struct src_register src) 322bf215546Sopenharmony_ci{ 323bf215546Sopenharmony_ci if (src.base.relAddr) { 324bf215546Sopenharmony_ci assert(src.base.reserved0); 325bf215546Sopenharmony_ci assert(src.indirect.reserved0); 326bf215546Sopenharmony_ci return (svga_shader_emit_dword( emit, src.base.value ) && 327bf215546Sopenharmony_ci svga_shader_emit_dword( emit, src.indirect.value )); 328bf215546Sopenharmony_ci } 329bf215546Sopenharmony_ci else { 330bf215546Sopenharmony_ci assert(src.base.reserved0); 331bf215546Sopenharmony_ci return svga_shader_emit_dword( emit, src.base.value ); 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci} 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci/** Emit bytecode for a dst_register */ 337bf215546Sopenharmony_cistatic boolean 338bf215546Sopenharmony_ciemit_dst(struct svga_shader_emitter *emit, SVGA3dShaderDestToken dest) 339bf215546Sopenharmony_ci{ 340bf215546Sopenharmony_ci assert(dest.reserved0); 341bf215546Sopenharmony_ci assert(dest.mask); 342bf215546Sopenharmony_ci return svga_shader_emit_dword( emit, dest.value ); 343bf215546Sopenharmony_ci} 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci/** Emit bytecode for a 1-operand instruction */ 347bf215546Sopenharmony_cistatic boolean 348bf215546Sopenharmony_ciemit_op1(struct svga_shader_emitter *emit, 349bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 350bf215546Sopenharmony_ci SVGA3dShaderDestToken dest, 351bf215546Sopenharmony_ci struct src_register src0) 352bf215546Sopenharmony_ci{ 353bf215546Sopenharmony_ci return (emit_instruction(emit, inst) && 354bf215546Sopenharmony_ci emit_dst(emit, dest) && 355bf215546Sopenharmony_ci emit_src(emit, src0)); 356bf215546Sopenharmony_ci} 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci/** Emit bytecode for a 2-operand instruction */ 360bf215546Sopenharmony_cistatic boolean 361bf215546Sopenharmony_ciemit_op2(struct svga_shader_emitter *emit, 362bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 363bf215546Sopenharmony_ci SVGA3dShaderDestToken dest, 364bf215546Sopenharmony_ci struct src_register src0, 365bf215546Sopenharmony_ci struct src_register src1) 366bf215546Sopenharmony_ci{ 367bf215546Sopenharmony_ci return (emit_instruction(emit, inst) && 368bf215546Sopenharmony_ci emit_dst(emit, dest) && 369bf215546Sopenharmony_ci emit_src(emit, src0) && 370bf215546Sopenharmony_ci emit_src(emit, src1)); 371bf215546Sopenharmony_ci} 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci/** Emit bytecode for a 3-operand instruction */ 375bf215546Sopenharmony_cistatic boolean 376bf215546Sopenharmony_ciemit_op3(struct svga_shader_emitter *emit, 377bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 378bf215546Sopenharmony_ci SVGA3dShaderDestToken dest, 379bf215546Sopenharmony_ci struct src_register src0, 380bf215546Sopenharmony_ci struct src_register src1, 381bf215546Sopenharmony_ci struct src_register src2) 382bf215546Sopenharmony_ci{ 383bf215546Sopenharmony_ci return (emit_instruction(emit, inst) && 384bf215546Sopenharmony_ci emit_dst(emit, dest) && 385bf215546Sopenharmony_ci emit_src(emit, src0) && 386bf215546Sopenharmony_ci emit_src(emit, src1) && 387bf215546Sopenharmony_ci emit_src(emit, src2)); 388bf215546Sopenharmony_ci} 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci/** Emit bytecode for a 4-operand instruction */ 392bf215546Sopenharmony_cistatic boolean 393bf215546Sopenharmony_ciemit_op4(struct svga_shader_emitter *emit, 394bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 395bf215546Sopenharmony_ci SVGA3dShaderDestToken dest, 396bf215546Sopenharmony_ci struct src_register src0, 397bf215546Sopenharmony_ci struct src_register src1, 398bf215546Sopenharmony_ci struct src_register src2, 399bf215546Sopenharmony_ci struct src_register src3) 400bf215546Sopenharmony_ci{ 401bf215546Sopenharmony_ci return (emit_instruction(emit, inst) && 402bf215546Sopenharmony_ci emit_dst(emit, dest) && 403bf215546Sopenharmony_ci emit_src(emit, src0) && 404bf215546Sopenharmony_ci emit_src(emit, src1) && 405bf215546Sopenharmony_ci emit_src(emit, src2) && 406bf215546Sopenharmony_ci emit_src(emit, src3)); 407bf215546Sopenharmony_ci} 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci/** 411bf215546Sopenharmony_ci * Apply the absolute value modifier to the given src_register, returning 412bf215546Sopenharmony_ci * a new src_register. 413bf215546Sopenharmony_ci */ 414bf215546Sopenharmony_cistatic struct src_register 415bf215546Sopenharmony_ciabsolute(struct src_register src) 416bf215546Sopenharmony_ci{ 417bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_ABS; 418bf215546Sopenharmony_ci return src; 419bf215546Sopenharmony_ci} 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci/** 423bf215546Sopenharmony_ci * Apply the negation modifier to the given src_register, returning 424bf215546Sopenharmony_ci * a new src_register. 425bf215546Sopenharmony_ci */ 426bf215546Sopenharmony_cistatic struct src_register 427bf215546Sopenharmony_cinegate(struct src_register src) 428bf215546Sopenharmony_ci{ 429bf215546Sopenharmony_ci switch (src.base.srcMod) { 430bf215546Sopenharmony_ci case SVGA3DSRCMOD_ABS: 431bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_ABSNEG; 432bf215546Sopenharmony_ci break; 433bf215546Sopenharmony_ci case SVGA3DSRCMOD_ABSNEG: 434bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_ABS; 435bf215546Sopenharmony_ci break; 436bf215546Sopenharmony_ci case SVGA3DSRCMOD_NEG: 437bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_NONE; 438bf215546Sopenharmony_ci break; 439bf215546Sopenharmony_ci case SVGA3DSRCMOD_NONE: 440bf215546Sopenharmony_ci src.base.srcMod = SVGA3DSRCMOD_NEG; 441bf215546Sopenharmony_ci break; 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci return src; 444bf215546Sopenharmony_ci} 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci/* Replace the src with the temporary specified in the dst, but copying 449bf215546Sopenharmony_ci * only the necessary channels, and preserving the original swizzle (which is 450bf215546Sopenharmony_ci * important given that several opcodes have constraints in the allowed 451bf215546Sopenharmony_ci * swizzles). 452bf215546Sopenharmony_ci */ 453bf215546Sopenharmony_cistatic boolean 454bf215546Sopenharmony_ciemit_repl(struct svga_shader_emitter *emit, 455bf215546Sopenharmony_ci SVGA3dShaderDestToken dst, 456bf215546Sopenharmony_ci struct src_register *src0) 457bf215546Sopenharmony_ci{ 458bf215546Sopenharmony_ci unsigned src0_swizzle; 459bf215546Sopenharmony_ci unsigned chan; 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci assert(SVGA3dShaderGetRegType(dst.value) == SVGA3DREG_TEMP); 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci src0_swizzle = src0->base.swizzle; 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci dst.mask = 0; 466bf215546Sopenharmony_ci for (chan = 0; chan < 4; ++chan) { 467bf215546Sopenharmony_ci unsigned swizzle = (src0_swizzle >> (chan *2)) & 0x3; 468bf215546Sopenharmony_ci dst.mask |= 1 << swizzle; 469bf215546Sopenharmony_ci } 470bf215546Sopenharmony_ci assert(dst.mask); 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci src0->base.swizzle = SVGA3DSWIZZLE_NONE; 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, *src0 )) 475bf215546Sopenharmony_ci return FALSE; 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci *src0 = src( dst ); 478bf215546Sopenharmony_ci src0->base.swizzle = src0_swizzle; 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci return TRUE; 481bf215546Sopenharmony_ci} 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci/** 485bf215546Sopenharmony_ci * Submit/emit an instruction with zero operands. 486bf215546Sopenharmony_ci */ 487bf215546Sopenharmony_cistatic boolean 488bf215546Sopenharmony_cisubmit_op0(struct svga_shader_emitter *emit, 489bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 490bf215546Sopenharmony_ci SVGA3dShaderDestToken dest) 491bf215546Sopenharmony_ci{ 492bf215546Sopenharmony_ci return (emit_instruction( emit, inst ) && 493bf215546Sopenharmony_ci emit_dst( emit, dest )); 494bf215546Sopenharmony_ci} 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci/** 498bf215546Sopenharmony_ci * Submit/emit an instruction with one operand. 499bf215546Sopenharmony_ci */ 500bf215546Sopenharmony_cistatic boolean 501bf215546Sopenharmony_cisubmit_op1(struct svga_shader_emitter *emit, 502bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 503bf215546Sopenharmony_ci SVGA3dShaderDestToken dest, 504bf215546Sopenharmony_ci struct src_register src0) 505bf215546Sopenharmony_ci{ 506bf215546Sopenharmony_ci return emit_op1( emit, inst, dest, src0 ); 507bf215546Sopenharmony_ci} 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci/** 511bf215546Sopenharmony_ci * Submit/emit an instruction with two operands. 512bf215546Sopenharmony_ci * 513bf215546Sopenharmony_ci * SVGA shaders may not refer to >1 constant register in a single 514bf215546Sopenharmony_ci * instruction. This function checks for that usage and inserts a 515bf215546Sopenharmony_ci * move to temporary if detected. 516bf215546Sopenharmony_ci * 517bf215546Sopenharmony_ci * The same applies to input registers -- at most a single input 518bf215546Sopenharmony_ci * register may be read by any instruction. 519bf215546Sopenharmony_ci */ 520bf215546Sopenharmony_cistatic boolean 521bf215546Sopenharmony_cisubmit_op2(struct svga_shader_emitter *emit, 522bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 523bf215546Sopenharmony_ci SVGA3dShaderDestToken dest, 524bf215546Sopenharmony_ci struct src_register src0, 525bf215546Sopenharmony_ci struct src_register src1) 526bf215546Sopenharmony_ci{ 527bf215546Sopenharmony_ci SVGA3dShaderDestToken temp; 528bf215546Sopenharmony_ci SVGA3dShaderRegType type0, type1; 529bf215546Sopenharmony_ci boolean need_temp = FALSE; 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci temp.value = 0; 532bf215546Sopenharmony_ci type0 = SVGA3dShaderGetRegType( src0.base.value ); 533bf215546Sopenharmony_ci type1 = SVGA3dShaderGetRegType( src1.base.value ); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci if (type0 == SVGA3DREG_CONST && 536bf215546Sopenharmony_ci type1 == SVGA3DREG_CONST && 537bf215546Sopenharmony_ci src0.base.num != src1.base.num) 538bf215546Sopenharmony_ci need_temp = TRUE; 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci if (type0 == SVGA3DREG_INPUT && 541bf215546Sopenharmony_ci type1 == SVGA3DREG_INPUT && 542bf215546Sopenharmony_ci src0.base.num != src1.base.num) 543bf215546Sopenharmony_ci need_temp = TRUE; 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ci if (need_temp) { 546bf215546Sopenharmony_ci temp = get_temp( emit ); 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci if (!emit_repl( emit, temp, &src0 )) 549bf215546Sopenharmony_ci return FALSE; 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci if (!emit_op2( emit, inst, dest, src0, src1 )) 553bf215546Sopenharmony_ci return FALSE; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci if (need_temp) 556bf215546Sopenharmony_ci release_temp( emit, temp ); 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci return TRUE; 559bf215546Sopenharmony_ci} 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci/** 563bf215546Sopenharmony_ci * Submit/emit an instruction with three operands. 564bf215546Sopenharmony_ci * 565bf215546Sopenharmony_ci * SVGA shaders may not refer to >1 constant register in a single 566bf215546Sopenharmony_ci * instruction. This function checks for that usage and inserts a 567bf215546Sopenharmony_ci * move to temporary if detected. 568bf215546Sopenharmony_ci */ 569bf215546Sopenharmony_cistatic boolean 570bf215546Sopenharmony_cisubmit_op3(struct svga_shader_emitter *emit, 571bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 572bf215546Sopenharmony_ci SVGA3dShaderDestToken dest, 573bf215546Sopenharmony_ci struct src_register src0, 574bf215546Sopenharmony_ci struct src_register src1, 575bf215546Sopenharmony_ci struct src_register src2) 576bf215546Sopenharmony_ci{ 577bf215546Sopenharmony_ci SVGA3dShaderDestToken temp0; 578bf215546Sopenharmony_ci SVGA3dShaderDestToken temp1; 579bf215546Sopenharmony_ci boolean need_temp0 = FALSE; 580bf215546Sopenharmony_ci boolean need_temp1 = FALSE; 581bf215546Sopenharmony_ci SVGA3dShaderRegType type0, type1, type2; 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci temp0.value = 0; 584bf215546Sopenharmony_ci temp1.value = 0; 585bf215546Sopenharmony_ci type0 = SVGA3dShaderGetRegType( src0.base.value ); 586bf215546Sopenharmony_ci type1 = SVGA3dShaderGetRegType( src1.base.value ); 587bf215546Sopenharmony_ci type2 = SVGA3dShaderGetRegType( src2.base.value ); 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_ci if (inst.op != SVGA3DOP_SINCOS) { 590bf215546Sopenharmony_ci if (type0 == SVGA3DREG_CONST && 591bf215546Sopenharmony_ci ((type1 == SVGA3DREG_CONST && src0.base.num != src1.base.num) || 592bf215546Sopenharmony_ci (type2 == SVGA3DREG_CONST && src0.base.num != src2.base.num))) 593bf215546Sopenharmony_ci need_temp0 = TRUE; 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci if (type1 == SVGA3DREG_CONST && 596bf215546Sopenharmony_ci (type2 == SVGA3DREG_CONST && src1.base.num != src2.base.num)) 597bf215546Sopenharmony_ci need_temp1 = TRUE; 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci if (type0 == SVGA3DREG_INPUT && 601bf215546Sopenharmony_ci ((type1 == SVGA3DREG_INPUT && src0.base.num != src1.base.num) || 602bf215546Sopenharmony_ci (type2 == SVGA3DREG_INPUT && src0.base.num != src2.base.num))) 603bf215546Sopenharmony_ci need_temp0 = TRUE; 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci if (type1 == SVGA3DREG_INPUT && 606bf215546Sopenharmony_ci (type2 == SVGA3DREG_INPUT && src1.base.num != src2.base.num)) 607bf215546Sopenharmony_ci need_temp1 = TRUE; 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci if (need_temp0) { 610bf215546Sopenharmony_ci temp0 = get_temp( emit ); 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci if (!emit_repl( emit, temp0, &src0 )) 613bf215546Sopenharmony_ci return FALSE; 614bf215546Sopenharmony_ci } 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_ci if (need_temp1) { 617bf215546Sopenharmony_ci temp1 = get_temp( emit ); 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci if (!emit_repl( emit, temp1, &src1 )) 620bf215546Sopenharmony_ci return FALSE; 621bf215546Sopenharmony_ci } 622bf215546Sopenharmony_ci 623bf215546Sopenharmony_ci if (!emit_op3( emit, inst, dest, src0, src1, src2 )) 624bf215546Sopenharmony_ci return FALSE; 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci if (need_temp1) 627bf215546Sopenharmony_ci release_temp( emit, temp1 ); 628bf215546Sopenharmony_ci if (need_temp0) 629bf215546Sopenharmony_ci release_temp( emit, temp0 ); 630bf215546Sopenharmony_ci return TRUE; 631bf215546Sopenharmony_ci} 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci/** 635bf215546Sopenharmony_ci * Submit/emit an instruction with four operands. 636bf215546Sopenharmony_ci * 637bf215546Sopenharmony_ci * SVGA shaders may not refer to >1 constant register in a single 638bf215546Sopenharmony_ci * instruction. This function checks for that usage and inserts a 639bf215546Sopenharmony_ci * move to temporary if detected. 640bf215546Sopenharmony_ci */ 641bf215546Sopenharmony_cistatic boolean 642bf215546Sopenharmony_cisubmit_op4(struct svga_shader_emitter *emit, 643bf215546Sopenharmony_ci SVGA3dShaderInstToken inst, 644bf215546Sopenharmony_ci SVGA3dShaderDestToken dest, 645bf215546Sopenharmony_ci struct src_register src0, 646bf215546Sopenharmony_ci struct src_register src1, 647bf215546Sopenharmony_ci struct src_register src2, 648bf215546Sopenharmony_ci struct src_register src3) 649bf215546Sopenharmony_ci{ 650bf215546Sopenharmony_ci SVGA3dShaderDestToken temp0; 651bf215546Sopenharmony_ci SVGA3dShaderDestToken temp3; 652bf215546Sopenharmony_ci boolean need_temp0 = FALSE; 653bf215546Sopenharmony_ci boolean need_temp3 = FALSE; 654bf215546Sopenharmony_ci SVGA3dShaderRegType type0, type1, type2, type3; 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci temp0.value = 0; 657bf215546Sopenharmony_ci temp3.value = 0; 658bf215546Sopenharmony_ci type0 = SVGA3dShaderGetRegType( src0.base.value ); 659bf215546Sopenharmony_ci type1 = SVGA3dShaderGetRegType( src1.base.value ); 660bf215546Sopenharmony_ci type2 = SVGA3dShaderGetRegType( src2.base.value ); 661bf215546Sopenharmony_ci type3 = SVGA3dShaderGetRegType( src2.base.value ); 662bf215546Sopenharmony_ci 663bf215546Sopenharmony_ci /* Make life a little easier - this is only used by the TXD 664bf215546Sopenharmony_ci * instruction which is guaranteed not to have a constant/input reg 665bf215546Sopenharmony_ci * in one slot at least: 666bf215546Sopenharmony_ci */ 667bf215546Sopenharmony_ci assert(type1 == SVGA3DREG_SAMPLER); 668bf215546Sopenharmony_ci (void) type1; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci if (type0 == SVGA3DREG_CONST && 671bf215546Sopenharmony_ci ((type3 == SVGA3DREG_CONST && src0.base.num != src3.base.num) || 672bf215546Sopenharmony_ci (type2 == SVGA3DREG_CONST && src0.base.num != src2.base.num))) 673bf215546Sopenharmony_ci need_temp0 = TRUE; 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_ci if (type3 == SVGA3DREG_CONST && 676bf215546Sopenharmony_ci (type2 == SVGA3DREG_CONST && src3.base.num != src2.base.num)) 677bf215546Sopenharmony_ci need_temp3 = TRUE; 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_ci if (type0 == SVGA3DREG_INPUT && 680bf215546Sopenharmony_ci ((type3 == SVGA3DREG_INPUT && src0.base.num != src3.base.num) || 681bf215546Sopenharmony_ci (type2 == SVGA3DREG_INPUT && src0.base.num != src2.base.num))) 682bf215546Sopenharmony_ci need_temp0 = TRUE; 683bf215546Sopenharmony_ci 684bf215546Sopenharmony_ci if (type3 == SVGA3DREG_INPUT && 685bf215546Sopenharmony_ci (type2 == SVGA3DREG_INPUT && src3.base.num != src2.base.num)) 686bf215546Sopenharmony_ci need_temp3 = TRUE; 687bf215546Sopenharmony_ci 688bf215546Sopenharmony_ci if (need_temp0) { 689bf215546Sopenharmony_ci temp0 = get_temp( emit ); 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci if (!emit_repl( emit, temp0, &src0 )) 692bf215546Sopenharmony_ci return FALSE; 693bf215546Sopenharmony_ci } 694bf215546Sopenharmony_ci 695bf215546Sopenharmony_ci if (need_temp3) { 696bf215546Sopenharmony_ci temp3 = get_temp( emit ); 697bf215546Sopenharmony_ci 698bf215546Sopenharmony_ci if (!emit_repl( emit, temp3, &src3 )) 699bf215546Sopenharmony_ci return FALSE; 700bf215546Sopenharmony_ci } 701bf215546Sopenharmony_ci 702bf215546Sopenharmony_ci if (!emit_op4( emit, inst, dest, src0, src1, src2, src3 )) 703bf215546Sopenharmony_ci return FALSE; 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ci if (need_temp3) 706bf215546Sopenharmony_ci release_temp( emit, temp3 ); 707bf215546Sopenharmony_ci if (need_temp0) 708bf215546Sopenharmony_ci release_temp( emit, temp0 ); 709bf215546Sopenharmony_ci return TRUE; 710bf215546Sopenharmony_ci} 711bf215546Sopenharmony_ci 712bf215546Sopenharmony_ci 713bf215546Sopenharmony_ci/** 714bf215546Sopenharmony_ci * Do the src and dest registers refer to the same register? 715bf215546Sopenharmony_ci */ 716bf215546Sopenharmony_cistatic boolean 717bf215546Sopenharmony_cialias_src_dst(struct src_register src, 718bf215546Sopenharmony_ci SVGA3dShaderDestToken dst) 719bf215546Sopenharmony_ci{ 720bf215546Sopenharmony_ci if (src.base.num != dst.num) 721bf215546Sopenharmony_ci return FALSE; 722bf215546Sopenharmony_ci 723bf215546Sopenharmony_ci if (SVGA3dShaderGetRegType(dst.value) != 724bf215546Sopenharmony_ci SVGA3dShaderGetRegType(src.base.value)) 725bf215546Sopenharmony_ci return FALSE; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci return TRUE; 728bf215546Sopenharmony_ci} 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_ci/** 732bf215546Sopenharmony_ci * Helper for emitting SVGA immediate values using the SVGA3DOP_DEF[I] 733bf215546Sopenharmony_ci * instructions. 734bf215546Sopenharmony_ci */ 735bf215546Sopenharmony_cistatic boolean 736bf215546Sopenharmony_ciemit_def_const(struct svga_shader_emitter *emit, 737bf215546Sopenharmony_ci SVGA3dShaderConstType type, 738bf215546Sopenharmony_ci unsigned idx, float a, float b, float c, float d) 739bf215546Sopenharmony_ci{ 740bf215546Sopenharmony_ci SVGA3DOpDefArgs def; 741bf215546Sopenharmony_ci SVGA3dShaderInstToken opcode; 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci switch (type) { 744bf215546Sopenharmony_ci case SVGA3D_CONST_TYPE_FLOAT: 745bf215546Sopenharmony_ci opcode = inst_token( SVGA3DOP_DEF ); 746bf215546Sopenharmony_ci def.dst = dst_register( SVGA3DREG_CONST, idx ); 747bf215546Sopenharmony_ci def.constValues[0] = a; 748bf215546Sopenharmony_ci def.constValues[1] = b; 749bf215546Sopenharmony_ci def.constValues[2] = c; 750bf215546Sopenharmony_ci def.constValues[3] = d; 751bf215546Sopenharmony_ci break; 752bf215546Sopenharmony_ci case SVGA3D_CONST_TYPE_INT: 753bf215546Sopenharmony_ci opcode = inst_token( SVGA3DOP_DEFI ); 754bf215546Sopenharmony_ci def.dst = dst_register( SVGA3DREG_CONSTINT, idx ); 755bf215546Sopenharmony_ci def.constIValues[0] = (int)a; 756bf215546Sopenharmony_ci def.constIValues[1] = (int)b; 757bf215546Sopenharmony_ci def.constIValues[2] = (int)c; 758bf215546Sopenharmony_ci def.constIValues[3] = (int)d; 759bf215546Sopenharmony_ci break; 760bf215546Sopenharmony_ci default: 761bf215546Sopenharmony_ci assert(0); 762bf215546Sopenharmony_ci opcode = inst_token( SVGA3DOP_NOP ); 763bf215546Sopenharmony_ci break; 764bf215546Sopenharmony_ci } 765bf215546Sopenharmony_ci 766bf215546Sopenharmony_ci if (!emit_instruction(emit, opcode) || 767bf215546Sopenharmony_ci !svga_shader_emit_dwords( emit, def.values, ARRAY_SIZE(def.values))) 768bf215546Sopenharmony_ci return FALSE; 769bf215546Sopenharmony_ci 770bf215546Sopenharmony_ci return TRUE; 771bf215546Sopenharmony_ci} 772bf215546Sopenharmony_ci 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_cistatic boolean 775bf215546Sopenharmony_cicreate_loop_const( struct svga_shader_emitter *emit ) 776bf215546Sopenharmony_ci{ 777bf215546Sopenharmony_ci unsigned idx = emit->nr_hw_int_const++; 778bf215546Sopenharmony_ci 779bf215546Sopenharmony_ci if (!emit_def_const( emit, SVGA3D_CONST_TYPE_INT, idx, 780bf215546Sopenharmony_ci 255, /* iteration count */ 781bf215546Sopenharmony_ci 0, /* initial value */ 782bf215546Sopenharmony_ci 1, /* step size */ 783bf215546Sopenharmony_ci 0 /* not used, must be 0 */)) 784bf215546Sopenharmony_ci return FALSE; 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci emit->loop_const_idx = idx; 787bf215546Sopenharmony_ci emit->created_loop_const = TRUE; 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_ci return TRUE; 790bf215546Sopenharmony_ci} 791bf215546Sopenharmony_ci 792bf215546Sopenharmony_cistatic boolean 793bf215546Sopenharmony_cicreate_arl_consts( struct svga_shader_emitter *emit ) 794bf215546Sopenharmony_ci{ 795bf215546Sopenharmony_ci int i; 796bf215546Sopenharmony_ci 797bf215546Sopenharmony_ci for (i = 0; i < emit->num_arl_consts; i += 4) { 798bf215546Sopenharmony_ci int j; 799bf215546Sopenharmony_ci unsigned idx = emit->nr_hw_float_const++; 800bf215546Sopenharmony_ci float vals[4]; 801bf215546Sopenharmony_ci for (j = 0; j < 4 && (j + i) < emit->num_arl_consts; ++j) { 802bf215546Sopenharmony_ci vals[j] = (float) emit->arl_consts[i + j].number; 803bf215546Sopenharmony_ci emit->arl_consts[i + j].idx = idx; 804bf215546Sopenharmony_ci switch (j) { 805bf215546Sopenharmony_ci case 0: 806bf215546Sopenharmony_ci emit->arl_consts[i + 0].swizzle = TGSI_SWIZZLE_X; 807bf215546Sopenharmony_ci break; 808bf215546Sopenharmony_ci case 1: 809bf215546Sopenharmony_ci emit->arl_consts[i + 0].swizzle = TGSI_SWIZZLE_Y; 810bf215546Sopenharmony_ci break; 811bf215546Sopenharmony_ci case 2: 812bf215546Sopenharmony_ci emit->arl_consts[i + 0].swizzle = TGSI_SWIZZLE_Z; 813bf215546Sopenharmony_ci break; 814bf215546Sopenharmony_ci case 3: 815bf215546Sopenharmony_ci emit->arl_consts[i + 0].swizzle = TGSI_SWIZZLE_W; 816bf215546Sopenharmony_ci break; 817bf215546Sopenharmony_ci } 818bf215546Sopenharmony_ci } 819bf215546Sopenharmony_ci while (j < 4) 820bf215546Sopenharmony_ci vals[j++] = 0; 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT, idx, 823bf215546Sopenharmony_ci vals[0], vals[1], 824bf215546Sopenharmony_ci vals[2], vals[3])) 825bf215546Sopenharmony_ci return FALSE; 826bf215546Sopenharmony_ci } 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci return TRUE; 829bf215546Sopenharmony_ci} 830bf215546Sopenharmony_ci 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci/** 833bf215546Sopenharmony_ci * Return the register which holds the pixel shaders front/back- 834bf215546Sopenharmony_ci * facing value. 835bf215546Sopenharmony_ci */ 836bf215546Sopenharmony_cistatic struct src_register 837bf215546Sopenharmony_ciget_vface( struct svga_shader_emitter *emit ) 838bf215546Sopenharmony_ci{ 839bf215546Sopenharmony_ci assert(emit->emitted_vface); 840bf215546Sopenharmony_ci return src_register(SVGA3DREG_MISCTYPE, SVGA3DMISCREG_FACE); 841bf215546Sopenharmony_ci} 842bf215546Sopenharmony_ci 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ci/** 845bf215546Sopenharmony_ci * Create/emit a "common" constant with values {0, 0.5, -1, 1}. 846bf215546Sopenharmony_ci * We can swizzle this to produce other useful constants such as 847bf215546Sopenharmony_ci * {0, 0, 0, 0}, {1, 1, 1, 1}, etc. 848bf215546Sopenharmony_ci */ 849bf215546Sopenharmony_cistatic boolean 850bf215546Sopenharmony_cicreate_common_immediate( struct svga_shader_emitter *emit ) 851bf215546Sopenharmony_ci{ 852bf215546Sopenharmony_ci unsigned idx = emit->nr_hw_float_const++; 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_ci /* Emit the constant (0, 0.5, -1, 1) and use swizzling to generate 855bf215546Sopenharmony_ci * other useful vectors. 856bf215546Sopenharmony_ci */ 857bf215546Sopenharmony_ci if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT, 858bf215546Sopenharmony_ci idx, 0.0f, 0.5f, -1.0f, 1.0f )) 859bf215546Sopenharmony_ci return FALSE; 860bf215546Sopenharmony_ci emit->common_immediate_idx[0] = idx; 861bf215546Sopenharmony_ci idx++; 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci /* Emit constant {2, 0, 0, 0} (only the 2 is used for now) */ 864bf215546Sopenharmony_ci if (emit->key.vs.adjust_attrib_range) { 865bf215546Sopenharmony_ci if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT, 866bf215546Sopenharmony_ci idx, 2.0f, 0.0f, 0.0f, 0.0f )) 867bf215546Sopenharmony_ci return FALSE; 868bf215546Sopenharmony_ci emit->common_immediate_idx[1] = idx; 869bf215546Sopenharmony_ci } 870bf215546Sopenharmony_ci else { 871bf215546Sopenharmony_ci emit->common_immediate_idx[1] = -1; 872bf215546Sopenharmony_ci } 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ci emit->created_common_immediate = TRUE; 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_ci return TRUE; 877bf215546Sopenharmony_ci} 878bf215546Sopenharmony_ci 879bf215546Sopenharmony_ci 880bf215546Sopenharmony_ci/** 881bf215546Sopenharmony_ci * Return swizzle/position for the given value in the "common" immediate. 882bf215546Sopenharmony_ci */ 883bf215546Sopenharmony_cistatic inline unsigned 884bf215546Sopenharmony_cicommon_immediate_swizzle(float value) 885bf215546Sopenharmony_ci{ 886bf215546Sopenharmony_ci if (value == 0.0f) 887bf215546Sopenharmony_ci return TGSI_SWIZZLE_X; 888bf215546Sopenharmony_ci else if (value == 0.5f) 889bf215546Sopenharmony_ci return TGSI_SWIZZLE_Y; 890bf215546Sopenharmony_ci else if (value == -1.0f) 891bf215546Sopenharmony_ci return TGSI_SWIZZLE_Z; 892bf215546Sopenharmony_ci else if (value == 1.0f) 893bf215546Sopenharmony_ci return TGSI_SWIZZLE_W; 894bf215546Sopenharmony_ci else { 895bf215546Sopenharmony_ci assert(!"illegal value in common_immediate_swizzle"); 896bf215546Sopenharmony_ci return TGSI_SWIZZLE_X; 897bf215546Sopenharmony_ci } 898bf215546Sopenharmony_ci} 899bf215546Sopenharmony_ci 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_ci/** 902bf215546Sopenharmony_ci * Returns an immediate reg where all the terms are either 0, 1, 2 or 0.5 903bf215546Sopenharmony_ci */ 904bf215546Sopenharmony_cistatic struct src_register 905bf215546Sopenharmony_ciget_immediate(struct svga_shader_emitter *emit, 906bf215546Sopenharmony_ci float x, float y, float z, float w) 907bf215546Sopenharmony_ci{ 908bf215546Sopenharmony_ci unsigned sx = common_immediate_swizzle(x); 909bf215546Sopenharmony_ci unsigned sy = common_immediate_swizzle(y); 910bf215546Sopenharmony_ci unsigned sz = common_immediate_swizzle(z); 911bf215546Sopenharmony_ci unsigned sw = common_immediate_swizzle(w); 912bf215546Sopenharmony_ci assert(emit->created_common_immediate); 913bf215546Sopenharmony_ci assert(emit->common_immediate_idx[0] >= 0); 914bf215546Sopenharmony_ci return swizzle(src_register(SVGA3DREG_CONST, emit->common_immediate_idx[0]), 915bf215546Sopenharmony_ci sx, sy, sz, sw); 916bf215546Sopenharmony_ci} 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci 919bf215546Sopenharmony_ci/** 920bf215546Sopenharmony_ci * returns {0, 0, 0, 0} immediate 921bf215546Sopenharmony_ci */ 922bf215546Sopenharmony_cistatic struct src_register 923bf215546Sopenharmony_ciget_zero_immediate( struct svga_shader_emitter *emit ) 924bf215546Sopenharmony_ci{ 925bf215546Sopenharmony_ci assert(emit->created_common_immediate); 926bf215546Sopenharmony_ci assert(emit->common_immediate_idx[0] >= 0); 927bf215546Sopenharmony_ci return swizzle(src_register( SVGA3DREG_CONST, 928bf215546Sopenharmony_ci emit->common_immediate_idx[0]), 929bf215546Sopenharmony_ci 0, 0, 0, 0); 930bf215546Sopenharmony_ci} 931bf215546Sopenharmony_ci 932bf215546Sopenharmony_ci 933bf215546Sopenharmony_ci/** 934bf215546Sopenharmony_ci * returns {1, 1, 1, 1} immediate 935bf215546Sopenharmony_ci */ 936bf215546Sopenharmony_cistatic struct src_register 937bf215546Sopenharmony_ciget_one_immediate( struct svga_shader_emitter *emit ) 938bf215546Sopenharmony_ci{ 939bf215546Sopenharmony_ci assert(emit->created_common_immediate); 940bf215546Sopenharmony_ci assert(emit->common_immediate_idx[0] >= 0); 941bf215546Sopenharmony_ci return swizzle(src_register( SVGA3DREG_CONST, 942bf215546Sopenharmony_ci emit->common_immediate_idx[0]), 943bf215546Sopenharmony_ci 3, 3, 3, 3); 944bf215546Sopenharmony_ci} 945bf215546Sopenharmony_ci 946bf215546Sopenharmony_ci 947bf215546Sopenharmony_ci/** 948bf215546Sopenharmony_ci * returns {0.5, 0.5, 0.5, 0.5} immediate 949bf215546Sopenharmony_ci */ 950bf215546Sopenharmony_cistatic struct src_register 951bf215546Sopenharmony_ciget_half_immediate( struct svga_shader_emitter *emit ) 952bf215546Sopenharmony_ci{ 953bf215546Sopenharmony_ci assert(emit->created_common_immediate); 954bf215546Sopenharmony_ci assert(emit->common_immediate_idx[0] >= 0); 955bf215546Sopenharmony_ci return swizzle(src_register(SVGA3DREG_CONST, emit->common_immediate_idx[0]), 956bf215546Sopenharmony_ci 1, 1, 1, 1); 957bf215546Sopenharmony_ci} 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_ci 960bf215546Sopenharmony_ci/** 961bf215546Sopenharmony_ci * returns {2, 2, 2, 2} immediate 962bf215546Sopenharmony_ci */ 963bf215546Sopenharmony_cistatic struct src_register 964bf215546Sopenharmony_ciget_two_immediate( struct svga_shader_emitter *emit ) 965bf215546Sopenharmony_ci{ 966bf215546Sopenharmony_ci /* Note we use the second common immediate here */ 967bf215546Sopenharmony_ci assert(emit->created_common_immediate); 968bf215546Sopenharmony_ci assert(emit->common_immediate_idx[1] >= 0); 969bf215546Sopenharmony_ci return swizzle(src_register( SVGA3DREG_CONST, 970bf215546Sopenharmony_ci emit->common_immediate_idx[1]), 971bf215546Sopenharmony_ci 0, 0, 0, 0); 972bf215546Sopenharmony_ci} 973bf215546Sopenharmony_ci 974bf215546Sopenharmony_ci 975bf215546Sopenharmony_ci/** 976bf215546Sopenharmony_ci * returns the loop const 977bf215546Sopenharmony_ci */ 978bf215546Sopenharmony_cistatic struct src_register 979bf215546Sopenharmony_ciget_loop_const( struct svga_shader_emitter *emit ) 980bf215546Sopenharmony_ci{ 981bf215546Sopenharmony_ci assert(emit->created_loop_const); 982bf215546Sopenharmony_ci assert(emit->loop_const_idx >= 0); 983bf215546Sopenharmony_ci return src_register( SVGA3DREG_CONSTINT, 984bf215546Sopenharmony_ci emit->loop_const_idx ); 985bf215546Sopenharmony_ci} 986bf215546Sopenharmony_ci 987bf215546Sopenharmony_ci 988bf215546Sopenharmony_cistatic struct src_register 989bf215546Sopenharmony_ciget_fake_arl_const( struct svga_shader_emitter *emit ) 990bf215546Sopenharmony_ci{ 991bf215546Sopenharmony_ci struct src_register reg; 992bf215546Sopenharmony_ci int idx = 0, swizzle = 0, i; 993bf215546Sopenharmony_ci 994bf215546Sopenharmony_ci for (i = 0; i < emit->num_arl_consts; ++ i) { 995bf215546Sopenharmony_ci if (emit->arl_consts[i].arl_num == emit->current_arl) { 996bf215546Sopenharmony_ci idx = emit->arl_consts[i].idx; 997bf215546Sopenharmony_ci swizzle = emit->arl_consts[i].swizzle; 998bf215546Sopenharmony_ci } 999bf215546Sopenharmony_ci } 1000bf215546Sopenharmony_ci 1001bf215546Sopenharmony_ci reg = src_register( SVGA3DREG_CONST, idx ); 1002bf215546Sopenharmony_ci return scalar(reg, swizzle); 1003bf215546Sopenharmony_ci} 1004bf215546Sopenharmony_ci 1005bf215546Sopenharmony_ci 1006bf215546Sopenharmony_ci/** 1007bf215546Sopenharmony_ci * Return a register which holds the width and height of the texture 1008bf215546Sopenharmony_ci * currently bound to the given sampler. 1009bf215546Sopenharmony_ci */ 1010bf215546Sopenharmony_cistatic struct src_register 1011bf215546Sopenharmony_ciget_tex_dimensions( struct svga_shader_emitter *emit, int sampler_num ) 1012bf215546Sopenharmony_ci{ 1013bf215546Sopenharmony_ci int idx; 1014bf215546Sopenharmony_ci struct src_register reg; 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci /* the width/height indexes start right after constants */ 1017bf215546Sopenharmony_ci idx = emit->key.tex[sampler_num].width_height_idx + 1018bf215546Sopenharmony_ci emit->info.file_max[TGSI_FILE_CONSTANT] + 1; 1019bf215546Sopenharmony_ci 1020bf215546Sopenharmony_ci reg = src_register( SVGA3DREG_CONST, idx ); 1021bf215546Sopenharmony_ci return reg; 1022bf215546Sopenharmony_ci} 1023bf215546Sopenharmony_ci 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_cistatic boolean 1026bf215546Sopenharmony_ciemit_fake_arl(struct svga_shader_emitter *emit, 1027bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1028bf215546Sopenharmony_ci{ 1029bf215546Sopenharmony_ci const struct src_register src0 = 1030bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0] ); 1031bf215546Sopenharmony_ci struct src_register src1 = get_fake_arl_const( emit ); 1032bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1033bf215546Sopenharmony_ci SVGA3dShaderDestToken tmp = get_temp( emit ); 1034bf215546Sopenharmony_ci 1035bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), tmp, src0)) 1036bf215546Sopenharmony_ci return FALSE; 1037bf215546Sopenharmony_ci 1038bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), tmp, src( tmp ), 1039bf215546Sopenharmony_ci src1)) 1040bf215546Sopenharmony_ci return FALSE; 1041bf215546Sopenharmony_ci 1042bf215546Sopenharmony_ci /* replicate the original swizzle */ 1043bf215546Sopenharmony_ci src1 = src(tmp); 1044bf215546Sopenharmony_ci src1.base.swizzle = src0.base.swizzle; 1045bf215546Sopenharmony_ci 1046bf215546Sopenharmony_ci return submit_op1( emit, inst_token( SVGA3DOP_MOVA ), 1047bf215546Sopenharmony_ci dst, src1 ); 1048bf215546Sopenharmony_ci} 1049bf215546Sopenharmony_ci 1050bf215546Sopenharmony_ci 1051bf215546Sopenharmony_cistatic boolean 1052bf215546Sopenharmony_ciemit_if(struct svga_shader_emitter *emit, 1053bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1054bf215546Sopenharmony_ci{ 1055bf215546Sopenharmony_ci struct src_register src0 = 1056bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0]); 1057bf215546Sopenharmony_ci struct src_register zero = get_zero_immediate(emit); 1058bf215546Sopenharmony_ci SVGA3dShaderInstToken if_token = inst_token( SVGA3DOP_IFC ); 1059bf215546Sopenharmony_ci 1060bf215546Sopenharmony_ci if_token.control = SVGA3DOPCOMPC_NE; 1061bf215546Sopenharmony_ci 1062bf215546Sopenharmony_ci if (SVGA3dShaderGetRegType(src0.base.value) == SVGA3DREG_CONST) { 1063bf215546Sopenharmony_ci /* 1064bf215546Sopenharmony_ci * Max different constant registers readable per IFC instruction is 1. 1065bf215546Sopenharmony_ci */ 1066bf215546Sopenharmony_ci SVGA3dShaderDestToken tmp = get_temp( emit ); 1067bf215546Sopenharmony_ci 1068bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), tmp, src0)) 1069bf215546Sopenharmony_ci return FALSE; 1070bf215546Sopenharmony_ci 1071bf215546Sopenharmony_ci src0 = scalar(src( tmp ), TGSI_SWIZZLE_X); 1072bf215546Sopenharmony_ci } 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci emit->dynamic_branching_level++; 1075bf215546Sopenharmony_ci 1076bf215546Sopenharmony_ci return (emit_instruction( emit, if_token ) && 1077bf215546Sopenharmony_ci emit_src( emit, src0 ) && 1078bf215546Sopenharmony_ci emit_src( emit, zero ) ); 1079bf215546Sopenharmony_ci} 1080bf215546Sopenharmony_ci 1081bf215546Sopenharmony_ci 1082bf215546Sopenharmony_cistatic boolean 1083bf215546Sopenharmony_ciemit_else(struct svga_shader_emitter *emit, 1084bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1085bf215546Sopenharmony_ci{ 1086bf215546Sopenharmony_ci return emit_instruction(emit, inst_token(SVGA3DOP_ELSE)); 1087bf215546Sopenharmony_ci} 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci 1090bf215546Sopenharmony_cistatic boolean 1091bf215546Sopenharmony_ciemit_endif(struct svga_shader_emitter *emit, 1092bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1093bf215546Sopenharmony_ci{ 1094bf215546Sopenharmony_ci emit->dynamic_branching_level--; 1095bf215546Sopenharmony_ci 1096bf215546Sopenharmony_ci return emit_instruction(emit, inst_token(SVGA3DOP_ENDIF)); 1097bf215546Sopenharmony_ci} 1098bf215546Sopenharmony_ci 1099bf215546Sopenharmony_ci 1100bf215546Sopenharmony_ci/** 1101bf215546Sopenharmony_ci * Translate the following TGSI FLR instruction. 1102bf215546Sopenharmony_ci * FLR DST, SRC 1103bf215546Sopenharmony_ci * To the following SVGA3D instruction sequence. 1104bf215546Sopenharmony_ci * FRC TMP, SRC 1105bf215546Sopenharmony_ci * SUB DST, SRC, TMP 1106bf215546Sopenharmony_ci */ 1107bf215546Sopenharmony_cistatic boolean 1108bf215546Sopenharmony_ciemit_floor(struct svga_shader_emitter *emit, 1109bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn ) 1110bf215546Sopenharmony_ci{ 1111bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1112bf215546Sopenharmony_ci const struct src_register src0 = 1113bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0] ); 1114bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp( emit ); 1115bf215546Sopenharmony_ci 1116bf215546Sopenharmony_ci /* FRC TMP, SRC */ 1117bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_FRC ), temp, src0 )) 1118bf215546Sopenharmony_ci return FALSE; 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_ci /* SUB DST, SRC, TMP */ 1121bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst, src0, 1122bf215546Sopenharmony_ci negate( src( temp ) ) )) 1123bf215546Sopenharmony_ci return FALSE; 1124bf215546Sopenharmony_ci 1125bf215546Sopenharmony_ci return TRUE; 1126bf215546Sopenharmony_ci} 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_ci 1129bf215546Sopenharmony_ci/** 1130bf215546Sopenharmony_ci * Translate the following TGSI CEIL instruction. 1131bf215546Sopenharmony_ci * CEIL DST, SRC 1132bf215546Sopenharmony_ci * To the following SVGA3D instruction sequence. 1133bf215546Sopenharmony_ci * FRC TMP, -SRC 1134bf215546Sopenharmony_ci * ADD DST, SRC, TMP 1135bf215546Sopenharmony_ci */ 1136bf215546Sopenharmony_cistatic boolean 1137bf215546Sopenharmony_ciemit_ceil(struct svga_shader_emitter *emit, 1138bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1139bf215546Sopenharmony_ci{ 1140bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register(emit, insn, 0); 1141bf215546Sopenharmony_ci const struct src_register src0 = 1142bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0]); 1143bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp(emit); 1144bf215546Sopenharmony_ci 1145bf215546Sopenharmony_ci /* FRC TMP, -SRC */ 1146bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token(SVGA3DOP_FRC), temp, negate(src0))) 1147bf215546Sopenharmony_ci return FALSE; 1148bf215546Sopenharmony_ci 1149bf215546Sopenharmony_ci /* ADD DST, SRC, TMP */ 1150bf215546Sopenharmony_ci if (!submit_op2(emit, inst_token(SVGA3DOP_ADD), dst, src0, src(temp))) 1151bf215546Sopenharmony_ci return FALSE; 1152bf215546Sopenharmony_ci 1153bf215546Sopenharmony_ci return TRUE; 1154bf215546Sopenharmony_ci} 1155bf215546Sopenharmony_ci 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_ci/** 1158bf215546Sopenharmony_ci * Translate the following TGSI DIV instruction. 1159bf215546Sopenharmony_ci * DIV DST.xy, SRC0, SRC1 1160bf215546Sopenharmony_ci * To the following SVGA3D instruction sequence. 1161bf215546Sopenharmony_ci * RCP TMP.x, SRC1.xxxx 1162bf215546Sopenharmony_ci * RCP TMP.y, SRC1.yyyy 1163bf215546Sopenharmony_ci * MUL DST.xy, SRC0, TMP 1164bf215546Sopenharmony_ci */ 1165bf215546Sopenharmony_cistatic boolean 1166bf215546Sopenharmony_ciemit_div(struct svga_shader_emitter *emit, 1167bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn ) 1168bf215546Sopenharmony_ci{ 1169bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1170bf215546Sopenharmony_ci const struct src_register src0 = 1171bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0] ); 1172bf215546Sopenharmony_ci const struct src_register src1 = 1173bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[1] ); 1174bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp( emit ); 1175bf215546Sopenharmony_ci unsigned i; 1176bf215546Sopenharmony_ci 1177bf215546Sopenharmony_ci /* For each enabled element, perform a RCP instruction. Note that 1178bf215546Sopenharmony_ci * RCP is scalar in SVGA3D: 1179bf215546Sopenharmony_ci */ 1180bf215546Sopenharmony_ci for (i = 0; i < 4; i++) { 1181bf215546Sopenharmony_ci unsigned channel = 1 << i; 1182bf215546Sopenharmony_ci if (dst.mask & channel) { 1183bf215546Sopenharmony_ci /* RCP TMP.?, SRC1.???? */ 1184bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ), 1185bf215546Sopenharmony_ci writemask(temp, channel), 1186bf215546Sopenharmony_ci scalar(src1, i) )) 1187bf215546Sopenharmony_ci return FALSE; 1188bf215546Sopenharmony_ci } 1189bf215546Sopenharmony_ci } 1190bf215546Sopenharmony_ci 1191bf215546Sopenharmony_ci /* Vector mul: 1192bf215546Sopenharmony_ci * MUL DST, SRC0, TMP 1193bf215546Sopenharmony_ci */ 1194bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), dst, src0, 1195bf215546Sopenharmony_ci src( temp ) )) 1196bf215546Sopenharmony_ci return FALSE; 1197bf215546Sopenharmony_ci 1198bf215546Sopenharmony_ci return TRUE; 1199bf215546Sopenharmony_ci} 1200bf215546Sopenharmony_ci 1201bf215546Sopenharmony_ci 1202bf215546Sopenharmony_ci/** 1203bf215546Sopenharmony_ci * Translate the following TGSI DP2 instruction. 1204bf215546Sopenharmony_ci * DP2 DST, SRC1, SRC2 1205bf215546Sopenharmony_ci * To the following SVGA3D instruction sequence. 1206bf215546Sopenharmony_ci * MUL TMP, SRC1, SRC2 1207bf215546Sopenharmony_ci * ADD DST, TMP.xxxx, TMP.yyyy 1208bf215546Sopenharmony_ci */ 1209bf215546Sopenharmony_cistatic boolean 1210bf215546Sopenharmony_ciemit_dp2(struct svga_shader_emitter *emit, 1211bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn ) 1212bf215546Sopenharmony_ci{ 1213bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1214bf215546Sopenharmony_ci const struct src_register src0 = 1215bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0]); 1216bf215546Sopenharmony_ci const struct src_register src1 = 1217bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[1]); 1218bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp( emit ); 1219bf215546Sopenharmony_ci struct src_register temp_src0, temp_src1; 1220bf215546Sopenharmony_ci 1221bf215546Sopenharmony_ci /* MUL TMP, SRC1, SRC2 */ 1222bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), temp, src0, src1 )) 1223bf215546Sopenharmony_ci return FALSE; 1224bf215546Sopenharmony_ci 1225bf215546Sopenharmony_ci temp_src0 = scalar(src( temp ), TGSI_SWIZZLE_X); 1226bf215546Sopenharmony_ci temp_src1 = scalar(src( temp ), TGSI_SWIZZLE_Y); 1227bf215546Sopenharmony_ci 1228bf215546Sopenharmony_ci /* ADD DST, TMP.xxxx, TMP.yyyy */ 1229bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst, 1230bf215546Sopenharmony_ci temp_src0, temp_src1 )) 1231bf215546Sopenharmony_ci return FALSE; 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_ci return TRUE; 1234bf215546Sopenharmony_ci} 1235bf215546Sopenharmony_ci 1236bf215546Sopenharmony_ci 1237bf215546Sopenharmony_ci/** 1238bf215546Sopenharmony_ci * Sine / Cosine helper function. 1239bf215546Sopenharmony_ci */ 1240bf215546Sopenharmony_cistatic boolean 1241bf215546Sopenharmony_cido_emit_sincos(struct svga_shader_emitter *emit, 1242bf215546Sopenharmony_ci SVGA3dShaderDestToken dst, 1243bf215546Sopenharmony_ci struct src_register src0) 1244bf215546Sopenharmony_ci{ 1245bf215546Sopenharmony_ci src0 = scalar(src0, TGSI_SWIZZLE_X); 1246bf215546Sopenharmony_ci return submit_op1(emit, inst_token(SVGA3DOP_SINCOS), dst, src0); 1247bf215546Sopenharmony_ci} 1248bf215546Sopenharmony_ci 1249bf215546Sopenharmony_ci 1250bf215546Sopenharmony_ci/** 1251bf215546Sopenharmony_ci * Translate TGSI SIN instruction into: 1252bf215546Sopenharmony_ci * SCS TMP SRC 1253bf215546Sopenharmony_ci * MOV DST TMP.yyyy 1254bf215546Sopenharmony_ci */ 1255bf215546Sopenharmony_cistatic boolean 1256bf215546Sopenharmony_ciemit_sin(struct svga_shader_emitter *emit, 1257bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn ) 1258bf215546Sopenharmony_ci{ 1259bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1260bf215546Sopenharmony_ci struct src_register src0 = 1261bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0] ); 1262bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp( emit ); 1263bf215546Sopenharmony_ci 1264bf215546Sopenharmony_ci /* SCS TMP SRC */ 1265bf215546Sopenharmony_ci if (!do_emit_sincos(emit, writemask(temp, TGSI_WRITEMASK_Y), src0)) 1266bf215546Sopenharmony_ci return FALSE; 1267bf215546Sopenharmony_ci 1268bf215546Sopenharmony_ci src0 = scalar(src( temp ), TGSI_SWIZZLE_Y); 1269bf215546Sopenharmony_ci 1270bf215546Sopenharmony_ci /* MOV DST TMP.yyyy */ 1271bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, src0 )) 1272bf215546Sopenharmony_ci return FALSE; 1273bf215546Sopenharmony_ci 1274bf215546Sopenharmony_ci return TRUE; 1275bf215546Sopenharmony_ci} 1276bf215546Sopenharmony_ci 1277bf215546Sopenharmony_ci 1278bf215546Sopenharmony_ci/* 1279bf215546Sopenharmony_ci * Translate TGSI COS instruction into: 1280bf215546Sopenharmony_ci * SCS TMP SRC 1281bf215546Sopenharmony_ci * MOV DST TMP.xxxx 1282bf215546Sopenharmony_ci */ 1283bf215546Sopenharmony_cistatic boolean 1284bf215546Sopenharmony_ciemit_cos(struct svga_shader_emitter *emit, 1285bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1286bf215546Sopenharmony_ci{ 1287bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1288bf215546Sopenharmony_ci struct src_register src0 = 1289bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0] ); 1290bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp( emit ); 1291bf215546Sopenharmony_ci 1292bf215546Sopenharmony_ci /* SCS TMP SRC */ 1293bf215546Sopenharmony_ci if (!do_emit_sincos( emit, writemask(temp, TGSI_WRITEMASK_X), src0 )) 1294bf215546Sopenharmony_ci return FALSE; 1295bf215546Sopenharmony_ci 1296bf215546Sopenharmony_ci src0 = scalar(src( temp ), TGSI_SWIZZLE_X); 1297bf215546Sopenharmony_ci 1298bf215546Sopenharmony_ci /* MOV DST TMP.xxxx */ 1299bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, src0 )) 1300bf215546Sopenharmony_ci return FALSE; 1301bf215546Sopenharmony_ci 1302bf215546Sopenharmony_ci return TRUE; 1303bf215546Sopenharmony_ci} 1304bf215546Sopenharmony_ci 1305bf215546Sopenharmony_ci 1306bf215546Sopenharmony_ci/** 1307bf215546Sopenharmony_ci * Translate/emit TGSI SSG (Set Sign: -1, 0, +1) instruction. 1308bf215546Sopenharmony_ci */ 1309bf215546Sopenharmony_cistatic boolean 1310bf215546Sopenharmony_ciemit_ssg(struct svga_shader_emitter *emit, 1311bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1312bf215546Sopenharmony_ci{ 1313bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1314bf215546Sopenharmony_ci struct src_register src0 = 1315bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0] ); 1316bf215546Sopenharmony_ci SVGA3dShaderDestToken temp0 = get_temp( emit ); 1317bf215546Sopenharmony_ci SVGA3dShaderDestToken temp1 = get_temp( emit ); 1318bf215546Sopenharmony_ci struct src_register zero, one; 1319bf215546Sopenharmony_ci 1320bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_VERTEX) { 1321bf215546Sopenharmony_ci /* SGN DST, SRC0, TMP0, TMP1 */ 1322bf215546Sopenharmony_ci return submit_op3( emit, inst_token( SVGA3DOP_SGN ), dst, src0, 1323bf215546Sopenharmony_ci src( temp0 ), src( temp1 ) ); 1324bf215546Sopenharmony_ci } 1325bf215546Sopenharmony_ci 1326bf215546Sopenharmony_ci one = get_one_immediate(emit); 1327bf215546Sopenharmony_ci zero = get_zero_immediate(emit); 1328bf215546Sopenharmony_ci 1329bf215546Sopenharmony_ci /* CMP TMP0, SRC0, one, zero */ 1330bf215546Sopenharmony_ci if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ), 1331bf215546Sopenharmony_ci writemask( temp0, dst.mask ), src0, one, zero )) 1332bf215546Sopenharmony_ci return FALSE; 1333bf215546Sopenharmony_ci 1334bf215546Sopenharmony_ci /* CMP TMP1, negate(SRC0), negate(one), zero */ 1335bf215546Sopenharmony_ci if (!submit_op3( emit, inst_token( SVGA3DOP_CMP ), 1336bf215546Sopenharmony_ci writemask( temp1, dst.mask ), negate( src0 ), negate( one ), 1337bf215546Sopenharmony_ci zero )) 1338bf215546Sopenharmony_ci return FALSE; 1339bf215546Sopenharmony_ci 1340bf215546Sopenharmony_ci /* ADD DST, TMP0, TMP1 */ 1341bf215546Sopenharmony_ci return submit_op2( emit, inst_token( SVGA3DOP_ADD ), dst, src( temp0 ), 1342bf215546Sopenharmony_ci src( temp1 ) ); 1343bf215546Sopenharmony_ci} 1344bf215546Sopenharmony_ci 1345bf215546Sopenharmony_ci 1346bf215546Sopenharmony_ci/** 1347bf215546Sopenharmony_ci * Translate/emit the conditional discard instruction (discard if 1348bf215546Sopenharmony_ci * any of X,Y,Z,W are negative). 1349bf215546Sopenharmony_ci */ 1350bf215546Sopenharmony_cistatic boolean 1351bf215546Sopenharmony_ciemit_cond_discard(struct svga_shader_emitter *emit, 1352bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1353bf215546Sopenharmony_ci{ 1354bf215546Sopenharmony_ci const struct tgsi_full_src_register *reg = &insn->Src[0]; 1355bf215546Sopenharmony_ci struct src_register src0, srcIn; 1356bf215546Sopenharmony_ci const boolean special = (reg->Register.Absolute || 1357bf215546Sopenharmony_ci reg->Register.Negate || 1358bf215546Sopenharmony_ci reg->Register.Indirect || 1359bf215546Sopenharmony_ci reg->Register.SwizzleX != 0 || 1360bf215546Sopenharmony_ci reg->Register.SwizzleY != 1 || 1361bf215546Sopenharmony_ci reg->Register.SwizzleZ != 2 || 1362bf215546Sopenharmony_ci reg->Register.File != TGSI_FILE_TEMPORARY); 1363bf215546Sopenharmony_ci SVGA3dShaderDestToken temp; 1364bf215546Sopenharmony_ci 1365bf215546Sopenharmony_ci src0 = srcIn = translate_src_register( emit, reg ); 1366bf215546Sopenharmony_ci 1367bf215546Sopenharmony_ci if (special) { 1368bf215546Sopenharmony_ci /* need a temp reg */ 1369bf215546Sopenharmony_ci temp = get_temp( emit ); 1370bf215546Sopenharmony_ci } 1371bf215546Sopenharmony_ci 1372bf215546Sopenharmony_ci if (special) { 1373bf215546Sopenharmony_ci /* move the source into a temp register */ 1374bf215546Sopenharmony_ci submit_op1(emit, inst_token(SVGA3DOP_MOV), temp, src0); 1375bf215546Sopenharmony_ci 1376bf215546Sopenharmony_ci src0 = src( temp ); 1377bf215546Sopenharmony_ci } 1378bf215546Sopenharmony_ci 1379bf215546Sopenharmony_ci /* Do the discard by checking if any of the XYZW components are < 0. 1380bf215546Sopenharmony_ci * Note that ps_2_0 and later take XYZW in consideration, while ps_1_x 1381bf215546Sopenharmony_ci * only used XYZ. The MSDN documentation about this is incorrect. 1382bf215546Sopenharmony_ci */ 1383bf215546Sopenharmony_ci if (!submit_op0( emit, inst_token( SVGA3DOP_TEXKILL ), dst(src0) )) 1384bf215546Sopenharmony_ci return FALSE; 1385bf215546Sopenharmony_ci 1386bf215546Sopenharmony_ci return TRUE; 1387bf215546Sopenharmony_ci} 1388bf215546Sopenharmony_ci 1389bf215546Sopenharmony_ci 1390bf215546Sopenharmony_ci/** 1391bf215546Sopenharmony_ci * Translate/emit the unconditional discard instruction (usually found inside 1392bf215546Sopenharmony_ci * an IF/ELSE/ENDIF block). 1393bf215546Sopenharmony_ci */ 1394bf215546Sopenharmony_cistatic boolean 1395bf215546Sopenharmony_ciemit_discard(struct svga_shader_emitter *emit, 1396bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1397bf215546Sopenharmony_ci{ 1398bf215546Sopenharmony_ci SVGA3dShaderDestToken temp; 1399bf215546Sopenharmony_ci struct src_register one = get_one_immediate(emit); 1400bf215546Sopenharmony_ci SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_TEXKILL ); 1401bf215546Sopenharmony_ci 1402bf215546Sopenharmony_ci /* texkill doesn't allow negation on the operand so lets move 1403bf215546Sopenharmony_ci * negation of {1} to a temp register */ 1404bf215546Sopenharmony_ci temp = get_temp( emit ); 1405bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), temp, 1406bf215546Sopenharmony_ci negate( one ) )) 1407bf215546Sopenharmony_ci return FALSE; 1408bf215546Sopenharmony_ci 1409bf215546Sopenharmony_ci return submit_op0( emit, inst, temp ); 1410bf215546Sopenharmony_ci} 1411bf215546Sopenharmony_ci 1412bf215546Sopenharmony_ci 1413bf215546Sopenharmony_ci/** 1414bf215546Sopenharmony_ci * Test if r1 and r2 are the same register. 1415bf215546Sopenharmony_ci */ 1416bf215546Sopenharmony_cistatic boolean 1417bf215546Sopenharmony_cisame_register(struct src_register r1, struct src_register r2) 1418bf215546Sopenharmony_ci{ 1419bf215546Sopenharmony_ci return (r1.base.num == r2.base.num && 1420bf215546Sopenharmony_ci r1.base.type_upper == r2.base.type_upper && 1421bf215546Sopenharmony_ci r1.base.type_lower == r2.base.type_lower); 1422bf215546Sopenharmony_ci} 1423bf215546Sopenharmony_ci 1424bf215546Sopenharmony_ci 1425bf215546Sopenharmony_ci 1426bf215546Sopenharmony_ci/** 1427bf215546Sopenharmony_ci * Implement conditionals by initializing destination reg to 'fail', 1428bf215546Sopenharmony_ci * then set predicate reg with UFOP_SETP, then move 'pass' to dest 1429bf215546Sopenharmony_ci * based on predicate reg. 1430bf215546Sopenharmony_ci * 1431bf215546Sopenharmony_ci * SETP src0, cmp, src1 -- do this first to avoid aliasing problems. 1432bf215546Sopenharmony_ci * MOV dst, fail 1433bf215546Sopenharmony_ci * MOV dst, pass, p0 1434bf215546Sopenharmony_ci */ 1435bf215546Sopenharmony_cistatic boolean 1436bf215546Sopenharmony_ciemit_conditional(struct svga_shader_emitter *emit, 1437bf215546Sopenharmony_ci enum pipe_compare_func compare_func, 1438bf215546Sopenharmony_ci SVGA3dShaderDestToken dst, 1439bf215546Sopenharmony_ci struct src_register src0, 1440bf215546Sopenharmony_ci struct src_register src1, 1441bf215546Sopenharmony_ci struct src_register pass, 1442bf215546Sopenharmony_ci struct src_register fail) 1443bf215546Sopenharmony_ci{ 1444bf215546Sopenharmony_ci SVGA3dShaderDestToken pred_reg = dst_register( SVGA3DREG_PREDICATE, 0 ); 1445bf215546Sopenharmony_ci SVGA3dShaderInstToken setp_token; 1446bf215546Sopenharmony_ci 1447bf215546Sopenharmony_ci switch (compare_func) { 1448bf215546Sopenharmony_ci case PIPE_FUNC_NEVER: 1449bf215546Sopenharmony_ci return submit_op1( emit, inst_token( SVGA3DOP_MOV ), 1450bf215546Sopenharmony_ci dst, fail ); 1451bf215546Sopenharmony_ci break; 1452bf215546Sopenharmony_ci case PIPE_FUNC_LESS: 1453bf215546Sopenharmony_ci setp_token = inst_token_setp(SVGA3DOPCOMP_LT); 1454bf215546Sopenharmony_ci break; 1455bf215546Sopenharmony_ci case PIPE_FUNC_EQUAL: 1456bf215546Sopenharmony_ci setp_token = inst_token_setp(SVGA3DOPCOMP_EQ); 1457bf215546Sopenharmony_ci break; 1458bf215546Sopenharmony_ci case PIPE_FUNC_LEQUAL: 1459bf215546Sopenharmony_ci setp_token = inst_token_setp(SVGA3DOPCOMP_LE); 1460bf215546Sopenharmony_ci break; 1461bf215546Sopenharmony_ci case PIPE_FUNC_GREATER: 1462bf215546Sopenharmony_ci setp_token = inst_token_setp(SVGA3DOPCOMP_GT); 1463bf215546Sopenharmony_ci break; 1464bf215546Sopenharmony_ci case PIPE_FUNC_NOTEQUAL: 1465bf215546Sopenharmony_ci setp_token = inst_token_setp(SVGA3DOPCOMPC_NE); 1466bf215546Sopenharmony_ci break; 1467bf215546Sopenharmony_ci case PIPE_FUNC_GEQUAL: 1468bf215546Sopenharmony_ci setp_token = inst_token_setp(SVGA3DOPCOMP_GE); 1469bf215546Sopenharmony_ci break; 1470bf215546Sopenharmony_ci case PIPE_FUNC_ALWAYS: 1471bf215546Sopenharmony_ci return submit_op1( emit, inst_token( SVGA3DOP_MOV ), 1472bf215546Sopenharmony_ci dst, pass ); 1473bf215546Sopenharmony_ci break; 1474bf215546Sopenharmony_ci } 1475bf215546Sopenharmony_ci 1476bf215546Sopenharmony_ci if (same_register(src(dst), pass)) { 1477bf215546Sopenharmony_ci /* We'll get bad results if the dst and pass registers are the same 1478bf215546Sopenharmony_ci * so use a temp register containing pass. 1479bf215546Sopenharmony_ci */ 1480bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp(emit); 1481bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token(SVGA3DOP_MOV), temp, pass)) 1482bf215546Sopenharmony_ci return FALSE; 1483bf215546Sopenharmony_ci pass = src(temp); 1484bf215546Sopenharmony_ci } 1485bf215546Sopenharmony_ci 1486bf215546Sopenharmony_ci /* SETP src0, COMPOP, src1 */ 1487bf215546Sopenharmony_ci if (!submit_op2( emit, setp_token, pred_reg, 1488bf215546Sopenharmony_ci src0, src1 )) 1489bf215546Sopenharmony_ci return FALSE; 1490bf215546Sopenharmony_ci 1491bf215546Sopenharmony_ci /* MOV dst, fail */ 1492bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token(SVGA3DOP_MOV), dst, fail)) 1493bf215546Sopenharmony_ci return FALSE; 1494bf215546Sopenharmony_ci 1495bf215546Sopenharmony_ci /* MOV dst, pass (predicated) 1496bf215546Sopenharmony_ci * 1497bf215546Sopenharmony_ci * Note that the predicate reg (and possible modifiers) is passed 1498bf215546Sopenharmony_ci * as the first source argument. 1499bf215546Sopenharmony_ci */ 1500bf215546Sopenharmony_ci if (!submit_op2(emit, 1501bf215546Sopenharmony_ci inst_token_predicated(SVGA3DOP_MOV), dst, 1502bf215546Sopenharmony_ci src(pred_reg), pass)) 1503bf215546Sopenharmony_ci return FALSE; 1504bf215546Sopenharmony_ci 1505bf215546Sopenharmony_ci return TRUE; 1506bf215546Sopenharmony_ci} 1507bf215546Sopenharmony_ci 1508bf215546Sopenharmony_ci 1509bf215546Sopenharmony_ci/** 1510bf215546Sopenharmony_ci * Helper for emiting 'selection' commands. Basically: 1511bf215546Sopenharmony_ci * if (src0 OP src1) 1512bf215546Sopenharmony_ci * dst = 1.0; 1513bf215546Sopenharmony_ci * else 1514bf215546Sopenharmony_ci * dst = 0.0; 1515bf215546Sopenharmony_ci */ 1516bf215546Sopenharmony_cistatic boolean 1517bf215546Sopenharmony_ciemit_select(struct svga_shader_emitter *emit, 1518bf215546Sopenharmony_ci enum pipe_compare_func compare_func, 1519bf215546Sopenharmony_ci SVGA3dShaderDestToken dst, 1520bf215546Sopenharmony_ci struct src_register src0, 1521bf215546Sopenharmony_ci struct src_register src1 ) 1522bf215546Sopenharmony_ci{ 1523bf215546Sopenharmony_ci /* There are some SVGA instructions which implement some selects 1524bf215546Sopenharmony_ci * directly, but they are only available in the vertex shader. 1525bf215546Sopenharmony_ci */ 1526bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_VERTEX) { 1527bf215546Sopenharmony_ci switch (compare_func) { 1528bf215546Sopenharmony_ci case PIPE_FUNC_GEQUAL: 1529bf215546Sopenharmony_ci return submit_op2( emit, inst_token( SVGA3DOP_SGE ), dst, src0, src1 ); 1530bf215546Sopenharmony_ci case PIPE_FUNC_LEQUAL: 1531bf215546Sopenharmony_ci return submit_op2( emit, inst_token( SVGA3DOP_SGE ), dst, src1, src0 ); 1532bf215546Sopenharmony_ci case PIPE_FUNC_GREATER: 1533bf215546Sopenharmony_ci return submit_op2( emit, inst_token( SVGA3DOP_SLT ), dst, src1, src0 ); 1534bf215546Sopenharmony_ci case PIPE_FUNC_LESS: 1535bf215546Sopenharmony_ci return submit_op2( emit, inst_token( SVGA3DOP_SLT ), dst, src0, src1 ); 1536bf215546Sopenharmony_ci default: 1537bf215546Sopenharmony_ci break; 1538bf215546Sopenharmony_ci } 1539bf215546Sopenharmony_ci } 1540bf215546Sopenharmony_ci 1541bf215546Sopenharmony_ci /* Otherwise, need to use the setp approach: 1542bf215546Sopenharmony_ci */ 1543bf215546Sopenharmony_ci { 1544bf215546Sopenharmony_ci struct src_register one, zero; 1545bf215546Sopenharmony_ci /* zero immediate is 0,0,0,1 */ 1546bf215546Sopenharmony_ci zero = get_zero_immediate(emit); 1547bf215546Sopenharmony_ci one = get_one_immediate(emit); 1548bf215546Sopenharmony_ci 1549bf215546Sopenharmony_ci return emit_conditional(emit, compare_func, dst, src0, src1, one, zero); 1550bf215546Sopenharmony_ci } 1551bf215546Sopenharmony_ci} 1552bf215546Sopenharmony_ci 1553bf215546Sopenharmony_ci 1554bf215546Sopenharmony_ci/** 1555bf215546Sopenharmony_ci * Translate/emit a TGSI SEQ, SNE, SLT, SGE, etc. instruction. 1556bf215546Sopenharmony_ci */ 1557bf215546Sopenharmony_cistatic boolean 1558bf215546Sopenharmony_ciemit_select_op(struct svga_shader_emitter *emit, 1559bf215546Sopenharmony_ci unsigned compare, 1560bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1561bf215546Sopenharmony_ci{ 1562bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1563bf215546Sopenharmony_ci struct src_register src0 = translate_src_register( 1564bf215546Sopenharmony_ci emit, &insn->Src[0] ); 1565bf215546Sopenharmony_ci struct src_register src1 = translate_src_register( 1566bf215546Sopenharmony_ci emit, &insn->Src[1] ); 1567bf215546Sopenharmony_ci 1568bf215546Sopenharmony_ci return emit_select( emit, compare, dst, src0, src1 ); 1569bf215546Sopenharmony_ci} 1570bf215546Sopenharmony_ci 1571bf215546Sopenharmony_ci 1572bf215546Sopenharmony_ci/** 1573bf215546Sopenharmony_ci * Translate TGSI CMP instruction. Component-wise: 1574bf215546Sopenharmony_ci * dst = (src0 < 0.0) ? src1 : src2 1575bf215546Sopenharmony_ci */ 1576bf215546Sopenharmony_cistatic boolean 1577bf215546Sopenharmony_ciemit_cmp(struct svga_shader_emitter *emit, 1578bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1579bf215546Sopenharmony_ci{ 1580bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 1581bf215546Sopenharmony_ci const struct src_register src0 = 1582bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0] ); 1583bf215546Sopenharmony_ci const struct src_register src1 = 1584bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[1] ); 1585bf215546Sopenharmony_ci const struct src_register src2 = 1586bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[2] ); 1587bf215546Sopenharmony_ci 1588bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_VERTEX) { 1589bf215546Sopenharmony_ci struct src_register zero = get_zero_immediate(emit); 1590bf215546Sopenharmony_ci /* We used to simulate CMP with SLT+LRP. But that didn't work when 1591bf215546Sopenharmony_ci * src1 or src2 was Inf/NaN. In particular, GLSL sqrt(0) failed 1592bf215546Sopenharmony_ci * because it involves a CMP to handle the 0 case. 1593bf215546Sopenharmony_ci * Use a conditional expression instead. 1594bf215546Sopenharmony_ci */ 1595bf215546Sopenharmony_ci return emit_conditional(emit, PIPE_FUNC_LESS, dst, 1596bf215546Sopenharmony_ci src0, zero, src1, src2); 1597bf215546Sopenharmony_ci } 1598bf215546Sopenharmony_ci else { 1599bf215546Sopenharmony_ci assert(emit->unit == PIPE_SHADER_FRAGMENT); 1600bf215546Sopenharmony_ci 1601bf215546Sopenharmony_ci /* CMP DST, SRC0, SRC2, SRC1 */ 1602bf215546Sopenharmony_ci return submit_op3( emit, inst_token( SVGA3DOP_CMP ), dst, 1603bf215546Sopenharmony_ci src0, src2, src1); 1604bf215546Sopenharmony_ci } 1605bf215546Sopenharmony_ci} 1606bf215546Sopenharmony_ci 1607bf215546Sopenharmony_ci 1608bf215546Sopenharmony_ci/** 1609bf215546Sopenharmony_ci * Translate/emit 2-operand (coord, sampler) texture instructions. 1610bf215546Sopenharmony_ci */ 1611bf215546Sopenharmony_cistatic boolean 1612bf215546Sopenharmony_ciemit_tex2(struct svga_shader_emitter *emit, 1613bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn, 1614bf215546Sopenharmony_ci SVGA3dShaderDestToken dst) 1615bf215546Sopenharmony_ci{ 1616bf215546Sopenharmony_ci SVGA3dShaderInstToken inst; 1617bf215546Sopenharmony_ci struct src_register texcoord; 1618bf215546Sopenharmony_ci struct src_register sampler; 1619bf215546Sopenharmony_ci SVGA3dShaderDestToken tmp; 1620bf215546Sopenharmony_ci 1621bf215546Sopenharmony_ci inst.value = 0; 1622bf215546Sopenharmony_ci 1623bf215546Sopenharmony_ci switch (insn->Instruction.Opcode) { 1624bf215546Sopenharmony_ci case TGSI_OPCODE_TEX: 1625bf215546Sopenharmony_ci inst.op = SVGA3DOP_TEX; 1626bf215546Sopenharmony_ci break; 1627bf215546Sopenharmony_ci case TGSI_OPCODE_TXP: 1628bf215546Sopenharmony_ci inst.op = SVGA3DOP_TEX; 1629bf215546Sopenharmony_ci inst.control = SVGA3DOPCONT_PROJECT; 1630bf215546Sopenharmony_ci break; 1631bf215546Sopenharmony_ci case TGSI_OPCODE_TXB: 1632bf215546Sopenharmony_ci inst.op = SVGA3DOP_TEX; 1633bf215546Sopenharmony_ci inst.control = SVGA3DOPCONT_BIAS; 1634bf215546Sopenharmony_ci break; 1635bf215546Sopenharmony_ci case TGSI_OPCODE_TXL: 1636bf215546Sopenharmony_ci inst.op = SVGA3DOP_TEXLDL; 1637bf215546Sopenharmony_ci break; 1638bf215546Sopenharmony_ci default: 1639bf215546Sopenharmony_ci assert(0); 1640bf215546Sopenharmony_ci return FALSE; 1641bf215546Sopenharmony_ci } 1642bf215546Sopenharmony_ci 1643bf215546Sopenharmony_ci texcoord = translate_src_register( emit, &insn->Src[0] ); 1644bf215546Sopenharmony_ci sampler = translate_src_register( emit, &insn->Src[1] ); 1645bf215546Sopenharmony_ci 1646bf215546Sopenharmony_ci if (emit->key.tex[sampler.base.num].unnormalized || 1647bf215546Sopenharmony_ci emit->dynamic_branching_level > 0) 1648bf215546Sopenharmony_ci tmp = get_temp( emit ); 1649bf215546Sopenharmony_ci 1650bf215546Sopenharmony_ci /* Can't do mipmapping inside dynamic branch constructs. Force LOD 1651bf215546Sopenharmony_ci * zero in that case. 1652bf215546Sopenharmony_ci */ 1653bf215546Sopenharmony_ci if (emit->dynamic_branching_level > 0 && 1654bf215546Sopenharmony_ci inst.op == SVGA3DOP_TEX && 1655bf215546Sopenharmony_ci SVGA3dShaderGetRegType(texcoord.base.value) == SVGA3DREG_TEMP) { 1656bf215546Sopenharmony_ci struct src_register zero = get_zero_immediate(emit); 1657bf215546Sopenharmony_ci 1658bf215546Sopenharmony_ci /* MOV tmp, texcoord */ 1659bf215546Sopenharmony_ci if (!submit_op1( emit, 1660bf215546Sopenharmony_ci inst_token( SVGA3DOP_MOV ), 1661bf215546Sopenharmony_ci tmp, 1662bf215546Sopenharmony_ci texcoord )) 1663bf215546Sopenharmony_ci return FALSE; 1664bf215546Sopenharmony_ci 1665bf215546Sopenharmony_ci /* MOV tmp.w, zero */ 1666bf215546Sopenharmony_ci if (!submit_op1( emit, 1667bf215546Sopenharmony_ci inst_token( SVGA3DOP_MOV ), 1668bf215546Sopenharmony_ci writemask( tmp, TGSI_WRITEMASK_W ), 1669bf215546Sopenharmony_ci zero )) 1670bf215546Sopenharmony_ci return FALSE; 1671bf215546Sopenharmony_ci 1672bf215546Sopenharmony_ci texcoord = src( tmp ); 1673bf215546Sopenharmony_ci inst.op = SVGA3DOP_TEXLDL; 1674bf215546Sopenharmony_ci } 1675bf215546Sopenharmony_ci 1676bf215546Sopenharmony_ci /* Explicit normalization of texcoords: 1677bf215546Sopenharmony_ci */ 1678bf215546Sopenharmony_ci if (emit->key.tex[sampler.base.num].unnormalized) { 1679bf215546Sopenharmony_ci struct src_register wh = get_tex_dimensions( emit, sampler.base.num ); 1680bf215546Sopenharmony_ci 1681bf215546Sopenharmony_ci /* MUL tmp, SRC0, WH */ 1682bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), 1683bf215546Sopenharmony_ci tmp, texcoord, wh )) 1684bf215546Sopenharmony_ci return FALSE; 1685bf215546Sopenharmony_ci 1686bf215546Sopenharmony_ci texcoord = src( tmp ); 1687bf215546Sopenharmony_ci } 1688bf215546Sopenharmony_ci 1689bf215546Sopenharmony_ci return submit_op2( emit, inst, dst, texcoord, sampler ); 1690bf215546Sopenharmony_ci} 1691bf215546Sopenharmony_ci 1692bf215546Sopenharmony_ci 1693bf215546Sopenharmony_ci/** 1694bf215546Sopenharmony_ci * Translate/emit 4-operand (coord, ddx, ddy, sampler) texture instructions. 1695bf215546Sopenharmony_ci */ 1696bf215546Sopenharmony_cistatic boolean 1697bf215546Sopenharmony_ciemit_tex4(struct svga_shader_emitter *emit, 1698bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn, 1699bf215546Sopenharmony_ci SVGA3dShaderDestToken dst ) 1700bf215546Sopenharmony_ci{ 1701bf215546Sopenharmony_ci SVGA3dShaderInstToken inst; 1702bf215546Sopenharmony_ci struct src_register texcoord; 1703bf215546Sopenharmony_ci struct src_register ddx; 1704bf215546Sopenharmony_ci struct src_register ddy; 1705bf215546Sopenharmony_ci struct src_register sampler; 1706bf215546Sopenharmony_ci 1707bf215546Sopenharmony_ci texcoord = translate_src_register( emit, &insn->Src[0] ); 1708bf215546Sopenharmony_ci ddx = translate_src_register( emit, &insn->Src[1] ); 1709bf215546Sopenharmony_ci ddy = translate_src_register( emit, &insn->Src[2] ); 1710bf215546Sopenharmony_ci sampler = translate_src_register( emit, &insn->Src[3] ); 1711bf215546Sopenharmony_ci 1712bf215546Sopenharmony_ci inst.value = 0; 1713bf215546Sopenharmony_ci 1714bf215546Sopenharmony_ci switch (insn->Instruction.Opcode) { 1715bf215546Sopenharmony_ci case TGSI_OPCODE_TXD: 1716bf215546Sopenharmony_ci inst.op = SVGA3DOP_TEXLDD; /* 4 args! */ 1717bf215546Sopenharmony_ci break; 1718bf215546Sopenharmony_ci default: 1719bf215546Sopenharmony_ci assert(0); 1720bf215546Sopenharmony_ci return FALSE; 1721bf215546Sopenharmony_ci } 1722bf215546Sopenharmony_ci 1723bf215546Sopenharmony_ci return submit_op4( emit, inst, dst, texcoord, sampler, ddx, ddy ); 1724bf215546Sopenharmony_ci} 1725bf215546Sopenharmony_ci 1726bf215546Sopenharmony_ci 1727bf215546Sopenharmony_ci/** 1728bf215546Sopenharmony_ci * Emit texture swizzle code. We do this here since SVGA samplers don't 1729bf215546Sopenharmony_ci * directly support swizzles. 1730bf215546Sopenharmony_ci */ 1731bf215546Sopenharmony_cistatic boolean 1732bf215546Sopenharmony_ciemit_tex_swizzle(struct svga_shader_emitter *emit, 1733bf215546Sopenharmony_ci SVGA3dShaderDestToken dst, 1734bf215546Sopenharmony_ci struct src_register src, 1735bf215546Sopenharmony_ci unsigned swizzle_x, 1736bf215546Sopenharmony_ci unsigned swizzle_y, 1737bf215546Sopenharmony_ci unsigned swizzle_z, 1738bf215546Sopenharmony_ci unsigned swizzle_w) 1739bf215546Sopenharmony_ci{ 1740bf215546Sopenharmony_ci const unsigned swizzleIn[4] = {swizzle_x, swizzle_y, swizzle_z, swizzle_w}; 1741bf215546Sopenharmony_ci unsigned srcSwizzle[4]; 1742bf215546Sopenharmony_ci unsigned srcWritemask = 0x0, zeroWritemask = 0x0, oneWritemask = 0x0; 1743bf215546Sopenharmony_ci unsigned i; 1744bf215546Sopenharmony_ci 1745bf215546Sopenharmony_ci /* build writemasks and srcSwizzle terms */ 1746bf215546Sopenharmony_ci for (i = 0; i < 4; i++) { 1747bf215546Sopenharmony_ci if (swizzleIn[i] == PIPE_SWIZZLE_0) { 1748bf215546Sopenharmony_ci srcSwizzle[i] = TGSI_SWIZZLE_X + i; 1749bf215546Sopenharmony_ci zeroWritemask |= (1 << i); 1750bf215546Sopenharmony_ci } 1751bf215546Sopenharmony_ci else if (swizzleIn[i] == PIPE_SWIZZLE_1) { 1752bf215546Sopenharmony_ci srcSwizzle[i] = TGSI_SWIZZLE_X + i; 1753bf215546Sopenharmony_ci oneWritemask |= (1 << i); 1754bf215546Sopenharmony_ci } 1755bf215546Sopenharmony_ci else { 1756bf215546Sopenharmony_ci srcSwizzle[i] = swizzleIn[i]; 1757bf215546Sopenharmony_ci srcWritemask |= (1 << i); 1758bf215546Sopenharmony_ci } 1759bf215546Sopenharmony_ci } 1760bf215546Sopenharmony_ci 1761bf215546Sopenharmony_ci /* write x/y/z/w comps */ 1762bf215546Sopenharmony_ci if (dst.mask & srcWritemask) { 1763bf215546Sopenharmony_ci if (!submit_op1(emit, 1764bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 1765bf215546Sopenharmony_ci writemask(dst, srcWritemask), 1766bf215546Sopenharmony_ci swizzle(src, 1767bf215546Sopenharmony_ci srcSwizzle[0], 1768bf215546Sopenharmony_ci srcSwizzle[1], 1769bf215546Sopenharmony_ci srcSwizzle[2], 1770bf215546Sopenharmony_ci srcSwizzle[3]))) 1771bf215546Sopenharmony_ci return FALSE; 1772bf215546Sopenharmony_ci } 1773bf215546Sopenharmony_ci 1774bf215546Sopenharmony_ci /* write 0 comps */ 1775bf215546Sopenharmony_ci if (dst.mask & zeroWritemask) { 1776bf215546Sopenharmony_ci if (!submit_op1(emit, 1777bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 1778bf215546Sopenharmony_ci writemask(dst, zeroWritemask), 1779bf215546Sopenharmony_ci get_zero_immediate(emit))) 1780bf215546Sopenharmony_ci return FALSE; 1781bf215546Sopenharmony_ci } 1782bf215546Sopenharmony_ci 1783bf215546Sopenharmony_ci /* write 1 comps */ 1784bf215546Sopenharmony_ci if (dst.mask & oneWritemask) { 1785bf215546Sopenharmony_ci if (!submit_op1(emit, 1786bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 1787bf215546Sopenharmony_ci writemask(dst, oneWritemask), 1788bf215546Sopenharmony_ci get_one_immediate(emit))) 1789bf215546Sopenharmony_ci return FALSE; 1790bf215546Sopenharmony_ci } 1791bf215546Sopenharmony_ci 1792bf215546Sopenharmony_ci return TRUE; 1793bf215546Sopenharmony_ci} 1794bf215546Sopenharmony_ci 1795bf215546Sopenharmony_ci 1796bf215546Sopenharmony_ci/** 1797bf215546Sopenharmony_ci * Translate/emit a TGSI texture sample instruction. 1798bf215546Sopenharmony_ci */ 1799bf215546Sopenharmony_cistatic boolean 1800bf215546Sopenharmony_ciemit_tex(struct svga_shader_emitter *emit, 1801bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1802bf215546Sopenharmony_ci{ 1803bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = 1804bf215546Sopenharmony_ci translate_dst_register( emit, insn, 0 ); 1805bf215546Sopenharmony_ci struct src_register src0 = 1806bf215546Sopenharmony_ci translate_src_register( emit, &insn->Src[0] ); 1807bf215546Sopenharmony_ci struct src_register src1 = 1808bf215546Sopenharmony_ci translate_src_register( emit, &insn->Src[1] ); 1809bf215546Sopenharmony_ci 1810bf215546Sopenharmony_ci SVGA3dShaderDestToken tex_result; 1811bf215546Sopenharmony_ci const unsigned unit = src1.base.num; 1812bf215546Sopenharmony_ci 1813bf215546Sopenharmony_ci /* check for shadow samplers */ 1814bf215546Sopenharmony_ci boolean compare = (emit->key.tex[unit].compare_mode == 1815bf215546Sopenharmony_ci PIPE_TEX_COMPARE_R_TO_TEXTURE); 1816bf215546Sopenharmony_ci 1817bf215546Sopenharmony_ci /* texture swizzle */ 1818bf215546Sopenharmony_ci boolean swizzle = (emit->key.tex[unit].swizzle_r != PIPE_SWIZZLE_X || 1819bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_g != PIPE_SWIZZLE_Y || 1820bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_b != PIPE_SWIZZLE_Z || 1821bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_a != PIPE_SWIZZLE_W); 1822bf215546Sopenharmony_ci 1823bf215546Sopenharmony_ci boolean saturate = insn->Instruction.Saturate; 1824bf215546Sopenharmony_ci 1825bf215546Sopenharmony_ci /* If doing compare processing or tex swizzle or saturation, we need to put 1826bf215546Sopenharmony_ci * the fetched color into a temporary so it can be used as a source later on. 1827bf215546Sopenharmony_ci */ 1828bf215546Sopenharmony_ci if (compare || swizzle || saturate) { 1829bf215546Sopenharmony_ci tex_result = get_temp( emit ); 1830bf215546Sopenharmony_ci } 1831bf215546Sopenharmony_ci else { 1832bf215546Sopenharmony_ci tex_result = dst; 1833bf215546Sopenharmony_ci } 1834bf215546Sopenharmony_ci 1835bf215546Sopenharmony_ci switch(insn->Instruction.Opcode) { 1836bf215546Sopenharmony_ci case TGSI_OPCODE_TEX: 1837bf215546Sopenharmony_ci case TGSI_OPCODE_TXB: 1838bf215546Sopenharmony_ci case TGSI_OPCODE_TXP: 1839bf215546Sopenharmony_ci case TGSI_OPCODE_TXL: 1840bf215546Sopenharmony_ci if (!emit_tex2( emit, insn, tex_result )) 1841bf215546Sopenharmony_ci return FALSE; 1842bf215546Sopenharmony_ci break; 1843bf215546Sopenharmony_ci case TGSI_OPCODE_TXD: 1844bf215546Sopenharmony_ci if (!emit_tex4( emit, insn, tex_result )) 1845bf215546Sopenharmony_ci return FALSE; 1846bf215546Sopenharmony_ci break; 1847bf215546Sopenharmony_ci default: 1848bf215546Sopenharmony_ci assert(0); 1849bf215546Sopenharmony_ci } 1850bf215546Sopenharmony_ci 1851bf215546Sopenharmony_ci if (compare) { 1852bf215546Sopenharmony_ci SVGA3dShaderDestToken dst2; 1853bf215546Sopenharmony_ci 1854bf215546Sopenharmony_ci if (swizzle || saturate) 1855bf215546Sopenharmony_ci dst2 = tex_result; 1856bf215546Sopenharmony_ci else 1857bf215546Sopenharmony_ci dst2 = dst; 1858bf215546Sopenharmony_ci 1859bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_XYZ) { 1860bf215546Sopenharmony_ci SVGA3dShaderDestToken src0_zdivw = get_temp( emit ); 1861bf215546Sopenharmony_ci /* When sampling a depth texture, the result of the comparison is in 1862bf215546Sopenharmony_ci * the Y component. 1863bf215546Sopenharmony_ci */ 1864bf215546Sopenharmony_ci struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y); 1865bf215546Sopenharmony_ci struct src_register r_coord; 1866bf215546Sopenharmony_ci 1867bf215546Sopenharmony_ci if (insn->Instruction.Opcode == TGSI_OPCODE_TXP) { 1868bf215546Sopenharmony_ci /* Divide texcoord R by Q */ 1869bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_RCP ), 1870bf215546Sopenharmony_ci writemask(src0_zdivw, TGSI_WRITEMASK_X), 1871bf215546Sopenharmony_ci scalar(src0, TGSI_SWIZZLE_W) )) 1872bf215546Sopenharmony_ci return FALSE; 1873bf215546Sopenharmony_ci 1874bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), 1875bf215546Sopenharmony_ci writemask(src0_zdivw, TGSI_WRITEMASK_X), 1876bf215546Sopenharmony_ci scalar(src0, TGSI_SWIZZLE_Z), 1877bf215546Sopenharmony_ci scalar(src(src0_zdivw), TGSI_SWIZZLE_X) )) 1878bf215546Sopenharmony_ci return FALSE; 1879bf215546Sopenharmony_ci 1880bf215546Sopenharmony_ci r_coord = scalar(src(src0_zdivw), TGSI_SWIZZLE_X); 1881bf215546Sopenharmony_ci } 1882bf215546Sopenharmony_ci else { 1883bf215546Sopenharmony_ci r_coord = scalar(src0, TGSI_SWIZZLE_Z); 1884bf215546Sopenharmony_ci } 1885bf215546Sopenharmony_ci 1886bf215546Sopenharmony_ci /* Compare texture sample value against R component of texcoord */ 1887bf215546Sopenharmony_ci if (!emit_select(emit, 1888bf215546Sopenharmony_ci emit->key.tex[unit].compare_func, 1889bf215546Sopenharmony_ci writemask( dst2, TGSI_WRITEMASK_XYZ ), 1890bf215546Sopenharmony_ci r_coord, 1891bf215546Sopenharmony_ci tex_src_x)) 1892bf215546Sopenharmony_ci return FALSE; 1893bf215546Sopenharmony_ci } 1894bf215546Sopenharmony_ci 1895bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_W) { 1896bf215546Sopenharmony_ci struct src_register one = get_one_immediate(emit); 1897bf215546Sopenharmony_ci 1898bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), 1899bf215546Sopenharmony_ci writemask( dst2, TGSI_WRITEMASK_W ), 1900bf215546Sopenharmony_ci one )) 1901bf215546Sopenharmony_ci return FALSE; 1902bf215546Sopenharmony_ci } 1903bf215546Sopenharmony_ci } 1904bf215546Sopenharmony_ci 1905bf215546Sopenharmony_ci if (saturate && !swizzle) { 1906bf215546Sopenharmony_ci /* MOV_SAT real_dst, dst */ 1907bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, src(tex_result) )) 1908bf215546Sopenharmony_ci return FALSE; 1909bf215546Sopenharmony_ci } 1910bf215546Sopenharmony_ci else if (swizzle) { 1911bf215546Sopenharmony_ci /* swizzle from tex_result to dst (handles saturation too, if any) */ 1912bf215546Sopenharmony_ci emit_tex_swizzle(emit, 1913bf215546Sopenharmony_ci dst, src(tex_result), 1914bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_r, 1915bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_g, 1916bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_b, 1917bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_a); 1918bf215546Sopenharmony_ci } 1919bf215546Sopenharmony_ci 1920bf215546Sopenharmony_ci return TRUE; 1921bf215546Sopenharmony_ci} 1922bf215546Sopenharmony_ci 1923bf215546Sopenharmony_ci 1924bf215546Sopenharmony_cistatic boolean 1925bf215546Sopenharmony_ciemit_bgnloop(struct svga_shader_emitter *emit, 1926bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1927bf215546Sopenharmony_ci{ 1928bf215546Sopenharmony_ci SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_LOOP ); 1929bf215546Sopenharmony_ci struct src_register loop_reg = src_register( SVGA3DREG_LOOP, 0 ); 1930bf215546Sopenharmony_ci struct src_register const_int = get_loop_const( emit ); 1931bf215546Sopenharmony_ci 1932bf215546Sopenharmony_ci emit->dynamic_branching_level++; 1933bf215546Sopenharmony_ci 1934bf215546Sopenharmony_ci return (emit_instruction( emit, inst ) && 1935bf215546Sopenharmony_ci emit_src( emit, loop_reg ) && 1936bf215546Sopenharmony_ci emit_src( emit, const_int ) ); 1937bf215546Sopenharmony_ci} 1938bf215546Sopenharmony_ci 1939bf215546Sopenharmony_ci 1940bf215546Sopenharmony_cistatic boolean 1941bf215546Sopenharmony_ciemit_endloop(struct svga_shader_emitter *emit, 1942bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1943bf215546Sopenharmony_ci{ 1944bf215546Sopenharmony_ci SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_ENDLOOP ); 1945bf215546Sopenharmony_ci 1946bf215546Sopenharmony_ci emit->dynamic_branching_level--; 1947bf215546Sopenharmony_ci 1948bf215546Sopenharmony_ci return emit_instruction( emit, inst ); 1949bf215546Sopenharmony_ci} 1950bf215546Sopenharmony_ci 1951bf215546Sopenharmony_ci 1952bf215546Sopenharmony_ci/** 1953bf215546Sopenharmony_ci * Translate/emit TGSI BREAK (out of loop) instruction. 1954bf215546Sopenharmony_ci */ 1955bf215546Sopenharmony_cistatic boolean 1956bf215546Sopenharmony_ciemit_brk(struct svga_shader_emitter *emit, 1957bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1958bf215546Sopenharmony_ci{ 1959bf215546Sopenharmony_ci SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_BREAK ); 1960bf215546Sopenharmony_ci return emit_instruction( emit, inst ); 1961bf215546Sopenharmony_ci} 1962bf215546Sopenharmony_ci 1963bf215546Sopenharmony_ci 1964bf215546Sopenharmony_ci/** 1965bf215546Sopenharmony_ci * Emit simple instruction which operates on one scalar value (not 1966bf215546Sopenharmony_ci * a vector). Ex: LG2, RCP, RSQ. 1967bf215546Sopenharmony_ci */ 1968bf215546Sopenharmony_cistatic boolean 1969bf215546Sopenharmony_ciemit_scalar_op1(struct svga_shader_emitter *emit, 1970bf215546Sopenharmony_ci SVGA3dShaderOpCodeType opcode, 1971bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1972bf215546Sopenharmony_ci{ 1973bf215546Sopenharmony_ci SVGA3dShaderInstToken inst; 1974bf215546Sopenharmony_ci SVGA3dShaderDestToken dst; 1975bf215546Sopenharmony_ci struct src_register src; 1976bf215546Sopenharmony_ci 1977bf215546Sopenharmony_ci inst = inst_token( opcode ); 1978bf215546Sopenharmony_ci dst = translate_dst_register( emit, insn, 0 ); 1979bf215546Sopenharmony_ci src = translate_src_register( emit, &insn->Src[0] ); 1980bf215546Sopenharmony_ci src = scalar( src, TGSI_SWIZZLE_X ); 1981bf215546Sopenharmony_ci 1982bf215546Sopenharmony_ci return submit_op1( emit, inst, dst, src ); 1983bf215546Sopenharmony_ci} 1984bf215546Sopenharmony_ci 1985bf215546Sopenharmony_ci 1986bf215546Sopenharmony_ci/** 1987bf215546Sopenharmony_ci * Translate/emit a simple instruction (one which has no special-case 1988bf215546Sopenharmony_ci * code) such as ADD, MUL, MIN, MAX. 1989bf215546Sopenharmony_ci */ 1990bf215546Sopenharmony_cistatic boolean 1991bf215546Sopenharmony_ciemit_simple_instruction(struct svga_shader_emitter *emit, 1992bf215546Sopenharmony_ci SVGA3dShaderOpCodeType opcode, 1993bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 1994bf215546Sopenharmony_ci{ 1995bf215546Sopenharmony_ci const struct tgsi_full_src_register *src = insn->Src; 1996bf215546Sopenharmony_ci SVGA3dShaderInstToken inst; 1997bf215546Sopenharmony_ci SVGA3dShaderDestToken dst; 1998bf215546Sopenharmony_ci 1999bf215546Sopenharmony_ci inst = inst_token( opcode ); 2000bf215546Sopenharmony_ci dst = translate_dst_register( emit, insn, 0 ); 2001bf215546Sopenharmony_ci 2002bf215546Sopenharmony_ci switch (insn->Instruction.NumSrcRegs) { 2003bf215546Sopenharmony_ci case 0: 2004bf215546Sopenharmony_ci return submit_op0( emit, inst, dst ); 2005bf215546Sopenharmony_ci case 1: 2006bf215546Sopenharmony_ci return submit_op1( emit, inst, dst, 2007bf215546Sopenharmony_ci translate_src_register( emit, &src[0] )); 2008bf215546Sopenharmony_ci case 2: 2009bf215546Sopenharmony_ci return submit_op2( emit, inst, dst, 2010bf215546Sopenharmony_ci translate_src_register( emit, &src[0] ), 2011bf215546Sopenharmony_ci translate_src_register( emit, &src[1] ) ); 2012bf215546Sopenharmony_ci case 3: 2013bf215546Sopenharmony_ci return submit_op3( emit, inst, dst, 2014bf215546Sopenharmony_ci translate_src_register( emit, &src[0] ), 2015bf215546Sopenharmony_ci translate_src_register( emit, &src[1] ), 2016bf215546Sopenharmony_ci translate_src_register( emit, &src[2] ) ); 2017bf215546Sopenharmony_ci default: 2018bf215546Sopenharmony_ci assert(0); 2019bf215546Sopenharmony_ci return FALSE; 2020bf215546Sopenharmony_ci } 2021bf215546Sopenharmony_ci} 2022bf215546Sopenharmony_ci 2023bf215546Sopenharmony_ci 2024bf215546Sopenharmony_ci/** 2025bf215546Sopenharmony_ci * TGSI_OPCODE_MOVE is only special-cased here to detect the 2026bf215546Sopenharmony_ci * svga_fragment_shader::constant_color_output case. 2027bf215546Sopenharmony_ci */ 2028bf215546Sopenharmony_cistatic boolean 2029bf215546Sopenharmony_ciemit_mov(struct svga_shader_emitter *emit, 2030bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2031bf215546Sopenharmony_ci{ 2032bf215546Sopenharmony_ci const struct tgsi_full_src_register *src = &insn->Src[0]; 2033bf215546Sopenharmony_ci const struct tgsi_full_dst_register *dst = &insn->Dst[0]; 2034bf215546Sopenharmony_ci 2035bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_FRAGMENT && 2036bf215546Sopenharmony_ci dst->Register.File == TGSI_FILE_OUTPUT && 2037bf215546Sopenharmony_ci dst->Register.Index == 0 && 2038bf215546Sopenharmony_ci src->Register.File == TGSI_FILE_CONSTANT && 2039bf215546Sopenharmony_ci !src->Register.Indirect) { 2040bf215546Sopenharmony_ci emit->constant_color_output = TRUE; 2041bf215546Sopenharmony_ci } 2042bf215546Sopenharmony_ci 2043bf215546Sopenharmony_ci return emit_simple_instruction(emit, SVGA3DOP_MOV, insn); 2044bf215546Sopenharmony_ci} 2045bf215546Sopenharmony_ci 2046bf215546Sopenharmony_ci 2047bf215546Sopenharmony_ci/** 2048bf215546Sopenharmony_ci * Translate TGSI SQRT instruction 2049bf215546Sopenharmony_ci * if src1 == 0 2050bf215546Sopenharmony_ci * mov dst, src1 2051bf215546Sopenharmony_ci * else 2052bf215546Sopenharmony_ci * rsq temp, src1 2053bf215546Sopenharmony_ci * rcp dst, temp 2054bf215546Sopenharmony_ci * endif 2055bf215546Sopenharmony_ci */ 2056bf215546Sopenharmony_cistatic boolean 2057bf215546Sopenharmony_ciemit_sqrt(struct svga_shader_emitter *emit, 2058bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2059bf215546Sopenharmony_ci{ 2060bf215546Sopenharmony_ci const struct src_register src1 = translate_src_register(emit, &insn->Src[0]); 2061bf215546Sopenharmony_ci const struct src_register zero = get_zero_immediate(emit); 2062bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register(emit, insn, 0); 2063bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp(emit); 2064bf215546Sopenharmony_ci SVGA3dShaderInstToken if_token = inst_token(SVGA3DOP_IFC); 2065bf215546Sopenharmony_ci boolean ret = TRUE; 2066bf215546Sopenharmony_ci 2067bf215546Sopenharmony_ci if_token.control = SVGA3DOPCOMP_EQ; 2068bf215546Sopenharmony_ci 2069bf215546Sopenharmony_ci if (!(emit_instruction(emit, if_token) && 2070bf215546Sopenharmony_ci emit_src(emit, src1) && 2071bf215546Sopenharmony_ci emit_src(emit, zero))) { 2072bf215546Sopenharmony_ci ret = FALSE; 2073bf215546Sopenharmony_ci goto cleanup; 2074bf215546Sopenharmony_ci } 2075bf215546Sopenharmony_ci 2076bf215546Sopenharmony_ci if (!submit_op1(emit, 2077bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 2078bf215546Sopenharmony_ci dst, src1)) { 2079bf215546Sopenharmony_ci ret = FALSE; 2080bf215546Sopenharmony_ci goto cleanup; 2081bf215546Sopenharmony_ci } 2082bf215546Sopenharmony_ci 2083bf215546Sopenharmony_ci if (!emit_instruction(emit, inst_token(SVGA3DOP_ELSE))) { 2084bf215546Sopenharmony_ci ret = FALSE; 2085bf215546Sopenharmony_ci goto cleanup; 2086bf215546Sopenharmony_ci } 2087bf215546Sopenharmony_ci 2088bf215546Sopenharmony_ci if (!submit_op1(emit, 2089bf215546Sopenharmony_ci inst_token(SVGA3DOP_RSQ), 2090bf215546Sopenharmony_ci temp, src1)) { 2091bf215546Sopenharmony_ci ret = FALSE; 2092bf215546Sopenharmony_ci goto cleanup; 2093bf215546Sopenharmony_ci } 2094bf215546Sopenharmony_ci 2095bf215546Sopenharmony_ci if (!submit_op1(emit, 2096bf215546Sopenharmony_ci inst_token(SVGA3DOP_RCP), 2097bf215546Sopenharmony_ci dst, src(temp))) { 2098bf215546Sopenharmony_ci ret = FALSE; 2099bf215546Sopenharmony_ci goto cleanup; 2100bf215546Sopenharmony_ci } 2101bf215546Sopenharmony_ci 2102bf215546Sopenharmony_ci if (!emit_instruction(emit, inst_token(SVGA3DOP_ENDIF))) { 2103bf215546Sopenharmony_ci ret = FALSE; 2104bf215546Sopenharmony_ci goto cleanup; 2105bf215546Sopenharmony_ci } 2106bf215546Sopenharmony_ci 2107bf215546Sopenharmony_cicleanup: 2108bf215546Sopenharmony_ci release_temp(emit, temp); 2109bf215546Sopenharmony_ci 2110bf215546Sopenharmony_ci return ret; 2111bf215546Sopenharmony_ci} 2112bf215546Sopenharmony_ci 2113bf215546Sopenharmony_ci 2114bf215546Sopenharmony_ci/** 2115bf215546Sopenharmony_ci * Translate/emit TGSI DDX, DDY instructions. 2116bf215546Sopenharmony_ci */ 2117bf215546Sopenharmony_cistatic boolean 2118bf215546Sopenharmony_ciemit_deriv(struct svga_shader_emitter *emit, 2119bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn ) 2120bf215546Sopenharmony_ci{ 2121bf215546Sopenharmony_ci if (emit->dynamic_branching_level > 0 && 2122bf215546Sopenharmony_ci insn->Src[0].Register.File == TGSI_FILE_TEMPORARY) 2123bf215546Sopenharmony_ci { 2124bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = 2125bf215546Sopenharmony_ci translate_dst_register( emit, insn, 0 ); 2126bf215546Sopenharmony_ci 2127bf215546Sopenharmony_ci /* Deriv opcodes not valid inside dynamic branching, workaround 2128bf215546Sopenharmony_ci * by zeroing out the destination. 2129bf215546Sopenharmony_ci */ 2130bf215546Sopenharmony_ci if (!submit_op1(emit, 2131bf215546Sopenharmony_ci inst_token( SVGA3DOP_MOV ), 2132bf215546Sopenharmony_ci dst, 2133bf215546Sopenharmony_ci get_zero_immediate(emit))) 2134bf215546Sopenharmony_ci return FALSE; 2135bf215546Sopenharmony_ci 2136bf215546Sopenharmony_ci return TRUE; 2137bf215546Sopenharmony_ci } 2138bf215546Sopenharmony_ci else { 2139bf215546Sopenharmony_ci SVGA3dShaderOpCodeType opcode; 2140bf215546Sopenharmony_ci const struct tgsi_full_src_register *reg = &insn->Src[0]; 2141bf215546Sopenharmony_ci SVGA3dShaderInstToken inst; 2142bf215546Sopenharmony_ci SVGA3dShaderDestToken dst; 2143bf215546Sopenharmony_ci struct src_register src0; 2144bf215546Sopenharmony_ci 2145bf215546Sopenharmony_ci switch (insn->Instruction.Opcode) { 2146bf215546Sopenharmony_ci case TGSI_OPCODE_DDX: 2147bf215546Sopenharmony_ci opcode = SVGA3DOP_DSX; 2148bf215546Sopenharmony_ci break; 2149bf215546Sopenharmony_ci case TGSI_OPCODE_DDY: 2150bf215546Sopenharmony_ci opcode = SVGA3DOP_DSY; 2151bf215546Sopenharmony_ci break; 2152bf215546Sopenharmony_ci default: 2153bf215546Sopenharmony_ci return FALSE; 2154bf215546Sopenharmony_ci } 2155bf215546Sopenharmony_ci 2156bf215546Sopenharmony_ci inst = inst_token( opcode ); 2157bf215546Sopenharmony_ci dst = translate_dst_register( emit, insn, 0 ); 2158bf215546Sopenharmony_ci src0 = translate_src_register( emit, reg ); 2159bf215546Sopenharmony_ci 2160bf215546Sopenharmony_ci /* We cannot use negate or abs on source to dsx/dsy instruction. 2161bf215546Sopenharmony_ci */ 2162bf215546Sopenharmony_ci if (reg->Register.Absolute || 2163bf215546Sopenharmony_ci reg->Register.Negate) { 2164bf215546Sopenharmony_ci SVGA3dShaderDestToken temp = get_temp( emit ); 2165bf215546Sopenharmony_ci 2166bf215546Sopenharmony_ci if (!emit_repl( emit, temp, &src0 )) 2167bf215546Sopenharmony_ci return FALSE; 2168bf215546Sopenharmony_ci } 2169bf215546Sopenharmony_ci 2170bf215546Sopenharmony_ci return submit_op1( emit, inst, dst, src0 ); 2171bf215546Sopenharmony_ci } 2172bf215546Sopenharmony_ci} 2173bf215546Sopenharmony_ci 2174bf215546Sopenharmony_ci 2175bf215546Sopenharmony_ci/** 2176bf215546Sopenharmony_ci * Translate/emit ARL (Address Register Load) instruction. Used to 2177bf215546Sopenharmony_ci * move a value into the special 'address' register. Used to implement 2178bf215546Sopenharmony_ci * indirect/variable indexing into arrays. 2179bf215546Sopenharmony_ci */ 2180bf215546Sopenharmony_cistatic boolean 2181bf215546Sopenharmony_ciemit_arl(struct svga_shader_emitter *emit, 2182bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2183bf215546Sopenharmony_ci{ 2184bf215546Sopenharmony_ci ++emit->current_arl; 2185bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_FRAGMENT) { 2186bf215546Sopenharmony_ci /* MOVA not present in pixel shader instruction set. 2187bf215546Sopenharmony_ci * Ignore this instruction altogether since it is 2188bf215546Sopenharmony_ci * only used for loop counters -- and for that 2189bf215546Sopenharmony_ci * we reference aL directly. 2190bf215546Sopenharmony_ci */ 2191bf215546Sopenharmony_ci return TRUE; 2192bf215546Sopenharmony_ci } 2193bf215546Sopenharmony_ci if (svga_arl_needs_adjustment( emit )) { 2194bf215546Sopenharmony_ci return emit_fake_arl( emit, insn ); 2195bf215546Sopenharmony_ci } else { 2196bf215546Sopenharmony_ci /* no need to adjust, just emit straight arl */ 2197bf215546Sopenharmony_ci return emit_simple_instruction(emit, SVGA3DOP_MOVA, insn); 2198bf215546Sopenharmony_ci } 2199bf215546Sopenharmony_ci} 2200bf215546Sopenharmony_ci 2201bf215546Sopenharmony_ci 2202bf215546Sopenharmony_cistatic boolean 2203bf215546Sopenharmony_ciemit_pow(struct svga_shader_emitter *emit, 2204bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2205bf215546Sopenharmony_ci{ 2206bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 2207bf215546Sopenharmony_ci struct src_register src0 = translate_src_register( 2208bf215546Sopenharmony_ci emit, &insn->Src[0] ); 2209bf215546Sopenharmony_ci struct src_register src1 = translate_src_register( 2210bf215546Sopenharmony_ci emit, &insn->Src[1] ); 2211bf215546Sopenharmony_ci boolean need_tmp = FALSE; 2212bf215546Sopenharmony_ci 2213bf215546Sopenharmony_ci /* POW can only output to a temporary */ 2214bf215546Sopenharmony_ci if (insn->Dst[0].Register.File != TGSI_FILE_TEMPORARY) 2215bf215546Sopenharmony_ci need_tmp = TRUE; 2216bf215546Sopenharmony_ci 2217bf215546Sopenharmony_ci /* POW src1 must not be the same register as dst */ 2218bf215546Sopenharmony_ci if (alias_src_dst( src1, dst )) 2219bf215546Sopenharmony_ci need_tmp = TRUE; 2220bf215546Sopenharmony_ci 2221bf215546Sopenharmony_ci /* it's a scalar op */ 2222bf215546Sopenharmony_ci src0 = scalar( src0, TGSI_SWIZZLE_X ); 2223bf215546Sopenharmony_ci src1 = scalar( src1, TGSI_SWIZZLE_X ); 2224bf215546Sopenharmony_ci 2225bf215546Sopenharmony_ci if (need_tmp) { 2226bf215546Sopenharmony_ci SVGA3dShaderDestToken tmp = 2227bf215546Sopenharmony_ci writemask(get_temp( emit ), TGSI_WRITEMASK_X ); 2228bf215546Sopenharmony_ci 2229bf215546Sopenharmony_ci if (!submit_op2(emit, inst_token( SVGA3DOP_POW ), tmp, src0, src1)) 2230bf215546Sopenharmony_ci return FALSE; 2231bf215546Sopenharmony_ci 2232bf215546Sopenharmony_ci return submit_op1(emit, inst_token( SVGA3DOP_MOV ), 2233bf215546Sopenharmony_ci dst, scalar(src(tmp), 0) ); 2234bf215546Sopenharmony_ci } 2235bf215546Sopenharmony_ci else { 2236bf215546Sopenharmony_ci return submit_op2(emit, inst_token( SVGA3DOP_POW ), dst, src0, src1); 2237bf215546Sopenharmony_ci } 2238bf215546Sopenharmony_ci} 2239bf215546Sopenharmony_ci 2240bf215546Sopenharmony_ci 2241bf215546Sopenharmony_ci/** 2242bf215546Sopenharmony_ci * Emit a LRP (linear interpolation) instruction. 2243bf215546Sopenharmony_ci */ 2244bf215546Sopenharmony_cistatic boolean 2245bf215546Sopenharmony_cisubmit_lrp(struct svga_shader_emitter *emit, 2246bf215546Sopenharmony_ci SVGA3dShaderDestToken dst, 2247bf215546Sopenharmony_ci struct src_register src0, 2248bf215546Sopenharmony_ci struct src_register src1, 2249bf215546Sopenharmony_ci struct src_register src2) 2250bf215546Sopenharmony_ci{ 2251bf215546Sopenharmony_ci SVGA3dShaderDestToken tmp; 2252bf215546Sopenharmony_ci boolean need_dst_tmp = FALSE; 2253bf215546Sopenharmony_ci 2254bf215546Sopenharmony_ci /* The dst reg must be a temporary, and not be the same as src0 or src2 */ 2255bf215546Sopenharmony_ci if (SVGA3dShaderGetRegType(dst.value) != SVGA3DREG_TEMP || 2256bf215546Sopenharmony_ci alias_src_dst(src0, dst) || 2257bf215546Sopenharmony_ci alias_src_dst(src2, dst)) 2258bf215546Sopenharmony_ci need_dst_tmp = TRUE; 2259bf215546Sopenharmony_ci 2260bf215546Sopenharmony_ci if (need_dst_tmp) { 2261bf215546Sopenharmony_ci tmp = get_temp( emit ); 2262bf215546Sopenharmony_ci tmp.mask = dst.mask; 2263bf215546Sopenharmony_ci } 2264bf215546Sopenharmony_ci else { 2265bf215546Sopenharmony_ci tmp = dst; 2266bf215546Sopenharmony_ci } 2267bf215546Sopenharmony_ci 2268bf215546Sopenharmony_ci if (!submit_op3(emit, inst_token( SVGA3DOP_LRP ), tmp, src0, src1, src2)) 2269bf215546Sopenharmony_ci return FALSE; 2270bf215546Sopenharmony_ci 2271bf215546Sopenharmony_ci if (need_dst_tmp) { 2272bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token( SVGA3DOP_MOV ), dst, src( tmp ))) 2273bf215546Sopenharmony_ci return FALSE; 2274bf215546Sopenharmony_ci } 2275bf215546Sopenharmony_ci 2276bf215546Sopenharmony_ci return TRUE; 2277bf215546Sopenharmony_ci} 2278bf215546Sopenharmony_ci 2279bf215546Sopenharmony_ci 2280bf215546Sopenharmony_ci/** 2281bf215546Sopenharmony_ci * Translate/emit LRP (Linear Interpolation) instruction. 2282bf215546Sopenharmony_ci */ 2283bf215546Sopenharmony_cistatic boolean 2284bf215546Sopenharmony_ciemit_lrp(struct svga_shader_emitter *emit, 2285bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2286bf215546Sopenharmony_ci{ 2287bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 2288bf215546Sopenharmony_ci const struct src_register src0 = translate_src_register( 2289bf215546Sopenharmony_ci emit, &insn->Src[0] ); 2290bf215546Sopenharmony_ci const struct src_register src1 = translate_src_register( 2291bf215546Sopenharmony_ci emit, &insn->Src[1] ); 2292bf215546Sopenharmony_ci const struct src_register src2 = translate_src_register( 2293bf215546Sopenharmony_ci emit, &insn->Src[2] ); 2294bf215546Sopenharmony_ci 2295bf215546Sopenharmony_ci return submit_lrp(emit, dst, src0, src1, src2); 2296bf215546Sopenharmony_ci} 2297bf215546Sopenharmony_ci 2298bf215546Sopenharmony_ci/** 2299bf215546Sopenharmony_ci * Translate/emit DST (Distance function) instruction. 2300bf215546Sopenharmony_ci */ 2301bf215546Sopenharmony_cistatic boolean 2302bf215546Sopenharmony_ciemit_dst_insn(struct svga_shader_emitter *emit, 2303bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2304bf215546Sopenharmony_ci{ 2305bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_VERTEX) { 2306bf215546Sopenharmony_ci /* SVGA/DX9 has a DST instruction, but only for vertex shaders: 2307bf215546Sopenharmony_ci */ 2308bf215546Sopenharmony_ci return emit_simple_instruction(emit, SVGA3DOP_DST, insn); 2309bf215546Sopenharmony_ci } 2310bf215546Sopenharmony_ci else { 2311bf215546Sopenharmony_ci /* result[0] = 1 * 1; 2312bf215546Sopenharmony_ci * result[1] = a[1] * b[1]; 2313bf215546Sopenharmony_ci * result[2] = a[2] * 1; 2314bf215546Sopenharmony_ci * result[3] = 1 * b[3]; 2315bf215546Sopenharmony_ci */ 2316bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 2317bf215546Sopenharmony_ci SVGA3dShaderDestToken tmp; 2318bf215546Sopenharmony_ci const struct src_register src0 = translate_src_register( 2319bf215546Sopenharmony_ci emit, &insn->Src[0] ); 2320bf215546Sopenharmony_ci const struct src_register src1 = translate_src_register( 2321bf215546Sopenharmony_ci emit, &insn->Src[1] ); 2322bf215546Sopenharmony_ci boolean need_tmp = FALSE; 2323bf215546Sopenharmony_ci 2324bf215546Sopenharmony_ci if (SVGA3dShaderGetRegType(dst.value) != SVGA3DREG_TEMP || 2325bf215546Sopenharmony_ci alias_src_dst(src0, dst) || 2326bf215546Sopenharmony_ci alias_src_dst(src1, dst)) 2327bf215546Sopenharmony_ci need_tmp = TRUE; 2328bf215546Sopenharmony_ci 2329bf215546Sopenharmony_ci if (need_tmp) { 2330bf215546Sopenharmony_ci tmp = get_temp( emit ); 2331bf215546Sopenharmony_ci } 2332bf215546Sopenharmony_ci else { 2333bf215546Sopenharmony_ci tmp = dst; 2334bf215546Sopenharmony_ci } 2335bf215546Sopenharmony_ci 2336bf215546Sopenharmony_ci /* tmp.xw = 1.0 2337bf215546Sopenharmony_ci */ 2338bf215546Sopenharmony_ci if (tmp.mask & TGSI_WRITEMASK_XW) { 2339bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), 2340bf215546Sopenharmony_ci writemask(tmp, TGSI_WRITEMASK_XW ), 2341bf215546Sopenharmony_ci get_one_immediate(emit))) 2342bf215546Sopenharmony_ci return FALSE; 2343bf215546Sopenharmony_ci } 2344bf215546Sopenharmony_ci 2345bf215546Sopenharmony_ci /* tmp.yz = src0 2346bf215546Sopenharmony_ci */ 2347bf215546Sopenharmony_ci if (tmp.mask & TGSI_WRITEMASK_YZ) { 2348bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), 2349bf215546Sopenharmony_ci writemask(tmp, TGSI_WRITEMASK_YZ ), 2350bf215546Sopenharmony_ci src0)) 2351bf215546Sopenharmony_ci return FALSE; 2352bf215546Sopenharmony_ci } 2353bf215546Sopenharmony_ci 2354bf215546Sopenharmony_ci /* tmp.yw = tmp * src1 2355bf215546Sopenharmony_ci */ 2356bf215546Sopenharmony_ci if (tmp.mask & TGSI_WRITEMASK_YW) { 2357bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), 2358bf215546Sopenharmony_ci writemask(tmp, TGSI_WRITEMASK_YW ), 2359bf215546Sopenharmony_ci src(tmp), 2360bf215546Sopenharmony_ci src1)) 2361bf215546Sopenharmony_ci return FALSE; 2362bf215546Sopenharmony_ci } 2363bf215546Sopenharmony_ci 2364bf215546Sopenharmony_ci /* dst = tmp 2365bf215546Sopenharmony_ci */ 2366bf215546Sopenharmony_ci if (need_tmp) { 2367bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), 2368bf215546Sopenharmony_ci dst, 2369bf215546Sopenharmony_ci src(tmp))) 2370bf215546Sopenharmony_ci return FALSE; 2371bf215546Sopenharmony_ci } 2372bf215546Sopenharmony_ci } 2373bf215546Sopenharmony_ci 2374bf215546Sopenharmony_ci return TRUE; 2375bf215546Sopenharmony_ci} 2376bf215546Sopenharmony_ci 2377bf215546Sopenharmony_ci 2378bf215546Sopenharmony_cistatic boolean 2379bf215546Sopenharmony_ciemit_exp(struct svga_shader_emitter *emit, 2380bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2381bf215546Sopenharmony_ci{ 2382bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 2383bf215546Sopenharmony_ci struct src_register src0 = 2384bf215546Sopenharmony_ci translate_src_register( emit, &insn->Src[0] ); 2385bf215546Sopenharmony_ci SVGA3dShaderDestToken fraction; 2386bf215546Sopenharmony_ci 2387bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_Y) 2388bf215546Sopenharmony_ci fraction = dst; 2389bf215546Sopenharmony_ci else if (dst.mask & TGSI_WRITEMASK_X) 2390bf215546Sopenharmony_ci fraction = get_temp( emit ); 2391bf215546Sopenharmony_ci else 2392bf215546Sopenharmony_ci fraction.value = 0; 2393bf215546Sopenharmony_ci 2394bf215546Sopenharmony_ci /* If y is being written, fill it with src0 - floor(src0). 2395bf215546Sopenharmony_ci */ 2396bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_XY) { 2397bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_FRC ), 2398bf215546Sopenharmony_ci writemask( fraction, TGSI_WRITEMASK_Y ), 2399bf215546Sopenharmony_ci src0 )) 2400bf215546Sopenharmony_ci return FALSE; 2401bf215546Sopenharmony_ci } 2402bf215546Sopenharmony_ci 2403bf215546Sopenharmony_ci /* If x is being written, fill it with 2 ^ floor(src0). 2404bf215546Sopenharmony_ci */ 2405bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_X) { 2406bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), 2407bf215546Sopenharmony_ci writemask( dst, TGSI_WRITEMASK_X ), 2408bf215546Sopenharmony_ci src0, 2409bf215546Sopenharmony_ci scalar( negate( src( fraction ) ), TGSI_SWIZZLE_Y ) ) ) 2410bf215546Sopenharmony_ci return FALSE; 2411bf215546Sopenharmony_ci 2412bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_EXP ), 2413bf215546Sopenharmony_ci writemask( dst, TGSI_WRITEMASK_X ), 2414bf215546Sopenharmony_ci scalar( src( dst ), TGSI_SWIZZLE_X ) ) ) 2415bf215546Sopenharmony_ci return FALSE; 2416bf215546Sopenharmony_ci 2417bf215546Sopenharmony_ci if (!(dst.mask & TGSI_WRITEMASK_Y)) 2418bf215546Sopenharmony_ci release_temp( emit, fraction ); 2419bf215546Sopenharmony_ci } 2420bf215546Sopenharmony_ci 2421bf215546Sopenharmony_ci /* If z is being written, fill it with 2 ^ src0 (partial precision). 2422bf215546Sopenharmony_ci */ 2423bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_Z) { 2424bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_EXPP ), 2425bf215546Sopenharmony_ci writemask( dst, TGSI_WRITEMASK_Z ), 2426bf215546Sopenharmony_ci src0 ) ) 2427bf215546Sopenharmony_ci return FALSE; 2428bf215546Sopenharmony_ci } 2429bf215546Sopenharmony_ci 2430bf215546Sopenharmony_ci /* If w is being written, fill it with one. 2431bf215546Sopenharmony_ci */ 2432bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_W) { 2433bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), 2434bf215546Sopenharmony_ci writemask(dst, TGSI_WRITEMASK_W), 2435bf215546Sopenharmony_ci get_one_immediate(emit))) 2436bf215546Sopenharmony_ci return FALSE; 2437bf215546Sopenharmony_ci } 2438bf215546Sopenharmony_ci 2439bf215546Sopenharmony_ci return TRUE; 2440bf215546Sopenharmony_ci} 2441bf215546Sopenharmony_ci 2442bf215546Sopenharmony_ci 2443bf215546Sopenharmony_ci/** 2444bf215546Sopenharmony_ci * Translate/emit LIT (Lighting helper) instruction. 2445bf215546Sopenharmony_ci */ 2446bf215546Sopenharmony_cistatic boolean 2447bf215546Sopenharmony_ciemit_lit(struct svga_shader_emitter *emit, 2448bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2449bf215546Sopenharmony_ci{ 2450bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_VERTEX) { 2451bf215546Sopenharmony_ci /* SVGA/DX9 has a LIT instruction, but only for vertex shaders: 2452bf215546Sopenharmony_ci */ 2453bf215546Sopenharmony_ci return emit_simple_instruction(emit, SVGA3DOP_LIT, insn); 2454bf215546Sopenharmony_ci } 2455bf215546Sopenharmony_ci else { 2456bf215546Sopenharmony_ci /* D3D vs. GL semantics can be fairly easily accommodated by 2457bf215546Sopenharmony_ci * variations on this sequence. 2458bf215546Sopenharmony_ci * 2459bf215546Sopenharmony_ci * GL: 2460bf215546Sopenharmony_ci * tmp.y = src.x 2461bf215546Sopenharmony_ci * tmp.z = pow(src.y,src.w) 2462bf215546Sopenharmony_ci * p0 = src0.xxxx > 0 2463bf215546Sopenharmony_ci * result = zero.wxxw 2464bf215546Sopenharmony_ci * (p0) result.yz = tmp 2465bf215546Sopenharmony_ci * 2466bf215546Sopenharmony_ci * D3D: 2467bf215546Sopenharmony_ci * tmp.y = src.x 2468bf215546Sopenharmony_ci * tmp.z = pow(src.y,src.w) 2469bf215546Sopenharmony_ci * p0 = src0.xxyy > 0 2470bf215546Sopenharmony_ci * result = zero.wxxw 2471bf215546Sopenharmony_ci * (p0) result.yz = tmp 2472bf215546Sopenharmony_ci * 2473bf215546Sopenharmony_ci * Will implement the GL version for now. 2474bf215546Sopenharmony_ci */ 2475bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 2476bf215546Sopenharmony_ci SVGA3dShaderDestToken tmp = get_temp( emit ); 2477bf215546Sopenharmony_ci const struct src_register src0 = translate_src_register( 2478bf215546Sopenharmony_ci emit, &insn->Src[0] ); 2479bf215546Sopenharmony_ci 2480bf215546Sopenharmony_ci /* tmp = pow(src.y, src.w) 2481bf215546Sopenharmony_ci */ 2482bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_Z) { 2483bf215546Sopenharmony_ci if (!submit_op2(emit, inst_token( SVGA3DOP_POW ), 2484bf215546Sopenharmony_ci tmp, 2485bf215546Sopenharmony_ci scalar(src0, 1), 2486bf215546Sopenharmony_ci scalar(src0, 3))) 2487bf215546Sopenharmony_ci return FALSE; 2488bf215546Sopenharmony_ci } 2489bf215546Sopenharmony_ci 2490bf215546Sopenharmony_ci /* tmp.y = src.x 2491bf215546Sopenharmony_ci */ 2492bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_Y) { 2493bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), 2494bf215546Sopenharmony_ci writemask(tmp, TGSI_WRITEMASK_Y ), 2495bf215546Sopenharmony_ci scalar(src0, 0))) 2496bf215546Sopenharmony_ci return FALSE; 2497bf215546Sopenharmony_ci } 2498bf215546Sopenharmony_ci 2499bf215546Sopenharmony_ci /* Can't quite do this with emit conditional due to the extra 2500bf215546Sopenharmony_ci * writemask on the predicated mov: 2501bf215546Sopenharmony_ci */ 2502bf215546Sopenharmony_ci { 2503bf215546Sopenharmony_ci SVGA3dShaderDestToken pred_reg = dst_register( SVGA3DREG_PREDICATE, 0 ); 2504bf215546Sopenharmony_ci struct src_register predsrc; 2505bf215546Sopenharmony_ci 2506bf215546Sopenharmony_ci /* D3D vs GL semantics: 2507bf215546Sopenharmony_ci */ 2508bf215546Sopenharmony_ci if (0) 2509bf215546Sopenharmony_ci predsrc = swizzle(src0, 0, 0, 1, 1); /* D3D */ 2510bf215546Sopenharmony_ci else 2511bf215546Sopenharmony_ci predsrc = swizzle(src0, 0, 0, 0, 0); /* GL */ 2512bf215546Sopenharmony_ci 2513bf215546Sopenharmony_ci /* SETP src0.xxyy, GT, {0}.x */ 2514bf215546Sopenharmony_ci if (!submit_op2( emit, 2515bf215546Sopenharmony_ci inst_token_setp(SVGA3DOPCOMP_GT), 2516bf215546Sopenharmony_ci pred_reg, 2517bf215546Sopenharmony_ci predsrc, 2518bf215546Sopenharmony_ci get_zero_immediate(emit))) 2519bf215546Sopenharmony_ci return FALSE; 2520bf215546Sopenharmony_ci 2521bf215546Sopenharmony_ci /* MOV dst, fail */ 2522bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, 2523bf215546Sopenharmony_ci get_immediate(emit, 1.0f, 0.0f, 0.0f, 1.0f))) 2524bf215546Sopenharmony_ci return FALSE; 2525bf215546Sopenharmony_ci 2526bf215546Sopenharmony_ci /* MOV dst.yz, tmp (predicated) 2527bf215546Sopenharmony_ci * 2528bf215546Sopenharmony_ci * Note that the predicate reg (and possible modifiers) is passed 2529bf215546Sopenharmony_ci * as the first source argument. 2530bf215546Sopenharmony_ci */ 2531bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_YZ) { 2532bf215546Sopenharmony_ci if (!submit_op2( emit, 2533bf215546Sopenharmony_ci inst_token_predicated(SVGA3DOP_MOV), 2534bf215546Sopenharmony_ci writemask(dst, TGSI_WRITEMASK_YZ), 2535bf215546Sopenharmony_ci src( pred_reg ), src( tmp ) )) 2536bf215546Sopenharmony_ci return FALSE; 2537bf215546Sopenharmony_ci } 2538bf215546Sopenharmony_ci } 2539bf215546Sopenharmony_ci } 2540bf215546Sopenharmony_ci 2541bf215546Sopenharmony_ci return TRUE; 2542bf215546Sopenharmony_ci} 2543bf215546Sopenharmony_ci 2544bf215546Sopenharmony_ci 2545bf215546Sopenharmony_cistatic boolean 2546bf215546Sopenharmony_ciemit_ex2(struct svga_shader_emitter *emit, 2547bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2548bf215546Sopenharmony_ci{ 2549bf215546Sopenharmony_ci SVGA3dShaderInstToken inst; 2550bf215546Sopenharmony_ci SVGA3dShaderDestToken dst; 2551bf215546Sopenharmony_ci struct src_register src0; 2552bf215546Sopenharmony_ci 2553bf215546Sopenharmony_ci inst = inst_token( SVGA3DOP_EXP ); 2554bf215546Sopenharmony_ci dst = translate_dst_register( emit, insn, 0 ); 2555bf215546Sopenharmony_ci src0 = translate_src_register( emit, &insn->Src[0] ); 2556bf215546Sopenharmony_ci src0 = scalar( src0, TGSI_SWIZZLE_X ); 2557bf215546Sopenharmony_ci 2558bf215546Sopenharmony_ci if (dst.mask != TGSI_WRITEMASK_XYZW) { 2559bf215546Sopenharmony_ci SVGA3dShaderDestToken tmp = get_temp( emit ); 2560bf215546Sopenharmony_ci 2561bf215546Sopenharmony_ci if (!submit_op1( emit, inst, tmp, src0 )) 2562bf215546Sopenharmony_ci return FALSE; 2563bf215546Sopenharmony_ci 2564bf215546Sopenharmony_ci return submit_op1( emit, inst_token( SVGA3DOP_MOV ), 2565bf215546Sopenharmony_ci dst, 2566bf215546Sopenharmony_ci scalar( src( tmp ), TGSI_SWIZZLE_X ) ); 2567bf215546Sopenharmony_ci } 2568bf215546Sopenharmony_ci 2569bf215546Sopenharmony_ci return submit_op1( emit, inst, dst, src0 ); 2570bf215546Sopenharmony_ci} 2571bf215546Sopenharmony_ci 2572bf215546Sopenharmony_ci 2573bf215546Sopenharmony_cistatic boolean 2574bf215546Sopenharmony_ciemit_log(struct svga_shader_emitter *emit, 2575bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2576bf215546Sopenharmony_ci{ 2577bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register( emit, insn, 0 ); 2578bf215546Sopenharmony_ci struct src_register src0 = 2579bf215546Sopenharmony_ci translate_src_register( emit, &insn->Src[0] ); 2580bf215546Sopenharmony_ci SVGA3dShaderDestToken abs_tmp; 2581bf215546Sopenharmony_ci struct src_register abs_src0; 2582bf215546Sopenharmony_ci SVGA3dShaderDestToken log2_abs; 2583bf215546Sopenharmony_ci 2584bf215546Sopenharmony_ci abs_tmp.value = 0; 2585bf215546Sopenharmony_ci 2586bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_Z) 2587bf215546Sopenharmony_ci log2_abs = dst; 2588bf215546Sopenharmony_ci else if (dst.mask & TGSI_WRITEMASK_XY) 2589bf215546Sopenharmony_ci log2_abs = get_temp( emit ); 2590bf215546Sopenharmony_ci else 2591bf215546Sopenharmony_ci log2_abs.value = 0; 2592bf215546Sopenharmony_ci 2593bf215546Sopenharmony_ci /* If z is being written, fill it with log2( abs( src0 ) ). 2594bf215546Sopenharmony_ci */ 2595bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_XYZ) { 2596bf215546Sopenharmony_ci if (!src0.base.srcMod || src0.base.srcMod == SVGA3DSRCMOD_ABS) 2597bf215546Sopenharmony_ci abs_src0 = src0; 2598bf215546Sopenharmony_ci else { 2599bf215546Sopenharmony_ci abs_tmp = get_temp( emit ); 2600bf215546Sopenharmony_ci 2601bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), 2602bf215546Sopenharmony_ci abs_tmp, 2603bf215546Sopenharmony_ci src0 ) ) 2604bf215546Sopenharmony_ci return FALSE; 2605bf215546Sopenharmony_ci 2606bf215546Sopenharmony_ci abs_src0 = src( abs_tmp ); 2607bf215546Sopenharmony_ci } 2608bf215546Sopenharmony_ci 2609bf215546Sopenharmony_ci abs_src0 = absolute( scalar( abs_src0, TGSI_SWIZZLE_X ) ); 2610bf215546Sopenharmony_ci 2611bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_LOG ), 2612bf215546Sopenharmony_ci writemask( log2_abs, TGSI_WRITEMASK_Z ), 2613bf215546Sopenharmony_ci abs_src0 ) ) 2614bf215546Sopenharmony_ci return FALSE; 2615bf215546Sopenharmony_ci } 2616bf215546Sopenharmony_ci 2617bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_XY) { 2618bf215546Sopenharmony_ci SVGA3dShaderDestToken floor_log2; 2619bf215546Sopenharmony_ci 2620bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_X) 2621bf215546Sopenharmony_ci floor_log2 = dst; 2622bf215546Sopenharmony_ci else 2623bf215546Sopenharmony_ci floor_log2 = get_temp( emit ); 2624bf215546Sopenharmony_ci 2625bf215546Sopenharmony_ci /* If x is being written, fill it with floor( log2( abs( src0 ) ) ). 2626bf215546Sopenharmony_ci */ 2627bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_FRC ), 2628bf215546Sopenharmony_ci writemask( floor_log2, TGSI_WRITEMASK_X ), 2629bf215546Sopenharmony_ci scalar( src( log2_abs ), TGSI_SWIZZLE_Z ) ) ) 2630bf215546Sopenharmony_ci return FALSE; 2631bf215546Sopenharmony_ci 2632bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_ADD ), 2633bf215546Sopenharmony_ci writemask( floor_log2, TGSI_WRITEMASK_X ), 2634bf215546Sopenharmony_ci scalar( src( log2_abs ), TGSI_SWIZZLE_Z ), 2635bf215546Sopenharmony_ci negate( src( floor_log2 ) ) ) ) 2636bf215546Sopenharmony_ci return FALSE; 2637bf215546Sopenharmony_ci 2638bf215546Sopenharmony_ci /* If y is being written, fill it with 2639bf215546Sopenharmony_ci * abs ( src0 ) / ( 2 ^ floor( log2( abs( src0 ) ) ) ). 2640bf215546Sopenharmony_ci */ 2641bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_Y) { 2642bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_EXP ), 2643bf215546Sopenharmony_ci writemask( dst, TGSI_WRITEMASK_Y ), 2644bf215546Sopenharmony_ci negate( scalar( src( floor_log2 ), 2645bf215546Sopenharmony_ci TGSI_SWIZZLE_X ) ) ) ) 2646bf215546Sopenharmony_ci return FALSE; 2647bf215546Sopenharmony_ci 2648bf215546Sopenharmony_ci if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), 2649bf215546Sopenharmony_ci writemask( dst, TGSI_WRITEMASK_Y ), 2650bf215546Sopenharmony_ci src( dst ), 2651bf215546Sopenharmony_ci abs_src0 ) ) 2652bf215546Sopenharmony_ci return FALSE; 2653bf215546Sopenharmony_ci } 2654bf215546Sopenharmony_ci 2655bf215546Sopenharmony_ci if (!(dst.mask & TGSI_WRITEMASK_X)) 2656bf215546Sopenharmony_ci release_temp( emit, floor_log2 ); 2657bf215546Sopenharmony_ci 2658bf215546Sopenharmony_ci if (!(dst.mask & TGSI_WRITEMASK_Z)) 2659bf215546Sopenharmony_ci release_temp( emit, log2_abs ); 2660bf215546Sopenharmony_ci } 2661bf215546Sopenharmony_ci 2662bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_XYZ && src0.base.srcMod && 2663bf215546Sopenharmony_ci src0.base.srcMod != SVGA3DSRCMOD_ABS) 2664bf215546Sopenharmony_ci release_temp( emit, abs_tmp ); 2665bf215546Sopenharmony_ci 2666bf215546Sopenharmony_ci /* If w is being written, fill it with one. 2667bf215546Sopenharmony_ci */ 2668bf215546Sopenharmony_ci if (dst.mask & TGSI_WRITEMASK_W) { 2669bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), 2670bf215546Sopenharmony_ci writemask(dst, TGSI_WRITEMASK_W), 2671bf215546Sopenharmony_ci get_one_immediate(emit))) 2672bf215546Sopenharmony_ci return FALSE; 2673bf215546Sopenharmony_ci } 2674bf215546Sopenharmony_ci 2675bf215546Sopenharmony_ci return TRUE; 2676bf215546Sopenharmony_ci} 2677bf215546Sopenharmony_ci 2678bf215546Sopenharmony_ci 2679bf215546Sopenharmony_ci/** 2680bf215546Sopenharmony_ci * Translate TGSI TRUNC or ROUND instruction. 2681bf215546Sopenharmony_ci * We need to truncate toward zero. Ex: trunc(-1.9) = -1 2682bf215546Sopenharmony_ci * Different approaches are needed for VS versus PS. 2683bf215546Sopenharmony_ci */ 2684bf215546Sopenharmony_cistatic boolean 2685bf215546Sopenharmony_ciemit_trunc_round(struct svga_shader_emitter *emit, 2686bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn, 2687bf215546Sopenharmony_ci boolean round) 2688bf215546Sopenharmony_ci{ 2689bf215546Sopenharmony_ci SVGA3dShaderDestToken dst = translate_dst_register(emit, insn, 0); 2690bf215546Sopenharmony_ci const struct src_register src0 = 2691bf215546Sopenharmony_ci translate_src_register(emit, &insn->Src[0] ); 2692bf215546Sopenharmony_ci SVGA3dShaderDestToken t1 = get_temp(emit); 2693bf215546Sopenharmony_ci 2694bf215546Sopenharmony_ci if (round) { 2695bf215546Sopenharmony_ci SVGA3dShaderDestToken t0 = get_temp(emit); 2696bf215546Sopenharmony_ci struct src_register half = get_half_immediate(emit); 2697bf215546Sopenharmony_ci 2698bf215546Sopenharmony_ci /* t0 = abs(src0) + 0.5 */ 2699bf215546Sopenharmony_ci if (!submit_op2(emit, inst_token(SVGA3DOP_ADD), t0, 2700bf215546Sopenharmony_ci absolute(src0), half)) 2701bf215546Sopenharmony_ci return FALSE; 2702bf215546Sopenharmony_ci 2703bf215546Sopenharmony_ci /* t1 = fract(t0) */ 2704bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token(SVGA3DOP_FRC), t1, src(t0))) 2705bf215546Sopenharmony_ci return FALSE; 2706bf215546Sopenharmony_ci 2707bf215546Sopenharmony_ci /* t1 = t0 - t1 */ 2708bf215546Sopenharmony_ci if (!submit_op2(emit, inst_token(SVGA3DOP_ADD), t1, src(t0), 2709bf215546Sopenharmony_ci negate(src(t1)))) 2710bf215546Sopenharmony_ci return FALSE; 2711bf215546Sopenharmony_ci } 2712bf215546Sopenharmony_ci else { 2713bf215546Sopenharmony_ci /* trunc */ 2714bf215546Sopenharmony_ci 2715bf215546Sopenharmony_ci /* t1 = fract(abs(src0)) */ 2716bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token(SVGA3DOP_FRC), t1, absolute(src0))) 2717bf215546Sopenharmony_ci return FALSE; 2718bf215546Sopenharmony_ci 2719bf215546Sopenharmony_ci /* t1 = abs(src0) - t1 */ 2720bf215546Sopenharmony_ci if (!submit_op2(emit, inst_token(SVGA3DOP_ADD), t1, absolute(src0), 2721bf215546Sopenharmony_ci negate(src(t1)))) 2722bf215546Sopenharmony_ci return FALSE; 2723bf215546Sopenharmony_ci } 2724bf215546Sopenharmony_ci 2725bf215546Sopenharmony_ci /* 2726bf215546Sopenharmony_ci * Now we need to multiply t1 by the sign of the original value. 2727bf215546Sopenharmony_ci */ 2728bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_VERTEX) { 2729bf215546Sopenharmony_ci /* For VS: use SGN instruction */ 2730bf215546Sopenharmony_ci /* Need two extra/dummy registers: */ 2731bf215546Sopenharmony_ci SVGA3dShaderDestToken t2 = get_temp(emit), t3 = get_temp(emit), 2732bf215546Sopenharmony_ci t4 = get_temp(emit); 2733bf215546Sopenharmony_ci 2734bf215546Sopenharmony_ci /* t2 = sign(src0) */ 2735bf215546Sopenharmony_ci if (!submit_op3(emit, inst_token(SVGA3DOP_SGN), t2, src0, 2736bf215546Sopenharmony_ci src(t3), src(t4))) 2737bf215546Sopenharmony_ci return FALSE; 2738bf215546Sopenharmony_ci 2739bf215546Sopenharmony_ci /* dst = t1 * t2 */ 2740bf215546Sopenharmony_ci if (!submit_op2(emit, inst_token(SVGA3DOP_MUL), dst, src(t1), src(t2))) 2741bf215546Sopenharmony_ci return FALSE; 2742bf215546Sopenharmony_ci } 2743bf215546Sopenharmony_ci else { 2744bf215546Sopenharmony_ci /* For FS: Use CMP instruction */ 2745bf215546Sopenharmony_ci return submit_op3(emit, inst_token( SVGA3DOP_CMP ), dst, 2746bf215546Sopenharmony_ci src0, src(t1), negate(src(t1))); 2747bf215546Sopenharmony_ci } 2748bf215546Sopenharmony_ci 2749bf215546Sopenharmony_ci return TRUE; 2750bf215546Sopenharmony_ci} 2751bf215546Sopenharmony_ci 2752bf215546Sopenharmony_ci 2753bf215546Sopenharmony_ci/** 2754bf215546Sopenharmony_ci * Translate/emit "begin subroutine" instruction/marker/label. 2755bf215546Sopenharmony_ci */ 2756bf215546Sopenharmony_cistatic boolean 2757bf215546Sopenharmony_ciemit_bgnsub(struct svga_shader_emitter *emit, 2758bf215546Sopenharmony_ci unsigned position, 2759bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2760bf215546Sopenharmony_ci{ 2761bf215546Sopenharmony_ci unsigned i; 2762bf215546Sopenharmony_ci 2763bf215546Sopenharmony_ci /* Note that we've finished the main function and are now emitting 2764bf215546Sopenharmony_ci * subroutines. This affects how we terminate the generated 2765bf215546Sopenharmony_ci * shader. 2766bf215546Sopenharmony_ci */ 2767bf215546Sopenharmony_ci emit->in_main_func = FALSE; 2768bf215546Sopenharmony_ci 2769bf215546Sopenharmony_ci for (i = 0; i < emit->nr_labels; i++) { 2770bf215546Sopenharmony_ci if (emit->label[i] == position) { 2771bf215546Sopenharmony_ci return (emit_instruction( emit, inst_token( SVGA3DOP_RET ) ) && 2772bf215546Sopenharmony_ci emit_instruction( emit, inst_token( SVGA3DOP_LABEL ) ) && 2773bf215546Sopenharmony_ci emit_src( emit, src_register( SVGA3DREG_LABEL, i ))); 2774bf215546Sopenharmony_ci } 2775bf215546Sopenharmony_ci } 2776bf215546Sopenharmony_ci 2777bf215546Sopenharmony_ci assert(0); 2778bf215546Sopenharmony_ci return TRUE; 2779bf215546Sopenharmony_ci} 2780bf215546Sopenharmony_ci 2781bf215546Sopenharmony_ci 2782bf215546Sopenharmony_ci/** 2783bf215546Sopenharmony_ci * Translate/emit subroutine call instruction. 2784bf215546Sopenharmony_ci */ 2785bf215546Sopenharmony_cistatic boolean 2786bf215546Sopenharmony_ciemit_call(struct svga_shader_emitter *emit, 2787bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2788bf215546Sopenharmony_ci{ 2789bf215546Sopenharmony_ci unsigned position = insn->Label.Label; 2790bf215546Sopenharmony_ci unsigned i; 2791bf215546Sopenharmony_ci 2792bf215546Sopenharmony_ci for (i = 0; i < emit->nr_labels; i++) { 2793bf215546Sopenharmony_ci if (emit->label[i] == position) 2794bf215546Sopenharmony_ci break; 2795bf215546Sopenharmony_ci } 2796bf215546Sopenharmony_ci 2797bf215546Sopenharmony_ci if (emit->nr_labels == ARRAY_SIZE(emit->label)) 2798bf215546Sopenharmony_ci return FALSE; 2799bf215546Sopenharmony_ci 2800bf215546Sopenharmony_ci if (i == emit->nr_labels) { 2801bf215546Sopenharmony_ci emit->label[i] = position; 2802bf215546Sopenharmony_ci emit->nr_labels++; 2803bf215546Sopenharmony_ci } 2804bf215546Sopenharmony_ci 2805bf215546Sopenharmony_ci return (emit_instruction( emit, inst_token( SVGA3DOP_CALL ) ) && 2806bf215546Sopenharmony_ci emit_src( emit, src_register( SVGA3DREG_LABEL, i ))); 2807bf215546Sopenharmony_ci} 2808bf215546Sopenharmony_ci 2809bf215546Sopenharmony_ci 2810bf215546Sopenharmony_ci/** 2811bf215546Sopenharmony_ci * Called at the end of the shader. Actually, emit special "fix-up" 2812bf215546Sopenharmony_ci * code for the vertex/fragment shader. 2813bf215546Sopenharmony_ci */ 2814bf215546Sopenharmony_cistatic boolean 2815bf215546Sopenharmony_ciemit_end(struct svga_shader_emitter *emit) 2816bf215546Sopenharmony_ci{ 2817bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_VERTEX) { 2818bf215546Sopenharmony_ci return emit_vs_postamble( emit ); 2819bf215546Sopenharmony_ci } 2820bf215546Sopenharmony_ci else { 2821bf215546Sopenharmony_ci return emit_ps_postamble( emit ); 2822bf215546Sopenharmony_ci } 2823bf215546Sopenharmony_ci} 2824bf215546Sopenharmony_ci 2825bf215546Sopenharmony_ci 2826bf215546Sopenharmony_ci/** 2827bf215546Sopenharmony_ci * Translate any TGSI instruction to SVGA. 2828bf215546Sopenharmony_ci */ 2829bf215546Sopenharmony_cistatic boolean 2830bf215546Sopenharmony_cisvga_emit_instruction(struct svga_shader_emitter *emit, 2831bf215546Sopenharmony_ci unsigned position, 2832bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn) 2833bf215546Sopenharmony_ci{ 2834bf215546Sopenharmony_ci switch (insn->Instruction.Opcode) { 2835bf215546Sopenharmony_ci 2836bf215546Sopenharmony_ci case TGSI_OPCODE_ARL: 2837bf215546Sopenharmony_ci return emit_arl( emit, insn ); 2838bf215546Sopenharmony_ci 2839bf215546Sopenharmony_ci case TGSI_OPCODE_TEX: 2840bf215546Sopenharmony_ci case TGSI_OPCODE_TXB: 2841bf215546Sopenharmony_ci case TGSI_OPCODE_TXP: 2842bf215546Sopenharmony_ci case TGSI_OPCODE_TXL: 2843bf215546Sopenharmony_ci case TGSI_OPCODE_TXD: 2844bf215546Sopenharmony_ci return emit_tex( emit, insn ); 2845bf215546Sopenharmony_ci 2846bf215546Sopenharmony_ci case TGSI_OPCODE_DDX: 2847bf215546Sopenharmony_ci case TGSI_OPCODE_DDY: 2848bf215546Sopenharmony_ci return emit_deriv( emit, insn ); 2849bf215546Sopenharmony_ci 2850bf215546Sopenharmony_ci case TGSI_OPCODE_BGNSUB: 2851bf215546Sopenharmony_ci return emit_bgnsub( emit, position, insn ); 2852bf215546Sopenharmony_ci 2853bf215546Sopenharmony_ci case TGSI_OPCODE_ENDSUB: 2854bf215546Sopenharmony_ci return TRUE; 2855bf215546Sopenharmony_ci 2856bf215546Sopenharmony_ci case TGSI_OPCODE_CAL: 2857bf215546Sopenharmony_ci return emit_call( emit, insn ); 2858bf215546Sopenharmony_ci 2859bf215546Sopenharmony_ci case TGSI_OPCODE_FLR: 2860bf215546Sopenharmony_ci return emit_floor( emit, insn ); 2861bf215546Sopenharmony_ci 2862bf215546Sopenharmony_ci case TGSI_OPCODE_TRUNC: 2863bf215546Sopenharmony_ci return emit_trunc_round( emit, insn, FALSE ); 2864bf215546Sopenharmony_ci 2865bf215546Sopenharmony_ci case TGSI_OPCODE_ROUND: 2866bf215546Sopenharmony_ci return emit_trunc_round( emit, insn, TRUE ); 2867bf215546Sopenharmony_ci 2868bf215546Sopenharmony_ci case TGSI_OPCODE_CEIL: 2869bf215546Sopenharmony_ci return emit_ceil( emit, insn ); 2870bf215546Sopenharmony_ci 2871bf215546Sopenharmony_ci case TGSI_OPCODE_CMP: 2872bf215546Sopenharmony_ci return emit_cmp( emit, insn ); 2873bf215546Sopenharmony_ci 2874bf215546Sopenharmony_ci case TGSI_OPCODE_DIV: 2875bf215546Sopenharmony_ci return emit_div( emit, insn ); 2876bf215546Sopenharmony_ci 2877bf215546Sopenharmony_ci case TGSI_OPCODE_DP2: 2878bf215546Sopenharmony_ci return emit_dp2( emit, insn ); 2879bf215546Sopenharmony_ci 2880bf215546Sopenharmony_ci case TGSI_OPCODE_COS: 2881bf215546Sopenharmony_ci return emit_cos( emit, insn ); 2882bf215546Sopenharmony_ci 2883bf215546Sopenharmony_ci case TGSI_OPCODE_SIN: 2884bf215546Sopenharmony_ci return emit_sin( emit, insn ); 2885bf215546Sopenharmony_ci 2886bf215546Sopenharmony_ci case TGSI_OPCODE_END: 2887bf215546Sopenharmony_ci /* TGSI always finishes the main func with an END */ 2888bf215546Sopenharmony_ci return emit_end( emit ); 2889bf215546Sopenharmony_ci 2890bf215546Sopenharmony_ci case TGSI_OPCODE_KILL_IF: 2891bf215546Sopenharmony_ci return emit_cond_discard( emit, insn ); 2892bf215546Sopenharmony_ci 2893bf215546Sopenharmony_ci /* Selection opcodes. The underlying language is fairly 2894bf215546Sopenharmony_ci * non-orthogonal about these. 2895bf215546Sopenharmony_ci */ 2896bf215546Sopenharmony_ci case TGSI_OPCODE_SEQ: 2897bf215546Sopenharmony_ci return emit_select_op( emit, PIPE_FUNC_EQUAL, insn ); 2898bf215546Sopenharmony_ci 2899bf215546Sopenharmony_ci case TGSI_OPCODE_SNE: 2900bf215546Sopenharmony_ci return emit_select_op( emit, PIPE_FUNC_NOTEQUAL, insn ); 2901bf215546Sopenharmony_ci 2902bf215546Sopenharmony_ci case TGSI_OPCODE_SGT: 2903bf215546Sopenharmony_ci return emit_select_op( emit, PIPE_FUNC_GREATER, insn ); 2904bf215546Sopenharmony_ci 2905bf215546Sopenharmony_ci case TGSI_OPCODE_SGE: 2906bf215546Sopenharmony_ci return emit_select_op( emit, PIPE_FUNC_GEQUAL, insn ); 2907bf215546Sopenharmony_ci 2908bf215546Sopenharmony_ci case TGSI_OPCODE_SLT: 2909bf215546Sopenharmony_ci return emit_select_op( emit, PIPE_FUNC_LESS, insn ); 2910bf215546Sopenharmony_ci 2911bf215546Sopenharmony_ci case TGSI_OPCODE_SLE: 2912bf215546Sopenharmony_ci return emit_select_op( emit, PIPE_FUNC_LEQUAL, insn ); 2913bf215546Sopenharmony_ci 2914bf215546Sopenharmony_ci case TGSI_OPCODE_POW: 2915bf215546Sopenharmony_ci return emit_pow( emit, insn ); 2916bf215546Sopenharmony_ci 2917bf215546Sopenharmony_ci case TGSI_OPCODE_EX2: 2918bf215546Sopenharmony_ci return emit_ex2( emit, insn ); 2919bf215546Sopenharmony_ci 2920bf215546Sopenharmony_ci case TGSI_OPCODE_EXP: 2921bf215546Sopenharmony_ci return emit_exp( emit, insn ); 2922bf215546Sopenharmony_ci 2923bf215546Sopenharmony_ci case TGSI_OPCODE_LOG: 2924bf215546Sopenharmony_ci return emit_log( emit, insn ); 2925bf215546Sopenharmony_ci 2926bf215546Sopenharmony_ci case TGSI_OPCODE_LG2: 2927bf215546Sopenharmony_ci return emit_scalar_op1( emit, SVGA3DOP_LOG, insn ); 2928bf215546Sopenharmony_ci 2929bf215546Sopenharmony_ci case TGSI_OPCODE_RSQ: 2930bf215546Sopenharmony_ci return emit_scalar_op1( emit, SVGA3DOP_RSQ, insn ); 2931bf215546Sopenharmony_ci 2932bf215546Sopenharmony_ci case TGSI_OPCODE_RCP: 2933bf215546Sopenharmony_ci return emit_scalar_op1( emit, SVGA3DOP_RCP, insn ); 2934bf215546Sopenharmony_ci 2935bf215546Sopenharmony_ci case TGSI_OPCODE_CONT: 2936bf215546Sopenharmony_ci /* not expected (we return PIPE_SHADER_CAP_CONT_SUPPORTED = 0) */ 2937bf215546Sopenharmony_ci return FALSE; 2938bf215546Sopenharmony_ci 2939bf215546Sopenharmony_ci case TGSI_OPCODE_RET: 2940bf215546Sopenharmony_ci /* This is a noop -- we tell mesa that we can't support RET 2941bf215546Sopenharmony_ci * within a function (early return), so this will always be 2942bf215546Sopenharmony_ci * followed by an ENDSUB. 2943bf215546Sopenharmony_ci */ 2944bf215546Sopenharmony_ci return TRUE; 2945bf215546Sopenharmony_ci 2946bf215546Sopenharmony_ci /* These aren't actually used by any of the frontends we care 2947bf215546Sopenharmony_ci * about: 2948bf215546Sopenharmony_ci */ 2949bf215546Sopenharmony_ci case TGSI_OPCODE_AND: 2950bf215546Sopenharmony_ci case TGSI_OPCODE_OR: 2951bf215546Sopenharmony_ci case TGSI_OPCODE_I2F: 2952bf215546Sopenharmony_ci case TGSI_OPCODE_NOT: 2953bf215546Sopenharmony_ci case TGSI_OPCODE_SHL: 2954bf215546Sopenharmony_ci case TGSI_OPCODE_ISHR: 2955bf215546Sopenharmony_ci case TGSI_OPCODE_XOR: 2956bf215546Sopenharmony_ci return FALSE; 2957bf215546Sopenharmony_ci 2958bf215546Sopenharmony_ci case TGSI_OPCODE_IF: 2959bf215546Sopenharmony_ci return emit_if( emit, insn ); 2960bf215546Sopenharmony_ci case TGSI_OPCODE_ELSE: 2961bf215546Sopenharmony_ci return emit_else( emit, insn ); 2962bf215546Sopenharmony_ci case TGSI_OPCODE_ENDIF: 2963bf215546Sopenharmony_ci return emit_endif( emit, insn ); 2964bf215546Sopenharmony_ci 2965bf215546Sopenharmony_ci case TGSI_OPCODE_BGNLOOP: 2966bf215546Sopenharmony_ci return emit_bgnloop( emit, insn ); 2967bf215546Sopenharmony_ci case TGSI_OPCODE_ENDLOOP: 2968bf215546Sopenharmony_ci return emit_endloop( emit, insn ); 2969bf215546Sopenharmony_ci case TGSI_OPCODE_BRK: 2970bf215546Sopenharmony_ci return emit_brk( emit, insn ); 2971bf215546Sopenharmony_ci 2972bf215546Sopenharmony_ci case TGSI_OPCODE_KILL: 2973bf215546Sopenharmony_ci return emit_discard( emit, insn ); 2974bf215546Sopenharmony_ci 2975bf215546Sopenharmony_ci case TGSI_OPCODE_DST: 2976bf215546Sopenharmony_ci return emit_dst_insn( emit, insn ); 2977bf215546Sopenharmony_ci 2978bf215546Sopenharmony_ci case TGSI_OPCODE_LIT: 2979bf215546Sopenharmony_ci return emit_lit( emit, insn ); 2980bf215546Sopenharmony_ci 2981bf215546Sopenharmony_ci case TGSI_OPCODE_LRP: 2982bf215546Sopenharmony_ci return emit_lrp( emit, insn ); 2983bf215546Sopenharmony_ci 2984bf215546Sopenharmony_ci case TGSI_OPCODE_SSG: 2985bf215546Sopenharmony_ci return emit_ssg( emit, insn ); 2986bf215546Sopenharmony_ci 2987bf215546Sopenharmony_ci case TGSI_OPCODE_MOV: 2988bf215546Sopenharmony_ci return emit_mov( emit, insn ); 2989bf215546Sopenharmony_ci 2990bf215546Sopenharmony_ci case TGSI_OPCODE_SQRT: 2991bf215546Sopenharmony_ci return emit_sqrt( emit, insn ); 2992bf215546Sopenharmony_ci 2993bf215546Sopenharmony_ci default: 2994bf215546Sopenharmony_ci { 2995bf215546Sopenharmony_ci SVGA3dShaderOpCodeType opcode = 2996bf215546Sopenharmony_ci translate_opcode(insn->Instruction.Opcode); 2997bf215546Sopenharmony_ci 2998bf215546Sopenharmony_ci if (opcode == SVGA3DOP_LAST_INST) 2999bf215546Sopenharmony_ci return FALSE; 3000bf215546Sopenharmony_ci 3001bf215546Sopenharmony_ci if (!emit_simple_instruction( emit, opcode, insn )) 3002bf215546Sopenharmony_ci return FALSE; 3003bf215546Sopenharmony_ci } 3004bf215546Sopenharmony_ci } 3005bf215546Sopenharmony_ci 3006bf215546Sopenharmony_ci return TRUE; 3007bf215546Sopenharmony_ci} 3008bf215546Sopenharmony_ci 3009bf215546Sopenharmony_ci 3010bf215546Sopenharmony_ci/** 3011bf215546Sopenharmony_ci * Translate/emit a TGSI IMMEDIATE declaration. 3012bf215546Sopenharmony_ci * An immediate vector is a constant that's hard-coded into the shader. 3013bf215546Sopenharmony_ci */ 3014bf215546Sopenharmony_cistatic boolean 3015bf215546Sopenharmony_cisvga_emit_immediate(struct svga_shader_emitter *emit, 3016bf215546Sopenharmony_ci const struct tgsi_full_immediate *imm) 3017bf215546Sopenharmony_ci{ 3018bf215546Sopenharmony_ci static const float id[4] = {0,0,0,1}; 3019bf215546Sopenharmony_ci float value[4]; 3020bf215546Sopenharmony_ci unsigned i; 3021bf215546Sopenharmony_ci 3022bf215546Sopenharmony_ci assert(1 <= imm->Immediate.NrTokens && imm->Immediate.NrTokens <= 5); 3023bf215546Sopenharmony_ci for (i = 0; i < 4 && i < imm->Immediate.NrTokens - 1; i++) { 3024bf215546Sopenharmony_ci float f = imm->u[i].Float; 3025bf215546Sopenharmony_ci value[i] = util_is_inf_or_nan(f) ? 0.0f : f; 3026bf215546Sopenharmony_ci } 3027bf215546Sopenharmony_ci 3028bf215546Sopenharmony_ci /* If the immediate has less than four values, fill in the remaining 3029bf215546Sopenharmony_ci * positions from id={0,0,0,1}. 3030bf215546Sopenharmony_ci */ 3031bf215546Sopenharmony_ci for ( ; i < 4; i++ ) 3032bf215546Sopenharmony_ci value[i] = id[i]; 3033bf215546Sopenharmony_ci 3034bf215546Sopenharmony_ci return emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT, 3035bf215546Sopenharmony_ci emit->imm_start + emit->internal_imm_count++, 3036bf215546Sopenharmony_ci value[0], value[1], value[2], value[3]); 3037bf215546Sopenharmony_ci} 3038bf215546Sopenharmony_ci 3039bf215546Sopenharmony_ci 3040bf215546Sopenharmony_cistatic boolean 3041bf215546Sopenharmony_cimake_immediate(struct svga_shader_emitter *emit, 3042bf215546Sopenharmony_ci float a, float b, float c, float d, 3043bf215546Sopenharmony_ci struct src_register *out ) 3044bf215546Sopenharmony_ci{ 3045bf215546Sopenharmony_ci unsigned idx = emit->nr_hw_float_const++; 3046bf215546Sopenharmony_ci 3047bf215546Sopenharmony_ci if (!emit_def_const( emit, SVGA3D_CONST_TYPE_FLOAT, 3048bf215546Sopenharmony_ci idx, a, b, c, d )) 3049bf215546Sopenharmony_ci return FALSE; 3050bf215546Sopenharmony_ci 3051bf215546Sopenharmony_ci *out = src_register( SVGA3DREG_CONST, idx ); 3052bf215546Sopenharmony_ci 3053bf215546Sopenharmony_ci return TRUE; 3054bf215546Sopenharmony_ci} 3055bf215546Sopenharmony_ci 3056bf215546Sopenharmony_ci 3057bf215546Sopenharmony_ci/** 3058bf215546Sopenharmony_ci * Emit special VS instructions at top of shader. 3059bf215546Sopenharmony_ci */ 3060bf215546Sopenharmony_cistatic boolean 3061bf215546Sopenharmony_ciemit_vs_preamble(struct svga_shader_emitter *emit) 3062bf215546Sopenharmony_ci{ 3063bf215546Sopenharmony_ci if (!emit->key.vs.need_prescale) { 3064bf215546Sopenharmony_ci if (!make_immediate( emit, 0, 0, .5, .5, 3065bf215546Sopenharmony_ci &emit->imm_0055)) 3066bf215546Sopenharmony_ci return FALSE; 3067bf215546Sopenharmony_ci } 3068bf215546Sopenharmony_ci 3069bf215546Sopenharmony_ci return TRUE; 3070bf215546Sopenharmony_ci} 3071bf215546Sopenharmony_ci 3072bf215546Sopenharmony_ci 3073bf215546Sopenharmony_ci/** 3074bf215546Sopenharmony_ci * Emit special PS instructions at top of shader. 3075bf215546Sopenharmony_ci */ 3076bf215546Sopenharmony_cistatic boolean 3077bf215546Sopenharmony_ciemit_ps_preamble(struct svga_shader_emitter *emit) 3078bf215546Sopenharmony_ci{ 3079bf215546Sopenharmony_ci if (emit->ps_reads_pos && emit->info.reads_z) { 3080bf215546Sopenharmony_ci /* 3081bf215546Sopenharmony_ci * Assemble the position from various bits of inputs. Depth and W are 3082bf215546Sopenharmony_ci * passed in a texcoord this is due to D3D's vPos not hold Z or W. 3083bf215546Sopenharmony_ci * Also fixup the perspective interpolation. 3084bf215546Sopenharmony_ci * 3085bf215546Sopenharmony_ci * temp_pos.xy = vPos.xy 3086bf215546Sopenharmony_ci * temp_pos.w = rcp(texcoord1.w); 3087bf215546Sopenharmony_ci * temp_pos.z = texcoord1.z * temp_pos.w; 3088bf215546Sopenharmony_ci */ 3089bf215546Sopenharmony_ci if (!submit_op1( emit, 3090bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3091bf215546Sopenharmony_ci writemask( emit->ps_temp_pos, TGSI_WRITEMASK_XY ), 3092bf215546Sopenharmony_ci emit->ps_true_pos )) 3093bf215546Sopenharmony_ci return FALSE; 3094bf215546Sopenharmony_ci 3095bf215546Sopenharmony_ci if (!submit_op1( emit, 3096bf215546Sopenharmony_ci inst_token(SVGA3DOP_RCP), 3097bf215546Sopenharmony_ci writemask( emit->ps_temp_pos, TGSI_WRITEMASK_W ), 3098bf215546Sopenharmony_ci scalar( emit->ps_depth_pos, TGSI_SWIZZLE_W ) )) 3099bf215546Sopenharmony_ci return FALSE; 3100bf215546Sopenharmony_ci 3101bf215546Sopenharmony_ci if (!submit_op2( emit, 3102bf215546Sopenharmony_ci inst_token(SVGA3DOP_MUL), 3103bf215546Sopenharmony_ci writemask( emit->ps_temp_pos, TGSI_WRITEMASK_Z ), 3104bf215546Sopenharmony_ci scalar( emit->ps_depth_pos, TGSI_SWIZZLE_Z ), 3105bf215546Sopenharmony_ci scalar( src(emit->ps_temp_pos), TGSI_SWIZZLE_W ) )) 3106bf215546Sopenharmony_ci return FALSE; 3107bf215546Sopenharmony_ci } 3108bf215546Sopenharmony_ci 3109bf215546Sopenharmony_ci return TRUE; 3110bf215546Sopenharmony_ci} 3111bf215546Sopenharmony_ci 3112bf215546Sopenharmony_ci 3113bf215546Sopenharmony_ci/** 3114bf215546Sopenharmony_ci * Emit special PS instructions at end of shader. 3115bf215546Sopenharmony_ci */ 3116bf215546Sopenharmony_cistatic boolean 3117bf215546Sopenharmony_ciemit_ps_postamble(struct svga_shader_emitter *emit) 3118bf215546Sopenharmony_ci{ 3119bf215546Sopenharmony_ci unsigned i; 3120bf215546Sopenharmony_ci 3121bf215546Sopenharmony_ci /* PS oDepth is incredibly fragile and it's very hard to catch the 3122bf215546Sopenharmony_ci * types of usage that break it during shader emit. Easier just to 3123bf215546Sopenharmony_ci * redirect the main program to a temporary and then only touch 3124bf215546Sopenharmony_ci * oDepth with a hand-crafted MOV below. 3125bf215546Sopenharmony_ci */ 3126bf215546Sopenharmony_ci if (SVGA3dShaderGetRegType(emit->true_pos.value) != 0) { 3127bf215546Sopenharmony_ci if (!submit_op1( emit, 3128bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3129bf215546Sopenharmony_ci emit->true_pos, 3130bf215546Sopenharmony_ci scalar(src(emit->temp_pos), TGSI_SWIZZLE_Z) )) 3131bf215546Sopenharmony_ci return FALSE; 3132bf215546Sopenharmony_ci } 3133bf215546Sopenharmony_ci 3134bf215546Sopenharmony_ci for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { 3135bf215546Sopenharmony_ci if (SVGA3dShaderGetRegType(emit->true_color_output[i].value) != 0) { 3136bf215546Sopenharmony_ci /* Potentially override output colors with white for XOR 3137bf215546Sopenharmony_ci * logicop workaround. 3138bf215546Sopenharmony_ci */ 3139bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_FRAGMENT && 3140bf215546Sopenharmony_ci emit->key.fs.white_fragments) { 3141bf215546Sopenharmony_ci struct src_register one = get_one_immediate(emit); 3142bf215546Sopenharmony_ci 3143bf215546Sopenharmony_ci if (!submit_op1( emit, 3144bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3145bf215546Sopenharmony_ci emit->true_color_output[i], 3146bf215546Sopenharmony_ci one )) 3147bf215546Sopenharmony_ci return FALSE; 3148bf215546Sopenharmony_ci } 3149bf215546Sopenharmony_ci else if (emit->unit == PIPE_SHADER_FRAGMENT && 3150bf215546Sopenharmony_ci i < emit->key.fs.write_color0_to_n_cbufs) { 3151bf215546Sopenharmony_ci /* Write temp color output [0] to true output [i] */ 3152bf215546Sopenharmony_ci if (!submit_op1(emit, inst_token(SVGA3DOP_MOV), 3153bf215546Sopenharmony_ci emit->true_color_output[i], 3154bf215546Sopenharmony_ci src(emit->temp_color_output[0]))) { 3155bf215546Sopenharmony_ci return FALSE; 3156bf215546Sopenharmony_ci } 3157bf215546Sopenharmony_ci } 3158bf215546Sopenharmony_ci else { 3159bf215546Sopenharmony_ci if (!submit_op1( emit, 3160bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3161bf215546Sopenharmony_ci emit->true_color_output[i], 3162bf215546Sopenharmony_ci src(emit->temp_color_output[i]) )) 3163bf215546Sopenharmony_ci return FALSE; 3164bf215546Sopenharmony_ci } 3165bf215546Sopenharmony_ci } 3166bf215546Sopenharmony_ci } 3167bf215546Sopenharmony_ci 3168bf215546Sopenharmony_ci return TRUE; 3169bf215546Sopenharmony_ci} 3170bf215546Sopenharmony_ci 3171bf215546Sopenharmony_ci 3172bf215546Sopenharmony_ci/** 3173bf215546Sopenharmony_ci * Emit special VS instructions at end of shader. 3174bf215546Sopenharmony_ci */ 3175bf215546Sopenharmony_cistatic boolean 3176bf215546Sopenharmony_ciemit_vs_postamble(struct svga_shader_emitter *emit) 3177bf215546Sopenharmony_ci{ 3178bf215546Sopenharmony_ci /* PSIZ output is incredibly fragile and it's very hard to catch 3179bf215546Sopenharmony_ci * the types of usage that break it during shader emit. Easier 3180bf215546Sopenharmony_ci * just to redirect the main program to a temporary and then only 3181bf215546Sopenharmony_ci * touch PSIZ with a hand-crafted MOV below. 3182bf215546Sopenharmony_ci */ 3183bf215546Sopenharmony_ci if (SVGA3dShaderGetRegType(emit->true_psiz.value) != 0) { 3184bf215546Sopenharmony_ci if (!submit_op1( emit, 3185bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3186bf215546Sopenharmony_ci emit->true_psiz, 3187bf215546Sopenharmony_ci scalar(src(emit->temp_psiz), TGSI_SWIZZLE_X) )) 3188bf215546Sopenharmony_ci return FALSE; 3189bf215546Sopenharmony_ci } 3190bf215546Sopenharmony_ci 3191bf215546Sopenharmony_ci /* Need to perform various manipulations on vertex position to cope 3192bf215546Sopenharmony_ci * with the different GL and D3D clip spaces. 3193bf215546Sopenharmony_ci */ 3194bf215546Sopenharmony_ci if (emit->key.vs.need_prescale) { 3195bf215546Sopenharmony_ci SVGA3dShaderDestToken temp_pos = emit->temp_pos; 3196bf215546Sopenharmony_ci SVGA3dShaderDestToken depth = emit->depth_pos; 3197bf215546Sopenharmony_ci SVGA3dShaderDestToken pos = emit->true_pos; 3198bf215546Sopenharmony_ci unsigned offset = emit->info.file_max[TGSI_FILE_CONSTANT] + 1; 3199bf215546Sopenharmony_ci struct src_register prescale_scale = src_register( SVGA3DREG_CONST, 3200bf215546Sopenharmony_ci offset + 0 ); 3201bf215546Sopenharmony_ci struct src_register prescale_trans = src_register( SVGA3DREG_CONST, 3202bf215546Sopenharmony_ci offset + 1 ); 3203bf215546Sopenharmony_ci 3204bf215546Sopenharmony_ci if (!submit_op1( emit, 3205bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3206bf215546Sopenharmony_ci writemask(depth, TGSI_WRITEMASK_W), 3207bf215546Sopenharmony_ci scalar(src(temp_pos), TGSI_SWIZZLE_W) )) 3208bf215546Sopenharmony_ci return FALSE; 3209bf215546Sopenharmony_ci 3210bf215546Sopenharmony_ci /* MUL temp_pos.xyz, temp_pos, prescale.scale 3211bf215546Sopenharmony_ci * MAD result.position, temp_pos.wwww, prescale.trans, temp_pos 3212bf215546Sopenharmony_ci * --> Note that prescale.trans.w == 0 3213bf215546Sopenharmony_ci */ 3214bf215546Sopenharmony_ci if (!submit_op2( emit, 3215bf215546Sopenharmony_ci inst_token(SVGA3DOP_MUL), 3216bf215546Sopenharmony_ci writemask(temp_pos, TGSI_WRITEMASK_XYZ), 3217bf215546Sopenharmony_ci src(temp_pos), 3218bf215546Sopenharmony_ci prescale_scale )) 3219bf215546Sopenharmony_ci return FALSE; 3220bf215546Sopenharmony_ci 3221bf215546Sopenharmony_ci if (!submit_op3( emit, 3222bf215546Sopenharmony_ci inst_token(SVGA3DOP_MAD), 3223bf215546Sopenharmony_ci pos, 3224bf215546Sopenharmony_ci swizzle(src(temp_pos), 3, 3, 3, 3), 3225bf215546Sopenharmony_ci prescale_trans, 3226bf215546Sopenharmony_ci src(temp_pos))) 3227bf215546Sopenharmony_ci return FALSE; 3228bf215546Sopenharmony_ci 3229bf215546Sopenharmony_ci /* Also write to depth value */ 3230bf215546Sopenharmony_ci if (!submit_op3( emit, 3231bf215546Sopenharmony_ci inst_token(SVGA3DOP_MAD), 3232bf215546Sopenharmony_ci writemask(depth, TGSI_WRITEMASK_Z), 3233bf215546Sopenharmony_ci swizzle(src(temp_pos), 3, 3, 3, 3), 3234bf215546Sopenharmony_ci prescale_trans, 3235bf215546Sopenharmony_ci src(temp_pos) )) 3236bf215546Sopenharmony_ci return FALSE; 3237bf215546Sopenharmony_ci } 3238bf215546Sopenharmony_ci else { 3239bf215546Sopenharmony_ci SVGA3dShaderDestToken temp_pos = emit->temp_pos; 3240bf215546Sopenharmony_ci SVGA3dShaderDestToken depth = emit->depth_pos; 3241bf215546Sopenharmony_ci SVGA3dShaderDestToken pos = emit->true_pos; 3242bf215546Sopenharmony_ci struct src_register imm_0055 = emit->imm_0055; 3243bf215546Sopenharmony_ci 3244bf215546Sopenharmony_ci /* Adjust GL clipping coordinate space to hardware (D3D-style): 3245bf215546Sopenharmony_ci * 3246bf215546Sopenharmony_ci * DP4 temp_pos.z, {0,0,.5,.5}, temp_pos 3247bf215546Sopenharmony_ci * MOV result.position, temp_pos 3248bf215546Sopenharmony_ci */ 3249bf215546Sopenharmony_ci if (!submit_op2( emit, 3250bf215546Sopenharmony_ci inst_token(SVGA3DOP_DP4), 3251bf215546Sopenharmony_ci writemask(temp_pos, TGSI_WRITEMASK_Z), 3252bf215546Sopenharmony_ci imm_0055, 3253bf215546Sopenharmony_ci src(temp_pos) )) 3254bf215546Sopenharmony_ci return FALSE; 3255bf215546Sopenharmony_ci 3256bf215546Sopenharmony_ci if (!submit_op1( emit, 3257bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3258bf215546Sopenharmony_ci pos, 3259bf215546Sopenharmony_ci src(temp_pos) )) 3260bf215546Sopenharmony_ci return FALSE; 3261bf215546Sopenharmony_ci 3262bf215546Sopenharmony_ci /* Move the manipulated depth into the extra texcoord reg */ 3263bf215546Sopenharmony_ci if (!submit_op1( emit, 3264bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3265bf215546Sopenharmony_ci writemask(depth, TGSI_WRITEMASK_ZW), 3266bf215546Sopenharmony_ci src(temp_pos) )) 3267bf215546Sopenharmony_ci return FALSE; 3268bf215546Sopenharmony_ci } 3269bf215546Sopenharmony_ci 3270bf215546Sopenharmony_ci return TRUE; 3271bf215546Sopenharmony_ci} 3272bf215546Sopenharmony_ci 3273bf215546Sopenharmony_ci 3274bf215546Sopenharmony_ci/** 3275bf215546Sopenharmony_ci * For the pixel shader: emit the code which chooses the front 3276bf215546Sopenharmony_ci * or back face color depending on triangle orientation. 3277bf215546Sopenharmony_ci * This happens at the top of the fragment shader. 3278bf215546Sopenharmony_ci * 3279bf215546Sopenharmony_ci * 0: IF VFACE :4 3280bf215546Sopenharmony_ci * 1: COLOR = FrontColor; 3281bf215546Sopenharmony_ci * 2: ELSE 3282bf215546Sopenharmony_ci * 3: COLOR = BackColor; 3283bf215546Sopenharmony_ci * 4: ENDIF 3284bf215546Sopenharmony_ci */ 3285bf215546Sopenharmony_cistatic boolean 3286bf215546Sopenharmony_ciemit_light_twoside(struct svga_shader_emitter *emit) 3287bf215546Sopenharmony_ci{ 3288bf215546Sopenharmony_ci struct src_register vface, zero; 3289bf215546Sopenharmony_ci struct src_register front[2]; 3290bf215546Sopenharmony_ci struct src_register back[2]; 3291bf215546Sopenharmony_ci SVGA3dShaderDestToken color[2]; 3292bf215546Sopenharmony_ci int count = emit->internal_color_count; 3293bf215546Sopenharmony_ci unsigned i; 3294bf215546Sopenharmony_ci SVGA3dShaderInstToken if_token; 3295bf215546Sopenharmony_ci 3296bf215546Sopenharmony_ci if (count == 0) 3297bf215546Sopenharmony_ci return TRUE; 3298bf215546Sopenharmony_ci 3299bf215546Sopenharmony_ci vface = get_vface( emit ); 3300bf215546Sopenharmony_ci zero = get_zero_immediate(emit); 3301bf215546Sopenharmony_ci 3302bf215546Sopenharmony_ci /* Can't use get_temp() to allocate the color reg as such 3303bf215546Sopenharmony_ci * temporaries will be reclaimed after each instruction by the call 3304bf215546Sopenharmony_ci * to reset_temp_regs(). 3305bf215546Sopenharmony_ci */ 3306bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 3307bf215546Sopenharmony_ci color[i] = dst_register( SVGA3DREG_TEMP, emit->nr_hw_temp++ ); 3308bf215546Sopenharmony_ci front[i] = emit->input_map[emit->internal_color_idx[i]]; 3309bf215546Sopenharmony_ci 3310bf215546Sopenharmony_ci /* Back is always the next input: 3311bf215546Sopenharmony_ci */ 3312bf215546Sopenharmony_ci back[i] = front[i]; 3313bf215546Sopenharmony_ci back[i].base.num = front[i].base.num + 1; 3314bf215546Sopenharmony_ci 3315bf215546Sopenharmony_ci /* Reassign the input_map to the actual front-face color: 3316bf215546Sopenharmony_ci */ 3317bf215546Sopenharmony_ci emit->input_map[emit->internal_color_idx[i]] = src(color[i]); 3318bf215546Sopenharmony_ci } 3319bf215546Sopenharmony_ci 3320bf215546Sopenharmony_ci if_token = inst_token( SVGA3DOP_IFC ); 3321bf215546Sopenharmony_ci 3322bf215546Sopenharmony_ci if (emit->key.fs.front_ccw) 3323bf215546Sopenharmony_ci if_token.control = SVGA3DOPCOMP_LT; 3324bf215546Sopenharmony_ci else 3325bf215546Sopenharmony_ci if_token.control = SVGA3DOPCOMP_GT; 3326bf215546Sopenharmony_ci 3327bf215546Sopenharmony_ci if (!(emit_instruction( emit, if_token ) && 3328bf215546Sopenharmony_ci emit_src( emit, vface ) && 3329bf215546Sopenharmony_ci emit_src( emit, zero ) )) 3330bf215546Sopenharmony_ci return FALSE; 3331bf215546Sopenharmony_ci 3332bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 3333bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), color[i], front[i] )) 3334bf215546Sopenharmony_ci return FALSE; 3335bf215546Sopenharmony_ci } 3336bf215546Sopenharmony_ci 3337bf215546Sopenharmony_ci if (!(emit_instruction( emit, inst_token( SVGA3DOP_ELSE)))) 3338bf215546Sopenharmony_ci return FALSE; 3339bf215546Sopenharmony_ci 3340bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 3341bf215546Sopenharmony_ci if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), color[i], back[i] )) 3342bf215546Sopenharmony_ci return FALSE; 3343bf215546Sopenharmony_ci } 3344bf215546Sopenharmony_ci 3345bf215546Sopenharmony_ci if (!emit_instruction( emit, inst_token( SVGA3DOP_ENDIF ) )) 3346bf215546Sopenharmony_ci return FALSE; 3347bf215546Sopenharmony_ci 3348bf215546Sopenharmony_ci return TRUE; 3349bf215546Sopenharmony_ci} 3350bf215546Sopenharmony_ci 3351bf215546Sopenharmony_ci 3352bf215546Sopenharmony_ci/** 3353bf215546Sopenharmony_ci * Emit special setup code for the front/back face register in the FS. 3354bf215546Sopenharmony_ci * 0: SETP_GT TEMP, VFACE, 0 3355bf215546Sopenharmony_ci * where TEMP is a fake frontface register 3356bf215546Sopenharmony_ci */ 3357bf215546Sopenharmony_cistatic boolean 3358bf215546Sopenharmony_ciemit_frontface(struct svga_shader_emitter *emit) 3359bf215546Sopenharmony_ci{ 3360bf215546Sopenharmony_ci struct src_register vface; 3361bf215546Sopenharmony_ci SVGA3dShaderDestToken temp; 3362bf215546Sopenharmony_ci struct src_register pass, fail; 3363bf215546Sopenharmony_ci 3364bf215546Sopenharmony_ci vface = get_vface( emit ); 3365bf215546Sopenharmony_ci 3366bf215546Sopenharmony_ci /* Can't use get_temp() to allocate the fake frontface reg as such 3367bf215546Sopenharmony_ci * temporaries will be reclaimed after each instruction by the call 3368bf215546Sopenharmony_ci * to reset_temp_regs(). 3369bf215546Sopenharmony_ci */ 3370bf215546Sopenharmony_ci temp = dst_register( SVGA3DREG_TEMP, 3371bf215546Sopenharmony_ci emit->nr_hw_temp++ ); 3372bf215546Sopenharmony_ci 3373bf215546Sopenharmony_ci if (emit->key.fs.front_ccw) { 3374bf215546Sopenharmony_ci pass = get_zero_immediate(emit); 3375bf215546Sopenharmony_ci fail = get_one_immediate(emit); 3376bf215546Sopenharmony_ci } else { 3377bf215546Sopenharmony_ci pass = get_one_immediate(emit); 3378bf215546Sopenharmony_ci fail = get_zero_immediate(emit); 3379bf215546Sopenharmony_ci } 3380bf215546Sopenharmony_ci 3381bf215546Sopenharmony_ci if (!emit_conditional(emit, PIPE_FUNC_GREATER, 3382bf215546Sopenharmony_ci temp, vface, get_zero_immediate(emit), 3383bf215546Sopenharmony_ci pass, fail)) 3384bf215546Sopenharmony_ci return FALSE; 3385bf215546Sopenharmony_ci 3386bf215546Sopenharmony_ci /* Reassign the input_map to the actual front-face color: 3387bf215546Sopenharmony_ci */ 3388bf215546Sopenharmony_ci emit->input_map[emit->internal_frontface_idx] = src(temp); 3389bf215546Sopenharmony_ci 3390bf215546Sopenharmony_ci return TRUE; 3391bf215546Sopenharmony_ci} 3392bf215546Sopenharmony_ci 3393bf215546Sopenharmony_ci 3394bf215546Sopenharmony_ci/** 3395bf215546Sopenharmony_ci * Emit code to invert the T component of the incoming texture coordinate. 3396bf215546Sopenharmony_ci * This is used for drawing point sprites when 3397bf215546Sopenharmony_ci * pipe_rasterizer_state::sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT. 3398bf215546Sopenharmony_ci */ 3399bf215546Sopenharmony_cistatic boolean 3400bf215546Sopenharmony_ciemit_inverted_texcoords(struct svga_shader_emitter *emit) 3401bf215546Sopenharmony_ci{ 3402bf215546Sopenharmony_ci unsigned inverted_texcoords = emit->inverted_texcoords; 3403bf215546Sopenharmony_ci 3404bf215546Sopenharmony_ci while (inverted_texcoords) { 3405bf215546Sopenharmony_ci const unsigned unit = ffs(inverted_texcoords) - 1; 3406bf215546Sopenharmony_ci 3407bf215546Sopenharmony_ci assert(emit->inverted_texcoords & (1 << unit)); 3408bf215546Sopenharmony_ci 3409bf215546Sopenharmony_ci assert(unit < ARRAY_SIZE(emit->ps_true_texcoord)); 3410bf215546Sopenharmony_ci 3411bf215546Sopenharmony_ci assert(unit < ARRAY_SIZE(emit->ps_inverted_texcoord_input)); 3412bf215546Sopenharmony_ci 3413bf215546Sopenharmony_ci assert(emit->ps_inverted_texcoord_input[unit] 3414bf215546Sopenharmony_ci < ARRAY_SIZE(emit->input_map)); 3415bf215546Sopenharmony_ci 3416bf215546Sopenharmony_ci /* inverted = coord * (1, -1, 1, 1) + (0, 1, 0, 0) */ 3417bf215546Sopenharmony_ci if (!submit_op3(emit, 3418bf215546Sopenharmony_ci inst_token(SVGA3DOP_MAD), 3419bf215546Sopenharmony_ci dst(emit->ps_inverted_texcoord[unit]), 3420bf215546Sopenharmony_ci emit->ps_true_texcoord[unit], 3421bf215546Sopenharmony_ci get_immediate(emit, 1.0f, -1.0f, 1.0f, 1.0f), 3422bf215546Sopenharmony_ci get_immediate(emit, 0.0f, 1.0f, 0.0f, 0.0f))) 3423bf215546Sopenharmony_ci return FALSE; 3424bf215546Sopenharmony_ci 3425bf215546Sopenharmony_ci /* Reassign the input_map entry to the new texcoord register */ 3426bf215546Sopenharmony_ci emit->input_map[emit->ps_inverted_texcoord_input[unit]] = 3427bf215546Sopenharmony_ci emit->ps_inverted_texcoord[unit]; 3428bf215546Sopenharmony_ci 3429bf215546Sopenharmony_ci inverted_texcoords &= ~(1 << unit); 3430bf215546Sopenharmony_ci } 3431bf215546Sopenharmony_ci 3432bf215546Sopenharmony_ci return TRUE; 3433bf215546Sopenharmony_ci} 3434bf215546Sopenharmony_ci 3435bf215546Sopenharmony_ci 3436bf215546Sopenharmony_ci/** 3437bf215546Sopenharmony_ci * Emit code to adjust vertex shader inputs/attributes: 3438bf215546Sopenharmony_ci * - Change range from [0,1] to [-1,1] (for normalized byte/short attribs). 3439bf215546Sopenharmony_ci * - Set attrib W component = 1. 3440bf215546Sopenharmony_ci */ 3441bf215546Sopenharmony_cistatic boolean 3442bf215546Sopenharmony_ciemit_adjusted_vertex_attribs(struct svga_shader_emitter *emit) 3443bf215546Sopenharmony_ci{ 3444bf215546Sopenharmony_ci unsigned adjust_mask = (emit->key.vs.adjust_attrib_range | 3445bf215546Sopenharmony_ci emit->key.vs.adjust_attrib_w_1); 3446bf215546Sopenharmony_ci 3447bf215546Sopenharmony_ci while (adjust_mask) { 3448bf215546Sopenharmony_ci /* Adjust vertex attrib range and/or set W component = 1 */ 3449bf215546Sopenharmony_ci const unsigned index = u_bit_scan(&adjust_mask); 3450bf215546Sopenharmony_ci struct src_register tmp; 3451bf215546Sopenharmony_ci 3452bf215546Sopenharmony_ci /* allocate a temp reg */ 3453bf215546Sopenharmony_ci tmp = src_register(SVGA3DREG_TEMP, emit->nr_hw_temp); 3454bf215546Sopenharmony_ci emit->nr_hw_temp++; 3455bf215546Sopenharmony_ci 3456bf215546Sopenharmony_ci if (emit->key.vs.adjust_attrib_range & (1 << index)) { 3457bf215546Sopenharmony_ci /* The vertex input/attribute is supposed to be a signed value in 3458bf215546Sopenharmony_ci * the range [-1,1] but we actually fetched/converted it to the 3459bf215546Sopenharmony_ci * range [0,1]. This most likely happens when the app specifies a 3460bf215546Sopenharmony_ci * signed byte attribute but we interpreted it as unsigned bytes. 3461bf215546Sopenharmony_ci * See also svga_translate_vertex_format(). 3462bf215546Sopenharmony_ci * 3463bf215546Sopenharmony_ci * Here, we emit some extra instructions to adjust 3464bf215546Sopenharmony_ci * the attribute values from [0,1] to [-1,1]. 3465bf215546Sopenharmony_ci * 3466bf215546Sopenharmony_ci * The adjustment we implement is: 3467bf215546Sopenharmony_ci * new_attrib = attrib * 2.0; 3468bf215546Sopenharmony_ci * if (attrib >= 0.5) 3469bf215546Sopenharmony_ci * new_attrib = new_attrib - 2.0; 3470bf215546Sopenharmony_ci * This isn't exactly right (it's off by a bit or so) but close enough. 3471bf215546Sopenharmony_ci */ 3472bf215546Sopenharmony_ci SVGA3dShaderDestToken pred_reg = dst_register(SVGA3DREG_PREDICATE, 0); 3473bf215546Sopenharmony_ci 3474bf215546Sopenharmony_ci /* tmp = attrib * 2.0 */ 3475bf215546Sopenharmony_ci if (!submit_op2(emit, 3476bf215546Sopenharmony_ci inst_token(SVGA3DOP_MUL), 3477bf215546Sopenharmony_ci dst(tmp), 3478bf215546Sopenharmony_ci emit->input_map[index], 3479bf215546Sopenharmony_ci get_two_immediate(emit))) 3480bf215546Sopenharmony_ci return FALSE; 3481bf215546Sopenharmony_ci 3482bf215546Sopenharmony_ci /* pred = (attrib >= 0.5) */ 3483bf215546Sopenharmony_ci if (!submit_op2(emit, 3484bf215546Sopenharmony_ci inst_token_setp(SVGA3DOPCOMP_GE), 3485bf215546Sopenharmony_ci pred_reg, 3486bf215546Sopenharmony_ci emit->input_map[index], /* vert attrib */ 3487bf215546Sopenharmony_ci get_half_immediate(emit))) /* 0.5 */ 3488bf215546Sopenharmony_ci return FALSE; 3489bf215546Sopenharmony_ci 3490bf215546Sopenharmony_ci /* sub(pred) tmp, tmp, 2.0 */ 3491bf215546Sopenharmony_ci if (!submit_op3(emit, 3492bf215546Sopenharmony_ci inst_token_predicated(SVGA3DOP_SUB), 3493bf215546Sopenharmony_ci dst(tmp), 3494bf215546Sopenharmony_ci src(pred_reg), 3495bf215546Sopenharmony_ci tmp, 3496bf215546Sopenharmony_ci get_two_immediate(emit))) 3497bf215546Sopenharmony_ci return FALSE; 3498bf215546Sopenharmony_ci } 3499bf215546Sopenharmony_ci else { 3500bf215546Sopenharmony_ci /* just copy the vertex input attrib to the temp register */ 3501bf215546Sopenharmony_ci if (!submit_op1(emit, 3502bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3503bf215546Sopenharmony_ci dst(tmp), 3504bf215546Sopenharmony_ci emit->input_map[index])) 3505bf215546Sopenharmony_ci return FALSE; 3506bf215546Sopenharmony_ci } 3507bf215546Sopenharmony_ci 3508bf215546Sopenharmony_ci if (emit->key.vs.adjust_attrib_w_1 & (1 << index)) { 3509bf215546Sopenharmony_ci /* move 1 into W position of tmp */ 3510bf215546Sopenharmony_ci if (!submit_op1(emit, 3511bf215546Sopenharmony_ci inst_token(SVGA3DOP_MOV), 3512bf215546Sopenharmony_ci writemask(dst(tmp), TGSI_WRITEMASK_W), 3513bf215546Sopenharmony_ci get_one_immediate(emit))) 3514bf215546Sopenharmony_ci return FALSE; 3515bf215546Sopenharmony_ci } 3516bf215546Sopenharmony_ci 3517bf215546Sopenharmony_ci /* Reassign the input_map entry to the new tmp register */ 3518bf215546Sopenharmony_ci emit->input_map[index] = tmp; 3519bf215546Sopenharmony_ci } 3520bf215546Sopenharmony_ci 3521bf215546Sopenharmony_ci return TRUE; 3522bf215546Sopenharmony_ci} 3523bf215546Sopenharmony_ci 3524bf215546Sopenharmony_ci 3525bf215546Sopenharmony_ci/** 3526bf215546Sopenharmony_ci * Determine if we need to create the "common" immediate value which is 3527bf215546Sopenharmony_ci * used for generating useful vector constants such as {0,0,0,0} and 3528bf215546Sopenharmony_ci * {1,1,1,1}. 3529bf215546Sopenharmony_ci * We could just do this all the time except that we want to conserve 3530bf215546Sopenharmony_ci * registers whenever possible. 3531bf215546Sopenharmony_ci */ 3532bf215546Sopenharmony_cistatic boolean 3533bf215546Sopenharmony_cineeds_to_create_common_immediate(const struct svga_shader_emitter *emit) 3534bf215546Sopenharmony_ci{ 3535bf215546Sopenharmony_ci unsigned i; 3536bf215546Sopenharmony_ci 3537bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_FRAGMENT) { 3538bf215546Sopenharmony_ci if (emit->key.fs.light_twoside) 3539bf215546Sopenharmony_ci return TRUE; 3540bf215546Sopenharmony_ci 3541bf215546Sopenharmony_ci if (emit->key.fs.white_fragments) 3542bf215546Sopenharmony_ci return TRUE; 3543bf215546Sopenharmony_ci 3544bf215546Sopenharmony_ci if (emit->emit_frontface) 3545bf215546Sopenharmony_ci return TRUE; 3546bf215546Sopenharmony_ci 3547bf215546Sopenharmony_ci if (emit->info.opcode_count[TGSI_OPCODE_DST] >= 1 || 3548bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_SSG] >= 1 || 3549bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_LIT] >= 1) 3550bf215546Sopenharmony_ci return TRUE; 3551bf215546Sopenharmony_ci 3552bf215546Sopenharmony_ci if (emit->inverted_texcoords) 3553bf215546Sopenharmony_ci return TRUE; 3554bf215546Sopenharmony_ci 3555bf215546Sopenharmony_ci /* look for any PIPE_SWIZZLE_0/ONE terms */ 3556bf215546Sopenharmony_ci for (i = 0; i < emit->key.num_textures; i++) { 3557bf215546Sopenharmony_ci if (emit->key.tex[i].swizzle_r > PIPE_SWIZZLE_W || 3558bf215546Sopenharmony_ci emit->key.tex[i].swizzle_g > PIPE_SWIZZLE_W || 3559bf215546Sopenharmony_ci emit->key.tex[i].swizzle_b > PIPE_SWIZZLE_W || 3560bf215546Sopenharmony_ci emit->key.tex[i].swizzle_a > PIPE_SWIZZLE_W) 3561bf215546Sopenharmony_ci return TRUE; 3562bf215546Sopenharmony_ci } 3563bf215546Sopenharmony_ci 3564bf215546Sopenharmony_ci for (i = 0; i < emit->key.num_textures; i++) { 3565bf215546Sopenharmony_ci if (emit->key.tex[i].compare_mode 3566bf215546Sopenharmony_ci == PIPE_TEX_COMPARE_R_TO_TEXTURE) 3567bf215546Sopenharmony_ci return TRUE; 3568bf215546Sopenharmony_ci } 3569bf215546Sopenharmony_ci } 3570bf215546Sopenharmony_ci else if (emit->unit == PIPE_SHADER_VERTEX) { 3571bf215546Sopenharmony_ci if (emit->info.opcode_count[TGSI_OPCODE_CMP] >= 1) 3572bf215546Sopenharmony_ci return TRUE; 3573bf215546Sopenharmony_ci if (emit->key.vs.adjust_attrib_range || 3574bf215546Sopenharmony_ci emit->key.vs.adjust_attrib_w_1) 3575bf215546Sopenharmony_ci return TRUE; 3576bf215546Sopenharmony_ci } 3577bf215546Sopenharmony_ci 3578bf215546Sopenharmony_ci if (emit->info.opcode_count[TGSI_OPCODE_IF] >= 1 || 3579bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_BGNLOOP] >= 1 || 3580bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_DDX] >= 1 || 3581bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_DDY] >= 1 || 3582bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_ROUND] >= 1 || 3583bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_SGE] >= 1 || 3584bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_SGT] >= 1 || 3585bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_SLE] >= 1 || 3586bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_SLT] >= 1 || 3587bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_SNE] >= 1 || 3588bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_SEQ] >= 1 || 3589bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_EXP] >= 1 || 3590bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_LOG] >= 1 || 3591bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_KILL] >= 1 || 3592bf215546Sopenharmony_ci emit->info.opcode_count[TGSI_OPCODE_SQRT] >= 1) 3593bf215546Sopenharmony_ci return TRUE; 3594bf215546Sopenharmony_ci 3595bf215546Sopenharmony_ci return FALSE; 3596bf215546Sopenharmony_ci} 3597bf215546Sopenharmony_ci 3598bf215546Sopenharmony_ci 3599bf215546Sopenharmony_ci/** 3600bf215546Sopenharmony_ci * Do we need to create a looping constant? 3601bf215546Sopenharmony_ci */ 3602bf215546Sopenharmony_cistatic boolean 3603bf215546Sopenharmony_cineeds_to_create_loop_const(const struct svga_shader_emitter *emit) 3604bf215546Sopenharmony_ci{ 3605bf215546Sopenharmony_ci return (emit->info.opcode_count[TGSI_OPCODE_BGNLOOP] >= 1); 3606bf215546Sopenharmony_ci} 3607bf215546Sopenharmony_ci 3608bf215546Sopenharmony_ci 3609bf215546Sopenharmony_cistatic boolean 3610bf215546Sopenharmony_cineeds_to_create_arl_consts(const struct svga_shader_emitter *emit) 3611bf215546Sopenharmony_ci{ 3612bf215546Sopenharmony_ci return (emit->num_arl_consts > 0); 3613bf215546Sopenharmony_ci} 3614bf215546Sopenharmony_ci 3615bf215546Sopenharmony_ci 3616bf215546Sopenharmony_cistatic boolean 3617bf215546Sopenharmony_cipre_parse_add_indirect( struct svga_shader_emitter *emit, 3618bf215546Sopenharmony_ci int num, int current_arl) 3619bf215546Sopenharmony_ci{ 3620bf215546Sopenharmony_ci unsigned i; 3621bf215546Sopenharmony_ci assert(num < 0); 3622bf215546Sopenharmony_ci 3623bf215546Sopenharmony_ci for (i = 0; i < emit->num_arl_consts; ++i) { 3624bf215546Sopenharmony_ci if (emit->arl_consts[i].arl_num == current_arl) 3625bf215546Sopenharmony_ci break; 3626bf215546Sopenharmony_ci } 3627bf215546Sopenharmony_ci /* new entry */ 3628bf215546Sopenharmony_ci if (emit->num_arl_consts == i) { 3629bf215546Sopenharmony_ci ++emit->num_arl_consts; 3630bf215546Sopenharmony_ci } 3631bf215546Sopenharmony_ci emit->arl_consts[i].number = (emit->arl_consts[i].number > num) ? 3632bf215546Sopenharmony_ci num : 3633bf215546Sopenharmony_ci emit->arl_consts[i].number; 3634bf215546Sopenharmony_ci emit->arl_consts[i].arl_num = current_arl; 3635bf215546Sopenharmony_ci return TRUE; 3636bf215546Sopenharmony_ci} 3637bf215546Sopenharmony_ci 3638bf215546Sopenharmony_ci 3639bf215546Sopenharmony_cistatic boolean 3640bf215546Sopenharmony_cipre_parse_instruction( struct svga_shader_emitter *emit, 3641bf215546Sopenharmony_ci const struct tgsi_full_instruction *insn, 3642bf215546Sopenharmony_ci int current_arl) 3643bf215546Sopenharmony_ci{ 3644bf215546Sopenharmony_ci if (insn->Src[0].Register.Indirect && 3645bf215546Sopenharmony_ci insn->Src[0].Indirect.File == TGSI_FILE_ADDRESS) { 3646bf215546Sopenharmony_ci const struct tgsi_full_src_register *reg = &insn->Src[0]; 3647bf215546Sopenharmony_ci if (reg->Register.Index < 0) { 3648bf215546Sopenharmony_ci pre_parse_add_indirect(emit, reg->Register.Index, current_arl); 3649bf215546Sopenharmony_ci } 3650bf215546Sopenharmony_ci } 3651bf215546Sopenharmony_ci 3652bf215546Sopenharmony_ci if (insn->Src[1].Register.Indirect && 3653bf215546Sopenharmony_ci insn->Src[1].Indirect.File == TGSI_FILE_ADDRESS) { 3654bf215546Sopenharmony_ci const struct tgsi_full_src_register *reg = &insn->Src[1]; 3655bf215546Sopenharmony_ci if (reg->Register.Index < 0) { 3656bf215546Sopenharmony_ci pre_parse_add_indirect(emit, reg->Register.Index, current_arl); 3657bf215546Sopenharmony_ci } 3658bf215546Sopenharmony_ci } 3659bf215546Sopenharmony_ci 3660bf215546Sopenharmony_ci if (insn->Src[2].Register.Indirect && 3661bf215546Sopenharmony_ci insn->Src[2].Indirect.File == TGSI_FILE_ADDRESS) { 3662bf215546Sopenharmony_ci const struct tgsi_full_src_register *reg = &insn->Src[2]; 3663bf215546Sopenharmony_ci if (reg->Register.Index < 0) { 3664bf215546Sopenharmony_ci pre_parse_add_indirect(emit, reg->Register.Index, current_arl); 3665bf215546Sopenharmony_ci } 3666bf215546Sopenharmony_ci } 3667bf215546Sopenharmony_ci 3668bf215546Sopenharmony_ci return TRUE; 3669bf215546Sopenharmony_ci} 3670bf215546Sopenharmony_ci 3671bf215546Sopenharmony_ci 3672bf215546Sopenharmony_cistatic boolean 3673bf215546Sopenharmony_cipre_parse_tokens( struct svga_shader_emitter *emit, 3674bf215546Sopenharmony_ci const struct tgsi_token *tokens ) 3675bf215546Sopenharmony_ci{ 3676bf215546Sopenharmony_ci struct tgsi_parse_context parse; 3677bf215546Sopenharmony_ci int current_arl = 0; 3678bf215546Sopenharmony_ci 3679bf215546Sopenharmony_ci tgsi_parse_init( &parse, tokens ); 3680bf215546Sopenharmony_ci 3681bf215546Sopenharmony_ci while (!tgsi_parse_end_of_tokens( &parse )) { 3682bf215546Sopenharmony_ci tgsi_parse_token( &parse ); 3683bf215546Sopenharmony_ci switch (parse.FullToken.Token.Type) { 3684bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_IMMEDIATE: 3685bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_DECLARATION: 3686bf215546Sopenharmony_ci break; 3687bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_INSTRUCTION: 3688bf215546Sopenharmony_ci if (parse.FullToken.FullInstruction.Instruction.Opcode == 3689bf215546Sopenharmony_ci TGSI_OPCODE_ARL) { 3690bf215546Sopenharmony_ci ++current_arl; 3691bf215546Sopenharmony_ci } 3692bf215546Sopenharmony_ci if (!pre_parse_instruction( emit, &parse.FullToken.FullInstruction, 3693bf215546Sopenharmony_ci current_arl )) 3694bf215546Sopenharmony_ci return FALSE; 3695bf215546Sopenharmony_ci break; 3696bf215546Sopenharmony_ci default: 3697bf215546Sopenharmony_ci break; 3698bf215546Sopenharmony_ci } 3699bf215546Sopenharmony_ci 3700bf215546Sopenharmony_ci } 3701bf215546Sopenharmony_ci return TRUE; 3702bf215546Sopenharmony_ci} 3703bf215546Sopenharmony_ci 3704bf215546Sopenharmony_ci 3705bf215546Sopenharmony_cistatic boolean 3706bf215546Sopenharmony_cisvga_shader_emit_helpers(struct svga_shader_emitter *emit) 3707bf215546Sopenharmony_ci{ 3708bf215546Sopenharmony_ci if (needs_to_create_common_immediate( emit )) { 3709bf215546Sopenharmony_ci create_common_immediate( emit ); 3710bf215546Sopenharmony_ci } 3711bf215546Sopenharmony_ci if (needs_to_create_loop_const( emit )) { 3712bf215546Sopenharmony_ci create_loop_const( emit ); 3713bf215546Sopenharmony_ci } 3714bf215546Sopenharmony_ci if (needs_to_create_arl_consts( emit )) { 3715bf215546Sopenharmony_ci create_arl_consts( emit ); 3716bf215546Sopenharmony_ci } 3717bf215546Sopenharmony_ci 3718bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_FRAGMENT) { 3719bf215546Sopenharmony_ci if (!svga_shader_emit_samplers_decl( emit )) 3720bf215546Sopenharmony_ci return FALSE; 3721bf215546Sopenharmony_ci 3722bf215546Sopenharmony_ci if (!emit_ps_preamble( emit )) 3723bf215546Sopenharmony_ci return FALSE; 3724bf215546Sopenharmony_ci 3725bf215546Sopenharmony_ci if (emit->key.fs.light_twoside) { 3726bf215546Sopenharmony_ci if (!emit_light_twoside( emit )) 3727bf215546Sopenharmony_ci return FALSE; 3728bf215546Sopenharmony_ci } 3729bf215546Sopenharmony_ci if (emit->emit_frontface) { 3730bf215546Sopenharmony_ci if (!emit_frontface( emit )) 3731bf215546Sopenharmony_ci return FALSE; 3732bf215546Sopenharmony_ci } 3733bf215546Sopenharmony_ci if (emit->inverted_texcoords) { 3734bf215546Sopenharmony_ci if (!emit_inverted_texcoords( emit )) 3735bf215546Sopenharmony_ci return FALSE; 3736bf215546Sopenharmony_ci } 3737bf215546Sopenharmony_ci } 3738bf215546Sopenharmony_ci else { 3739bf215546Sopenharmony_ci assert(emit->unit == PIPE_SHADER_VERTEX); 3740bf215546Sopenharmony_ci if (emit->key.vs.adjust_attrib_range) { 3741bf215546Sopenharmony_ci if (!emit_adjusted_vertex_attribs(emit) || 3742bf215546Sopenharmony_ci emit->key.vs.adjust_attrib_w_1) { 3743bf215546Sopenharmony_ci return FALSE; 3744bf215546Sopenharmony_ci } 3745bf215546Sopenharmony_ci } 3746bf215546Sopenharmony_ci } 3747bf215546Sopenharmony_ci 3748bf215546Sopenharmony_ci return TRUE; 3749bf215546Sopenharmony_ci} 3750bf215546Sopenharmony_ci 3751bf215546Sopenharmony_ci 3752bf215546Sopenharmony_ci/** 3753bf215546Sopenharmony_ci * This is the main entrypoint into the TGSI instruction translater. 3754bf215546Sopenharmony_ci * Translate TGSI shader tokens into an SVGA shader. 3755bf215546Sopenharmony_ci */ 3756bf215546Sopenharmony_ciboolean 3757bf215546Sopenharmony_cisvga_shader_emit_instructions(struct svga_shader_emitter *emit, 3758bf215546Sopenharmony_ci const struct tgsi_token *tokens) 3759bf215546Sopenharmony_ci{ 3760bf215546Sopenharmony_ci struct tgsi_parse_context parse; 3761bf215546Sopenharmony_ci const struct tgsi_token *new_tokens = NULL; 3762bf215546Sopenharmony_ci boolean ret = TRUE; 3763bf215546Sopenharmony_ci boolean helpers_emitted = FALSE; 3764bf215546Sopenharmony_ci unsigned line_nr = 0; 3765bf215546Sopenharmony_ci 3766bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_FRAGMENT && emit->key.fs.pstipple) { 3767bf215546Sopenharmony_ci unsigned unit; 3768bf215546Sopenharmony_ci 3769bf215546Sopenharmony_ci new_tokens = util_pstipple_create_fragment_shader(tokens, &unit, 0, 3770bf215546Sopenharmony_ci TGSI_FILE_INPUT); 3771bf215546Sopenharmony_ci 3772bf215546Sopenharmony_ci if (new_tokens) { 3773bf215546Sopenharmony_ci /* Setup texture state for stipple */ 3774bf215546Sopenharmony_ci emit->sampler_target[unit] = TGSI_TEXTURE_2D; 3775bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_r = TGSI_SWIZZLE_X; 3776bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_g = TGSI_SWIZZLE_Y; 3777bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_b = TGSI_SWIZZLE_Z; 3778bf215546Sopenharmony_ci emit->key.tex[unit].swizzle_a = TGSI_SWIZZLE_W; 3779bf215546Sopenharmony_ci 3780bf215546Sopenharmony_ci emit->pstipple_sampler_unit = unit; 3781bf215546Sopenharmony_ci 3782bf215546Sopenharmony_ci tokens = new_tokens; 3783bf215546Sopenharmony_ci } 3784bf215546Sopenharmony_ci } 3785bf215546Sopenharmony_ci 3786bf215546Sopenharmony_ci tgsi_parse_init( &parse, tokens ); 3787bf215546Sopenharmony_ci emit->internal_imm_count = 0; 3788bf215546Sopenharmony_ci 3789bf215546Sopenharmony_ci if (emit->unit == PIPE_SHADER_VERTEX) { 3790bf215546Sopenharmony_ci ret = emit_vs_preamble( emit ); 3791bf215546Sopenharmony_ci if (!ret) 3792bf215546Sopenharmony_ci goto done; 3793bf215546Sopenharmony_ci } 3794bf215546Sopenharmony_ci 3795bf215546Sopenharmony_ci pre_parse_tokens(emit, tokens); 3796bf215546Sopenharmony_ci 3797bf215546Sopenharmony_ci while (!tgsi_parse_end_of_tokens( &parse )) { 3798bf215546Sopenharmony_ci tgsi_parse_token( &parse ); 3799bf215546Sopenharmony_ci 3800bf215546Sopenharmony_ci switch (parse.FullToken.Token.Type) { 3801bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_IMMEDIATE: 3802bf215546Sopenharmony_ci ret = svga_emit_immediate( emit, &parse.FullToken.FullImmediate ); 3803bf215546Sopenharmony_ci if (!ret) 3804bf215546Sopenharmony_ci goto done; 3805bf215546Sopenharmony_ci break; 3806bf215546Sopenharmony_ci 3807bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_DECLARATION: 3808bf215546Sopenharmony_ci ret = svga_translate_decl_sm30( emit, &parse.FullToken.FullDeclaration ); 3809bf215546Sopenharmony_ci if (!ret) 3810bf215546Sopenharmony_ci goto done; 3811bf215546Sopenharmony_ci break; 3812bf215546Sopenharmony_ci 3813bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_INSTRUCTION: 3814bf215546Sopenharmony_ci if (!helpers_emitted) { 3815bf215546Sopenharmony_ci if (!svga_shader_emit_helpers( emit )) 3816bf215546Sopenharmony_ci goto done; 3817bf215546Sopenharmony_ci helpers_emitted = TRUE; 3818bf215546Sopenharmony_ci } 3819bf215546Sopenharmony_ci ret = svga_emit_instruction( emit, 3820bf215546Sopenharmony_ci line_nr++, 3821bf215546Sopenharmony_ci &parse.FullToken.FullInstruction ); 3822bf215546Sopenharmony_ci if (!ret) 3823bf215546Sopenharmony_ci goto done; 3824bf215546Sopenharmony_ci break; 3825bf215546Sopenharmony_ci default: 3826bf215546Sopenharmony_ci break; 3827bf215546Sopenharmony_ci } 3828bf215546Sopenharmony_ci 3829bf215546Sopenharmony_ci reset_temp_regs( emit ); 3830bf215546Sopenharmony_ci } 3831bf215546Sopenharmony_ci 3832bf215546Sopenharmony_ci /* Need to terminate the current subroutine. Note that the 3833bf215546Sopenharmony_ci * hardware doesn't tolerate shaders without sub-routines 3834bf215546Sopenharmony_ci * terminating with RET+END. 3835bf215546Sopenharmony_ci */ 3836bf215546Sopenharmony_ci if (!emit->in_main_func) { 3837bf215546Sopenharmony_ci ret = emit_instruction( emit, inst_token( SVGA3DOP_RET ) ); 3838bf215546Sopenharmony_ci if (!ret) 3839bf215546Sopenharmony_ci goto done; 3840bf215546Sopenharmony_ci } 3841bf215546Sopenharmony_ci 3842bf215546Sopenharmony_ci assert(emit->dynamic_branching_level == 0); 3843bf215546Sopenharmony_ci 3844bf215546Sopenharmony_ci /* Need to terminate the whole shader: 3845bf215546Sopenharmony_ci */ 3846bf215546Sopenharmony_ci ret = emit_instruction( emit, inst_token( SVGA3DOP_END ) ); 3847bf215546Sopenharmony_ci if (!ret) 3848bf215546Sopenharmony_ci goto done; 3849bf215546Sopenharmony_ci 3850bf215546Sopenharmony_cidone: 3851bf215546Sopenharmony_ci tgsi_parse_free( &parse ); 3852bf215546Sopenharmony_ci if (new_tokens) { 3853bf215546Sopenharmony_ci tgsi_free_tokens(new_tokens); 3854bf215546Sopenharmony_ci } 3855bf215546Sopenharmony_ci 3856bf215546Sopenharmony_ci return ret; 3857bf215546Sopenharmony_ci} 3858