1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci * Copyright 2009 Marek Olšák <maraeo@gmail.com>
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
9bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
10bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
11bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
12bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
13bf215546Sopenharmony_ci * the following conditions:
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
16bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
17bf215546Sopenharmony_ci * of the Software.
18bf215546Sopenharmony_ci *
19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26bf215546Sopenharmony_ci *
27bf215546Sopenharmony_ci **************************************************************************/
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci/**
30bf215546Sopenharmony_ci * @file
31bf215546Sopenharmony_ci * Simple vertex/fragment shader generators.
32bf215546Sopenharmony_ci *
33bf215546Sopenharmony_ci * @author Brian Paul
34bf215546Sopenharmony_ci           Marek Olšák
35bf215546Sopenharmony_ci */
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include "pipe/p_context.h"
39bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h"
40bf215546Sopenharmony_ci#include "pipe/p_state.h"
41bf215546Sopenharmony_ci#include "util/u_simple_shaders.h"
42bf215546Sopenharmony_ci#include "util/u_debug.h"
43bf215546Sopenharmony_ci#include "util/u_memory.h"
44bf215546Sopenharmony_ci#include "util/u_string.h"
45bf215546Sopenharmony_ci#include "tgsi/tgsi_dump.h"
46bf215546Sopenharmony_ci#include "tgsi/tgsi_strings.h"
47bf215546Sopenharmony_ci#include "tgsi/tgsi_ureg.h"
48bf215546Sopenharmony_ci#include "tgsi/tgsi_text.h"
49bf215546Sopenharmony_ci#include <stdio.h> /* include last */
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci/**
54bf215546Sopenharmony_ci * Make simple vertex pass-through shader.
55bf215546Sopenharmony_ci * \param num_attribs  number of attributes to pass through
56bf215546Sopenharmony_ci * \param semantic_names  array of semantic names for each attribute
57bf215546Sopenharmony_ci * \param semantic_indexes  array of semantic indexes for each attribute
58bf215546Sopenharmony_ci */
59bf215546Sopenharmony_civoid *
60bf215546Sopenharmony_ciutil_make_vertex_passthrough_shader(struct pipe_context *pipe,
61bf215546Sopenharmony_ci                                    uint num_attribs,
62bf215546Sopenharmony_ci                                    const enum tgsi_semantic *semantic_names,
63bf215546Sopenharmony_ci                                    const uint *semantic_indexes,
64bf215546Sopenharmony_ci                                    bool window_space)
65bf215546Sopenharmony_ci{
66bf215546Sopenharmony_ci   return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs,
67bf215546Sopenharmony_ci                                                      semantic_names,
68bf215546Sopenharmony_ci                                                      semantic_indexes,
69bf215546Sopenharmony_ci                                                      window_space, false, NULL);
70bf215546Sopenharmony_ci}
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_civoid *
73bf215546Sopenharmony_ciutil_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
74bf215546Sopenharmony_ci                                    uint num_attribs,
75bf215546Sopenharmony_ci                                    const enum tgsi_semantic *semantic_names,
76bf215546Sopenharmony_ci                                    const uint *semantic_indexes,
77bf215546Sopenharmony_ci                                    bool window_space, bool layered,
78bf215546Sopenharmony_ci				    const struct pipe_stream_output_info *so)
79bf215546Sopenharmony_ci{
80bf215546Sopenharmony_ci   struct ureg_program *ureg;
81bf215546Sopenharmony_ci   uint i;
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   ureg = ureg_create( PIPE_SHADER_VERTEX );
84bf215546Sopenharmony_ci   if (!ureg)
85bf215546Sopenharmony_ci      return NULL;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   if (window_space)
88bf215546Sopenharmony_ci      ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci   for (i = 0; i < num_attribs; i++) {
91bf215546Sopenharmony_ci      struct ureg_src src;
92bf215546Sopenharmony_ci      struct ureg_dst dst;
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci      src = ureg_DECL_vs_input( ureg, i );
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci      dst = ureg_DECL_output( ureg,
97bf215546Sopenharmony_ci                              semantic_names[i],
98bf215546Sopenharmony_ci                              semantic_indexes[i]);
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci      ureg_MOV( ureg, dst, src );
101bf215546Sopenharmony_ci   }
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   if (layered) {
104bf215546Sopenharmony_ci      struct ureg_src instance_id =
105bf215546Sopenharmony_ci         ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0);
106bf215546Sopenharmony_ci      struct ureg_dst layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0);
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci      ureg_MOV(ureg, ureg_writemask(layer, TGSI_WRITEMASK_X),
109bf215546Sopenharmony_ci               ureg_scalar(instance_id, TGSI_SWIZZLE_X));
110bf215546Sopenharmony_ci   }
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   ureg_END( ureg );
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci   return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
115bf215546Sopenharmony_ci}
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_civoid *util_make_layered_clear_vertex_shader(struct pipe_context *pipe)
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   const enum tgsi_semantic semantic_names[] = {TGSI_SEMANTIC_POSITION,
121bf215546Sopenharmony_ci                                                TGSI_SEMANTIC_GENERIC};
122bf215546Sopenharmony_ci   const unsigned semantic_indices[] = {0, 0};
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   return util_make_vertex_passthrough_shader_with_so(pipe, 2, semantic_names,
125bf215546Sopenharmony_ci                                                      semantic_indices, false,
126bf215546Sopenharmony_ci                                                      true, NULL);
127bf215546Sopenharmony_ci}
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci/**
130bf215546Sopenharmony_ci * Takes position and color, and outputs position, color, and instance id.
131bf215546Sopenharmony_ci */
132bf215546Sopenharmony_civoid *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe)
133bf215546Sopenharmony_ci{
134bf215546Sopenharmony_ci   static const char text[] =
135bf215546Sopenharmony_ci         "VERT\n"
136bf215546Sopenharmony_ci         "DCL IN[0]\n"
137bf215546Sopenharmony_ci         "DCL IN[1]\n"
138bf215546Sopenharmony_ci         "DCL SV[0], INSTANCEID\n"
139bf215546Sopenharmony_ci         "DCL OUT[0], POSITION\n"
140bf215546Sopenharmony_ci         "DCL OUT[1], GENERIC[0]\n"
141bf215546Sopenharmony_ci         "DCL OUT[2], GENERIC[1]\n"
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci         "MOV OUT[0], IN[0]\n"
144bf215546Sopenharmony_ci         "MOV OUT[1], IN[1]\n"
145bf215546Sopenharmony_ci         "MOV OUT[2].x, SV[0].xxxx\n"
146bf215546Sopenharmony_ci         "END\n";
147bf215546Sopenharmony_ci   struct tgsi_token tokens[1000];
148bf215546Sopenharmony_ci   struct pipe_shader_state state = {0};
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
151bf215546Sopenharmony_ci      assert(0);
152bf215546Sopenharmony_ci      return NULL;
153bf215546Sopenharmony_ci   }
154bf215546Sopenharmony_ci   pipe_shader_state_from_tgsi(&state, tokens);
155bf215546Sopenharmony_ci   return pipe->create_vs_state(pipe, &state);
156bf215546Sopenharmony_ci}
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci/**
159bf215546Sopenharmony_ci * Takes position, color, and target layer, and emits vertices on that target
160bf215546Sopenharmony_ci * layer, with the specified color.
161bf215546Sopenharmony_ci */
162bf215546Sopenharmony_civoid *util_make_layered_clear_geometry_shader(struct pipe_context *pipe)
163bf215546Sopenharmony_ci{
164bf215546Sopenharmony_ci   static const char text[] =
165bf215546Sopenharmony_ci      "GEOM\n"
166bf215546Sopenharmony_ci      "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
167bf215546Sopenharmony_ci      "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
168bf215546Sopenharmony_ci      "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n"
169bf215546Sopenharmony_ci      "PROPERTY GS_INVOCATIONS 1\n"
170bf215546Sopenharmony_ci      "DCL IN[][0], POSITION\n" /* position */
171bf215546Sopenharmony_ci      "DCL IN[][1], GENERIC[0]\n" /* color */
172bf215546Sopenharmony_ci      "DCL IN[][2], GENERIC[1]\n" /* vs invocation */
173bf215546Sopenharmony_ci      "DCL OUT[0], POSITION\n"
174bf215546Sopenharmony_ci      "DCL OUT[1], GENERIC[0]\n"
175bf215546Sopenharmony_ci      "DCL OUT[2], LAYER\n"
176bf215546Sopenharmony_ci      "IMM[0] INT32 {0, 0, 0, 0}\n"
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci      "MOV OUT[0], IN[0][0]\n"
179bf215546Sopenharmony_ci      "MOV OUT[1], IN[0][1]\n"
180bf215546Sopenharmony_ci      "MOV OUT[2].x, IN[0][2].xxxx\n"
181bf215546Sopenharmony_ci      "EMIT IMM[0].xxxx\n"
182bf215546Sopenharmony_ci      "MOV OUT[0], IN[1][0]\n"
183bf215546Sopenharmony_ci      "MOV OUT[1], IN[1][1]\n"
184bf215546Sopenharmony_ci      "MOV OUT[2].x, IN[1][2].xxxx\n"
185bf215546Sopenharmony_ci      "EMIT IMM[0].xxxx\n"
186bf215546Sopenharmony_ci      "MOV OUT[0], IN[2][0]\n"
187bf215546Sopenharmony_ci      "MOV OUT[1], IN[2][1]\n"
188bf215546Sopenharmony_ci      "MOV OUT[2].x, IN[2][2].xxxx\n"
189bf215546Sopenharmony_ci      "EMIT IMM[0].xxxx\n"
190bf215546Sopenharmony_ci      "END\n";
191bf215546Sopenharmony_ci   struct tgsi_token tokens[1000];
192bf215546Sopenharmony_ci   struct pipe_shader_state state = {0};
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
195bf215546Sopenharmony_ci      assert(0);
196bf215546Sopenharmony_ci      return NULL;
197bf215546Sopenharmony_ci   }
198bf215546Sopenharmony_ci   pipe_shader_state_from_tgsi(&state, tokens);
199bf215546Sopenharmony_ci   return pipe->create_gs_state(pipe, &state);
200bf215546Sopenharmony_ci}
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_cistatic void
203bf215546Sopenharmony_ciureg_load_tex(struct ureg_program *ureg, struct ureg_dst out,
204bf215546Sopenharmony_ci              struct ureg_src coord, struct ureg_src sampler,
205bf215546Sopenharmony_ci              enum tgsi_texture_type tex_target,
206bf215546Sopenharmony_ci              bool load_level_zero, bool use_txf)
207bf215546Sopenharmony_ci{
208bf215546Sopenharmony_ci   if (use_txf) {
209bf215546Sopenharmony_ci      struct ureg_dst temp = ureg_DECL_temporary(ureg);
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci      ureg_F2I(ureg, temp, coord);
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci      if (load_level_zero)
214bf215546Sopenharmony_ci         ureg_TXF_LZ(ureg, out, tex_target, ureg_src(temp), sampler);
215bf215546Sopenharmony_ci      else
216bf215546Sopenharmony_ci         ureg_TXF(ureg, out, tex_target, ureg_src(temp), sampler);
217bf215546Sopenharmony_ci   } else {
218bf215546Sopenharmony_ci      if (load_level_zero)
219bf215546Sopenharmony_ci         ureg_TEX_LZ(ureg, out, tex_target, coord, sampler);
220bf215546Sopenharmony_ci      else
221bf215546Sopenharmony_ci         ureg_TEX(ureg, out, tex_target, coord, sampler);
222bf215546Sopenharmony_ci   }
223bf215546Sopenharmony_ci}
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci/**
226bf215546Sopenharmony_ci * Make simple fragment texture shader, with xrbias->float conversion:
227bf215546Sopenharmony_ci *  IMM {1023/510, -384/510, 0, 1}
228bf215546Sopenharmony_ci *  TEX TEMP[0], IN[0], SAMP[0], 2D;
229bf215546Sopenharmony_ci *  MAD TEMP[0].xyz TEMP[0], IMM[0].xxxx, IMM[0].yyyy
230bf215546Sopenharmony_ci *  MOV OUT[0], TEMP[0]
231bf215546Sopenharmony_ci *  END;
232bf215546Sopenharmony_ci *
233bf215546Sopenharmony_ci * \param tex_target  one of PIPE_TEXTURE_x
234bf215546Sopenharmony_ci */
235bf215546Sopenharmony_civoid *
236bf215546Sopenharmony_ciutil_make_fragment_tex_shader_xrbias(struct pipe_context *pipe,
237bf215546Sopenharmony_ci                                     enum tgsi_texture_type tex_target)
238bf215546Sopenharmony_ci{
239bf215546Sopenharmony_ci   struct ureg_program *ureg;
240bf215546Sopenharmony_ci   struct ureg_src sampler;
241bf215546Sopenharmony_ci   struct ureg_src coord;
242bf215546Sopenharmony_ci   struct ureg_dst temp;
243bf215546Sopenharmony_ci   struct ureg_dst out;
244bf215546Sopenharmony_ci   struct ureg_src imm;
245bf215546Sopenharmony_ci   enum tgsi_return_type stype = TGSI_RETURN_TYPE_FLOAT;
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci   ureg = ureg_create(PIPE_SHADER_FRAGMENT);
248bf215546Sopenharmony_ci   if (!ureg)
249bf215546Sopenharmony_ci      return NULL;
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci   imm = ureg_imm4f(ureg, 1023.0f/510.0f, -384.0f/510.0f, 0.0f, 1.0f);
252bf215546Sopenharmony_ci   sampler = ureg_DECL_sampler(ureg, 0);
253bf215546Sopenharmony_ci   ureg_DECL_sampler_view(ureg, 0, tex_target, stype, stype, stype, stype);
254bf215546Sopenharmony_ci   coord = ureg_DECL_fs_input(ureg,
255bf215546Sopenharmony_ci                              TGSI_SEMANTIC_GENERIC, 0,
256bf215546Sopenharmony_ci                              TGSI_INTERPOLATE_LINEAR);
257bf215546Sopenharmony_ci   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
258bf215546Sopenharmony_ci   temp = ureg_DECL_temporary(ureg);
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci   ureg_TEX(ureg, temp, tex_target, coord, sampler);
261bf215546Sopenharmony_ci   ureg_MAD(ureg, ureg_writemask(temp, TGSI_WRITEMASK_XYZ),
262bf215546Sopenharmony_ci            ureg_src(temp),
263bf215546Sopenharmony_ci            ureg_scalar(imm, TGSI_SWIZZLE_X),
264bf215546Sopenharmony_ci            ureg_scalar(imm, TGSI_SWIZZLE_Y));
265bf215546Sopenharmony_ci   ureg_MOV(ureg, out, ureg_src(temp));
266bf215546Sopenharmony_ci   ureg_END(ureg);
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy(ureg, pipe);
269bf215546Sopenharmony_ci}
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci/**
273bf215546Sopenharmony_ci * Make simple fragment texture shader:
274bf215546Sopenharmony_ci *  IMM {0,0,0,1}                         // (if writemask != 0xf)
275bf215546Sopenharmony_ci *  MOV TEMP[0], IMM[0]                   // (if writemask != 0xf)
276bf215546Sopenharmony_ci *  TEX TEMP[0].writemask, IN[0], SAMP[0], 2D;
277bf215546Sopenharmony_ci *   .. optional SINT <-> UINT clamping ..
278bf215546Sopenharmony_ci *  MOV OUT[0], TEMP[0]
279bf215546Sopenharmony_ci *  END;
280bf215546Sopenharmony_ci *
281bf215546Sopenharmony_ci * \param tex_target  one of TGSI_TEXTURE_x
282bf215546Sopenharmony_ci * \parma interp_mode  either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
283bf215546Sopenharmony_ci * \param writemask  mask of TGSI_WRITEMASK_x
284bf215546Sopenharmony_ci */
285bf215546Sopenharmony_civoid *
286bf215546Sopenharmony_ciutil_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
287bf215546Sopenharmony_ci                                        enum tgsi_texture_type tex_target,
288bf215546Sopenharmony_ci                                        enum tgsi_interpolate_mode interp_mode,
289bf215546Sopenharmony_ci                                        unsigned writemask,
290bf215546Sopenharmony_ci                                        enum tgsi_return_type stype,
291bf215546Sopenharmony_ci                                        enum tgsi_return_type dtype,
292bf215546Sopenharmony_ci                                        bool load_level_zero,
293bf215546Sopenharmony_ci                                        bool use_txf)
294bf215546Sopenharmony_ci{
295bf215546Sopenharmony_ci   struct ureg_program *ureg;
296bf215546Sopenharmony_ci   struct ureg_src sampler;
297bf215546Sopenharmony_ci   struct ureg_src tex;
298bf215546Sopenharmony_ci   struct ureg_dst temp;
299bf215546Sopenharmony_ci   struct ureg_dst out;
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   assert((stype == TGSI_RETURN_TYPE_FLOAT) == (dtype == TGSI_RETURN_TYPE_FLOAT));
302bf215546Sopenharmony_ci   assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
303bf215546Sopenharmony_ci          interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci   ureg = ureg_create( PIPE_SHADER_FRAGMENT );
306bf215546Sopenharmony_ci   if (!ureg)
307bf215546Sopenharmony_ci      return NULL;
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci   sampler = ureg_DECL_sampler( ureg, 0 );
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci   ureg_DECL_sampler_view(ureg, 0, tex_target, stype, stype, stype, stype);
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   tex = ureg_DECL_fs_input( ureg,
314bf215546Sopenharmony_ci                             TGSI_SEMANTIC_GENERIC, 0,
315bf215546Sopenharmony_ci                             interp_mode );
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   out = ureg_DECL_output( ureg,
318bf215546Sopenharmony_ci                           TGSI_SEMANTIC_COLOR,
319bf215546Sopenharmony_ci                           0 );
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   temp = ureg_DECL_temporary(ureg);
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   if (writemask != TGSI_WRITEMASK_XYZW) {
324bf215546Sopenharmony_ci      struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci      ureg_MOV(ureg, temp, imm);
327bf215546Sopenharmony_ci   }
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   if (tex_target == TGSI_TEXTURE_BUFFER)
330bf215546Sopenharmony_ci      ureg_TXF(ureg,
331bf215546Sopenharmony_ci               ureg_writemask(temp, writemask),
332bf215546Sopenharmony_ci               tex_target, tex, sampler);
333bf215546Sopenharmony_ci   else
334bf215546Sopenharmony_ci      ureg_load_tex(ureg, ureg_writemask(temp, writemask), tex, sampler,
335bf215546Sopenharmony_ci                    tex_target, load_level_zero, use_txf);
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   if (stype != dtype) {
338bf215546Sopenharmony_ci      if (stype == TGSI_RETURN_TYPE_SINT) {
339bf215546Sopenharmony_ci         assert(dtype == TGSI_RETURN_TYPE_UINT);
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci         ureg_IMAX(ureg, temp, ureg_src(temp), ureg_imm1i(ureg, 0));
342bf215546Sopenharmony_ci      } else {
343bf215546Sopenharmony_ci         assert(stype == TGSI_RETURN_TYPE_UINT);
344bf215546Sopenharmony_ci         assert(dtype == TGSI_RETURN_TYPE_SINT);
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci         ureg_UMIN(ureg, temp, ureg_src(temp), ureg_imm1u(ureg, (1u << 31) - 1));
347bf215546Sopenharmony_ci      }
348bf215546Sopenharmony_ci   }
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   ureg_MOV(ureg, out, ureg_src(temp));
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci   ureg_END( ureg );
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy( ureg, pipe );
355bf215546Sopenharmony_ci}
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci/**
359bf215546Sopenharmony_ci * Make a simple fragment shader that sets the output color to a color
360bf215546Sopenharmony_ci * taken from a texture.
361bf215546Sopenharmony_ci * \param tex_target  one of TGSI_TEXTURE_x
362bf215546Sopenharmony_ci */
363bf215546Sopenharmony_civoid *
364bf215546Sopenharmony_ciutil_make_fragment_tex_shader(struct pipe_context *pipe,
365bf215546Sopenharmony_ci                              enum tgsi_texture_type tex_target,
366bf215546Sopenharmony_ci                              enum tgsi_interpolate_mode interp_mode,
367bf215546Sopenharmony_ci                              enum tgsi_return_type stype,
368bf215546Sopenharmony_ci                              enum tgsi_return_type dtype,
369bf215546Sopenharmony_ci                              bool load_level_zero,
370bf215546Sopenharmony_ci                              bool use_txf)
371bf215546Sopenharmony_ci{
372bf215546Sopenharmony_ci   return util_make_fragment_tex_shader_writemask( pipe,
373bf215546Sopenharmony_ci                                                   tex_target,
374bf215546Sopenharmony_ci                                                   interp_mode,
375bf215546Sopenharmony_ci                                                   TGSI_WRITEMASK_XYZW,
376bf215546Sopenharmony_ci                                                   stype, dtype, load_level_zero,
377bf215546Sopenharmony_ci                                                   use_txf);
378bf215546Sopenharmony_ci}
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci/**
382bf215546Sopenharmony_ci * Make a simple fragment texture shader which reads the texture unit 0 and 1
383bf215546Sopenharmony_ci * and writes it as depth and stencil, respectively.
384bf215546Sopenharmony_ci */
385bf215546Sopenharmony_civoid *
386bf215546Sopenharmony_ciutil_make_fs_blit_zs(struct pipe_context *pipe, unsigned zs_mask,
387bf215546Sopenharmony_ci                     enum tgsi_texture_type tex_target,
388bf215546Sopenharmony_ci                     bool load_level_zero, bool use_txf)
389bf215546Sopenharmony_ci{
390bf215546Sopenharmony_ci   struct ureg_program *ureg;
391bf215546Sopenharmony_ci   struct ureg_src depth_sampler, stencil_sampler, coord;
392bf215546Sopenharmony_ci   struct ureg_dst depth, stencil, tmp;
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   ureg = ureg_create(PIPE_SHADER_FRAGMENT);
395bf215546Sopenharmony_ci   if (!ureg)
396bf215546Sopenharmony_ci      return NULL;
397bf215546Sopenharmony_ci
398bf215546Sopenharmony_ci   coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
399bf215546Sopenharmony_ci                              TGSI_INTERPOLATE_LINEAR);
400bf215546Sopenharmony_ci   tmp = ureg_DECL_temporary(ureg);
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci   if (zs_mask & PIPE_MASK_Z) {
403bf215546Sopenharmony_ci      depth_sampler = ureg_DECL_sampler(ureg, 0);
404bf215546Sopenharmony_ci      ureg_DECL_sampler_view(ureg, 0, tex_target,
405bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_FLOAT,
406bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_FLOAT,
407bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_FLOAT,
408bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_FLOAT);
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci      ureg_load_tex(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), coord,
411bf215546Sopenharmony_ci                    depth_sampler, tex_target, load_level_zero, use_txf);
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci      depth = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
414bf215546Sopenharmony_ci      ureg_MOV(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Z),
415bf215546Sopenharmony_ci               ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
416bf215546Sopenharmony_ci   }
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci   if (zs_mask & PIPE_MASK_S) {
419bf215546Sopenharmony_ci      stencil_sampler = ureg_DECL_sampler(ureg, zs_mask & PIPE_MASK_Z ? 1 : 0);
420bf215546Sopenharmony_ci      ureg_DECL_sampler_view(ureg, zs_mask & PIPE_MASK_Z ? 1 : 0, tex_target,
421bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_UINT,
422bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_UINT,
423bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_UINT,
424bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_UINT);
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci      ureg_load_tex(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), coord,
427bf215546Sopenharmony_ci                    stencil_sampler, tex_target, load_level_zero, use_txf);
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci      stencil = ureg_DECL_output(ureg, TGSI_SEMANTIC_STENCIL, 0);
430bf215546Sopenharmony_ci      ureg_MOV(ureg, ureg_writemask(stencil, TGSI_WRITEMASK_Y),
431bf215546Sopenharmony_ci               ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
432bf215546Sopenharmony_ci   }
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci   ureg_END(ureg);
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy(ureg, pipe);
437bf215546Sopenharmony_ci}
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci/**
441bf215546Sopenharmony_ci * Make simple fragment color pass-through shader that replicates OUT[0]
442bf215546Sopenharmony_ci * to all bound colorbuffers.
443bf215546Sopenharmony_ci */
444bf215546Sopenharmony_civoid *
445bf215546Sopenharmony_ciutil_make_fragment_passthrough_shader(struct pipe_context *pipe,
446bf215546Sopenharmony_ci                                      int input_semantic,
447bf215546Sopenharmony_ci                                      int input_interpolate,
448bf215546Sopenharmony_ci                                      boolean write_all_cbufs)
449bf215546Sopenharmony_ci{
450bf215546Sopenharmony_ci   static const char shader_templ[] =
451bf215546Sopenharmony_ci         "FRAG\n"
452bf215546Sopenharmony_ci         "%s"
453bf215546Sopenharmony_ci         "DCL IN[0], %s[0], %s\n"
454bf215546Sopenharmony_ci         "DCL OUT[0], COLOR[0]\n"
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci         "MOV OUT[0], IN[0]\n"
457bf215546Sopenharmony_ci         "END\n";
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   char text[sizeof(shader_templ)+100];
460bf215546Sopenharmony_ci   struct tgsi_token tokens[1000];
461bf215546Sopenharmony_ci   struct pipe_shader_state state = {0};
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci   sprintf(text, shader_templ,
464bf215546Sopenharmony_ci           write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
465bf215546Sopenharmony_ci           tgsi_semantic_names[input_semantic],
466bf215546Sopenharmony_ci           tgsi_interpolate_names[input_interpolate]);
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci   if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
469bf215546Sopenharmony_ci      assert(0);
470bf215546Sopenharmony_ci      return NULL;
471bf215546Sopenharmony_ci   }
472bf215546Sopenharmony_ci   pipe_shader_state_from_tgsi(&state, tokens);
473bf215546Sopenharmony_ci#if 0
474bf215546Sopenharmony_ci   tgsi_dump(state.tokens, 0);
475bf215546Sopenharmony_ci#endif
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_ci   return pipe->create_fs_state(pipe, &state);
478bf215546Sopenharmony_ci}
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_civoid *
482bf215546Sopenharmony_ciutil_make_empty_fragment_shader(struct pipe_context *pipe)
483bf215546Sopenharmony_ci{
484bf215546Sopenharmony_ci   struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT);
485bf215546Sopenharmony_ci   if (!ureg)
486bf215546Sopenharmony_ci      return NULL;
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci   ureg_END(ureg);
489bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy(ureg, pipe);
490bf215546Sopenharmony_ci}
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci/**
494bf215546Sopenharmony_ci * Make a fragment shader that copies the input color to N output colors.
495bf215546Sopenharmony_ci */
496bf215546Sopenharmony_civoid *
497bf215546Sopenharmony_ciutil_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
498bf215546Sopenharmony_ci                                     int input_semantic,
499bf215546Sopenharmony_ci                                     int input_interpolate)
500bf215546Sopenharmony_ci{
501bf215546Sopenharmony_ci   struct ureg_program *ureg;
502bf215546Sopenharmony_ci   struct ureg_src src;
503bf215546Sopenharmony_ci   struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
504bf215546Sopenharmony_ci   int i;
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci   assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_ci   ureg = ureg_create( PIPE_SHADER_FRAGMENT );
509bf215546Sopenharmony_ci   if (!ureg)
510bf215546Sopenharmony_ci      return NULL;
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci   src = ureg_DECL_fs_input( ureg, input_semantic, 0,
513bf215546Sopenharmony_ci                             input_interpolate );
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci   for (i = 0; i < num_cbufs; i++)
516bf215546Sopenharmony_ci      dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ci   for (i = 0; i < num_cbufs; i++)
519bf215546Sopenharmony_ci      ureg_MOV( ureg, dst[i], src );
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci   ureg_END( ureg );
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy( ureg, pipe );
524bf215546Sopenharmony_ci}
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_cistatic void *
528bf215546Sopenharmony_ciutil_make_fs_blit_msaa_gen(struct pipe_context *pipe,
529bf215546Sopenharmony_ci                           enum tgsi_texture_type tgsi_tex,
530bf215546Sopenharmony_ci                           bool sample_shading,
531bf215546Sopenharmony_ci                           const char *samp_type,
532bf215546Sopenharmony_ci                           const char *output_semantic,
533bf215546Sopenharmony_ci                           const char *output_mask,
534bf215546Sopenharmony_ci                           const char *conversion_decl,
535bf215546Sopenharmony_ci                           const char *conversion)
536bf215546Sopenharmony_ci{
537bf215546Sopenharmony_ci   static const char shader_templ[] =
538bf215546Sopenharmony_ci         "FRAG\n"
539bf215546Sopenharmony_ci         "DCL IN[0], GENERIC[0], LINEAR\n"
540bf215546Sopenharmony_ci         "DCL SAMP[0]\n"
541bf215546Sopenharmony_ci         "DCL SVIEW[0], %s, %s\n"
542bf215546Sopenharmony_ci         "DCL OUT[0], %s\n"
543bf215546Sopenharmony_ci         "DCL TEMP[0]\n"
544bf215546Sopenharmony_ci         "%s"
545bf215546Sopenharmony_ci         "%s"
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci         "F2U TEMP[0], IN[0]\n"
548bf215546Sopenharmony_ci         "%s"
549bf215546Sopenharmony_ci         "TXF TEMP[0], TEMP[0], SAMP[0], %s\n"
550bf215546Sopenharmony_ci         "%s"
551bf215546Sopenharmony_ci         "MOV OUT[0]%s, TEMP[0]\n"
552bf215546Sopenharmony_ci         "END\n";
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci   const char *type = tgsi_texture_names[tgsi_tex];
555bf215546Sopenharmony_ci   char text[sizeof(shader_templ)+400];
556bf215546Sopenharmony_ci   struct tgsi_token tokens[1000];
557bf215546Sopenharmony_ci   struct pipe_shader_state state = {0};
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci   assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
560bf215546Sopenharmony_ci          tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ci   snprintf(text, sizeof(text), shader_templ, type, samp_type,
563bf215546Sopenharmony_ci            output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
564bf215546Sopenharmony_ci            conversion_decl, sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
565bf215546Sopenharmony_ci            type, conversion, output_mask);
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
568bf215546Sopenharmony_ci      puts(text);
569bf215546Sopenharmony_ci      assert(0);
570bf215546Sopenharmony_ci      return NULL;
571bf215546Sopenharmony_ci   }
572bf215546Sopenharmony_ci   pipe_shader_state_from_tgsi(&state, tokens);
573bf215546Sopenharmony_ci#if 0
574bf215546Sopenharmony_ci   tgsi_dump(state.tokens, 0);
575bf215546Sopenharmony_ci#endif
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci   return pipe->create_fs_state(pipe, &state);
578bf215546Sopenharmony_ci}
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci/**
582bf215546Sopenharmony_ci * Make a fragment shader that sets the output color to a color
583bf215546Sopenharmony_ci * fetched from a multisample texture.
584bf215546Sopenharmony_ci * \param tex_target  one of PIPE_TEXTURE_x
585bf215546Sopenharmony_ci */
586bf215546Sopenharmony_civoid *
587bf215546Sopenharmony_ciutil_make_fs_blit_msaa_color(struct pipe_context *pipe,
588bf215546Sopenharmony_ci                             enum tgsi_texture_type tgsi_tex,
589bf215546Sopenharmony_ci                             enum tgsi_return_type stype,
590bf215546Sopenharmony_ci                             enum tgsi_return_type dtype,
591bf215546Sopenharmony_ci                             bool sample_shading)
592bf215546Sopenharmony_ci{
593bf215546Sopenharmony_ci   const char *samp_type;
594bf215546Sopenharmony_ci   const char *conversion_decl = "";
595bf215546Sopenharmony_ci   const char *conversion = "";
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci   if (stype == TGSI_RETURN_TYPE_UINT) {
598bf215546Sopenharmony_ci      samp_type = "UINT";
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci      if (dtype == TGSI_RETURN_TYPE_SINT) {
601bf215546Sopenharmony_ci         conversion_decl = "IMM[0] UINT32 {2147483647, 0, 0, 0}\n";
602bf215546Sopenharmony_ci         conversion = "UMIN TEMP[0], TEMP[0], IMM[0].xxxx\n";
603bf215546Sopenharmony_ci      }
604bf215546Sopenharmony_ci   } else if (stype == TGSI_RETURN_TYPE_SINT) {
605bf215546Sopenharmony_ci      samp_type = "SINT";
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci      if (dtype == TGSI_RETURN_TYPE_UINT) {
608bf215546Sopenharmony_ci         conversion_decl = "IMM[0] INT32 {0, 0, 0, 0}\n";
609bf215546Sopenharmony_ci         conversion = "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n";
610bf215546Sopenharmony_ci      }
611bf215546Sopenharmony_ci   } else {
612bf215546Sopenharmony_ci      assert(dtype == TGSI_RETURN_TYPE_FLOAT);
613bf215546Sopenharmony_ci      samp_type = "FLOAT";
614bf215546Sopenharmony_ci   }
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, samp_type,
617bf215546Sopenharmony_ci                                     "COLOR[0]", "", conversion_decl,
618bf215546Sopenharmony_ci                                     conversion);
619bf215546Sopenharmony_ci}
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci/**
623bf215546Sopenharmony_ci * Make a fragment shader that sets the output depth to a depth value
624bf215546Sopenharmony_ci * fetched from a multisample texture.
625bf215546Sopenharmony_ci * \param tex_target  one of PIPE_TEXTURE_x
626bf215546Sopenharmony_ci */
627bf215546Sopenharmony_civoid *
628bf215546Sopenharmony_ciutil_make_fs_blit_msaa_depth(struct pipe_context *pipe,
629bf215546Sopenharmony_ci                             enum tgsi_texture_type tgsi_tex,
630bf215546Sopenharmony_ci                             bool sample_shading)
631bf215546Sopenharmony_ci{
632bf215546Sopenharmony_ci   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, "FLOAT",
633bf215546Sopenharmony_ci                                     "POSITION", ".z", "",
634bf215546Sopenharmony_ci                                     "MOV TEMP[0].z, TEMP[0].xxxx\n");
635bf215546Sopenharmony_ci}
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci/**
639bf215546Sopenharmony_ci * Make a fragment shader that sets the output stencil to a stencil value
640bf215546Sopenharmony_ci * fetched from a multisample texture.
641bf215546Sopenharmony_ci * \param tex_target  one of PIPE_TEXTURE_x
642bf215546Sopenharmony_ci */
643bf215546Sopenharmony_civoid *
644bf215546Sopenharmony_ciutil_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
645bf215546Sopenharmony_ci                               enum tgsi_texture_type tgsi_tex,
646bf215546Sopenharmony_ci                               bool sample_shading)
647bf215546Sopenharmony_ci{
648bf215546Sopenharmony_ci   return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, "UINT",
649bf215546Sopenharmony_ci                                     "STENCIL", ".y", "",
650bf215546Sopenharmony_ci                                     "MOV TEMP[0].y, TEMP[0].xxxx\n");
651bf215546Sopenharmony_ci}
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci
654bf215546Sopenharmony_ci/**
655bf215546Sopenharmony_ci * Make a fragment shader that sets the output depth and stencil to depth
656bf215546Sopenharmony_ci * and stencil values fetched from two multisample textures / samplers.
657bf215546Sopenharmony_ci * The sizes of both textures should match (it should be one depth-stencil
658bf215546Sopenharmony_ci * texture).
659bf215546Sopenharmony_ci * \param tex_target  one of PIPE_TEXTURE_x
660bf215546Sopenharmony_ci */
661bf215546Sopenharmony_civoid *
662bf215546Sopenharmony_ciutil_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
663bf215546Sopenharmony_ci                                    enum tgsi_texture_type tgsi_tex,
664bf215546Sopenharmony_ci                                    bool sample_shading)
665bf215546Sopenharmony_ci{
666bf215546Sopenharmony_ci   static const char shader_templ[] =
667bf215546Sopenharmony_ci         "FRAG\n"
668bf215546Sopenharmony_ci         "DCL IN[0], GENERIC[0], LINEAR\n"
669bf215546Sopenharmony_ci         "DCL SAMP[0..1]\n"
670bf215546Sopenharmony_ci         "DCL SVIEW[0], %s, FLOAT\n"
671bf215546Sopenharmony_ci         "DCL SVIEW[1], %s, UINT\n"
672bf215546Sopenharmony_ci         "DCL OUT[0], POSITION\n"
673bf215546Sopenharmony_ci         "DCL OUT[1], STENCIL\n"
674bf215546Sopenharmony_ci         "DCL TEMP[0]\n"
675bf215546Sopenharmony_ci         "%s"
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_ci         "F2U TEMP[0], IN[0]\n"
678bf215546Sopenharmony_ci         "%s"
679bf215546Sopenharmony_ci         "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
680bf215546Sopenharmony_ci         "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
681bf215546Sopenharmony_ci         "END\n";
682bf215546Sopenharmony_ci
683bf215546Sopenharmony_ci   const char *type = tgsi_texture_names[tgsi_tex];
684bf215546Sopenharmony_ci   char text[sizeof(shader_templ)+400];
685bf215546Sopenharmony_ci   struct tgsi_token tokens[1000];
686bf215546Sopenharmony_ci   struct pipe_shader_state state = {0};
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci   assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
689bf215546Sopenharmony_ci          tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci   sprintf(text, shader_templ, type, type,
692bf215546Sopenharmony_ci           sample_shading ? "DCL SV[0], SAMPLEID\n" : "",
693bf215546Sopenharmony_ci           sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "",
694bf215546Sopenharmony_ci           type, type);
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci   if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
697bf215546Sopenharmony_ci      assert(0);
698bf215546Sopenharmony_ci      return NULL;
699bf215546Sopenharmony_ci   }
700bf215546Sopenharmony_ci   pipe_shader_state_from_tgsi(&state, tokens);
701bf215546Sopenharmony_ci#if 0
702bf215546Sopenharmony_ci   tgsi_dump(state.tokens, 0);
703bf215546Sopenharmony_ci#endif
704bf215546Sopenharmony_ci
705bf215546Sopenharmony_ci   return pipe->create_fs_state(pipe, &state);
706bf215546Sopenharmony_ci}
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_civoid *
710bf215546Sopenharmony_ciutil_make_fs_msaa_resolve(struct pipe_context *pipe,
711bf215546Sopenharmony_ci                          enum tgsi_texture_type tgsi_tex, unsigned nr_samples,
712bf215546Sopenharmony_ci                          enum tgsi_return_type stype)
713bf215546Sopenharmony_ci{
714bf215546Sopenharmony_ci   struct ureg_program *ureg;
715bf215546Sopenharmony_ci   struct ureg_src sampler, coord;
716bf215546Sopenharmony_ci   struct ureg_dst out, tmp_sum, tmp_coord, tmp;
717bf215546Sopenharmony_ci   unsigned i;
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci   ureg = ureg_create(PIPE_SHADER_FRAGMENT);
720bf215546Sopenharmony_ci   if (!ureg)
721bf215546Sopenharmony_ci      return NULL;
722bf215546Sopenharmony_ci
723bf215546Sopenharmony_ci   /* Declarations. */
724bf215546Sopenharmony_ci   sampler = ureg_DECL_sampler(ureg, 0);
725bf215546Sopenharmony_ci   ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype);
726bf215546Sopenharmony_ci   coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
727bf215546Sopenharmony_ci                              TGSI_INTERPOLATE_LINEAR);
728bf215546Sopenharmony_ci   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
729bf215546Sopenharmony_ci   tmp_sum = ureg_DECL_temporary(ureg);
730bf215546Sopenharmony_ci   tmp_coord = ureg_DECL_temporary(ureg);
731bf215546Sopenharmony_ci   tmp = ureg_DECL_temporary(ureg);
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci   /* Instructions. */
734bf215546Sopenharmony_ci   ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0));
735bf215546Sopenharmony_ci   ureg_F2U(ureg, tmp_coord, coord);
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci   for (i = 0; i < nr_samples; i++) {
738bf215546Sopenharmony_ci      /* Read one sample. */
739bf215546Sopenharmony_ci      ureg_MOV(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_W),
740bf215546Sopenharmony_ci               ureg_imm1u(ureg, i));
741bf215546Sopenharmony_ci      ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler);
742bf215546Sopenharmony_ci
743bf215546Sopenharmony_ci      if (stype == TGSI_RETURN_TYPE_UINT)
744bf215546Sopenharmony_ci         ureg_U2F(ureg, tmp, ureg_src(tmp));
745bf215546Sopenharmony_ci      else if (stype == TGSI_RETURN_TYPE_SINT)
746bf215546Sopenharmony_ci         ureg_I2F(ureg, tmp, ureg_src(tmp));
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_ci      /* Add it to the sum.*/
749bf215546Sopenharmony_ci      ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp));
750bf215546Sopenharmony_ci   }
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci   /* Calculate the average and return. */
753bf215546Sopenharmony_ci   ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum),
754bf215546Sopenharmony_ci            ureg_imm1f(ureg, 1.0 / nr_samples));
755bf215546Sopenharmony_ci
756bf215546Sopenharmony_ci   if (stype == TGSI_RETURN_TYPE_UINT)
757bf215546Sopenharmony_ci      ureg_F2U(ureg, out, ureg_src(tmp_sum));
758bf215546Sopenharmony_ci   else if (stype == TGSI_RETURN_TYPE_SINT)
759bf215546Sopenharmony_ci      ureg_F2I(ureg, out, ureg_src(tmp_sum));
760bf215546Sopenharmony_ci   else
761bf215546Sopenharmony_ci      ureg_MOV(ureg, out, ureg_src(tmp_sum));
762bf215546Sopenharmony_ci
763bf215546Sopenharmony_ci   ureg_END(ureg);
764bf215546Sopenharmony_ci
765bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy(ureg, pipe);
766bf215546Sopenharmony_ci}
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci
769bf215546Sopenharmony_civoid *
770bf215546Sopenharmony_ciutil_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
771bf215546Sopenharmony_ci                                   enum tgsi_texture_type tgsi_tex,
772bf215546Sopenharmony_ci                                   unsigned nr_samples,
773bf215546Sopenharmony_ci                                   enum tgsi_return_type stype)
774bf215546Sopenharmony_ci{
775bf215546Sopenharmony_ci   struct ureg_program *ureg;
776bf215546Sopenharmony_ci   struct ureg_src sampler, coord;
777bf215546Sopenharmony_ci   struct ureg_dst out, tmp, top, bottom;
778bf215546Sopenharmony_ci   struct ureg_dst tmp_coord[4], tmp_sum[4];
779bf215546Sopenharmony_ci   unsigned i, c;
780bf215546Sopenharmony_ci
781bf215546Sopenharmony_ci   ureg = ureg_create(PIPE_SHADER_FRAGMENT);
782bf215546Sopenharmony_ci   if (!ureg)
783bf215546Sopenharmony_ci      return NULL;
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci   /* Declarations. */
786bf215546Sopenharmony_ci   sampler = ureg_DECL_sampler(ureg, 0);
787bf215546Sopenharmony_ci   ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype);
788bf215546Sopenharmony_ci   coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
789bf215546Sopenharmony_ci                              TGSI_INTERPOLATE_LINEAR);
790bf215546Sopenharmony_ci   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
791bf215546Sopenharmony_ci   for (c = 0; c < 4; c++)
792bf215546Sopenharmony_ci      tmp_sum[c] = ureg_DECL_temporary(ureg);
793bf215546Sopenharmony_ci   for (c = 0; c < 4; c++)
794bf215546Sopenharmony_ci      tmp_coord[c] = ureg_DECL_temporary(ureg);
795bf215546Sopenharmony_ci   tmp = ureg_DECL_temporary(ureg);
796bf215546Sopenharmony_ci   top = ureg_DECL_temporary(ureg);
797bf215546Sopenharmony_ci   bottom = ureg_DECL_temporary(ureg);
798bf215546Sopenharmony_ci
799bf215546Sopenharmony_ci   /* Instructions. */
800bf215546Sopenharmony_ci   for (c = 0; c < 4; c++)
801bf215546Sopenharmony_ci      ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0));
802bf215546Sopenharmony_ci
803bf215546Sopenharmony_ci   /* Get 4 texture coordinates for the bilinear filter. */
804bf215546Sopenharmony_ci   ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */
805bf215546Sopenharmony_ci   ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]),
806bf215546Sopenharmony_ci             ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */
807bf215546Sopenharmony_ci   ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]),
808bf215546Sopenharmony_ci             ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */
809bf215546Sopenharmony_ci   ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]),
810bf215546Sopenharmony_ci             ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */
811bf215546Sopenharmony_ci
812bf215546Sopenharmony_ci   for (i = 0; i < nr_samples; i++) {
813bf215546Sopenharmony_ci      for (c = 0; c < 4; c++) {
814bf215546Sopenharmony_ci         /* Read one sample. */
815bf215546Sopenharmony_ci         ureg_MOV(ureg, ureg_writemask(tmp_coord[c], TGSI_WRITEMASK_W),
816bf215546Sopenharmony_ci                  ureg_imm1u(ureg, i));
817bf215546Sopenharmony_ci         ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler);
818bf215546Sopenharmony_ci
819bf215546Sopenharmony_ci         if (stype == TGSI_RETURN_TYPE_UINT)
820bf215546Sopenharmony_ci            ureg_U2F(ureg, tmp, ureg_src(tmp));
821bf215546Sopenharmony_ci         else if (stype == TGSI_RETURN_TYPE_SINT)
822bf215546Sopenharmony_ci            ureg_I2F(ureg, tmp, ureg_src(tmp));
823bf215546Sopenharmony_ci
824bf215546Sopenharmony_ci         /* Add it to the sum.*/
825bf215546Sopenharmony_ci         ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp));
826bf215546Sopenharmony_ci      }
827bf215546Sopenharmony_ci   }
828bf215546Sopenharmony_ci
829bf215546Sopenharmony_ci   /* Calculate the average. */
830bf215546Sopenharmony_ci   for (c = 0; c < 4; c++)
831bf215546Sopenharmony_ci      ureg_MUL(ureg, tmp_sum[c], ureg_src(tmp_sum[c]),
832bf215546Sopenharmony_ci               ureg_imm1f(ureg, 1.0 / nr_samples));
833bf215546Sopenharmony_ci
834bf215546Sopenharmony_ci   /* Take the 4 average values and apply a standard bilinear filter. */
835bf215546Sopenharmony_ci   ureg_FRC(ureg, tmp, coord);
836bf215546Sopenharmony_ci
837bf215546Sopenharmony_ci   ureg_LRP(ureg, top,
838bf215546Sopenharmony_ci            ureg_scalar(ureg_src(tmp), 0),
839bf215546Sopenharmony_ci            ureg_src(tmp_sum[1]),
840bf215546Sopenharmony_ci            ureg_src(tmp_sum[0]));
841bf215546Sopenharmony_ci
842bf215546Sopenharmony_ci   ureg_LRP(ureg, bottom,
843bf215546Sopenharmony_ci            ureg_scalar(ureg_src(tmp), 0),
844bf215546Sopenharmony_ci            ureg_src(tmp_sum[3]),
845bf215546Sopenharmony_ci            ureg_src(tmp_sum[2]));
846bf215546Sopenharmony_ci
847bf215546Sopenharmony_ci   ureg_LRP(ureg, tmp,
848bf215546Sopenharmony_ci            ureg_scalar(ureg_src(tmp), 1),
849bf215546Sopenharmony_ci            ureg_src(bottom),
850bf215546Sopenharmony_ci            ureg_src(top));
851bf215546Sopenharmony_ci
852bf215546Sopenharmony_ci   /* Convert to the texture format and return. */
853bf215546Sopenharmony_ci   if (stype == TGSI_RETURN_TYPE_UINT)
854bf215546Sopenharmony_ci      ureg_F2U(ureg, out, ureg_src(tmp));
855bf215546Sopenharmony_ci   else if (stype == TGSI_RETURN_TYPE_SINT)
856bf215546Sopenharmony_ci      ureg_F2I(ureg, out, ureg_src(tmp));
857bf215546Sopenharmony_ci   else
858bf215546Sopenharmony_ci      ureg_MOV(ureg, out, ureg_src(tmp));
859bf215546Sopenharmony_ci
860bf215546Sopenharmony_ci   ureg_END(ureg);
861bf215546Sopenharmony_ci
862bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy(ureg, pipe);
863bf215546Sopenharmony_ci}
864bf215546Sopenharmony_ci
865bf215546Sopenharmony_civoid *
866bf215546Sopenharmony_ciutil_make_geometry_passthrough_shader(struct pipe_context *pipe,
867bf215546Sopenharmony_ci                                      uint num_attribs,
868bf215546Sopenharmony_ci                                      const ubyte *semantic_names,
869bf215546Sopenharmony_ci                                      const ubyte *semantic_indexes)
870bf215546Sopenharmony_ci{
871bf215546Sopenharmony_ci   static const unsigned zero[4] = {0, 0, 0, 0};
872bf215546Sopenharmony_ci
873bf215546Sopenharmony_ci   struct ureg_program *ureg;
874bf215546Sopenharmony_ci   struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
875bf215546Sopenharmony_ci   struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
876bf215546Sopenharmony_ci   struct ureg_src imm;
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci   unsigned i;
879bf215546Sopenharmony_ci
880bf215546Sopenharmony_ci   ureg = ureg_create(PIPE_SHADER_GEOMETRY);
881bf215546Sopenharmony_ci   if (!ureg)
882bf215546Sopenharmony_ci      return NULL;
883bf215546Sopenharmony_ci
884bf215546Sopenharmony_ci   ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_POINTS);
885bf215546Sopenharmony_ci   ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_POINTS);
886bf215546Sopenharmony_ci   ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1);
887bf215546Sopenharmony_ci   ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, 1);
888bf215546Sopenharmony_ci   imm = ureg_DECL_immediate_uint(ureg, zero, 4);
889bf215546Sopenharmony_ci
890bf215546Sopenharmony_ci   /**
891bf215546Sopenharmony_ci    * Loop over all the attribs and declare the corresponding
892bf215546Sopenharmony_ci    * declarations in the geometry shader
893bf215546Sopenharmony_ci    */
894bf215546Sopenharmony_ci   for (i = 0; i < num_attribs; i++) {
895bf215546Sopenharmony_ci      src[i] = ureg_DECL_input(ureg, semantic_names[i],
896bf215546Sopenharmony_ci                               semantic_indexes[i], 0, 1);
897bf215546Sopenharmony_ci      src[i] = ureg_src_dimension(src[i], 0);
898bf215546Sopenharmony_ci      dst[i] = ureg_DECL_output(ureg, semantic_names[i], semantic_indexes[i]);
899bf215546Sopenharmony_ci   }
900bf215546Sopenharmony_ci
901bf215546Sopenharmony_ci   /* MOV dst[i] src[i] */
902bf215546Sopenharmony_ci   for (i = 0; i < num_attribs; i++) {
903bf215546Sopenharmony_ci      ureg_MOV(ureg, dst[i], src[i]);
904bf215546Sopenharmony_ci   }
905bf215546Sopenharmony_ci
906bf215546Sopenharmony_ci   /* EMIT IMM[0] */
907bf215546Sopenharmony_ci   ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1, 0);
908bf215546Sopenharmony_ci
909bf215546Sopenharmony_ci   /* END */
910bf215546Sopenharmony_ci   ureg_END(ureg);
911bf215546Sopenharmony_ci
912bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy(ureg, pipe);
913bf215546Sopenharmony_ci}
914bf215546Sopenharmony_ci
915bf215546Sopenharmony_ci
916bf215546Sopenharmony_ci/**
917bf215546Sopenharmony_ci * Blit from color to ZS or from ZS to color in a manner that is equivalent
918bf215546Sopenharmony_ci * to memcpy.
919bf215546Sopenharmony_ci *
920bf215546Sopenharmony_ci * Color is either R32_UINT (for Z24S8 / S8Z24) or R32G32_UINT (Z32_S8X24).
921bf215546Sopenharmony_ci *
922bf215546Sopenharmony_ci * Depth and stencil samplers are used to load depth and stencil,
923bf215546Sopenharmony_ci * and they are packed and the result is written to a color output.
924bf215546Sopenharmony_ci *   OR
925bf215546Sopenharmony_ci * A color sampler is used to load a color value, which is unpacked and
926bf215546Sopenharmony_ci * written to depth and stencil shader outputs.
927bf215546Sopenharmony_ci */
928bf215546Sopenharmony_civoid *
929bf215546Sopenharmony_ciutil_make_fs_pack_color_zs(struct pipe_context *pipe,
930bf215546Sopenharmony_ci                           enum tgsi_texture_type tex_target,
931bf215546Sopenharmony_ci                           enum pipe_format zs_format,
932bf215546Sopenharmony_ci                           bool dst_is_color)
933bf215546Sopenharmony_ci{
934bf215546Sopenharmony_ci   struct ureg_program *ureg;
935bf215546Sopenharmony_ci   struct ureg_src depth_sampler, stencil_sampler, color_sampler, coord;
936bf215546Sopenharmony_ci   struct ureg_dst out, depth, depth_x, stencil, out_depth, out_stencil, color;
937bf215546Sopenharmony_ci
938bf215546Sopenharmony_ci   assert(zs_format == PIPE_FORMAT_Z24_UNORM_S8_UINT || /* color is R32_UINT */
939bf215546Sopenharmony_ci          zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM || /* color is R32_UINT */
940bf215546Sopenharmony_ci          zs_format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT || /* color is R32G32_UINT */
941bf215546Sopenharmony_ci          zs_format == PIPE_FORMAT_Z24X8_UNORM || /* color is R32_UINT */
942bf215546Sopenharmony_ci          zs_format == PIPE_FORMAT_X8Z24_UNORM); /* color is R32_UINT */
943bf215546Sopenharmony_ci
944bf215546Sopenharmony_ci   bool has_stencil = zs_format != PIPE_FORMAT_Z24X8_UNORM &&
945bf215546Sopenharmony_ci                      zs_format != PIPE_FORMAT_X8Z24_UNORM;
946bf215546Sopenharmony_ci   bool is_z24 = zs_format != PIPE_FORMAT_Z32_FLOAT_S8X24_UINT;
947bf215546Sopenharmony_ci   bool z24_is_high = zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM ||
948bf215546Sopenharmony_ci                      zs_format == PIPE_FORMAT_X8Z24_UNORM;
949bf215546Sopenharmony_ci
950bf215546Sopenharmony_ci   ureg = ureg_create(PIPE_SHADER_FRAGMENT);
951bf215546Sopenharmony_ci   if (!ureg)
952bf215546Sopenharmony_ci      return NULL;
953bf215546Sopenharmony_ci
954bf215546Sopenharmony_ci   coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
955bf215546Sopenharmony_ci                              TGSI_INTERPOLATE_LINEAR);
956bf215546Sopenharmony_ci
957bf215546Sopenharmony_ci   if (dst_is_color) {
958bf215546Sopenharmony_ci      /* Load depth. */
959bf215546Sopenharmony_ci      depth_sampler = ureg_DECL_sampler(ureg, 0);
960bf215546Sopenharmony_ci      ureg_DECL_sampler_view(ureg, 0, tex_target,
961bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_FLOAT,
962bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_FLOAT,
963bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_FLOAT,
964bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_FLOAT);
965bf215546Sopenharmony_ci
966bf215546Sopenharmony_ci      depth = ureg_DECL_temporary(ureg);
967bf215546Sopenharmony_ci      depth_x = ureg_writemask(depth, TGSI_WRITEMASK_X);
968bf215546Sopenharmony_ci      ureg_load_tex(ureg, depth_x, coord, depth_sampler, tex_target, true, true);
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_ci      /* Pack to Z24. */
971bf215546Sopenharmony_ci      if (is_z24) {
972bf215546Sopenharmony_ci         double imm = 0xffffff;
973bf215546Sopenharmony_ci         struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2);
974bf215546Sopenharmony_ci         struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg),
975bf215546Sopenharmony_ci                                                 TGSI_WRITEMASK_XY);
976bf215546Sopenharmony_ci
977bf215546Sopenharmony_ci         ureg_F2D(ureg, tmp_xy, ureg_src(depth));
978bf215546Sopenharmony_ci         ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64);
979bf215546Sopenharmony_ci         ureg_D2U(ureg, depth_x, ureg_src(tmp_xy));
980bf215546Sopenharmony_ci
981bf215546Sopenharmony_ci         if (z24_is_high)
982bf215546Sopenharmony_ci            ureg_SHL(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 8));
983bf215546Sopenharmony_ci         else
984bf215546Sopenharmony_ci            ureg_AND(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 0xffffff));
985bf215546Sopenharmony_ci      }
986bf215546Sopenharmony_ci
987bf215546Sopenharmony_ci      if (has_stencil) {
988bf215546Sopenharmony_ci         /* Load stencil. */
989bf215546Sopenharmony_ci         stencil_sampler = ureg_DECL_sampler(ureg, 1);
990bf215546Sopenharmony_ci         ureg_DECL_sampler_view(ureg, 0, tex_target,
991bf215546Sopenharmony_ci                                TGSI_RETURN_TYPE_UINT,
992bf215546Sopenharmony_ci                                TGSI_RETURN_TYPE_UINT,
993bf215546Sopenharmony_ci                                TGSI_RETURN_TYPE_UINT,
994bf215546Sopenharmony_ci                                TGSI_RETURN_TYPE_UINT);
995bf215546Sopenharmony_ci
996bf215546Sopenharmony_ci         stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
997bf215546Sopenharmony_ci         ureg_load_tex(ureg, stencil, coord, stencil_sampler, tex_target,
998bf215546Sopenharmony_ci                       true, true);
999bf215546Sopenharmony_ci
1000bf215546Sopenharmony_ci         /* Pack stencil into depth. */
1001bf215546Sopenharmony_ci         if (is_z24) {
1002bf215546Sopenharmony_ci            if (!z24_is_high)
1003bf215546Sopenharmony_ci               ureg_SHL(ureg, stencil, ureg_src(stencil), ureg_imm1u(ureg, 24));
1004bf215546Sopenharmony_ci
1005bf215546Sopenharmony_ci            ureg_OR(ureg, depth_x, ureg_src(depth), ureg_src(stencil));
1006bf215546Sopenharmony_ci         }
1007bf215546Sopenharmony_ci      }
1008bf215546Sopenharmony_ci
1009bf215546Sopenharmony_ci      out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
1010bf215546Sopenharmony_ci
1011bf215546Sopenharmony_ci      if (is_z24) {
1012bf215546Sopenharmony_ci         ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_X), ureg_src(depth));
1013bf215546Sopenharmony_ci      } else {
1014bf215546Sopenharmony_ci         /* Z32_S8X24 */
1015bf215546Sopenharmony_ci         ureg_MOV(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Y),
1016bf215546Sopenharmony_ci                  ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X));
1017bf215546Sopenharmony_ci         ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_XY), ureg_src(depth));
1018bf215546Sopenharmony_ci      }
1019bf215546Sopenharmony_ci   } else {
1020bf215546Sopenharmony_ci      color_sampler = ureg_DECL_sampler(ureg, 0);
1021bf215546Sopenharmony_ci      ureg_DECL_sampler_view(ureg, 0, tex_target,
1022bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_UINT,
1023bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_UINT,
1024bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_UINT,
1025bf215546Sopenharmony_ci                             TGSI_RETURN_TYPE_UINT);
1026bf215546Sopenharmony_ci
1027bf215546Sopenharmony_ci      color = ureg_DECL_temporary(ureg);
1028bf215546Sopenharmony_ci      ureg_load_tex(ureg, color, coord, color_sampler, tex_target, true, true);
1029bf215546Sopenharmony_ci
1030bf215546Sopenharmony_ci      depth = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
1031bf215546Sopenharmony_ci      stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X);
1032bf215546Sopenharmony_ci
1033bf215546Sopenharmony_ci      if (is_z24) {
1034bf215546Sopenharmony_ci         double imm = 1.0 / 0xffffff;
1035bf215546Sopenharmony_ci         struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2);
1036bf215546Sopenharmony_ci         struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg),
1037bf215546Sopenharmony_ci                                                 TGSI_WRITEMASK_XY);
1038bf215546Sopenharmony_ci
1039bf215546Sopenharmony_ci         ureg_UBFE(ureg, depth, ureg_src(color),
1040bf215546Sopenharmony_ci                   ureg_imm1u(ureg, z24_is_high ? 8 : 0),
1041bf215546Sopenharmony_ci                   ureg_imm1u(ureg, 24));
1042bf215546Sopenharmony_ci         ureg_U2D(ureg, tmp_xy, ureg_src(depth));
1043bf215546Sopenharmony_ci         ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64);
1044bf215546Sopenharmony_ci         ureg_D2F(ureg, depth, ureg_src(tmp_xy));
1045bf215546Sopenharmony_ci      } else {
1046bf215546Sopenharmony_ci         /* depth = color.x; (Z32_S8X24) */
1047bf215546Sopenharmony_ci         ureg_MOV(ureg, depth, ureg_src(color));
1048bf215546Sopenharmony_ci      }
1049bf215546Sopenharmony_ci
1050bf215546Sopenharmony_ci      out_depth = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
1051bf215546Sopenharmony_ci      ureg_MOV(ureg, ureg_writemask(out_depth, TGSI_WRITEMASK_Z),
1052bf215546Sopenharmony_ci               ureg_scalar(ureg_src(depth), TGSI_SWIZZLE_X));
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_ci      if (has_stencil) {
1055bf215546Sopenharmony_ci         if (is_z24) {
1056bf215546Sopenharmony_ci            ureg_UBFE(ureg, stencil, ureg_src(color),
1057bf215546Sopenharmony_ci                      ureg_imm1u(ureg, z24_is_high ? 0 : 24),
1058bf215546Sopenharmony_ci                      ureg_imm1u(ureg, 8));
1059bf215546Sopenharmony_ci         } else {
1060bf215546Sopenharmony_ci            /* stencil = color.y[0:7]; (Z32_S8X24) */
1061bf215546Sopenharmony_ci            ureg_UBFE(ureg, stencil,
1062bf215546Sopenharmony_ci                      ureg_scalar(ureg_src(color), TGSI_SWIZZLE_Y),
1063bf215546Sopenharmony_ci                      ureg_imm1u(ureg, 0),
1064bf215546Sopenharmony_ci                      ureg_imm1u(ureg, 8));
1065bf215546Sopenharmony_ci         }
1066bf215546Sopenharmony_ci
1067bf215546Sopenharmony_ci         out_stencil = ureg_DECL_output(ureg, TGSI_SEMANTIC_STENCIL, 0);
1068bf215546Sopenharmony_ci         ureg_MOV(ureg, ureg_writemask(out_stencil, TGSI_WRITEMASK_Y),
1069bf215546Sopenharmony_ci                  ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X));
1070bf215546Sopenharmony_ci      }
1071bf215546Sopenharmony_ci   }
1072bf215546Sopenharmony_ci
1073bf215546Sopenharmony_ci   ureg_END(ureg);
1074bf215546Sopenharmony_ci
1075bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy(ureg, pipe);
1076bf215546Sopenharmony_ci}
1077bf215546Sopenharmony_ci
1078bf215546Sopenharmony_ci
1079bf215546Sopenharmony_ci/**
1080bf215546Sopenharmony_ci * Create passthrough tessellation control shader.
1081bf215546Sopenharmony_ci * Passthrough tessellation control shader has output of vertex shader
1082bf215546Sopenharmony_ci * as input and input of tessellation eval shader as output.
1083bf215546Sopenharmony_ci */
1084bf215546Sopenharmony_civoid *
1085bf215546Sopenharmony_ciutil_make_tess_ctrl_passthrough_shader(struct pipe_context *pipe,
1086bf215546Sopenharmony_ci                                       uint num_vs_outputs,
1087bf215546Sopenharmony_ci                                       uint num_tes_inputs,
1088bf215546Sopenharmony_ci                                       const ubyte *vs_semantic_names,
1089bf215546Sopenharmony_ci                                       const ubyte *vs_semantic_indexes,
1090bf215546Sopenharmony_ci                                       const ubyte *tes_semantic_names,
1091bf215546Sopenharmony_ci                                       const ubyte *tes_semantic_indexes,
1092bf215546Sopenharmony_ci                                       const unsigned vertices_per_patch)
1093bf215546Sopenharmony_ci{
1094bf215546Sopenharmony_ci   unsigned i, j;
1095bf215546Sopenharmony_ci   unsigned num_regs;
1096bf215546Sopenharmony_ci
1097bf215546Sopenharmony_ci   struct ureg_program *ureg;
1098bf215546Sopenharmony_ci   struct ureg_dst temp, addr;
1099bf215546Sopenharmony_ci   struct ureg_src invocationID;
1100bf215546Sopenharmony_ci   struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS];
1101bf215546Sopenharmony_ci   struct ureg_src src[PIPE_MAX_SHADER_INPUTS];
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_ci   ureg = ureg_create(PIPE_SHADER_TESS_CTRL);
1104bf215546Sopenharmony_ci
1105bf215546Sopenharmony_ci   if (!ureg)
1106bf215546Sopenharmony_ci      return NULL;
1107bf215546Sopenharmony_ci
1108bf215546Sopenharmony_ci   ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT, vertices_per_patch);
1109bf215546Sopenharmony_ci
1110bf215546Sopenharmony_ci   num_regs = 0;
1111bf215546Sopenharmony_ci
1112bf215546Sopenharmony_ci   for (i = 0; i < num_tes_inputs; i++) {
1113bf215546Sopenharmony_ci      switch (tes_semantic_names[i]) {
1114bf215546Sopenharmony_ci      case TGSI_SEMANTIC_POSITION:
1115bf215546Sopenharmony_ci      case TGSI_SEMANTIC_PSIZE:
1116bf215546Sopenharmony_ci      case TGSI_SEMANTIC_COLOR:
1117bf215546Sopenharmony_ci      case TGSI_SEMANTIC_BCOLOR:
1118bf215546Sopenharmony_ci      case TGSI_SEMANTIC_CLIPDIST:
1119bf215546Sopenharmony_ci      case TGSI_SEMANTIC_CLIPVERTEX:
1120bf215546Sopenharmony_ci      case TGSI_SEMANTIC_TEXCOORD:
1121bf215546Sopenharmony_ci      case TGSI_SEMANTIC_FOG:
1122bf215546Sopenharmony_ci      case TGSI_SEMANTIC_GENERIC:
1123bf215546Sopenharmony_ci         for (j = 0; j < num_vs_outputs; j++) {
1124bf215546Sopenharmony_ci            if (tes_semantic_names[i] == vs_semantic_names[j] &&
1125bf215546Sopenharmony_ci                tes_semantic_indexes[i] == vs_semantic_indexes[j]) {
1126bf215546Sopenharmony_ci
1127bf215546Sopenharmony_ci               dst[num_regs] = ureg_DECL_output(ureg,
1128bf215546Sopenharmony_ci                                               tes_semantic_names[i],
1129bf215546Sopenharmony_ci                                               tes_semantic_indexes[i]);
1130bf215546Sopenharmony_ci               src[num_regs] = ureg_DECL_input(ureg, vs_semantic_names[j],
1131bf215546Sopenharmony_ci                                               vs_semantic_indexes[j],
1132bf215546Sopenharmony_ci                                               0, 1);
1133bf215546Sopenharmony_ci
1134bf215546Sopenharmony_ci               if (tes_semantic_names[i] == TGSI_SEMANTIC_GENERIC ||
1135bf215546Sopenharmony_ci                   tes_semantic_names[i] == TGSI_SEMANTIC_POSITION) {
1136bf215546Sopenharmony_ci                  src[num_regs] = ureg_src_dimension(src[num_regs], 0);
1137bf215546Sopenharmony_ci                  dst[num_regs] = ureg_dst_dimension(dst[num_regs], 0);
1138bf215546Sopenharmony_ci               }
1139bf215546Sopenharmony_ci
1140bf215546Sopenharmony_ci               num_regs++;
1141bf215546Sopenharmony_ci               break;
1142bf215546Sopenharmony_ci            }
1143bf215546Sopenharmony_ci         }
1144bf215546Sopenharmony_ci         break;
1145bf215546Sopenharmony_ci      default:
1146bf215546Sopenharmony_ci         break;
1147bf215546Sopenharmony_ci      }
1148bf215546Sopenharmony_ci   }
1149bf215546Sopenharmony_ci
1150bf215546Sopenharmony_ci   dst[num_regs] = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSOUTER,
1151bf215546Sopenharmony_ci                                    num_regs);
1152bf215546Sopenharmony_ci   src[num_regs] = ureg_DECL_constant(ureg, 0);
1153bf215546Sopenharmony_ci   num_regs++;
1154bf215546Sopenharmony_ci   dst[num_regs] = ureg_DECL_output(ureg, TGSI_SEMANTIC_TESSINNER,
1155bf215546Sopenharmony_ci                                    num_regs);
1156bf215546Sopenharmony_ci   src[num_regs] = ureg_DECL_constant(ureg, 1);
1157bf215546Sopenharmony_ci   num_regs++;
1158bf215546Sopenharmony_ci
1159bf215546Sopenharmony_ci   if (vertices_per_patch > 1) {
1160bf215546Sopenharmony_ci      invocationID = ureg_DECL_system_value(ureg,
1161bf215546Sopenharmony_ci                        TGSI_SEMANTIC_INVOCATIONID, 0);
1162bf215546Sopenharmony_ci      temp = ureg_DECL_local_temporary(ureg);
1163bf215546Sopenharmony_ci      addr = ureg_DECL_address(ureg);
1164bf215546Sopenharmony_ci      ureg_UARL(ureg, ureg_writemask(addr, TGSI_WRITEMASK_X),
1165bf215546Sopenharmony_ci                ureg_scalar(invocationID, TGSI_SWIZZLE_X));
1166bf215546Sopenharmony_ci   }
1167bf215546Sopenharmony_ci
1168bf215546Sopenharmony_ci   for (i = 0; i < num_regs; i++) {
1169bf215546Sopenharmony_ci      if (dst[i].Dimension && vertices_per_patch > 1) {
1170bf215546Sopenharmony_ci         struct ureg_src addr_x = ureg_scalar(ureg_src(addr), TGSI_SWIZZLE_X);
1171bf215546Sopenharmony_ci         ureg_MOV(ureg, temp, ureg_src_dimension_indirect(src[i],
1172bf215546Sopenharmony_ci                  addr_x, 0));
1173bf215546Sopenharmony_ci         ureg_MOV(ureg, ureg_dst_dimension_indirect(dst[i],
1174bf215546Sopenharmony_ci                  addr_x, 0), ureg_src(temp));
1175bf215546Sopenharmony_ci      }
1176bf215546Sopenharmony_ci      else
1177bf215546Sopenharmony_ci         ureg_MOV(ureg, dst[i], src[i]);
1178bf215546Sopenharmony_ci   }
1179bf215546Sopenharmony_ci
1180bf215546Sopenharmony_ci   ureg_END(ureg);
1181bf215546Sopenharmony_ci
1182bf215546Sopenharmony_ci   return ureg_create_shader_and_destroy(ureg, pipe);
1183bf215546Sopenharmony_ci}
1184bf215546Sopenharmony_ci
1185bf215546Sopenharmony_civoid *
1186bf215546Sopenharmony_ciutil_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src)
1187bf215546Sopenharmony_ci{
1188bf215546Sopenharmony_ci   static const char shader_templ[] =
1189bf215546Sopenharmony_ci      "FRAG\n"
1190bf215546Sopenharmony_ci      "DCL IN[0], GENERIC[0], LINEAR\n"
1191bf215546Sopenharmony_ci      "DCL SAMP[0]\n"
1192bf215546Sopenharmony_ci      "DCL SVIEW[0], %s, UINT\n"
1193bf215546Sopenharmony_ci      "DCL CONST[0][0]\n"
1194bf215546Sopenharmony_ci      "DCL TEMP[0]\n"
1195bf215546Sopenharmony_ci
1196bf215546Sopenharmony_ci      "F2U TEMP[0], IN[0]\n"
1197bf215546Sopenharmony_ci      "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n"
1198bf215546Sopenharmony_ci      "AND TEMP[0].x, TEMP[0], CONST[0][0]\n"
1199bf215546Sopenharmony_ci      "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n"
1200bf215546Sopenharmony_ci      "U2F TEMP[0].x, TEMP[0]\n"
1201bf215546Sopenharmony_ci      "KILL_IF -TEMP[0].xxxx\n"
1202bf215546Sopenharmony_ci      "END\n";
1203bf215546Sopenharmony_ci
1204bf215546Sopenharmony_ci   char text[sizeof(shader_templ)+100];
1205bf215546Sopenharmony_ci   struct tgsi_token tokens[1000];
1206bf215546Sopenharmony_ci   struct pipe_shader_state state = { 0 };
1207bf215546Sopenharmony_ci
1208bf215546Sopenharmony_ci   enum tgsi_texture_type tgsi_tex = msaa_src ? TGSI_TEXTURE_2D_MSAA :
1209bf215546Sopenharmony_ci                                                TGSI_TEXTURE_2D;
1210bf215546Sopenharmony_ci
1211bf215546Sopenharmony_ci   sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex], tgsi_texture_names[tgsi_tex]);
1212bf215546Sopenharmony_ci
1213bf215546Sopenharmony_ci   if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
1214bf215546Sopenharmony_ci      assert(0);
1215bf215546Sopenharmony_ci      return NULL;
1216bf215546Sopenharmony_ci   }
1217bf215546Sopenharmony_ci
1218bf215546Sopenharmony_ci   pipe_shader_state_from_tgsi(&state, tokens);
1219bf215546Sopenharmony_ci
1220bf215546Sopenharmony_ci   return pipe->create_fs_state(pipe, &state);
1221bf215546Sopenharmony_ci}
1222bf215546Sopenharmony_ci
1223bf215546Sopenharmony_civoid *
1224bf215546Sopenharmony_ciutil_make_fs_clear_all_cbufs(struct pipe_context *pipe)
1225bf215546Sopenharmony_ci{
1226bf215546Sopenharmony_ci   static const char text[] =
1227bf215546Sopenharmony_ci      "FRAG\n"
1228bf215546Sopenharmony_ci      "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n"
1229bf215546Sopenharmony_ci      "DCL OUT[0], COLOR[0]\n"
1230bf215546Sopenharmony_ci      "DCL CONST[0][0]\n"
1231bf215546Sopenharmony_ci
1232bf215546Sopenharmony_ci      "MOV OUT[0], CONST[0][0]\n"
1233bf215546Sopenharmony_ci      "END\n";
1234bf215546Sopenharmony_ci
1235bf215546Sopenharmony_ci   struct tgsi_token tokens[1000];
1236bf215546Sopenharmony_ci   struct pipe_shader_state state = { 0 };
1237bf215546Sopenharmony_ci
1238bf215546Sopenharmony_ci   if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) {
1239bf215546Sopenharmony_ci      assert(0);
1240bf215546Sopenharmony_ci      return NULL;
1241bf215546Sopenharmony_ci   }
1242bf215546Sopenharmony_ci
1243bf215546Sopenharmony_ci   pipe_shader_state_from_tgsi(&state, tokens);
1244bf215546Sopenharmony_ci
1245bf215546Sopenharmony_ci   return pipe->create_fs_state(pipe, &state);
1246bf215546Sopenharmony_ci}
1247