101e04c3fSmrg/* 201e04c3fSmrg * Copyright (C) 2015 Advanced Micro Devices, Inc. 301e04c3fSmrg * All Rights Reserved. 401e04c3fSmrg * 501e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 601e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 701e04c3fSmrg * to deal in the Software without restriction, including without limitation 801e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 901e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 1001e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1101e04c3fSmrg * 1201e04c3fSmrg * The above copyright notice and this permission notice (including the next 1301e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1401e04c3fSmrg * Software. 1501e04c3fSmrg * 1601e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1701e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1801e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1901e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2001e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2101e04c3fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2201e04c3fSmrg * SOFTWARE. 2301e04c3fSmrg * 2401e04c3fSmrg */ 2501e04c3fSmrg 2601e04c3fSmrg#include "tgsi/tgsi_transform.h" 2701e04c3fSmrg#include "tgsi/tgsi_scan.h" 2801e04c3fSmrg#include "tgsi/tgsi_dump.h" 2901e04c3fSmrg#include "util/u_debug.h" 3001e04c3fSmrg 3101e04c3fSmrg#include "tgsi_emulate.h" 3201e04c3fSmrg 3301e04c3fSmrgstruct tgsi_emulation_context { 3401e04c3fSmrg struct tgsi_transform_context base; 3501e04c3fSmrg struct tgsi_shader_info info; 3601e04c3fSmrg unsigned flags; 3701e04c3fSmrg bool first_instruction_emitted; 3801e04c3fSmrg}; 3901e04c3fSmrg 4001e04c3fSmrgstatic inline struct tgsi_emulation_context * 4101e04c3fSmrgtgsi_emulation_context(struct tgsi_transform_context *tctx) 4201e04c3fSmrg{ 4301e04c3fSmrg return (struct tgsi_emulation_context *)tctx; 4401e04c3fSmrg} 4501e04c3fSmrg 4601e04c3fSmrgstatic void 4701e04c3fSmrgtransform_decl(struct tgsi_transform_context *tctx, 4801e04c3fSmrg struct tgsi_full_declaration *decl) 4901e04c3fSmrg{ 5001e04c3fSmrg struct tgsi_emulation_context *ctx = tgsi_emulation_context(tctx); 5101e04c3fSmrg 5201e04c3fSmrg if (ctx->flags & TGSI_EMU_FORCE_PERSAMPLE_INTERP && 5301e04c3fSmrg decl->Declaration.File == TGSI_FILE_INPUT) { 5401e04c3fSmrg assert(decl->Declaration.Interpolate); 5501e04c3fSmrg decl->Interp.Location = TGSI_INTERPOLATE_LOC_SAMPLE; 5601e04c3fSmrg } 5701e04c3fSmrg 5801e04c3fSmrg tctx->emit_declaration(tctx, decl); 5901e04c3fSmrg} 6001e04c3fSmrg 6101e04c3fSmrgstatic void 6201e04c3fSmrgpassthrough_edgeflag(struct tgsi_transform_context *tctx) 6301e04c3fSmrg{ 6401e04c3fSmrg struct tgsi_emulation_context *ctx = tgsi_emulation_context(tctx); 6501e04c3fSmrg struct tgsi_full_declaration decl; 6601e04c3fSmrg struct tgsi_full_instruction new_inst; 6701e04c3fSmrg 6801e04c3fSmrg /* Input */ 6901e04c3fSmrg decl = tgsi_default_full_declaration(); 7001e04c3fSmrg decl.Declaration.File = TGSI_FILE_INPUT; 7101e04c3fSmrg decl.Range.First = decl.Range.Last = ctx->info.num_inputs; 7201e04c3fSmrg tctx->emit_declaration(tctx, &decl); 7301e04c3fSmrg 7401e04c3fSmrg /* Output */ 7501e04c3fSmrg decl = tgsi_default_full_declaration(); 7601e04c3fSmrg decl.Declaration.File = TGSI_FILE_OUTPUT; 7701e04c3fSmrg decl.Declaration.Semantic = true; 7801e04c3fSmrg decl.Range.First = decl.Range.Last = ctx->info.num_outputs; 7901e04c3fSmrg decl.Semantic.Name = TGSI_SEMANTIC_EDGEFLAG; 8001e04c3fSmrg decl.Semantic.Index = 0; 8101e04c3fSmrg tctx->emit_declaration(tctx, &decl); 8201e04c3fSmrg 8301e04c3fSmrg /* MOV */ 8401e04c3fSmrg new_inst = tgsi_default_full_instruction(); 8501e04c3fSmrg new_inst.Instruction.Opcode = TGSI_OPCODE_MOV; 8601e04c3fSmrg 8701e04c3fSmrg new_inst.Instruction.NumDstRegs = 1; 8801e04c3fSmrg new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT; 8901e04c3fSmrg new_inst.Dst[0].Register.Index = ctx->info.num_outputs; 9001e04c3fSmrg new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; 9101e04c3fSmrg 9201e04c3fSmrg new_inst.Instruction.NumSrcRegs = 1; 9301e04c3fSmrg new_inst.Src[0].Register.File = TGSI_FILE_INPUT; 9401e04c3fSmrg new_inst.Src[0].Register.Index = ctx->info.num_inputs; 9501e04c3fSmrg new_inst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_X; 9601e04c3fSmrg new_inst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_X; 9701e04c3fSmrg new_inst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_X; 9801e04c3fSmrg new_inst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_X; 9901e04c3fSmrg 10001e04c3fSmrg tctx->emit_instruction(tctx, &new_inst); 10101e04c3fSmrg} 10201e04c3fSmrg 10301e04c3fSmrgstatic void 10401e04c3fSmrgtransform_instr(struct tgsi_transform_context *tctx, 10501e04c3fSmrg struct tgsi_full_instruction *inst) 10601e04c3fSmrg{ 10701e04c3fSmrg struct tgsi_emulation_context *ctx = tgsi_emulation_context(tctx); 10801e04c3fSmrg 10901e04c3fSmrg /* Pass through edgeflags. */ 11001e04c3fSmrg if (!ctx->first_instruction_emitted) { 11101e04c3fSmrg ctx->first_instruction_emitted = true; 11201e04c3fSmrg 11301e04c3fSmrg if (ctx->flags & TGSI_EMU_PASSTHROUGH_EDGEFLAG) 11401e04c3fSmrg passthrough_edgeflag(tctx); 11501e04c3fSmrg } 11601e04c3fSmrg 11701e04c3fSmrg /* Clamp color outputs. */ 11801e04c3fSmrg if (ctx->flags & TGSI_EMU_CLAMP_COLOR_OUTPUTS) { 11901e04c3fSmrg int i; 12001e04c3fSmrg for (i = 0; i < inst->Instruction.NumDstRegs; i++) { 12101e04c3fSmrg unsigned semantic; 12201e04c3fSmrg 12301e04c3fSmrg if (inst->Dst[i].Register.File != TGSI_FILE_OUTPUT || 12401e04c3fSmrg inst->Dst[i].Register.Indirect) 12501e04c3fSmrg continue; 12601e04c3fSmrg 12701e04c3fSmrg semantic = 12801e04c3fSmrg ctx->info.output_semantic_name[inst->Dst[i].Register.Index]; 12901e04c3fSmrg 13001e04c3fSmrg if (semantic == TGSI_SEMANTIC_COLOR || 13101e04c3fSmrg semantic == TGSI_SEMANTIC_BCOLOR) 13201e04c3fSmrg inst->Instruction.Saturate = true; 13301e04c3fSmrg } 13401e04c3fSmrg } 13501e04c3fSmrg 13601e04c3fSmrg tctx->emit_instruction(tctx, inst); 13701e04c3fSmrg} 13801e04c3fSmrg 13901e04c3fSmrgconst struct tgsi_token * 14001e04c3fSmrgtgsi_emulate(const struct tgsi_token *tokens, unsigned flags) 14101e04c3fSmrg{ 14201e04c3fSmrg struct tgsi_emulation_context ctx; 14301e04c3fSmrg struct tgsi_token *newtoks; 14401e04c3fSmrg int newlen; 14501e04c3fSmrg 14601e04c3fSmrg if (!(flags & (TGSI_EMU_CLAMP_COLOR_OUTPUTS | 14701e04c3fSmrg TGSI_EMU_PASSTHROUGH_EDGEFLAG | 14801e04c3fSmrg TGSI_EMU_FORCE_PERSAMPLE_INTERP))) 14901e04c3fSmrg return NULL; 15001e04c3fSmrg 15101e04c3fSmrg memset(&ctx, 0, sizeof(ctx)); 15201e04c3fSmrg ctx.flags = flags; 15301e04c3fSmrg tgsi_scan_shader(tokens, &ctx.info); 15401e04c3fSmrg 15501e04c3fSmrg if (flags & TGSI_EMU_FORCE_PERSAMPLE_INTERP) 15601e04c3fSmrg ctx.base.transform_declaration = transform_decl; 15701e04c3fSmrg 15801e04c3fSmrg if (flags & (TGSI_EMU_CLAMP_COLOR_OUTPUTS | 15901e04c3fSmrg TGSI_EMU_PASSTHROUGH_EDGEFLAG)) 16001e04c3fSmrg ctx.base.transform_instruction = transform_instr; 16101e04c3fSmrg 16201e04c3fSmrg newlen = tgsi_num_tokens(tokens) + 20; 16301e04c3fSmrg newtoks = tgsi_alloc_tokens(newlen); 16401e04c3fSmrg if (!newtoks) 16501e04c3fSmrg return NULL; 16601e04c3fSmrg 16701e04c3fSmrg tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base); 16801e04c3fSmrg return newtoks; 16901e04c3fSmrg} 170