Path: blob/21.2-virgl/src/gallium/drivers/r300/compiler/r3xx_fragprog.c
4574 views
/*1* Copyright 2009 Nicolai Hähnle <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE. */2122#include "radeon_compiler.h"2324#include <stdio.h>2526#include "radeon_compiler_util.h"27#include "radeon_dataflow.h"28#include "radeon_emulate_branches.h"29#include "radeon_emulate_loops.h"30#include "radeon_program_alu.h"31#include "radeon_program_tex.h"32#include "radeon_rename_regs.h"33#include "radeon_remove_constants.h"34#include "r300_fragprog.h"35#include "r300_fragprog_swizzle.h"36#include "r500_fragprog.h"373839static void dataflow_outputs_mark_use(void * userdata, void * data,40void (*callback)(void *, unsigned int, unsigned int))41{42struct r300_fragment_program_compiler * c = userdata;43callback(data, c->OutputColor[0], RC_MASK_XYZW);44callback(data, c->OutputColor[1], RC_MASK_XYZW);45callback(data, c->OutputColor[2], RC_MASK_XYZW);46callback(data, c->OutputColor[3], RC_MASK_XYZW);47callback(data, c->OutputDepth, RC_MASK_W);48}4950static void rc_rewrite_depth_out(struct radeon_compiler *cc, void *user)51{52struct r300_fragment_program_compiler *c = (struct r300_fragment_program_compiler*)cc;53struct rc_instruction *rci;5455for (rci = c->Base.Program.Instructions.Next; rci != &c->Base.Program.Instructions; rci = rci->Next) {56struct rc_sub_instruction * inst = &rci->U.I;57unsigned i;58const struct rc_opcode_info *info = rc_get_opcode_info(inst->Opcode);5960if (inst->DstReg.File != RC_FILE_OUTPUT || inst->DstReg.Index != c->OutputDepth)61continue;6263if (inst->DstReg.WriteMask & RC_MASK_Z) {64inst->DstReg.WriteMask = RC_MASK_W;65} else {66inst->DstReg.WriteMask = 0;67continue;68}6970if (!info->IsComponentwise) {71continue;72}7374for (i = 0; i < info->NumSrcRegs; i++) {75inst->SrcReg[i] = lmul_swizzle(RC_SWIZZLE_ZZZZ, inst->SrcReg[i]);76}77}78}7980void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)81{82int is_r500 = c->Base.is_r500;83int opt = !c->Base.disable_optimizations;84int alpha2one = c->state.alpha_to_one;8586/* Lists of instruction transformations. */87struct radeon_program_transformation force_alpha_to_one[] = {88{ &rc_force_output_alpha_to_one, c },89{ 0, 0 }90};9192struct radeon_program_transformation rewrite_tex[] = {93{ &radeonTransformTEX, c },94{ 0, 0 }95};9697struct radeon_program_transformation rewrite_if[] = {98{ &r500_transform_IF, 0 },99{0, 0}100};101102struct radeon_program_transformation native_rewrite_r500[] = {103{ &radeonTransformALU, 0 },104{ &radeonTransformDeriv, 0 },105{ &radeonTransformTrigScale, 0 },106{ 0, 0 }107};108109struct radeon_program_transformation native_rewrite_r300[] = {110{ &radeonTransformALU, 0 },111{ &r300_transform_trig_simple, 0 },112{ 0, 0 }113};114115/* List of compiler passes. */116struct radeon_compiler_pass fs_list[] = {117/* NAME DUMP PREDICATE FUNCTION PARAM */118{"rewrite depth out", 1, 1, rc_rewrite_depth_out, NULL},119/* This transformation needs to be done before any of the IF120* instructions are modified. */121{"transform KILP", 1, 1, rc_transform_KILL, NULL},122{"unroll loops", 1, is_r500, rc_unroll_loops, NULL},123{"transform loops", 1, !is_r500, rc_transform_loops, NULL},124{"emulate branches", 1, !is_r500, rc_emulate_branches, NULL},125{"force alpha to one", 1, alpha2one, rc_local_transform, force_alpha_to_one},126{"transform TEX", 1, 1, rc_local_transform, rewrite_tex},127{"transform IF", 1, is_r500, rc_local_transform, rewrite_if},128{"native rewrite", 1, is_r500, rc_local_transform, native_rewrite_r500},129{"native rewrite", 1, !is_r500, rc_local_transform, native_rewrite_r300},130{"deadcode", 1, opt, rc_dataflow_deadcode, dataflow_outputs_mark_use},131{"emulate loops", 1, !is_r500, rc_emulate_loops, NULL},132{"register rename", 1, !is_r500 || opt, rc_rename_regs, NULL},133{"dataflow optimize", 1, opt, rc_optimize, NULL},134{"inline literals", 1, is_r500 && opt, rc_inline_literals, NULL},135{"dataflow swizzles", 1, 1, rc_dataflow_swizzles, NULL},136{"dead constants", 1, 1, rc_remove_unused_constants, &c->code->constants_remap_table},137{"pair translate", 1, 1, rc_pair_translate, NULL},138{"pair scheduling", 1, 1, rc_pair_schedule, &opt},139{"dead sources", 1, 1, rc_pair_remove_dead_sources, NULL},140{"register allocation", 1, 1, rc_pair_regalloc, &opt},141{"final code validation", 0, 1, rc_validate_final_shader, NULL},142{"machine code generation", 0, is_r500, r500BuildFragmentProgramHwCode, NULL},143{"machine code generation", 0, !is_r500, r300BuildFragmentProgramHwCode, NULL},144{"dump machine code", 0, is_r500 && (c->Base.Debug & RC_DBG_LOG), r500FragmentProgramDump, NULL},145{"dump machine code", 0, !is_r500 && (c->Base.Debug & RC_DBG_LOG), r300FragmentProgramDump, NULL},146{NULL, 0, 0, NULL, NULL}147};148149c->Base.type = RC_FRAGMENT_PROGRAM;150c->Base.SwizzleCaps = c->Base.is_r500 ? &r500_swizzle_caps : &r300_swizzle_caps;151152rc_run_compiler(&c->Base, fs_list);153154rc_constants_copy(&c->code->constants, &c->Base.Program.Constants);155}156157158