1bf215546Sopenharmony_ci/**********************************************************
2bf215546Sopenharmony_ci * Copyright 2008-2022 VMware, Inc.  All rights reserved.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person
5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation
6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without
7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy,
8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies
9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is
10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be
13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci **********************************************************/
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "util/u_bitmask.h"
27bf215546Sopenharmony_ci#include "util/u_memory.h"
28bf215546Sopenharmony_ci#include "util/format/u_format.h"
29bf215546Sopenharmony_ci#include "svga_context.h"
30bf215546Sopenharmony_ci#include "svga_cmd.h"
31bf215546Sopenharmony_ci#include "svga_format.h"
32bf215546Sopenharmony_ci#include "svga_shader.h"
33bf215546Sopenharmony_ci#include "svga_tgsi.h"
34bf215546Sopenharmony_ci#include "svga_resource_texture.h"
35bf215546Sopenharmony_ci#include "VGPU10ShaderTokens.h"
36bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h"
37bf215546Sopenharmony_ci#include "tgsi/tgsi_text.h"
38bf215546Sopenharmony_ci#include "nir/nir_to_tgsi.h"
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci/**
42bf215546Sopenharmony_ci * This bit isn't really used anywhere.  It only serves to help
43bf215546Sopenharmony_ci * generate a unique "signature" for the vertex shader output bitmask.
44bf215546Sopenharmony_ci * Shader input/output signatures are used to resolve shader linking
45bf215546Sopenharmony_ci * issues.
46bf215546Sopenharmony_ci */
47bf215546Sopenharmony_ci#define FOG_GENERIC_BIT (((uint64_t) 1) << 63)
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci/**
51bf215546Sopenharmony_ci * Use the shader info to generate a bitmask indicating which generic
52bf215546Sopenharmony_ci * inputs are used by the shader.  A set bit indicates that GENERIC[i]
53bf215546Sopenharmony_ci * is used.
54bf215546Sopenharmony_ci */
55bf215546Sopenharmony_ciuint64_t
56bf215546Sopenharmony_cisvga_get_generic_inputs_mask(const struct tgsi_shader_info *info)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci   unsigned i;
59bf215546Sopenharmony_ci   uint64_t mask = 0x0;
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci   for (i = 0; i < info->num_inputs; i++) {
62bf215546Sopenharmony_ci      if (info->input_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
63bf215546Sopenharmony_ci         unsigned j = info->input_semantic_index[i];
64bf215546Sopenharmony_ci         assert(j < sizeof(mask) * 8);
65bf215546Sopenharmony_ci         mask |= ((uint64_t) 1) << j;
66bf215546Sopenharmony_ci      }
67bf215546Sopenharmony_ci   }
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   return mask;
70bf215546Sopenharmony_ci}
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci/**
74bf215546Sopenharmony_ci * Scan shader info to return a bitmask of written outputs.
75bf215546Sopenharmony_ci */
76bf215546Sopenharmony_ciuint64_t
77bf215546Sopenharmony_cisvga_get_generic_outputs_mask(const struct tgsi_shader_info *info)
78bf215546Sopenharmony_ci{
79bf215546Sopenharmony_ci   unsigned i;
80bf215546Sopenharmony_ci   uint64_t mask = 0x0;
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci   for (i = 0; i < info->num_outputs; i++) {
83bf215546Sopenharmony_ci      switch (info->output_semantic_name[i]) {
84bf215546Sopenharmony_ci      case TGSI_SEMANTIC_GENERIC:
85bf215546Sopenharmony_ci         {
86bf215546Sopenharmony_ci            unsigned j = info->output_semantic_index[i];
87bf215546Sopenharmony_ci            assert(j < sizeof(mask) * 8);
88bf215546Sopenharmony_ci            mask |= ((uint64_t) 1) << j;
89bf215546Sopenharmony_ci         }
90bf215546Sopenharmony_ci         break;
91bf215546Sopenharmony_ci      case TGSI_SEMANTIC_FOG:
92bf215546Sopenharmony_ci         mask |= FOG_GENERIC_BIT;
93bf215546Sopenharmony_ci         break;
94bf215546Sopenharmony_ci      }
95bf215546Sopenharmony_ci   }
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   return mask;
98bf215546Sopenharmony_ci}
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci/**
103bf215546Sopenharmony_ci * Given a mask of used generic variables (as returned by the above functions)
104bf215546Sopenharmony_ci * fill in a table which maps those indexes to small integers.
105bf215546Sopenharmony_ci * This table is used by the remap_generic_index() function in
106bf215546Sopenharmony_ci * svga_tgsi_decl_sm30.c
107bf215546Sopenharmony_ci * Example: if generics_mask = binary(1010) it means that GENERIC[1] and
108bf215546Sopenharmony_ci * GENERIC[3] are used.  The remap_table will contain:
109bf215546Sopenharmony_ci *   table[1] = 0;
110bf215546Sopenharmony_ci *   table[3] = 1;
111bf215546Sopenharmony_ci * The remaining table entries will be filled in with the next unused
112bf215546Sopenharmony_ci * generic index (in this example, 2).
113bf215546Sopenharmony_ci */
114bf215546Sopenharmony_civoid
115bf215546Sopenharmony_cisvga_remap_generics(uint64_t generics_mask,
116bf215546Sopenharmony_ci                    int8_t remap_table[MAX_GENERIC_VARYING])
117bf215546Sopenharmony_ci{
118bf215546Sopenharmony_ci   /* Note texcoord[0] is reserved so start at 1 */
119bf215546Sopenharmony_ci   unsigned count = 1, i;
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   for (i = 0; i < MAX_GENERIC_VARYING; i++) {
122bf215546Sopenharmony_ci      remap_table[i] = -1;
123bf215546Sopenharmony_ci   }
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci   /* for each bit set in generic_mask */
126bf215546Sopenharmony_ci   while (generics_mask) {
127bf215546Sopenharmony_ci      unsigned index = ffsll(generics_mask) - 1;
128bf215546Sopenharmony_ci      remap_table[index] = count++;
129bf215546Sopenharmony_ci      generics_mask &= ~((uint64_t) 1 << index);
130bf215546Sopenharmony_ci   }
131bf215546Sopenharmony_ci}
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci/**
135bf215546Sopenharmony_ci * Use the generic remap table to map a TGSI generic varying variable
136bf215546Sopenharmony_ci * index to a small integer.  If the remapping table doesn't have a
137bf215546Sopenharmony_ci * valid value for the given index (the table entry is -1) it means
138bf215546Sopenharmony_ci * the fragment shader doesn't use that VS output.  Just allocate
139bf215546Sopenharmony_ci * the next free value in that case.  Alternately, we could cull
140bf215546Sopenharmony_ci * VS instructions that write to register, or replace the register
141bf215546Sopenharmony_ci * with a dummy temp register.
142bf215546Sopenharmony_ci * XXX TODO: we should do one of the later as it would save precious
143bf215546Sopenharmony_ci * texcoord registers.
144bf215546Sopenharmony_ci */
145bf215546Sopenharmony_ciint
146bf215546Sopenharmony_cisvga_remap_generic_index(int8_t remap_table[MAX_GENERIC_VARYING],
147bf215546Sopenharmony_ci                         int generic_index)
148bf215546Sopenharmony_ci{
149bf215546Sopenharmony_ci   assert(generic_index < MAX_GENERIC_VARYING);
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci   if (generic_index >= MAX_GENERIC_VARYING) {
152bf215546Sopenharmony_ci      /* just don't return a random/garbage value */
153bf215546Sopenharmony_ci      generic_index = MAX_GENERIC_VARYING - 1;
154bf215546Sopenharmony_ci   }
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   if (remap_table[generic_index] == -1) {
157bf215546Sopenharmony_ci      /* This is a VS output that has no matching PS input.  Find a
158bf215546Sopenharmony_ci       * free index.
159bf215546Sopenharmony_ci       */
160bf215546Sopenharmony_ci      int i, max = 0;
161bf215546Sopenharmony_ci      for (i = 0; i < MAX_GENERIC_VARYING; i++) {
162bf215546Sopenharmony_ci         max = MAX2(max, remap_table[i]);
163bf215546Sopenharmony_ci      }
164bf215546Sopenharmony_ci      remap_table[generic_index] = max + 1;
165bf215546Sopenharmony_ci   }
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   return remap_table[generic_index];
168bf215546Sopenharmony_ci}
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_cistatic const enum pipe_swizzle copy_alpha[PIPE_SWIZZLE_MAX] = {
171bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
172bf215546Sopenharmony_ci   PIPE_SWIZZLE_Y,
173bf215546Sopenharmony_ci   PIPE_SWIZZLE_Z,
174bf215546Sopenharmony_ci   PIPE_SWIZZLE_W,
175bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
176bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
177bf215546Sopenharmony_ci   PIPE_SWIZZLE_NONE
178bf215546Sopenharmony_ci};
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_cistatic const enum pipe_swizzle set_alpha[PIPE_SWIZZLE_MAX] = {
181bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
182bf215546Sopenharmony_ci   PIPE_SWIZZLE_Y,
183bf215546Sopenharmony_ci   PIPE_SWIZZLE_Z,
184bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
185bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
186bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
187bf215546Sopenharmony_ci   PIPE_SWIZZLE_NONE
188bf215546Sopenharmony_ci};
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_cistatic const enum pipe_swizzle set_000X[PIPE_SWIZZLE_MAX] = {
191bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
192bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
193bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
194bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
195bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
196bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
197bf215546Sopenharmony_ci   PIPE_SWIZZLE_NONE
198bf215546Sopenharmony_ci};
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_cistatic const enum pipe_swizzle set_XXXX[PIPE_SWIZZLE_MAX] = {
201bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
202bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
203bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
204bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
205bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
206bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
207bf215546Sopenharmony_ci   PIPE_SWIZZLE_NONE
208bf215546Sopenharmony_ci};
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_cistatic const enum pipe_swizzle set_XXX1[PIPE_SWIZZLE_MAX] = {
211bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
212bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
213bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
214bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
215bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
216bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
217bf215546Sopenharmony_ci   PIPE_SWIZZLE_NONE
218bf215546Sopenharmony_ci};
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_cistatic const enum pipe_swizzle set_XXXY[PIPE_SWIZZLE_MAX] = {
221bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
222bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
223bf215546Sopenharmony_ci   PIPE_SWIZZLE_X,
224bf215546Sopenharmony_ci   PIPE_SWIZZLE_Y,
225bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
226bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
227bf215546Sopenharmony_ci   PIPE_SWIZZLE_NONE
228bf215546Sopenharmony_ci};
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_cistatic const enum pipe_swizzle set_YYYY[PIPE_SWIZZLE_MAX] = {
231bf215546Sopenharmony_ci   PIPE_SWIZZLE_Y,
232bf215546Sopenharmony_ci   PIPE_SWIZZLE_Y,
233bf215546Sopenharmony_ci   PIPE_SWIZZLE_Y,
234bf215546Sopenharmony_ci   PIPE_SWIZZLE_Y,
235bf215546Sopenharmony_ci   PIPE_SWIZZLE_0,
236bf215546Sopenharmony_ci   PIPE_SWIZZLE_1,
237bf215546Sopenharmony_ci   PIPE_SWIZZLE_NONE
238bf215546Sopenharmony_ci};
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_cistatic VGPU10_RESOURCE_RETURN_TYPE
242bf215546Sopenharmony_civgpu10_return_type(enum pipe_format format)
243bf215546Sopenharmony_ci{
244bf215546Sopenharmony_ci   if (util_format_is_unorm(format))
245bf215546Sopenharmony_ci      return VGPU10_RETURN_TYPE_UNORM;
246bf215546Sopenharmony_ci   else if (util_format_is_snorm(format))
247bf215546Sopenharmony_ci      return VGPU10_RETURN_TYPE_SNORM;
248bf215546Sopenharmony_ci   else if (util_format_is_pure_uint(format))
249bf215546Sopenharmony_ci      return VGPU10_RETURN_TYPE_UINT;
250bf215546Sopenharmony_ci   else if (util_format_is_pure_sint(format))
251bf215546Sopenharmony_ci      return VGPU10_RETURN_TYPE_SINT;
252bf215546Sopenharmony_ci   else if (util_format_is_float(format))
253bf215546Sopenharmony_ci      return VGPU10_RETURN_TYPE_FLOAT;
254bf215546Sopenharmony_ci   else
255bf215546Sopenharmony_ci      return VGPU10_RETURN_TYPE_MAX;
256bf215546Sopenharmony_ci}
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci/**
260bf215546Sopenharmony_ci * A helper function to return TRUE if the specified format
261bf215546Sopenharmony_ci * is a supported format for sample_c instruction.
262bf215546Sopenharmony_ci */
263bf215546Sopenharmony_cistatic bool
264bf215546Sopenharmony_ciisValidSampleCFormat(enum pipe_format format)
265bf215546Sopenharmony_ci{
266bf215546Sopenharmony_ci   return util_format_is_depth_or_stencil(format);
267bf215546Sopenharmony_ci}
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci/**
271bf215546Sopenharmony_ci * Initialize the shader-neutral fields of svga_compile_key from context
272bf215546Sopenharmony_ci * state.  This is basically the texture-related state.
273bf215546Sopenharmony_ci */
274bf215546Sopenharmony_civoid
275bf215546Sopenharmony_cisvga_init_shader_key_common(const struct svga_context *svga,
276bf215546Sopenharmony_ci                            enum pipe_shader_type shader_type,
277bf215546Sopenharmony_ci                            const struct svga_shader *shader,
278bf215546Sopenharmony_ci                            struct svga_compile_key *key)
279bf215546Sopenharmony_ci{
280bf215546Sopenharmony_ci   unsigned i, idx = 0;
281bf215546Sopenharmony_ci   unsigned sampler_slots = 0;
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci   assert(shader_type < ARRAY_SIZE(svga->curr.num_sampler_views));
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   /* In case the number of samplers and sampler_views doesn't match,
286bf215546Sopenharmony_ci    * loop over the upper of the two counts.
287bf215546Sopenharmony_ci    */
288bf215546Sopenharmony_ci   key->num_textures = MAX2(svga->curr.num_sampler_views[shader_type],
289bf215546Sopenharmony_ci                            svga->curr.num_samplers[shader_type]);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   key->num_samplers = 0;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   /* Set sampler_state_mapping only if GL43 is supported and
294bf215546Sopenharmony_ci    * the number of samplers exceeds SVGA limit or the sampler state
295bf215546Sopenharmony_ci    * mapping env is set.
296bf215546Sopenharmony_ci    */
297bf215546Sopenharmony_ci   boolean sampler_state_mapping =
298bf215546Sopenharmony_ci      svga_use_sampler_state_mapping(svga, svga->curr.num_samplers[shader_type]);
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci   key->sampler_state_mapping =
301bf215546Sopenharmony_ci      key->num_textures && sampler_state_mapping ? 1 : 0;
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   for (i = 0; i < key->num_textures; i++) {
304bf215546Sopenharmony_ci      struct pipe_sampler_view *view = svga->curr.sampler_views[shader_type][i];
305bf215546Sopenharmony_ci      const struct svga_sampler_state
306bf215546Sopenharmony_ci         *sampler = svga->curr.sampler[shader_type][i];
307bf215546Sopenharmony_ci
308bf215546Sopenharmony_ci      if (view) {
309bf215546Sopenharmony_ci         assert(view->texture);
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci         enum pipe_texture_target target = view->target;
312bf215546Sopenharmony_ci         assert(target < (1 << 4)); /* texture_target:4 */
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci	 key->tex[i].target = target;
315bf215546Sopenharmony_ci	 key->tex[i].sampler_return_type = vgpu10_return_type(view->format);
316bf215546Sopenharmony_ci	 key->tex[i].sampler_view = 1;
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci         /* 1D/2D array textures with one slice and cube map array textures
319bf215546Sopenharmony_ci          * with one cube are treated as non-arrays by the SVGA3D device.
320bf215546Sopenharmony_ci          * Set the is_array flag only if we know that we have more than 1
321bf215546Sopenharmony_ci          * element.  This will be used to select shader instruction/resource
322bf215546Sopenharmony_ci          * types during shader translation.
323bf215546Sopenharmony_ci          */
324bf215546Sopenharmony_ci         switch (target) {
325bf215546Sopenharmony_ci         case PIPE_TEXTURE_1D_ARRAY:
326bf215546Sopenharmony_ci         case PIPE_TEXTURE_2D_ARRAY:
327bf215546Sopenharmony_ci            key->tex[i].is_array = view->texture->array_size > 1;
328bf215546Sopenharmony_ci            break;
329bf215546Sopenharmony_ci         case PIPE_TEXTURE_CUBE_ARRAY:
330bf215546Sopenharmony_ci            key->tex[i].is_array = view->texture->array_size > 6;
331bf215546Sopenharmony_ci            break;
332bf215546Sopenharmony_ci         default:
333bf215546Sopenharmony_ci            ; /* nothing / silence compiler warning */
334bf215546Sopenharmony_ci         }
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci         assert(view->texture->nr_samples < (1 << 5)); /* 5-bit field */
337bf215546Sopenharmony_ci         key->tex[i].num_samples = view->texture->nr_samples;
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci         const enum pipe_swizzle *swizzle_tab;
340bf215546Sopenharmony_ci         if (target == PIPE_BUFFER) {
341bf215546Sopenharmony_ci            SVGA3dSurfaceFormat svga_format;
342bf215546Sopenharmony_ci            unsigned tf_flags;
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci            assert(view->texture->target == PIPE_BUFFER);
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci            /* Apply any special swizzle mask for the view format if needed */
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci            svga_translate_texture_buffer_view_format(view->format,
349bf215546Sopenharmony_ci                                                      &svga_format, &tf_flags);
350bf215546Sopenharmony_ci            if (tf_flags & TF_000X)
351bf215546Sopenharmony_ci               swizzle_tab = set_000X;
352bf215546Sopenharmony_ci            else if (tf_flags & TF_XXXX)
353bf215546Sopenharmony_ci               swizzle_tab = set_XXXX;
354bf215546Sopenharmony_ci            else if (tf_flags & TF_XXX1)
355bf215546Sopenharmony_ci               swizzle_tab = set_XXX1;
356bf215546Sopenharmony_ci            else if (tf_flags & TF_XXXY)
357bf215546Sopenharmony_ci               swizzle_tab = set_XXXY;
358bf215546Sopenharmony_ci            else
359bf215546Sopenharmony_ci               swizzle_tab = copy_alpha;
360bf215546Sopenharmony_ci         }
361bf215546Sopenharmony_ci         else {
362bf215546Sopenharmony_ci            /* If we have a non-alpha view into an svga3d surface with an
363bf215546Sopenharmony_ci             * alpha channel, then explicitly set the alpha channel to 1
364bf215546Sopenharmony_ci             * when sampling. Note that we need to check the
365bf215546Sopenharmony_ci             * actual device format to cover also imported surface cases.
366bf215546Sopenharmony_ci             */
367bf215546Sopenharmony_ci            swizzle_tab =
368bf215546Sopenharmony_ci               (!util_format_has_alpha(view->format) &&
369bf215546Sopenharmony_ci                svga_texture_device_format_has_alpha(view->texture)) ?
370bf215546Sopenharmony_ci                set_alpha : copy_alpha;
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci            if (view->texture->format == PIPE_FORMAT_DXT1_RGB ||
373bf215546Sopenharmony_ci                view->texture->format == PIPE_FORMAT_DXT1_SRGB)
374bf215546Sopenharmony_ci               swizzle_tab = set_alpha;
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci            if (view->format == PIPE_FORMAT_X24S8_UINT ||
377bf215546Sopenharmony_ci                view->format == PIPE_FORMAT_X32_S8X24_UINT)
378bf215546Sopenharmony_ci               swizzle_tab = set_YYYY;
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci            /* Save the compare function as we need to handle
381bf215546Sopenharmony_ci             * depth compare in the shader.
382bf215546Sopenharmony_ci             */
383bf215546Sopenharmony_ci            key->tex[i].compare_mode = sampler->compare_mode;
384bf215546Sopenharmony_ci            key->tex[i].compare_func = sampler->compare_func;
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci            /* Set the compare_in_shader bit if the view format
387bf215546Sopenharmony_ci             * is not a supported format for shadow compare.
388bf215546Sopenharmony_ci             * In this case, we'll do the comparison in the shader.
389bf215546Sopenharmony_ci             */
390bf215546Sopenharmony_ci            if ((sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) &&
391bf215546Sopenharmony_ci                !isValidSampleCFormat(view->format)) {
392bf215546Sopenharmony_ci               key->tex[i].compare_in_shader = TRUE;
393bf215546Sopenharmony_ci            }
394bf215546Sopenharmony_ci         }
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci         key->tex[i].swizzle_r = swizzle_tab[view->swizzle_r];
397bf215546Sopenharmony_ci         key->tex[i].swizzle_g = swizzle_tab[view->swizzle_g];
398bf215546Sopenharmony_ci         key->tex[i].swizzle_b = swizzle_tab[view->swizzle_b];
399bf215546Sopenharmony_ci         key->tex[i].swizzle_a = swizzle_tab[view->swizzle_a];
400bf215546Sopenharmony_ci      }
401bf215546Sopenharmony_ci      else {
402bf215546Sopenharmony_ci	 key->tex[i].sampler_view = 0;
403bf215546Sopenharmony_ci      }
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci      if (sampler) {
406bf215546Sopenharmony_ci         if (!sampler->normalized_coords) {
407bf215546Sopenharmony_ci            if (view) {
408bf215546Sopenharmony_ci               assert(idx < (1 << 5));  /* width_height_idx:5 bitfield */
409bf215546Sopenharmony_ci               key->tex[i].width_height_idx = idx++;
410bf215546Sopenharmony_ci	    }
411bf215546Sopenharmony_ci            key->tex[i].unnormalized = TRUE;
412bf215546Sopenharmony_ci            ++key->num_unnormalized_coords;
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci            if (sampler->magfilter == SVGA3D_TEX_FILTER_NEAREST ||
415bf215546Sopenharmony_ci                sampler->minfilter == SVGA3D_TEX_FILTER_NEAREST) {
416bf215546Sopenharmony_ci                key->tex[i].texel_bias = TRUE;
417bf215546Sopenharmony_ci            }
418bf215546Sopenharmony_ci         }
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci         if (!sampler_state_mapping) {
421bf215546Sopenharmony_ci            /* Use the same index if sampler state mapping is not supported */
422bf215546Sopenharmony_ci            key->tex[i].sampler_index = i;
423bf215546Sopenharmony_ci            key->num_samplers = i + 1;
424bf215546Sopenharmony_ci         }
425bf215546Sopenharmony_ci         else {
426bf215546Sopenharmony_ci
427bf215546Sopenharmony_ci            /* The current samplers list can have redundant entries.
428bf215546Sopenharmony_ci             * In order to allow the number of bound samplers within the
429bf215546Sopenharmony_ci             * max limit supported by SVGA, we'll recreate the list with
430bf215546Sopenharmony_ci             * unique sampler state objects only.
431bf215546Sopenharmony_ci             */
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci            /* Check to see if this sampler is already on the list.
434bf215546Sopenharmony_ci             * If so, set the sampler index of this sampler to the
435bf215546Sopenharmony_ci             * same sampler index.
436bf215546Sopenharmony_ci             */
437bf215546Sopenharmony_ci            for (unsigned j = 0; j <= i; j++) {
438bf215546Sopenharmony_ci               if (svga->curr.sampler[shader_type][j] == sampler) {
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci                  if (!(sampler_slots & (1 << j))) {
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci                     /* if this sampler is not added to the new list yet,
443bf215546Sopenharmony_ci                      * set its sampler index to the next sampler index,
444bf215546Sopenharmony_ci                      * increment the sampler count, and mark this
445bf215546Sopenharmony_ci                      * sampler as added to the list.
446bf215546Sopenharmony_ci                      */
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci                     unsigned next_index =
449bf215546Sopenharmony_ci                        MIN2(key->num_samplers, SVGA3D_DX_MAX_SAMPLERS-1);
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci                     key->tex[i].sampler_index = next_index;
452bf215546Sopenharmony_ci                     key->num_samplers = next_index + 1;
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci                     if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
455bf215546Sopenharmony_ci                        /* reserve one slot for the alternate sampler */
456bf215546Sopenharmony_ci                        key->num_samplers++;
457bf215546Sopenharmony_ci                     }
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci                     sampler_slots |= (1 << j);
460bf215546Sopenharmony_ci                  }
461bf215546Sopenharmony_ci                  else {
462bf215546Sopenharmony_ci                     key->tex[i].sampler_index = key->tex[j].sampler_index;
463bf215546Sopenharmony_ci                  }
464bf215546Sopenharmony_ci                  break;
465bf215546Sopenharmony_ci               }
466bf215546Sopenharmony_ci            }
467bf215546Sopenharmony_ci         }
468bf215546Sopenharmony_ci      }
469bf215546Sopenharmony_ci   }
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci   if (svga_have_gl43(svga)) {
472bf215546Sopenharmony_ci      if (shader->info.uses_images || shader->info.uses_hw_atomic ||
473bf215546Sopenharmony_ci          shader->info.uses_shader_buffers) {
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci         /* Save the uavSpliceIndex which is the index used for the first uav
476bf215546Sopenharmony_ci          * in the draw pipeline. For compute, uavSpliceIndex is always 0.
477bf215546Sopenharmony_ci          */
478bf215546Sopenharmony_ci         if (shader_type != PIPE_SHADER_COMPUTE)
479bf215546Sopenharmony_ci            key->uav_splice_index = svga->state.hw_draw.uavSpliceIndex;
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_ci         unsigned uav_splice_index = key->uav_splice_index;
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci         /* Also get the texture data type to be used in the uav declaration */
484bf215546Sopenharmony_ci         const struct svga_image_view *cur_image_view =
485bf215546Sopenharmony_ci            &svga->curr.image_views[shader_type][0];
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci         for (unsigned i = 0; i < ARRAY_SIZE(svga->curr.image_views[shader_type]);
488bf215546Sopenharmony_ci              i++, cur_image_view++) {
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci            struct pipe_resource *resource = cur_image_view->desc.resource;
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci            if (resource) {
493bf215546Sopenharmony_ci               key->images[i].return_type =
494bf215546Sopenharmony_ci                  svga_get_texture_datatype(cur_image_view->desc.format);
495bf215546Sopenharmony_ci
496bf215546Sopenharmony_ci               key->images[i].is_array = resource->array_size > 1;
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci               /* Save the image resource target in the shader key because
499bf215546Sopenharmony_ci                * for single layer image view, the resource target in the
500bf215546Sopenharmony_ci                * tgsi shader is changed to a different texture target.
501bf215546Sopenharmony_ci                */
502bf215546Sopenharmony_ci               key->images[i].resource_target = resource->target;
503bf215546Sopenharmony_ci               if (resource->target == PIPE_TEXTURE_3D ||
504bf215546Sopenharmony_ci                   resource->target == PIPE_TEXTURE_1D_ARRAY ||
505bf215546Sopenharmony_ci                   resource->target == PIPE_TEXTURE_2D_ARRAY ||
506bf215546Sopenharmony_ci                   resource->target == PIPE_TEXTURE_CUBE ||
507bf215546Sopenharmony_ci                   resource->target == PIPE_TEXTURE_CUBE_ARRAY) {
508bf215546Sopenharmony_ci                  key->images[i].is_single_layer =
509bf215546Sopenharmony_ci                     cur_image_view->desc.u.tex.first_layer ==
510bf215546Sopenharmony_ci                     cur_image_view->desc.u.tex.last_layer;
511bf215546Sopenharmony_ci               }
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci               key->images[i].uav_index = cur_image_view->uav_index + uav_splice_index;
514bf215546Sopenharmony_ci            }
515bf215546Sopenharmony_ci            else
516bf215546Sopenharmony_ci               key->images[i].uav_index = SVGA3D_INVALID_ID;
517bf215546Sopenharmony_ci         }
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci         const struct svga_shader_buffer *cur_sbuf =
520bf215546Sopenharmony_ci            &svga->curr.shader_buffers[shader_type][0];
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ci         for (unsigned i = 0; i < ARRAY_SIZE(svga->curr.shader_buffers[shader_type]);
523bf215546Sopenharmony_ci              i++, cur_sbuf++) {
524bf215546Sopenharmony_ci
525bf215546Sopenharmony_ci            if (cur_sbuf->resource)
526bf215546Sopenharmony_ci               key->shader_buf_uav_index[i] = cur_sbuf->uav_index + uav_splice_index;
527bf215546Sopenharmony_ci            else
528bf215546Sopenharmony_ci               key->shader_buf_uav_index[i] = SVGA3D_INVALID_ID;
529bf215546Sopenharmony_ci         }
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci         const struct svga_shader_buffer *cur_buf = &svga->curr.atomic_buffers[0];
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci         for (unsigned i = 0; i < ARRAY_SIZE(svga->curr.atomic_buffers);
534bf215546Sopenharmony_ci              i++, cur_buf++) {
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci            if (cur_buf->resource)
537bf215546Sopenharmony_ci               key->atomic_buf_uav_index[i] = cur_buf->uav_index + uav_splice_index;
538bf215546Sopenharmony_ci            else
539bf215546Sopenharmony_ci               key->atomic_buf_uav_index[i] = SVGA3D_INVALID_ID;
540bf215546Sopenharmony_ci         }
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci         key->image_size_used = shader->info.uses_image_size;
543bf215546Sopenharmony_ci      }
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci      /* Save info about which constant buffers are to be viewed
546bf215546Sopenharmony_ci       * as raw buffers in the shader key.
547bf215546Sopenharmony_ci       */
548bf215546Sopenharmony_ci      if (shader->info.const_buffers_declared &
549bf215546Sopenharmony_ci          svga->state.raw_constbufs[shader_type]) {
550bf215546Sopenharmony_ci         key->raw_buffers = svga->state.raw_constbufs[shader_type];
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci         /* beginning index for srv for raw buffers */
553bf215546Sopenharmony_ci         key->srv_raw_buf_index = PIPE_MAX_SAMPLERS;
554bf215546Sopenharmony_ci      }
555bf215546Sopenharmony_ci   }
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci   key->clamp_vertex_color = svga->curr.rast ?
558bf215546Sopenharmony_ci                             svga->curr.rast->templ.clamp_vertex_color : 0;
559bf215546Sopenharmony_ci}
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ci/** Search for a compiled shader variant with the same compile key */
563bf215546Sopenharmony_cistruct svga_shader_variant *
564bf215546Sopenharmony_cisvga_search_shader_key(const struct svga_shader *shader,
565bf215546Sopenharmony_ci                       const struct svga_compile_key *key)
566bf215546Sopenharmony_ci{
567bf215546Sopenharmony_ci   struct svga_shader_variant *variant = shader->variants;
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci   assert(key);
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci   for ( ; variant; variant = variant->next) {
572bf215546Sopenharmony_ci      if (svga_compile_keys_equal(key, &variant->key))
573bf215546Sopenharmony_ci         return variant;
574bf215546Sopenharmony_ci   }
575bf215546Sopenharmony_ci   return NULL;
576bf215546Sopenharmony_ci}
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci/** Search for a shader with the same token key */
579bf215546Sopenharmony_cistruct svga_shader *
580bf215546Sopenharmony_cisvga_search_shader_token_key(struct svga_shader *pshader,
581bf215546Sopenharmony_ci                             const struct svga_token_key *key)
582bf215546Sopenharmony_ci{
583bf215546Sopenharmony_ci   struct svga_shader *shader = pshader;
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   assert(key);
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci   for ( ; shader; shader = shader->next) {
588bf215546Sopenharmony_ci      if (memcmp(key, &shader->token_key, sizeof(struct svga_token_key)) == 0)
589bf215546Sopenharmony_ci         return shader;
590bf215546Sopenharmony_ci   }
591bf215546Sopenharmony_ci   return NULL;
592bf215546Sopenharmony_ci}
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_ci/**
595bf215546Sopenharmony_ci * Helper function to define a gb shader for non-vgpu10 device
596bf215546Sopenharmony_ci */
597bf215546Sopenharmony_cistatic enum pipe_error
598bf215546Sopenharmony_cidefine_gb_shader_vgpu9(struct svga_context *svga,
599bf215546Sopenharmony_ci                       struct svga_shader_variant *variant,
600bf215546Sopenharmony_ci                       unsigned codeLen)
601bf215546Sopenharmony_ci{
602bf215546Sopenharmony_ci   struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
603bf215546Sopenharmony_ci   enum pipe_error ret;
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   /**
606bf215546Sopenharmony_ci    * Create gb memory for the shader and upload the shader code.
607bf215546Sopenharmony_ci    * Kernel module will allocate an id for the shader and issue
608bf215546Sopenharmony_ci    * the DefineGBShader command.
609bf215546Sopenharmony_ci    */
610bf215546Sopenharmony_ci   variant->gb_shader = sws->shader_create(sws, variant->type,
611bf215546Sopenharmony_ci                                           variant->tokens, codeLen);
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ci   svga->hud.shader_mem_used += codeLen;
614bf215546Sopenharmony_ci
615bf215546Sopenharmony_ci   if (!variant->gb_shader)
616bf215546Sopenharmony_ci      return PIPE_ERROR_OUT_OF_MEMORY;
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci   ret = SVGA3D_BindGBShader(svga->swc, variant->gb_shader);
619bf215546Sopenharmony_ci
620bf215546Sopenharmony_ci   return ret;
621bf215546Sopenharmony_ci}
622bf215546Sopenharmony_ci
623bf215546Sopenharmony_ci/**
624bf215546Sopenharmony_ci * Helper function to define a gb shader for vgpu10 device
625bf215546Sopenharmony_ci */
626bf215546Sopenharmony_cistatic enum pipe_error
627bf215546Sopenharmony_cidefine_gb_shader_vgpu10(struct svga_context *svga,
628bf215546Sopenharmony_ci                        struct svga_shader_variant *variant,
629bf215546Sopenharmony_ci                        unsigned codeLen)
630bf215546Sopenharmony_ci{
631bf215546Sopenharmony_ci   struct svga_winsys_context *swc = svga->swc;
632bf215546Sopenharmony_ci   enum pipe_error ret;
633bf215546Sopenharmony_ci   unsigned len = codeLen + variant->signatureLen;
634bf215546Sopenharmony_ci
635bf215546Sopenharmony_ci   /**
636bf215546Sopenharmony_ci    * Shaders in VGPU10 enabled device reside in the device COTable.
637bf215546Sopenharmony_ci    * SVGA driver will allocate an integer ID for the shader and
638bf215546Sopenharmony_ci    * issue DXDefineShader and DXBindShader commands.
639bf215546Sopenharmony_ci    */
640bf215546Sopenharmony_ci   variant->id = util_bitmask_add(svga->shader_id_bm);
641bf215546Sopenharmony_ci   if (variant->id == UTIL_BITMASK_INVALID_INDEX) {
642bf215546Sopenharmony_ci      return PIPE_ERROR_OUT_OF_MEMORY;
643bf215546Sopenharmony_ci   }
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci   /* Create gb memory for the shader and upload the shader code */
646bf215546Sopenharmony_ci   variant->gb_shader = swc->shader_create(swc,
647bf215546Sopenharmony_ci                                           variant->id, variant->type,
648bf215546Sopenharmony_ci                                           variant->tokens, codeLen,
649bf215546Sopenharmony_ci                                           variant->signature,
650bf215546Sopenharmony_ci                                           variant->signatureLen);
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_ci   svga->hud.shader_mem_used += len;
653bf215546Sopenharmony_ci
654bf215546Sopenharmony_ci   if (!variant->gb_shader) {
655bf215546Sopenharmony_ci      /* Free the shader ID */
656bf215546Sopenharmony_ci      assert(variant->id != UTIL_BITMASK_INVALID_INDEX);
657bf215546Sopenharmony_ci      goto fail_no_allocation;
658bf215546Sopenharmony_ci   }
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci   /**
661bf215546Sopenharmony_ci    * Since we don't want to do any flush within state emission to avoid
662bf215546Sopenharmony_ci    * partial state in a command buffer, it's important to make sure that
663bf215546Sopenharmony_ci    * there is enough room to send both the DXDefineShader & DXBindShader
664bf215546Sopenharmony_ci    * commands in the same command buffer. So let's send both
665bf215546Sopenharmony_ci    * commands in one command reservation. If it fails, we'll undo
666bf215546Sopenharmony_ci    * the shader creation and return an error.
667bf215546Sopenharmony_ci    */
668bf215546Sopenharmony_ci   ret = SVGA3D_vgpu10_DefineAndBindShader(swc, variant->gb_shader,
669bf215546Sopenharmony_ci                                           variant->id, variant->type,
670bf215546Sopenharmony_ci                                           len);
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci   if (ret != PIPE_OK)
673bf215546Sopenharmony_ci      goto fail;
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_ci   return PIPE_OK;
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_cifail:
678bf215546Sopenharmony_ci   swc->shader_destroy(swc, variant->gb_shader);
679bf215546Sopenharmony_ci   variant->gb_shader = NULL;
680bf215546Sopenharmony_ci
681bf215546Sopenharmony_cifail_no_allocation:
682bf215546Sopenharmony_ci   util_bitmask_clear(svga->shader_id_bm, variant->id);
683bf215546Sopenharmony_ci   variant->id = UTIL_BITMASK_INVALID_INDEX;
684bf215546Sopenharmony_ci
685bf215546Sopenharmony_ci   return PIPE_ERROR_OUT_OF_MEMORY;
686bf215546Sopenharmony_ci}
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci/**
689bf215546Sopenharmony_ci * Issue the SVGA3D commands to define a new shader.
690bf215546Sopenharmony_ci * \param variant  contains the shader tokens, etc.  The result->id field will
691bf215546Sopenharmony_ci *                 be set here.
692bf215546Sopenharmony_ci */
693bf215546Sopenharmony_cienum pipe_error
694bf215546Sopenharmony_cisvga_define_shader(struct svga_context *svga,
695bf215546Sopenharmony_ci                   struct svga_shader_variant *variant)
696bf215546Sopenharmony_ci{
697bf215546Sopenharmony_ci   unsigned codeLen = variant->nr_tokens * sizeof(variant->tokens[0]);
698bf215546Sopenharmony_ci   enum pipe_error ret;
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_ci   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DEFINESHADER);
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ci   variant->id = UTIL_BITMASK_INVALID_INDEX;
703bf215546Sopenharmony_ci
704bf215546Sopenharmony_ci   if (svga_have_gb_objects(svga)) {
705bf215546Sopenharmony_ci      if (svga_have_vgpu10(svga))
706bf215546Sopenharmony_ci         ret = define_gb_shader_vgpu10(svga, variant, codeLen);
707bf215546Sopenharmony_ci      else
708bf215546Sopenharmony_ci         ret = define_gb_shader_vgpu9(svga, variant, codeLen);
709bf215546Sopenharmony_ci   }
710bf215546Sopenharmony_ci   else {
711bf215546Sopenharmony_ci      /* Allocate an integer ID for the shader */
712bf215546Sopenharmony_ci      variant->id = util_bitmask_add(svga->shader_id_bm);
713bf215546Sopenharmony_ci      if (variant->id == UTIL_BITMASK_INVALID_INDEX) {
714bf215546Sopenharmony_ci         ret = PIPE_ERROR_OUT_OF_MEMORY;
715bf215546Sopenharmony_ci         goto done;
716bf215546Sopenharmony_ci      }
717bf215546Sopenharmony_ci
718bf215546Sopenharmony_ci      /* Issue SVGA3D device command to define the shader */
719bf215546Sopenharmony_ci      ret = SVGA3D_DefineShader(svga->swc,
720bf215546Sopenharmony_ci                                variant->id,
721bf215546Sopenharmony_ci                                variant->type,
722bf215546Sopenharmony_ci                                variant->tokens,
723bf215546Sopenharmony_ci                                codeLen);
724bf215546Sopenharmony_ci      if (ret != PIPE_OK) {
725bf215546Sopenharmony_ci         /* free the ID */
726bf215546Sopenharmony_ci         assert(variant->id != UTIL_BITMASK_INVALID_INDEX);
727bf215546Sopenharmony_ci         util_bitmask_clear(svga->shader_id_bm, variant->id);
728bf215546Sopenharmony_ci         variant->id = UTIL_BITMASK_INVALID_INDEX;
729bf215546Sopenharmony_ci      }
730bf215546Sopenharmony_ci   }
731bf215546Sopenharmony_ci
732bf215546Sopenharmony_cidone:
733bf215546Sopenharmony_ci   SVGA_STATS_TIME_POP(svga_sws(svga));
734bf215546Sopenharmony_ci   return ret;
735bf215546Sopenharmony_ci}
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci
738bf215546Sopenharmony_ci/**
739bf215546Sopenharmony_ci * Issue the SVGA3D commands to set/bind a shader.
740bf215546Sopenharmony_ci * \param result  the shader to bind.
741bf215546Sopenharmony_ci */
742bf215546Sopenharmony_cienum pipe_error
743bf215546Sopenharmony_cisvga_set_shader(struct svga_context *svga,
744bf215546Sopenharmony_ci                SVGA3dShaderType type,
745bf215546Sopenharmony_ci                struct svga_shader_variant *variant)
746bf215546Sopenharmony_ci{
747bf215546Sopenharmony_ci   enum pipe_error ret;
748bf215546Sopenharmony_ci   unsigned id = variant ? variant->id : SVGA3D_INVALID_ID;
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_ci   assert(type == SVGA3D_SHADERTYPE_VS ||
751bf215546Sopenharmony_ci          type == SVGA3D_SHADERTYPE_GS ||
752bf215546Sopenharmony_ci          type == SVGA3D_SHADERTYPE_PS ||
753bf215546Sopenharmony_ci          type == SVGA3D_SHADERTYPE_HS ||
754bf215546Sopenharmony_ci          type == SVGA3D_SHADERTYPE_DS ||
755bf215546Sopenharmony_ci          type == SVGA3D_SHADERTYPE_CS);
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ci   if (svga_have_gb_objects(svga)) {
758bf215546Sopenharmony_ci      struct svga_winsys_gb_shader *gbshader =
759bf215546Sopenharmony_ci         variant ? variant->gb_shader : NULL;
760bf215546Sopenharmony_ci
761bf215546Sopenharmony_ci      if (svga_have_vgpu10(svga))
762bf215546Sopenharmony_ci         ret = SVGA3D_vgpu10_SetShader(svga->swc, type, gbshader, id);
763bf215546Sopenharmony_ci      else
764bf215546Sopenharmony_ci         ret = SVGA3D_SetGBShader(svga->swc, type, gbshader);
765bf215546Sopenharmony_ci   }
766bf215546Sopenharmony_ci   else {
767bf215546Sopenharmony_ci      ret = SVGA3D_SetShader(svga->swc, type, id);
768bf215546Sopenharmony_ci   }
769bf215546Sopenharmony_ci
770bf215546Sopenharmony_ci   return ret;
771bf215546Sopenharmony_ci}
772bf215546Sopenharmony_ci
773bf215546Sopenharmony_ci
774bf215546Sopenharmony_cistruct svga_shader_variant *
775bf215546Sopenharmony_cisvga_new_shader_variant(struct svga_context *svga, enum pipe_shader_type type)
776bf215546Sopenharmony_ci{
777bf215546Sopenharmony_ci   struct svga_shader_variant *variant;
778bf215546Sopenharmony_ci
779bf215546Sopenharmony_ci   switch (type) {
780bf215546Sopenharmony_ci   case PIPE_SHADER_FRAGMENT:
781bf215546Sopenharmony_ci      variant = CALLOC(1, sizeof(struct svga_fs_variant));
782bf215546Sopenharmony_ci      break;
783bf215546Sopenharmony_ci   case PIPE_SHADER_GEOMETRY:
784bf215546Sopenharmony_ci      variant = CALLOC(1, sizeof(struct svga_gs_variant));
785bf215546Sopenharmony_ci      break;
786bf215546Sopenharmony_ci   case PIPE_SHADER_VERTEX:
787bf215546Sopenharmony_ci      variant = CALLOC(1, sizeof(struct svga_vs_variant));
788bf215546Sopenharmony_ci      break;
789bf215546Sopenharmony_ci   case PIPE_SHADER_TESS_EVAL:
790bf215546Sopenharmony_ci      variant = CALLOC(1, sizeof(struct svga_tes_variant));
791bf215546Sopenharmony_ci      break;
792bf215546Sopenharmony_ci   case PIPE_SHADER_TESS_CTRL:
793bf215546Sopenharmony_ci      variant = CALLOC(1, sizeof(struct svga_tcs_variant));
794bf215546Sopenharmony_ci      break;
795bf215546Sopenharmony_ci   case PIPE_SHADER_COMPUTE:
796bf215546Sopenharmony_ci      variant = CALLOC(1, sizeof(struct svga_cs_variant));
797bf215546Sopenharmony_ci      break;
798bf215546Sopenharmony_ci   default:
799bf215546Sopenharmony_ci      return NULL;
800bf215546Sopenharmony_ci   }
801bf215546Sopenharmony_ci
802bf215546Sopenharmony_ci   if (variant) {
803bf215546Sopenharmony_ci      variant->type = svga_shader_type(type);
804bf215546Sopenharmony_ci      svga->hud.num_shaders++;
805bf215546Sopenharmony_ci   }
806bf215546Sopenharmony_ci   return variant;
807bf215546Sopenharmony_ci}
808bf215546Sopenharmony_ci
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_civoid
811bf215546Sopenharmony_cisvga_destroy_shader_variant(struct svga_context *svga,
812bf215546Sopenharmony_ci                            struct svga_shader_variant *variant)
813bf215546Sopenharmony_ci{
814bf215546Sopenharmony_ci   if (svga_have_gb_objects(svga) && variant->gb_shader) {
815bf215546Sopenharmony_ci      if (svga_have_vgpu10(svga)) {
816bf215546Sopenharmony_ci         struct svga_winsys_context *swc = svga->swc;
817bf215546Sopenharmony_ci         swc->shader_destroy(swc, variant->gb_shader);
818bf215546Sopenharmony_ci         SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyShader(svga->swc, variant->id));
819bf215546Sopenharmony_ci         util_bitmask_clear(svga->shader_id_bm, variant->id);
820bf215546Sopenharmony_ci      }
821bf215546Sopenharmony_ci      else {
822bf215546Sopenharmony_ci         struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
823bf215546Sopenharmony_ci         sws->shader_destroy(sws, variant->gb_shader);
824bf215546Sopenharmony_ci      }
825bf215546Sopenharmony_ci      variant->gb_shader = NULL;
826bf215546Sopenharmony_ci   }
827bf215546Sopenharmony_ci   else {
828bf215546Sopenharmony_ci      if (variant->id != UTIL_BITMASK_INVALID_INDEX) {
829bf215546Sopenharmony_ci         SVGA_RETRY(svga, SVGA3D_DestroyShader(svga->swc, variant->id,
830bf215546Sopenharmony_ci                                               variant->type));
831bf215546Sopenharmony_ci         util_bitmask_clear(svga->shader_id_bm, variant->id);
832bf215546Sopenharmony_ci      }
833bf215546Sopenharmony_ci   }
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci   FREE(variant->signature);
836bf215546Sopenharmony_ci   FREE((unsigned *)variant->tokens);
837bf215546Sopenharmony_ci   FREE(variant);
838bf215546Sopenharmony_ci
839bf215546Sopenharmony_ci   svga->hud.num_shaders--;
840bf215546Sopenharmony_ci}
841bf215546Sopenharmony_ci
842bf215546Sopenharmony_ci/*
843bf215546Sopenharmony_ci * Rebind shaders.
844bf215546Sopenharmony_ci * Called at the beginning of every new command buffer to ensure that
845bf215546Sopenharmony_ci * shaders are properly paged-in. Instead of sending the SetShader
846bf215546Sopenharmony_ci * command, this function sends a private allocation command to
847bf215546Sopenharmony_ci * page in a shader. This avoids emitting redundant state to the device
848bf215546Sopenharmony_ci * just to page in a resource.
849bf215546Sopenharmony_ci */
850bf215546Sopenharmony_cienum pipe_error
851bf215546Sopenharmony_cisvga_rebind_shaders(struct svga_context *svga)
852bf215546Sopenharmony_ci{
853bf215546Sopenharmony_ci   struct svga_winsys_context *swc = svga->swc;
854bf215546Sopenharmony_ci   struct svga_hw_draw_state *hw = &svga->state.hw_draw;
855bf215546Sopenharmony_ci   enum pipe_error ret;
856bf215546Sopenharmony_ci
857bf215546Sopenharmony_ci   assert(svga_have_vgpu10(svga));
858bf215546Sopenharmony_ci
859bf215546Sopenharmony_ci   /**
860bf215546Sopenharmony_ci    * If the underlying winsys layer does not need resource rebinding,
861bf215546Sopenharmony_ci    * just clear the rebind flags and return.
862bf215546Sopenharmony_ci    */
863bf215546Sopenharmony_ci   if (swc->resource_rebind == NULL) {
864bf215546Sopenharmony_ci      svga->rebind.flags.vs = 0;
865bf215546Sopenharmony_ci      svga->rebind.flags.gs = 0;
866bf215546Sopenharmony_ci      svga->rebind.flags.fs = 0;
867bf215546Sopenharmony_ci      svga->rebind.flags.tcs = 0;
868bf215546Sopenharmony_ci      svga->rebind.flags.tes = 0;
869bf215546Sopenharmony_ci
870bf215546Sopenharmony_ci      return PIPE_OK;
871bf215546Sopenharmony_ci   }
872bf215546Sopenharmony_ci
873bf215546Sopenharmony_ci   if (svga->rebind.flags.vs && hw->vs && hw->vs->gb_shader) {
874bf215546Sopenharmony_ci      ret = swc->resource_rebind(swc, NULL, hw->vs->gb_shader, SVGA_RELOC_READ);
875bf215546Sopenharmony_ci      if (ret != PIPE_OK)
876bf215546Sopenharmony_ci         return ret;
877bf215546Sopenharmony_ci   }
878bf215546Sopenharmony_ci   svga->rebind.flags.vs = 0;
879bf215546Sopenharmony_ci
880bf215546Sopenharmony_ci   if (svga->rebind.flags.gs && hw->gs && hw->gs->gb_shader) {
881bf215546Sopenharmony_ci      ret = swc->resource_rebind(swc, NULL, hw->gs->gb_shader, SVGA_RELOC_READ);
882bf215546Sopenharmony_ci      if (ret != PIPE_OK)
883bf215546Sopenharmony_ci         return ret;
884bf215546Sopenharmony_ci   }
885bf215546Sopenharmony_ci   svga->rebind.flags.gs = 0;
886bf215546Sopenharmony_ci
887bf215546Sopenharmony_ci   if (svga->rebind.flags.fs && hw->fs && hw->fs->gb_shader) {
888bf215546Sopenharmony_ci      ret = swc->resource_rebind(swc, NULL, hw->fs->gb_shader, SVGA_RELOC_READ);
889bf215546Sopenharmony_ci      if (ret != PIPE_OK)
890bf215546Sopenharmony_ci         return ret;
891bf215546Sopenharmony_ci   }
892bf215546Sopenharmony_ci   svga->rebind.flags.fs = 0;
893bf215546Sopenharmony_ci
894bf215546Sopenharmony_ci   if (svga->rebind.flags.tcs && hw->tcs && hw->tcs->gb_shader) {
895bf215546Sopenharmony_ci      ret = swc->resource_rebind(swc, NULL, hw->tcs->gb_shader, SVGA_RELOC_READ);
896bf215546Sopenharmony_ci      if (ret != PIPE_OK)
897bf215546Sopenharmony_ci         return ret;
898bf215546Sopenharmony_ci   }
899bf215546Sopenharmony_ci   svga->rebind.flags.tcs = 0;
900bf215546Sopenharmony_ci
901bf215546Sopenharmony_ci   if (svga->rebind.flags.tes && hw->tes && hw->tes->gb_shader) {
902bf215546Sopenharmony_ci      ret = swc->resource_rebind(swc, NULL, hw->tes->gb_shader, SVGA_RELOC_READ);
903bf215546Sopenharmony_ci      if (ret != PIPE_OK)
904bf215546Sopenharmony_ci         return ret;
905bf215546Sopenharmony_ci   }
906bf215546Sopenharmony_ci   svga->rebind.flags.tes = 0;
907bf215546Sopenharmony_ci
908bf215546Sopenharmony_ci   return PIPE_OK;
909bf215546Sopenharmony_ci}
910bf215546Sopenharmony_ci
911bf215546Sopenharmony_ci
912bf215546Sopenharmony_ci/**
913bf215546Sopenharmony_ci * Helper function to create a shader object.
914bf215546Sopenharmony_ci */
915bf215546Sopenharmony_cistruct svga_shader *
916bf215546Sopenharmony_cisvga_create_shader(struct pipe_context *pipe,
917bf215546Sopenharmony_ci                   const struct pipe_shader_state *templ,
918bf215546Sopenharmony_ci                   enum pipe_shader_type stage,
919bf215546Sopenharmony_ci                   unsigned shader_structlen)
920bf215546Sopenharmony_ci{
921bf215546Sopenharmony_ci   struct svga_context *svga = svga_context(pipe);
922bf215546Sopenharmony_ci   struct svga_shader *shader = CALLOC(1, shader_structlen);
923bf215546Sopenharmony_ci
924bf215546Sopenharmony_ci   if (shader == NULL)
925bf215546Sopenharmony_ci      return NULL;
926bf215546Sopenharmony_ci
927bf215546Sopenharmony_ci   shader->id = svga->debug.shader_id++;
928bf215546Sopenharmony_ci   shader->type = templ->type;
929bf215546Sopenharmony_ci   shader->stage = stage;
930bf215546Sopenharmony_ci
931bf215546Sopenharmony_ci   shader->tokens = pipe_shader_state_to_tgsi_tokens(pipe->screen, templ);
932bf215546Sopenharmony_ci
933bf215546Sopenharmony_ci   if (shader->type == PIPE_SHADER_IR_TGSI) {
934bf215546Sopenharmony_ci      /* Collect basic info of the shader */
935bf215546Sopenharmony_ci      svga_tgsi_scan_shader(shader);
936bf215546Sopenharmony_ci   }
937bf215546Sopenharmony_ci   else {
938bf215546Sopenharmony_ci      debug_printf("Unexpected nir shader\n");
939bf215546Sopenharmony_ci      assert(0);
940bf215546Sopenharmony_ci   }
941bf215546Sopenharmony_ci
942bf215546Sopenharmony_ci   /* check for any stream output declarations */
943bf215546Sopenharmony_ci   if (templ->stream_output.num_outputs) {
944bf215546Sopenharmony_ci      shader->stream_output = svga_create_stream_output(svga, shader,
945bf215546Sopenharmony_ci                                                        &templ->stream_output);
946bf215546Sopenharmony_ci   }
947bf215546Sopenharmony_ci
948bf215546Sopenharmony_ci   return shader;
949bf215546Sopenharmony_ci}
950bf215546Sopenharmony_ci
951bf215546Sopenharmony_ci
952bf215546Sopenharmony_ci/**
953bf215546Sopenharmony_ci * Helper function to compile a shader.
954bf215546Sopenharmony_ci * Depending on the shader IR type, it calls the corresponding
955bf215546Sopenharmony_ci * compile shader function.
956bf215546Sopenharmony_ci */
957bf215546Sopenharmony_cienum pipe_error
958bf215546Sopenharmony_cisvga_compile_shader(struct svga_context *svga,
959bf215546Sopenharmony_ci                    struct svga_shader *shader,
960bf215546Sopenharmony_ci                    const struct svga_compile_key *key,
961bf215546Sopenharmony_ci                    struct svga_shader_variant **out_variant)
962bf215546Sopenharmony_ci{
963bf215546Sopenharmony_ci   struct svga_shader_variant *variant = NULL;
964bf215546Sopenharmony_ci   enum pipe_error ret = PIPE_ERROR;
965bf215546Sopenharmony_ci
966bf215546Sopenharmony_ci   if (shader->type == PIPE_SHADER_IR_TGSI) {
967bf215546Sopenharmony_ci      variant = svga_tgsi_compile_shader(svga, shader, key);
968bf215546Sopenharmony_ci   } else {
969bf215546Sopenharmony_ci      debug_printf("Unexpected nir shader\n");
970bf215546Sopenharmony_ci      assert(0);
971bf215546Sopenharmony_ci   }
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_ci   if (variant == NULL) {
974bf215546Sopenharmony_ci      if (shader->get_dummy_shader != NULL) {
975bf215546Sopenharmony_ci         debug_printf("Failed to compile shader, using dummy shader.\n");
976bf215546Sopenharmony_ci         variant = shader->get_dummy_shader(svga, shader, key);
977bf215546Sopenharmony_ci      }
978bf215546Sopenharmony_ci   }
979bf215546Sopenharmony_ci   else if (svga_shader_too_large(svga, variant)) {
980bf215546Sopenharmony_ci      /* too big, use shader */
981bf215546Sopenharmony_ci      if (shader->get_dummy_shader != NULL) {
982bf215546Sopenharmony_ci         debug_printf("Shader too large (%u bytes), using dummy shader.\n",
983bf215546Sopenharmony_ci                      (unsigned)(variant->nr_tokens
984bf215546Sopenharmony_ci                                 * sizeof(variant->tokens[0])));
985bf215546Sopenharmony_ci
986bf215546Sopenharmony_ci         /* Free the too-large variant */
987bf215546Sopenharmony_ci         svga_destroy_shader_variant(svga, variant);
988bf215546Sopenharmony_ci
989bf215546Sopenharmony_ci         /* Use simple pass-through shader instead */
990bf215546Sopenharmony_ci         variant = shader->get_dummy_shader(svga, shader, key);
991bf215546Sopenharmony_ci      }
992bf215546Sopenharmony_ci   }
993bf215546Sopenharmony_ci
994bf215546Sopenharmony_ci   if (variant == NULL)
995bf215546Sopenharmony_ci      return PIPE_ERROR;
996bf215546Sopenharmony_ci
997bf215546Sopenharmony_ci   ret = svga_define_shader(svga, variant);
998bf215546Sopenharmony_ci   if (ret != PIPE_OK) {
999bf215546Sopenharmony_ci      svga_destroy_shader_variant(svga, variant);
1000bf215546Sopenharmony_ci      return ret;
1001bf215546Sopenharmony_ci   }
1002bf215546Sopenharmony_ci
1003bf215546Sopenharmony_ci   *out_variant = variant;
1004bf215546Sopenharmony_ci
1005bf215546Sopenharmony_ci   /* insert variant at head of linked list */
1006bf215546Sopenharmony_ci   variant->next = shader->variants;
1007bf215546Sopenharmony_ci   shader->variants = variant;
1008bf215546Sopenharmony_ci
1009bf215546Sopenharmony_ci   return PIPE_OK;
1010bf215546Sopenharmony_ci}
1011