1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "nir.h"
25bf215546Sopenharmony_ci#include "nir_builder.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_cistatic nir_ssa_def *
28bf215546Sopenharmony_ciload_frag_coord(nir_builder *b, const nir_input_attachment_options *options)
29bf215546Sopenharmony_ci{
30bf215546Sopenharmony_ci   if (options->use_fragcoord_sysval)
31bf215546Sopenharmony_ci      return nir_load_frag_coord(b);
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci   nir_variable *pos =
34bf215546Sopenharmony_ci      nir_find_variable_with_location(b->shader, nir_var_shader_in,
35bf215546Sopenharmony_ci                                      VARYING_SLOT_POS);
36bf215546Sopenharmony_ci   if (pos == NULL) {
37bf215546Sopenharmony_ci      pos = nir_variable_create(b->shader, nir_var_shader_in,
38bf215546Sopenharmony_ci                                glsl_vec4_type(), NULL);
39bf215546Sopenharmony_ci      pos->data.location = VARYING_SLOT_POS;
40bf215546Sopenharmony_ci   }
41bf215546Sopenharmony_ci   /**
42bf215546Sopenharmony_ci    * From Vulkan spec:
43bf215546Sopenharmony_ci    *   "The OriginLowerLeft execution mode must not be used; fragment entry
44bf215546Sopenharmony_ci    *    points must declare OriginUpperLeft."
45bf215546Sopenharmony_ci    *
46bf215546Sopenharmony_ci    * So at this point origin_upper_left should be true
47bf215546Sopenharmony_ci    */
48bf215546Sopenharmony_ci   assert(b->shader->info.fs.origin_upper_left == true);
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci   return nir_load_var(b, pos);
51bf215546Sopenharmony_ci}
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistatic nir_ssa_def *
54bf215546Sopenharmony_ciload_layer_id(nir_builder *b, const nir_input_attachment_options *options)
55bf215546Sopenharmony_ci{
56bf215546Sopenharmony_ci   if (options->use_layer_id_sysval) {
57bf215546Sopenharmony_ci      if (options->use_view_id_for_layer)
58bf215546Sopenharmony_ci         return nir_load_view_index(b);
59bf215546Sopenharmony_ci      else
60bf215546Sopenharmony_ci         return nir_load_layer_id(b);
61bf215546Sopenharmony_ci   }
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   gl_varying_slot slot = options->use_view_id_for_layer ?
64bf215546Sopenharmony_ci      VARYING_SLOT_VIEW_INDEX : VARYING_SLOT_LAYER;
65bf215546Sopenharmony_ci   nir_variable *layer_id =
66bf215546Sopenharmony_ci      nir_find_variable_with_location(b->shader, nir_var_shader_in, slot);
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   if (layer_id == NULL) {
69bf215546Sopenharmony_ci      layer_id = nir_variable_create(b->shader, nir_var_shader_in,
70bf215546Sopenharmony_ci                                     glsl_int_type(), NULL);
71bf215546Sopenharmony_ci      layer_id->data.location = slot;
72bf215546Sopenharmony_ci      layer_id->data.interpolation = INTERP_MODE_FLAT;
73bf215546Sopenharmony_ci      layer_id->data.driver_location = b->shader->num_inputs++;
74bf215546Sopenharmony_ci   }
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   return nir_load_var(b, layer_id);
77bf215546Sopenharmony_ci}
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_cistatic bool
80bf215546Sopenharmony_citry_lower_input_load(nir_builder *b, nir_intrinsic_instr *load,
81bf215546Sopenharmony_ci                     const nir_input_attachment_options *options)
82bf215546Sopenharmony_ci{
83bf215546Sopenharmony_ci   nir_deref_instr *deref = nir_src_as_deref(load->src[0]);
84bf215546Sopenharmony_ci   assert(glsl_type_is_image(deref->type));
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   enum glsl_sampler_dim image_dim = glsl_get_sampler_dim(deref->type);
87bf215546Sopenharmony_ci   if (image_dim != GLSL_SAMPLER_DIM_SUBPASS &&
88bf215546Sopenharmony_ci       image_dim != GLSL_SAMPLER_DIM_SUBPASS_MS)
89bf215546Sopenharmony_ci      return false;
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci   const bool multisampled = (image_dim == GLSL_SAMPLER_DIM_SUBPASS_MS);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   b->cursor = nir_instr_remove(&load->instr);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   nir_ssa_def *frag_coord = load_frag_coord(b, options);
96bf215546Sopenharmony_ci   frag_coord = nir_f2i32(b, frag_coord);
97bf215546Sopenharmony_ci   nir_ssa_def *offset = nir_ssa_for_src(b, load->src[1], 2);
98bf215546Sopenharmony_ci   nir_ssa_def *pos = nir_iadd(b, frag_coord, offset);
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   nir_ssa_def *layer = load_layer_id(b, options);
101bf215546Sopenharmony_ci   nir_ssa_def *coord =
102bf215546Sopenharmony_ci      nir_vec3(b, nir_channel(b, pos, 0), nir_channel(b, pos, 1), layer);
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   nir_tex_instr *tex = nir_tex_instr_create(b->shader, 3 + multisampled);
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   tex->op = nir_texop_txf;
107bf215546Sopenharmony_ci   tex->sampler_dim = image_dim;
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   tex->dest_type =
110bf215546Sopenharmony_ci      nir_get_nir_type_for_glsl_base_type(glsl_get_sampler_result_type(deref->type));
111bf215546Sopenharmony_ci   tex->is_array = true;
112bf215546Sopenharmony_ci   tex->is_shadow = false;
113bf215546Sopenharmony_ci   tex->is_sparse = load->intrinsic == nir_intrinsic_image_deref_sparse_load;
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   tex->texture_index = 0;
116bf215546Sopenharmony_ci   tex->sampler_index = 0;
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci   tex->src[0].src_type = nir_tex_src_texture_deref;
119bf215546Sopenharmony_ci   tex->src[0].src = nir_src_for_ssa(&deref->dest.ssa);
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   tex->src[1].src_type = nir_tex_src_coord;
122bf215546Sopenharmony_ci   tex->src[1].src = nir_src_for_ssa(coord);
123bf215546Sopenharmony_ci   tex->coord_components = 3;
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   tex->src[2].src_type = nir_tex_src_lod;
126bf215546Sopenharmony_ci   tex->src[2].src = nir_src_for_ssa(nir_imm_int(b, 0));
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   if (image_dim == GLSL_SAMPLER_DIM_SUBPASS_MS) {
129bf215546Sopenharmony_ci      tex->op = nir_texop_txf_ms;
130bf215546Sopenharmony_ci      tex->src[3].src_type = nir_tex_src_ms_index;
131bf215546Sopenharmony_ci      tex->src[3].src = load->src[2];
132bf215546Sopenharmony_ci   }
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci   tex->texture_non_uniform = nir_intrinsic_access(load) & ACCESS_NON_UNIFORM;
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   nir_ssa_dest_init(&tex->instr, &tex->dest, nir_tex_instr_dest_size(tex), 32, NULL);
137bf215546Sopenharmony_ci   nir_builder_instr_insert(b, &tex->instr);
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci   if (tex->is_sparse) {
140bf215546Sopenharmony_ci      unsigned load_result_size = load->dest.ssa.num_components - 1;
141bf215546Sopenharmony_ci      nir_component_mask_t load_result_mask = nir_component_mask(load_result_size);
142bf215546Sopenharmony_ci      nir_ssa_def *res = nir_channels(
143bf215546Sopenharmony_ci         b, &tex->dest.ssa, load_result_mask | 0x10);
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci      nir_ssa_def_rewrite_uses(&load->dest.ssa, res);
146bf215546Sopenharmony_ci   } else {
147bf215546Sopenharmony_ci      nir_ssa_def_rewrite_uses(&load->dest.ssa,
148bf215546Sopenharmony_ci                               &tex->dest.ssa);
149bf215546Sopenharmony_ci   }
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   return true;
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_cistatic bool
155bf215546Sopenharmony_citry_lower_input_texop(nir_builder *b, nir_tex_instr *tex,
156bf215546Sopenharmony_ci                      const nir_input_attachment_options *options)
157bf215546Sopenharmony_ci{
158bf215546Sopenharmony_ci   nir_deref_instr *deref = nir_src_as_deref(tex->src[0].src);
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   if (glsl_get_sampler_dim(deref->type) != GLSL_SAMPLER_DIM_SUBPASS_MS)
161bf215546Sopenharmony_ci      return false;
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   nir_ssa_def *frag_coord = load_frag_coord(b, options);
166bf215546Sopenharmony_ci   frag_coord = nir_f2i32(b, frag_coord);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   nir_ssa_def *layer = load_layer_id(b, options);
169bf215546Sopenharmony_ci   nir_ssa_def *coord = nir_vec3(b, nir_channel(b, frag_coord, 0),
170bf215546Sopenharmony_ci                                    nir_channel(b, frag_coord, 1), layer);
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   tex->coord_components = 3;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   nir_instr_rewrite_src(&tex->instr, &tex->src[1].src, nir_src_for_ssa(coord));
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   return true;
177bf215546Sopenharmony_ci}
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_cistatic bool
180bf215546Sopenharmony_cilower_input_attachments_instr(nir_builder *b, nir_instr *instr, void *_data)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci   const nir_input_attachment_options *options = _data;
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci   switch (instr->type) {
185bf215546Sopenharmony_ci   case nir_instr_type_tex: {
186bf215546Sopenharmony_ci      nir_tex_instr *tex = nir_instr_as_tex(instr);
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci      if (tex->op == nir_texop_fragment_mask_fetch_amd ||
189bf215546Sopenharmony_ci          tex->op == nir_texop_fragment_fetch_amd)
190bf215546Sopenharmony_ci         return try_lower_input_texop(b, tex, options);
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci      return false;
193bf215546Sopenharmony_ci   }
194bf215546Sopenharmony_ci   case nir_instr_type_intrinsic: {
195bf215546Sopenharmony_ci      nir_intrinsic_instr *load = nir_instr_as_intrinsic(instr);
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci      if (load->intrinsic == nir_intrinsic_image_deref_load ||
198bf215546Sopenharmony_ci          load->intrinsic == nir_intrinsic_image_deref_sparse_load)
199bf215546Sopenharmony_ci         return try_lower_input_load(b, load, options);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci      return false;
202bf215546Sopenharmony_ci   }
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   default:
205bf215546Sopenharmony_ci      return false;
206bf215546Sopenharmony_ci   }
207bf215546Sopenharmony_ci}
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_cibool
210bf215546Sopenharmony_cinir_lower_input_attachments(nir_shader *shader,
211bf215546Sopenharmony_ci                            const nir_input_attachment_options *options)
212bf215546Sopenharmony_ci{
213bf215546Sopenharmony_ci   assert(shader->info.stage == MESA_SHADER_FRAGMENT);
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   return nir_shader_instructions_pass(shader, lower_input_attachments_instr,
216bf215546Sopenharmony_ci                                       nir_metadata_block_index |
217bf215546Sopenharmony_ci                                       nir_metadata_dominance,
218bf215546Sopenharmony_ci                                       (void *)options);
219bf215546Sopenharmony_ci}
220