1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2015 Red Hat 3bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22bf215546Sopenharmony_ci * IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "nir.h" 26bf215546Sopenharmony_ci#include "nir_builder.h" 27bf215546Sopenharmony_ci#include "program/prog_instruction.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci/** 30bf215546Sopenharmony_ci * This pass adds <0.5, 0.5> to all uses of gl_FragCoord. 31bf215546Sopenharmony_ci * 32bf215546Sopenharmony_ci * Run before nir_lower_io(). 33bf215546Sopenharmony_ci * 34bf215546Sopenharmony_ci * For a more full featured pass, consider using nir_lower_wpos_ytransform(), 35bf215546Sopenharmony_ci * which can handle pixel center integer / half integer, and origin lower 36bf215546Sopenharmony_ci * left / upper left transformations. 37bf215546Sopenharmony_ci * 38bf215546Sopenharmony_ci * This simple pass is primarily intended for use by Vulkan drivers on 39bf215546Sopenharmony_ci * hardware which provides an integer pixel center. Vulkan mandates that 40bf215546Sopenharmony_ci * the pixel center must be half-integer, and also that the coordinate 41bf215546Sopenharmony_ci * system's origin must be upper left. This means that there's no need 42bf215546Sopenharmony_ci * for a uniform - we can always just add a constant. In the case that 43bf215546Sopenharmony_ci * sample shading is enabled, Vulkan expects FragCoord to include sample 44bf215546Sopenharmony_ci * positions. 45bf215546Sopenharmony_ci */ 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistatic void 48bf215546Sopenharmony_ciupdate_fragcoord(nir_builder *b, nir_intrinsic_instr *intr) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci nir_ssa_def *wpos = &intr->dest.ssa; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci assert(intr->dest.is_ssa); 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci b->cursor = nir_after_instr(&intr->instr); 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci nir_ssa_def *spos = nir_load_sample_pos_or_center(b); 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci wpos = nir_fadd(b, wpos, 59bf215546Sopenharmony_ci nir_vec4(b, 60bf215546Sopenharmony_ci nir_channel(b, spos, 0), 61bf215546Sopenharmony_ci nir_channel(b, spos, 1), 62bf215546Sopenharmony_ci nir_imm_float(b, 0.0f), 63bf215546Sopenharmony_ci nir_imm_float(b, 0.0f))); 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, wpos, 66bf215546Sopenharmony_ci wpos->parent_instr); 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic bool 70bf215546Sopenharmony_cilower_wpos_center_block(nir_builder *b, nir_block *block) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci bool progress = false; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci nir_foreach_instr(instr, block) { 75bf215546Sopenharmony_ci if (instr->type == nir_instr_type_intrinsic) { 76bf215546Sopenharmony_ci nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); 77bf215546Sopenharmony_ci if (intr->intrinsic == nir_intrinsic_load_frag_coord) { 78bf215546Sopenharmony_ci update_fragcoord(b, intr); 79bf215546Sopenharmony_ci progress = true; 80bf215546Sopenharmony_ci } 81bf215546Sopenharmony_ci } 82bf215546Sopenharmony_ci } 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci return progress; 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cibool 88bf215546Sopenharmony_cinir_lower_wpos_center(nir_shader *shader) 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci bool progress = false; 91bf215546Sopenharmony_ci nir_builder b; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci assert(shader->info.stage == MESA_SHADER_FRAGMENT); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci nir_foreach_function(function, shader) { 96bf215546Sopenharmony_ci if (function->impl) { 97bf215546Sopenharmony_ci nir_builder_init(&b, function->impl); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci nir_foreach_block(block, function->impl) { 100bf215546Sopenharmony_ci progress = lower_wpos_center_block(&b, block) || 101bf215546Sopenharmony_ci progress; 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci nir_metadata_preserve(function->impl, nir_metadata_block_index | 104bf215546Sopenharmony_ci nir_metadata_dominance); 105bf215546Sopenharmony_ci } 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci return progress; 109bf215546Sopenharmony_ci} 110