14a49301eSmrg/**************************************************************************
201e04c3fSmrg *
33464ebd5Sriastradh * Copyright 2009-2010 VMware, Inc.
44a49301eSmrg * All Rights Reserved.
501e04c3fSmrg *
64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a
74a49301eSmrg * copy of this software and associated documentation files (the
84a49301eSmrg * "Software"), to deal in the Software without restriction, including
94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish,
104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to
114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to
124a49301eSmrg * the following conditions:
1301e04c3fSmrg *
144a49301eSmrg * The above copyright notice and this permission notice (including the
154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions
164a49301eSmrg * of the Software.
1701e04c3fSmrg *
184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
214a49301eSmrg * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2501e04c3fSmrg *
264a49301eSmrg **************************************************************************/
274a49301eSmrg
284a49301eSmrg
2901e04c3fSmrg#include "pipe/p_screen.h"
304a49301eSmrg#include "pipe/p_context.h"
314a49301eSmrg#include "pipe/p_state.h"
324a49301eSmrg#include "tgsi/tgsi_ureg.h"
334a49301eSmrg#include "tgsi/tgsi_build.h"
347ec681f3Smrg#include "tgsi/tgsi_from_mesa.h"
354a49301eSmrg#include "tgsi/tgsi_info.h"
364a49301eSmrg#include "tgsi/tgsi_dump.h"
374a49301eSmrg#include "tgsi/tgsi_sanity.h"
38cdc920a0Smrg#include "util/u_debug.h"
3901e04c3fSmrg#include "util/u_inlines.h"
404a49301eSmrg#include "util/u_memory.h"
414a49301eSmrg#include "util/u_math.h"
42af69d88dSmrg#include "util/u_bitmask.h"
437ec681f3Smrg#include "GL/gl.h"
447ec681f3Smrg#include "compiler/shader_info.h"
454a49301eSmrg
464a49301eSmrgunion tgsi_any_token {
474a49301eSmrg   struct tgsi_header header;
484a49301eSmrg   struct tgsi_processor processor;
494a49301eSmrg   struct tgsi_token token;
50cdc920a0Smrg   struct tgsi_property prop;
51cdc920a0Smrg   struct tgsi_property_data prop_data;
524a49301eSmrg   struct tgsi_declaration decl;
534a49301eSmrg   struct tgsi_declaration_range decl_range;
54cdc920a0Smrg   struct tgsi_declaration_dimension decl_dim;
55af69d88dSmrg   struct tgsi_declaration_interp decl_interp;
5601e04c3fSmrg   struct tgsi_declaration_image decl_image;
574a49301eSmrg   struct tgsi_declaration_semantic decl_semantic;
58af69d88dSmrg   struct tgsi_declaration_sampler_view decl_sampler_view;
59af69d88dSmrg   struct tgsi_declaration_array array;
604a49301eSmrg   struct tgsi_immediate imm;
614a49301eSmrg   union  tgsi_immediate_data imm_data;
624a49301eSmrg   struct tgsi_instruction insn;
63cdc920a0Smrg   struct tgsi_instruction_label insn_label;
64cdc920a0Smrg   struct tgsi_instruction_texture insn_texture;
6501e04c3fSmrg   struct tgsi_instruction_memory insn_memory;
66af69d88dSmrg   struct tgsi_texture_offset insn_texture_offset;
674a49301eSmrg   struct tgsi_src_register src;
68af69d88dSmrg   struct tgsi_ind_register ind;
694a49301eSmrg   struct tgsi_dimension dim;
704a49301eSmrg   struct tgsi_dst_register dst;
714a49301eSmrg   unsigned value;
724a49301eSmrg};
734a49301eSmrg
744a49301eSmrg
754a49301eSmrgstruct ureg_tokens {
764a49301eSmrg   union tgsi_any_token *tokens;
774a49301eSmrg   unsigned size;
784a49301eSmrg   unsigned order;
794a49301eSmrg   unsigned count;
804a49301eSmrg};
814a49301eSmrg
8201e04c3fSmrg#define UREG_MAX_INPUT (4 * PIPE_MAX_SHADER_INPUTS)
83cdc920a0Smrg#define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
8401e04c3fSmrg#define UREG_MAX_OUTPUT (4 * PIPE_MAX_SHADER_OUTPUTS)
854a49301eSmrg#define UREG_MAX_CONSTANT_RANGE 32
8601e04c3fSmrg#define UREG_MAX_HW_ATOMIC_RANGE 32
87af69d88dSmrg#define UREG_MAX_IMMEDIATE 4096
88af69d88dSmrg#define UREG_MAX_ADDR 3
89af69d88dSmrg#define UREG_MAX_ARRAY_TEMPS 256
904a49301eSmrg
91cdc920a0Smrgstruct const_decl {
92cdc920a0Smrg   struct {
93cdc920a0Smrg      unsigned first;
94cdc920a0Smrg      unsigned last;
95cdc920a0Smrg   } constant_range[UREG_MAX_CONSTANT_RANGE];
96cdc920a0Smrg   unsigned nr_constant_ranges;
97cdc920a0Smrg};
98cdc920a0Smrg
9901e04c3fSmrgstruct hw_atomic_decl {
10001e04c3fSmrg   struct {
10101e04c3fSmrg      unsigned first;
10201e04c3fSmrg      unsigned last;
10301e04c3fSmrg      unsigned array_id;
10401e04c3fSmrg   } hw_atomic_range[UREG_MAX_HW_ATOMIC_RANGE];
10501e04c3fSmrg   unsigned nr_hw_atomic_ranges;
10601e04c3fSmrg};
10701e04c3fSmrg
1084a49301eSmrg#define DOMAIN_DECL 0
1094a49301eSmrg#define DOMAIN_INSN 1
1104a49301eSmrg
1114a49301eSmrgstruct ureg_program
1124a49301eSmrg{
11301e04c3fSmrg   enum pipe_shader_type processor;
11401e04c3fSmrg   bool supports_any_inout_decl_range;
11501e04c3fSmrg   int next_shader_processor;
1164a49301eSmrg
1177ec681f3Smrg   struct ureg_input_decl {
11801e04c3fSmrg      enum tgsi_semantic semantic_name;
1194a49301eSmrg      unsigned semantic_index;
12001e04c3fSmrg      enum tgsi_interpolate_mode interp;
12101e04c3fSmrg      unsigned char usage_mask;
12201e04c3fSmrg      enum tgsi_interpolate_loc interp_location;
12301e04c3fSmrg      unsigned first;
12401e04c3fSmrg      unsigned last;
12501e04c3fSmrg      unsigned array_id;
12601e04c3fSmrg   } input[UREG_MAX_INPUT];
12701e04c3fSmrg   unsigned nr_inputs, nr_input_regs;
1284a49301eSmrg
12901e04c3fSmrg   unsigned vs_inputs[PIPE_MAX_ATTRIBS/32];
1304a49301eSmrg
131cdc920a0Smrg   struct {
13201e04c3fSmrg      enum tgsi_semantic semantic_name;
133cdc920a0Smrg      unsigned semantic_index;
134cdc920a0Smrg   } system_value[UREG_MAX_SYSTEM_VALUE];
135cdc920a0Smrg   unsigned nr_system_values;
136cdc920a0Smrg
1377ec681f3Smrg   struct ureg_output_decl {
13801e04c3fSmrg      enum tgsi_semantic semantic_name;
1394a49301eSmrg      unsigned semantic_index;
14001e04c3fSmrg      unsigned streams;
141af69d88dSmrg      unsigned usage_mask; /* = TGSI_WRITEMASK_* */
14201e04c3fSmrg      unsigned first;
14301e04c3fSmrg      unsigned last;
14401e04c3fSmrg      unsigned array_id;
14501e04c3fSmrg      boolean invariant;
1464a49301eSmrg   } output[UREG_MAX_OUTPUT];
14701e04c3fSmrg   unsigned nr_outputs, nr_output_regs;
1484a49301eSmrg
1494a49301eSmrg   struct {
150cdc920a0Smrg      union {
151cdc920a0Smrg         float f[4];
152cdc920a0Smrg         unsigned u[4];
153cdc920a0Smrg         int i[4];
154cdc920a0Smrg      } value;
1554a49301eSmrg      unsigned nr;
156cdc920a0Smrg      unsigned type;
1574a49301eSmrg   } immediate[UREG_MAX_IMMEDIATE];
1584a49301eSmrg   unsigned nr_immediates;
1594a49301eSmrg
1604a49301eSmrg   struct ureg_src sampler[PIPE_MAX_SAMPLERS];
1614a49301eSmrg   unsigned nr_samplers;
1624a49301eSmrg
1633464ebd5Sriastradh   struct {
1643464ebd5Sriastradh      unsigned index;
16501e04c3fSmrg      enum tgsi_texture_type target;
16601e04c3fSmrg      enum tgsi_return_type return_type_x;
16701e04c3fSmrg      enum tgsi_return_type return_type_y;
16801e04c3fSmrg      enum tgsi_return_type return_type_z;
16901e04c3fSmrg      enum tgsi_return_type return_type_w;
170af69d88dSmrg   } sampler_view[PIPE_MAX_SHADER_SAMPLER_VIEWS];
171af69d88dSmrg   unsigned nr_sampler_views;
1723464ebd5Sriastradh
17301e04c3fSmrg   struct {
17401e04c3fSmrg      unsigned index;
17501e04c3fSmrg      enum tgsi_texture_type target;
17601e04c3fSmrg      enum pipe_format format;
17701e04c3fSmrg      boolean wr;
17801e04c3fSmrg      boolean raw;
17901e04c3fSmrg   } image[PIPE_MAX_SHADER_IMAGES];
18001e04c3fSmrg   unsigned nr_images;
18101e04c3fSmrg
18201e04c3fSmrg   struct {
18301e04c3fSmrg      unsigned index;
18401e04c3fSmrg      bool atomic;
18501e04c3fSmrg   } buffer[PIPE_MAX_SHADER_BUFFERS];
18601e04c3fSmrg   unsigned nr_buffers;
18701e04c3fSmrg
188af69d88dSmrg   struct util_bitmask *free_temps;
189af69d88dSmrg   struct util_bitmask *local_temps;
190af69d88dSmrg   struct util_bitmask *decl_temps;
1914a49301eSmrg   unsigned nr_temps;
1924a49301eSmrg
193af69d88dSmrg   unsigned array_temps[UREG_MAX_ARRAY_TEMPS];
194af69d88dSmrg   unsigned nr_array_temps;
195af69d88dSmrg
19601e04c3fSmrg   struct const_decl const_decls[PIPE_MAX_CONSTANT_BUFFERS];
19701e04c3fSmrg
19801e04c3fSmrg   struct hw_atomic_decl hw_atomic_decls[PIPE_MAX_HW_ATOMIC_BUFFERS];
199cdc920a0Smrg
20001e04c3fSmrg   unsigned properties[TGSI_PROPERTY_COUNT];
2014a49301eSmrg
2024a49301eSmrg   unsigned nr_addrs;
2034a49301eSmrg   unsigned nr_instructions;
2044a49301eSmrg
2054a49301eSmrg   struct ureg_tokens domain[2];
20601e04c3fSmrg
20701e04c3fSmrg   bool use_memory[TGSI_MEMORY_TYPE_COUNT];
2084a49301eSmrg};
2094a49301eSmrg
2104a49301eSmrgstatic union tgsi_any_token error_tokens[32];
2114a49301eSmrg
2124a49301eSmrgstatic void tokens_error( struct ureg_tokens *tokens )
2134a49301eSmrg{
2144a49301eSmrg   if (tokens->tokens && tokens->tokens != error_tokens)
2154a49301eSmrg      FREE(tokens->tokens);
2164a49301eSmrg
2174a49301eSmrg   tokens->tokens = error_tokens;
21801e04c3fSmrg   tokens->size = ARRAY_SIZE(error_tokens);
2194a49301eSmrg   tokens->count = 0;
2204a49301eSmrg}
2214a49301eSmrg
2224a49301eSmrg
2234a49301eSmrgstatic void tokens_expand( struct ureg_tokens *tokens,
2244a49301eSmrg                           unsigned count )
2254a49301eSmrg{
2264a49301eSmrg   unsigned old_size = tokens->size * sizeof(unsigned);
2274a49301eSmrg
2284a49301eSmrg   if (tokens->tokens == error_tokens) {
2294a49301eSmrg      return;
2304a49301eSmrg   }
2314a49301eSmrg
2324a49301eSmrg   while (tokens->count + count > tokens->size) {
2334a49301eSmrg      tokens->size = (1 << ++tokens->order);
2344a49301eSmrg   }
2354a49301eSmrg
2364a49301eSmrg   tokens->tokens = REALLOC(tokens->tokens,
2374a49301eSmrg                            old_size,
2384a49301eSmrg                            tokens->size * sizeof(unsigned));
2394a49301eSmrg   if (tokens->tokens == NULL) {
2404a49301eSmrg      tokens_error(tokens);
2414a49301eSmrg   }
2424a49301eSmrg}
2434a49301eSmrg
2444a49301eSmrgstatic void set_bad( struct ureg_program *ureg )
2454a49301eSmrg{
2464a49301eSmrg   tokens_error(&ureg->domain[0]);
2474a49301eSmrg}
2484a49301eSmrg
2494a49301eSmrg
2504a49301eSmrg
2514a49301eSmrgstatic union tgsi_any_token *get_tokens( struct ureg_program *ureg,
2524a49301eSmrg                                         unsigned domain,
2534a49301eSmrg                                         unsigned count )
2544a49301eSmrg{
2554a49301eSmrg   struct ureg_tokens *tokens = &ureg->domain[domain];
2564a49301eSmrg   union tgsi_any_token *result;
2574a49301eSmrg
2584a49301eSmrg   if (tokens->count + count > tokens->size)
2594a49301eSmrg      tokens_expand(tokens, count);
2604a49301eSmrg
2614a49301eSmrg   result = &tokens->tokens[tokens->count];
2624a49301eSmrg   tokens->count += count;
2634a49301eSmrg   return result;
2644a49301eSmrg}
2654a49301eSmrg
2664a49301eSmrg
2674a49301eSmrgstatic union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
2684a49301eSmrg                                            unsigned domain,
2694a49301eSmrg                                            unsigned nr )
2704a49301eSmrg{
2714a49301eSmrg   if (ureg->domain[domain].tokens == error_tokens)
2724a49301eSmrg      return &error_tokens[0];
2734a49301eSmrg
2744a49301eSmrg   return &ureg->domain[domain].tokens[nr];
2754a49301eSmrg}
2764a49301eSmrg
2774a49301eSmrg
278af69d88dSmrgvoid
27901e04c3fSmrgureg_property(struct ureg_program *ureg, unsigned name, unsigned value)
280af69d88dSmrg{
28101e04c3fSmrg   assert(name < ARRAY_SIZE(ureg->properties));
28201e04c3fSmrg   ureg->properties[name] = value;
283af69d88dSmrg}
284af69d88dSmrg
285cdc920a0Smrgstruct ureg_src
2867ec681f3Smrgureg_DECL_fs_input_centroid_layout(struct ureg_program *ureg,
28701e04c3fSmrg                       enum tgsi_semantic semantic_name,
288cdc920a0Smrg                       unsigned semantic_index,
28901e04c3fSmrg                       enum tgsi_interpolate_mode interp_mode,
29001e04c3fSmrg                       enum tgsi_interpolate_loc interp_location,
29101e04c3fSmrg                       unsigned index,
29201e04c3fSmrg                       unsigned usage_mask,
29301e04c3fSmrg                       unsigned array_id,
29401e04c3fSmrg                       unsigned array_size)
2954a49301eSmrg{
2964a49301eSmrg   unsigned i;
2974a49301eSmrg
29801e04c3fSmrg   assert(usage_mask != 0);
29901e04c3fSmrg   assert(usage_mask <= TGSI_WRITEMASK_XYZW);
30001e04c3fSmrg
30101e04c3fSmrg   for (i = 0; i < ureg->nr_inputs; i++) {
30201e04c3fSmrg      if (ureg->input[i].semantic_name == semantic_name &&
30301e04c3fSmrg          ureg->input[i].semantic_index == semantic_index) {
30401e04c3fSmrg         assert(ureg->input[i].interp == interp_mode);
30501e04c3fSmrg         assert(ureg->input[i].interp_location == interp_location);
30601e04c3fSmrg         if (ureg->input[i].array_id == array_id) {
30701e04c3fSmrg            ureg->input[i].usage_mask |= usage_mask;
30801e04c3fSmrg            goto out;
30901e04c3fSmrg         }
31001e04c3fSmrg         assert((ureg->input[i].usage_mask & usage_mask) == 0);
311cdc920a0Smrg      }
3124a49301eSmrg   }
3134a49301eSmrg
31401e04c3fSmrg   if (ureg->nr_inputs < UREG_MAX_INPUT) {
31501e04c3fSmrg      assert(array_size >= 1);
31601e04c3fSmrg      ureg->input[i].semantic_name = semantic_name;
31701e04c3fSmrg      ureg->input[i].semantic_index = semantic_index;
31801e04c3fSmrg      ureg->input[i].interp = interp_mode;
31901e04c3fSmrg      ureg->input[i].interp_location = interp_location;
32001e04c3fSmrg      ureg->input[i].first = index;
32101e04c3fSmrg      ureg->input[i].last = index + array_size - 1;
32201e04c3fSmrg      ureg->input[i].array_id = array_id;
32301e04c3fSmrg      ureg->input[i].usage_mask = usage_mask;
32401e04c3fSmrg      ureg->nr_input_regs = MAX2(ureg->nr_input_regs, index + array_size);
32501e04c3fSmrg      ureg->nr_inputs++;
326cdc920a0Smrg   } else {
327cdc920a0Smrg      set_bad(ureg);
3284a49301eSmrg   }
3294a49301eSmrg
3304a49301eSmrgout:
33101e04c3fSmrg   return ureg_src_array_register(TGSI_FILE_INPUT, ureg->input[i].first,
33201e04c3fSmrg                                  array_id);
33301e04c3fSmrg}
33401e04c3fSmrg
33501e04c3fSmrgstruct ureg_src
3367ec681f3Smrgureg_DECL_fs_input_centroid(struct ureg_program *ureg,
33701e04c3fSmrg                       enum tgsi_semantic semantic_name,
33801e04c3fSmrg                       unsigned semantic_index,
33901e04c3fSmrg                       enum tgsi_interpolate_mode interp_mode,
34001e04c3fSmrg                       enum tgsi_interpolate_loc interp_location,
34101e04c3fSmrg                       unsigned array_id,
34201e04c3fSmrg                       unsigned array_size)
34301e04c3fSmrg{
3447ec681f3Smrg   return ureg_DECL_fs_input_centroid_layout(ureg,
34501e04c3fSmrg         semantic_name, semantic_index, interp_mode,
3467ec681f3Smrg         interp_location,
34701e04c3fSmrg         ureg->nr_input_regs, TGSI_WRITEMASK_XYZW, array_id, array_size);
3484a49301eSmrg}
3494a49301eSmrg
3504a49301eSmrg
35101e04c3fSmrgstruct ureg_src
3524a49301eSmrgureg_DECL_vs_input( struct ureg_program *ureg,
3534a49301eSmrg                    unsigned index )
3544a49301eSmrg{
35501e04c3fSmrg   assert(ureg->processor == PIPE_SHADER_VERTEX);
35601e04c3fSmrg   assert(index / 32 < ARRAY_SIZE(ureg->vs_inputs));
35701e04c3fSmrg
3584a49301eSmrg   ureg->vs_inputs[index/32] |= 1 << (index % 32);
3594a49301eSmrg   return ureg_src_register( TGSI_FILE_INPUT, index );
3604a49301eSmrg}
3614a49301eSmrg
3624a49301eSmrg
363cdc920a0Smrgstruct ureg_src
36401e04c3fSmrgureg_DECL_input_layout(struct ureg_program *ureg,
36501e04c3fSmrg                enum tgsi_semantic semantic_name,
36601e04c3fSmrg                unsigned semantic_index,
36701e04c3fSmrg                unsigned index,
36801e04c3fSmrg                unsigned usage_mask,
36901e04c3fSmrg                unsigned array_id,
37001e04c3fSmrg                unsigned array_size)
37101e04c3fSmrg{
3727ec681f3Smrg   return ureg_DECL_fs_input_centroid_layout(ureg,
37301e04c3fSmrg               semantic_name, semantic_index,
3747ec681f3Smrg               TGSI_INTERPOLATE_CONSTANT, TGSI_INTERPOLATE_LOC_CENTER,
37501e04c3fSmrg               index, usage_mask, array_id, array_size);
37601e04c3fSmrg}
377cdc920a0Smrg
37801e04c3fSmrg
37901e04c3fSmrgstruct ureg_src
38001e04c3fSmrgureg_DECL_input(struct ureg_program *ureg,
38101e04c3fSmrg                enum tgsi_semantic semantic_name,
38201e04c3fSmrg                unsigned semantic_index,
38301e04c3fSmrg                unsigned array_id,
38401e04c3fSmrg                unsigned array_size)
38501e04c3fSmrg{
3867ec681f3Smrg   return ureg_DECL_fs_input_centroid(ureg, semantic_name, semantic_index,
3877ec681f3Smrg                                          TGSI_INTERPOLATE_CONSTANT,
38801e04c3fSmrg                                          TGSI_INTERPOLATE_LOC_CENTER,
38901e04c3fSmrg                                          array_id, array_size);
390cdc920a0Smrg}
391cdc920a0Smrg
392cdc920a0Smrg
393cdc920a0Smrgstruct ureg_src
394cdc920a0Smrgureg_DECL_system_value(struct ureg_program *ureg,
39501e04c3fSmrg                       enum tgsi_semantic semantic_name,
396cdc920a0Smrg                       unsigned semantic_index)
397cdc920a0Smrg{
39801e04c3fSmrg   unsigned i;
39901e04c3fSmrg
40001e04c3fSmrg   for (i = 0; i < ureg->nr_system_values; i++) {
40101e04c3fSmrg      if (ureg->system_value[i].semantic_name == semantic_name &&
40201e04c3fSmrg          ureg->system_value[i].semantic_index == semantic_index) {
40301e04c3fSmrg         goto out;
40401e04c3fSmrg      }
40501e04c3fSmrg   }
40601e04c3fSmrg
407cdc920a0Smrg   if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) {
408cdc920a0Smrg      ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name;
409cdc920a0Smrg      ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index;
41001e04c3fSmrg      i = ureg->nr_system_values;
411cdc920a0Smrg      ureg->nr_system_values++;
412cdc920a0Smrg   } else {
413cdc920a0Smrg      set_bad(ureg);
414cdc920a0Smrg   }
415cdc920a0Smrg
41601e04c3fSmrgout:
41701e04c3fSmrg   return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, i);
418cdc920a0Smrg}
419cdc920a0Smrg
420cdc920a0Smrg
42101e04c3fSmrgstruct ureg_dst
42201e04c3fSmrgureg_DECL_output_layout(struct ureg_program *ureg,
42301e04c3fSmrg                        enum tgsi_semantic semantic_name,
42401e04c3fSmrg                        unsigned semantic_index,
42501e04c3fSmrg                        unsigned streams,
42601e04c3fSmrg                        unsigned index,
42701e04c3fSmrg                        unsigned usage_mask,
42801e04c3fSmrg                        unsigned array_id,
42901e04c3fSmrg                        unsigned array_size,
43001e04c3fSmrg                        boolean invariant)
4314a49301eSmrg{
4324a49301eSmrg   unsigned i;
4334a49301eSmrg
434af69d88dSmrg   assert(usage_mask != 0);
43501e04c3fSmrg   assert(!(streams & 0x03) || (usage_mask & 1));
43601e04c3fSmrg   assert(!(streams & 0x0c) || (usage_mask & 2));
43701e04c3fSmrg   assert(!(streams & 0x30) || (usage_mask & 4));
43801e04c3fSmrg   assert(!(streams & 0xc0) || (usage_mask & 8));
439af69d88dSmrg
4404a49301eSmrg   for (i = 0; i < ureg->nr_outputs; i++) {
44101e04c3fSmrg      if (ureg->output[i].semantic_name == semantic_name &&
44201e04c3fSmrg          ureg->output[i].semantic_index == semantic_index) {
44301e04c3fSmrg         if (ureg->output[i].array_id == array_id) {
44401e04c3fSmrg            ureg->output[i].usage_mask |= usage_mask;
44501e04c3fSmrg            goto out;
44601e04c3fSmrg         }
44701e04c3fSmrg         assert((ureg->output[i].usage_mask & usage_mask) == 0);
448af69d88dSmrg      }
4494a49301eSmrg   }
4504a49301eSmrg
4514a49301eSmrg   if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
45201e04c3fSmrg      ureg->output[i].semantic_name = semantic_name;
45301e04c3fSmrg      ureg->output[i].semantic_index = semantic_index;
454af69d88dSmrg      ureg->output[i].usage_mask = usage_mask;
45501e04c3fSmrg      ureg->output[i].first = index;
45601e04c3fSmrg      ureg->output[i].last = index + array_size - 1;
45701e04c3fSmrg      ureg->output[i].array_id = array_id;
45801e04c3fSmrg      ureg->output[i].invariant = invariant;
45901e04c3fSmrg      ureg->nr_output_regs = MAX2(ureg->nr_output_regs, index + array_size);
4604a49301eSmrg      ureg->nr_outputs++;
4614a49301eSmrg   }
4624a49301eSmrg   else {
4634a49301eSmrg      set_bad( ureg );
46401e04c3fSmrg      i = 0;
4654a49301eSmrg   }
4664a49301eSmrg
4674a49301eSmrgout:
46801e04c3fSmrg   ureg->output[i].streams |= streams;
46901e04c3fSmrg
47001e04c3fSmrg   return ureg_dst_array_register(TGSI_FILE_OUTPUT, ureg->output[i].first,
47101e04c3fSmrg                                  array_id);
4724a49301eSmrg}
4734a49301eSmrg
4744a49301eSmrg
47501e04c3fSmrgstruct ureg_dst
47601e04c3fSmrgureg_DECL_output_masked(struct ureg_program *ureg,
47701e04c3fSmrg                        unsigned name,
47801e04c3fSmrg                        unsigned index,
47901e04c3fSmrg                        unsigned usage_mask,
48001e04c3fSmrg                        unsigned array_id,
48101e04c3fSmrg                        unsigned array_size)
48201e04c3fSmrg{
48301e04c3fSmrg   return ureg_DECL_output_layout(ureg, name, index, 0,
48401e04c3fSmrg                                  ureg->nr_output_regs, usage_mask, array_id,
48501e04c3fSmrg                                  array_size, FALSE);
48601e04c3fSmrg}
48701e04c3fSmrg
48801e04c3fSmrg
48901e04c3fSmrgstruct ureg_dst
49001e04c3fSmrgureg_DECL_output(struct ureg_program *ureg,
49101e04c3fSmrg                 enum tgsi_semantic name,
49201e04c3fSmrg                 unsigned index)
49301e04c3fSmrg{
49401e04c3fSmrg   return ureg_DECL_output_masked(ureg, name, index, TGSI_WRITEMASK_XYZW,
49501e04c3fSmrg                                  0, 1);
49601e04c3fSmrg}
49701e04c3fSmrg
49801e04c3fSmrgstruct ureg_dst
49901e04c3fSmrgureg_DECL_output_array(struct ureg_program *ureg,
50001e04c3fSmrg                       enum tgsi_semantic semantic_name,
50101e04c3fSmrg                       unsigned semantic_index,
50201e04c3fSmrg                       unsigned array_id,
50301e04c3fSmrg                       unsigned array_size)
504af69d88dSmrg{
50501e04c3fSmrg   return ureg_DECL_output_masked(ureg, semantic_name, semantic_index,
50601e04c3fSmrg                                  TGSI_WRITEMASK_XYZW,
50701e04c3fSmrg                                  array_id, array_size);
508af69d88dSmrg}
509af69d88dSmrg
510af69d88dSmrg
5114a49301eSmrg/* Returns a new constant register.  Keep track of which have been
5124a49301eSmrg * referred to so that we can emit decls later.
5134a49301eSmrg *
514cdc920a0Smrg * Constant operands declared with this function must be addressed
515cdc920a0Smrg * with a two-dimensional index.
516cdc920a0Smrg *
5174a49301eSmrg * There is nothing in this code to bind this constant to any tracked
5184a49301eSmrg * value or manage any constant_buffer contents -- that's the
5194a49301eSmrg * resposibility of the calling code.
5204a49301eSmrg */
521cdc920a0Smrgvoid
522cdc920a0Smrgureg_DECL_constant2D(struct ureg_program *ureg,
523cdc920a0Smrg                     unsigned first,
524cdc920a0Smrg                     unsigned last,
525cdc920a0Smrg                     unsigned index2D)
5264a49301eSmrg{
52701e04c3fSmrg   struct const_decl *decl = &ureg->const_decls[index2D];
528cdc920a0Smrg
529cdc920a0Smrg   assert(index2D < PIPE_MAX_CONSTANT_BUFFERS);
530cdc920a0Smrg
531cdc920a0Smrg   if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
532cdc920a0Smrg      uint i = decl->nr_constant_ranges++;
533cdc920a0Smrg
534cdc920a0Smrg      decl->constant_range[i].first = first;
535cdc920a0Smrg      decl->constant_range[i].last = last;
536cdc920a0Smrg   }
537cdc920a0Smrg}
538cdc920a0Smrg
539cdc920a0Smrg
54001e04c3fSmrg/* A one-dimensional, deprecated version of ureg_DECL_constant2D().
541cdc920a0Smrg *
542cdc920a0Smrg * Constant operands declared with this function must be addressed
543cdc920a0Smrg * with a one-dimensional index.
544cdc920a0Smrg */
545cdc920a0Smrgstruct ureg_src
546cdc920a0Smrgureg_DECL_constant(struct ureg_program *ureg,
547cdc920a0Smrg                   unsigned index)
548cdc920a0Smrg{
54901e04c3fSmrg   struct const_decl *decl = &ureg->const_decls[0];
5504a49301eSmrg   unsigned minconst = index, maxconst = index;
5514a49301eSmrg   unsigned i;
5524a49301eSmrg
5534a49301eSmrg   /* Inside existing range?
5544a49301eSmrg    */
555cdc920a0Smrg   for (i = 0; i < decl->nr_constant_ranges; i++) {
556cdc920a0Smrg      if (decl->constant_range[i].first <= index &&
557cdc920a0Smrg          decl->constant_range[i].last >= index) {
5584a49301eSmrg         goto out;
559cdc920a0Smrg      }
5604a49301eSmrg   }
5614a49301eSmrg
5624a49301eSmrg   /* Extend existing range?
5634a49301eSmrg    */
564cdc920a0Smrg   for (i = 0; i < decl->nr_constant_ranges; i++) {
565cdc920a0Smrg      if (decl->constant_range[i].last == index - 1) {
566cdc920a0Smrg         decl->constant_range[i].last = index;
5674a49301eSmrg         goto out;
5684a49301eSmrg      }
5694a49301eSmrg
570cdc920a0Smrg      if (decl->constant_range[i].first == index + 1) {
571cdc920a0Smrg         decl->constant_range[i].first = index;
5724a49301eSmrg         goto out;
5734a49301eSmrg      }
5744a49301eSmrg
575cdc920a0Smrg      minconst = MIN2(minconst, decl->constant_range[i].first);
576cdc920a0Smrg      maxconst = MAX2(maxconst, decl->constant_range[i].last);
5774a49301eSmrg   }
5784a49301eSmrg
5794a49301eSmrg   /* Create new range?
5804a49301eSmrg    */
581cdc920a0Smrg   if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
582cdc920a0Smrg      i = decl->nr_constant_ranges++;
583cdc920a0Smrg      decl->constant_range[i].first = index;
584cdc920a0Smrg      decl->constant_range[i].last = index;
585cdc920a0Smrg      goto out;
5864a49301eSmrg   }
5874a49301eSmrg
5884a49301eSmrg   /* Collapse all ranges down to one:
5894a49301eSmrg    */
5904a49301eSmrg   i = 0;
591cdc920a0Smrg   decl->constant_range[0].first = minconst;
592cdc920a0Smrg   decl->constant_range[0].last = maxconst;
593cdc920a0Smrg   decl->nr_constant_ranges = 1;
5944a49301eSmrg
5954a49301eSmrgout:
596cdc920a0Smrg   assert(i < decl->nr_constant_ranges);
597cdc920a0Smrg   assert(decl->constant_range[i].first <= index);
598cdc920a0Smrg   assert(decl->constant_range[i].last >= index);
59901e04c3fSmrg
60001e04c3fSmrg   struct ureg_src src = ureg_src_register(TGSI_FILE_CONSTANT, index);
60101e04c3fSmrg   return ureg_src_dimension(src, 0);
60201e04c3fSmrg}
60301e04c3fSmrg
60401e04c3fSmrg
60501e04c3fSmrg/* Returns a new hw atomic register.  Keep track of which have been
60601e04c3fSmrg * referred to so that we can emit decls later.
60701e04c3fSmrg */
60801e04c3fSmrgvoid
60901e04c3fSmrgureg_DECL_hw_atomic(struct ureg_program *ureg,
61001e04c3fSmrg                    unsigned first,
61101e04c3fSmrg                    unsigned last,
61201e04c3fSmrg                    unsigned buffer_id,
61301e04c3fSmrg                    unsigned array_id)
61401e04c3fSmrg{
61501e04c3fSmrg   struct hw_atomic_decl *decl = &ureg->hw_atomic_decls[buffer_id];
61601e04c3fSmrg
61701e04c3fSmrg   if (decl->nr_hw_atomic_ranges < UREG_MAX_HW_ATOMIC_RANGE) {
61801e04c3fSmrg      uint i = decl->nr_hw_atomic_ranges++;
61901e04c3fSmrg
62001e04c3fSmrg      decl->hw_atomic_range[i].first = first;
62101e04c3fSmrg      decl->hw_atomic_range[i].last = last;
62201e04c3fSmrg      decl->hw_atomic_range[i].array_id = array_id;
62301e04c3fSmrg   } else {
62401e04c3fSmrg      set_bad(ureg);
62501e04c3fSmrg   }
6264a49301eSmrg}
6274a49301eSmrg
628af69d88dSmrgstatic struct ureg_dst alloc_temporary( struct ureg_program *ureg,
629af69d88dSmrg                                        boolean local )
6304a49301eSmrg{
6314a49301eSmrg   unsigned i;
6324a49301eSmrg
633af69d88dSmrg   /* Look for a released temporary.
634af69d88dSmrg    */
635af69d88dSmrg   for (i = util_bitmask_get_first_index(ureg->free_temps);
636af69d88dSmrg        i != UTIL_BITMASK_INVALID_INDEX;
637af69d88dSmrg        i = util_bitmask_get_next_index(ureg->free_temps, i + 1)) {
638af69d88dSmrg      if (util_bitmask_get(ureg->local_temps, i) == local)
639af69d88dSmrg         break;
6404a49301eSmrg   }
6414a49301eSmrg
642af69d88dSmrg   /* Or allocate a new one.
6434a49301eSmrg    */
644af69d88dSmrg   if (i == UTIL_BITMASK_INVALID_INDEX) {
645af69d88dSmrg      i = ureg->nr_temps++;
6464a49301eSmrg
647af69d88dSmrg      if (local)
648af69d88dSmrg         util_bitmask_set(ureg->local_temps, i);
6494a49301eSmrg
650af69d88dSmrg      /* Start a new declaration when the local flag changes */
651af69d88dSmrg      if (!i || util_bitmask_get(ureg->local_temps, i - 1) != local)
652af69d88dSmrg         util_bitmask_set(ureg->decl_temps, i);
653af69d88dSmrg   }
654af69d88dSmrg
655af69d88dSmrg   util_bitmask_clear(ureg->free_temps, i);
6564a49301eSmrg
6574a49301eSmrg   return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
6584a49301eSmrg}
6594a49301eSmrg
660af69d88dSmrgstruct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
661af69d88dSmrg{
662af69d88dSmrg   return alloc_temporary(ureg, FALSE);
663af69d88dSmrg}
664af69d88dSmrg
665af69d88dSmrgstruct ureg_dst ureg_DECL_local_temporary( struct ureg_program *ureg )
666af69d88dSmrg{
667af69d88dSmrg   return alloc_temporary(ureg, TRUE);
668af69d88dSmrg}
669af69d88dSmrg
670af69d88dSmrgstruct ureg_dst ureg_DECL_array_temporary( struct ureg_program *ureg,
671af69d88dSmrg                                           unsigned size,
672af69d88dSmrg                                           boolean local )
673af69d88dSmrg{
674af69d88dSmrg   unsigned i = ureg->nr_temps;
675af69d88dSmrg   struct ureg_dst dst = ureg_dst_register( TGSI_FILE_TEMPORARY, i );
676af69d88dSmrg
677af69d88dSmrg   if (local)
678af69d88dSmrg      util_bitmask_set(ureg->local_temps, i);
679af69d88dSmrg
680af69d88dSmrg   /* Always start a new declaration at the start */
681af69d88dSmrg   util_bitmask_set(ureg->decl_temps, i);
682af69d88dSmrg
683af69d88dSmrg   ureg->nr_temps += size;
684af69d88dSmrg
685af69d88dSmrg   /* and also at the end of the array */
686af69d88dSmrg   util_bitmask_set(ureg->decl_temps, ureg->nr_temps);
687af69d88dSmrg
688af69d88dSmrg   if (ureg->nr_array_temps < UREG_MAX_ARRAY_TEMPS) {
689af69d88dSmrg      ureg->array_temps[ureg->nr_array_temps++] = i;
690af69d88dSmrg      dst.ArrayID = ureg->nr_array_temps;
691af69d88dSmrg   }
692af69d88dSmrg
693af69d88dSmrg   return dst;
694af69d88dSmrg}
6954a49301eSmrg
6964a49301eSmrgvoid ureg_release_temporary( struct ureg_program *ureg,
6974a49301eSmrg                             struct ureg_dst tmp )
6984a49301eSmrg{
6994a49301eSmrg   if(tmp.File == TGSI_FILE_TEMPORARY)
700af69d88dSmrg      util_bitmask_set(ureg->free_temps, tmp.Index);
7014a49301eSmrg}
7024a49301eSmrg
7034a49301eSmrg
7044a49301eSmrg/* Allocate a new address register.
7054a49301eSmrg */
7064a49301eSmrgstruct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
7074a49301eSmrg{
7084a49301eSmrg   if (ureg->nr_addrs < UREG_MAX_ADDR)
7094a49301eSmrg      return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
7104a49301eSmrg
7114a49301eSmrg   assert( 0 );
7124a49301eSmrg   return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
7134a49301eSmrg}
7144a49301eSmrg
7154a49301eSmrg/* Allocate a new sampler.
7164a49301eSmrg */
7174a49301eSmrgstruct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
7184a49301eSmrg                                   unsigned nr )
7194a49301eSmrg{
7204a49301eSmrg   unsigned i;
7214a49301eSmrg
7224a49301eSmrg   for (i = 0; i < ureg->nr_samplers; i++)
72301e04c3fSmrg      if (ureg->sampler[i].Index == (int)nr)
7244a49301eSmrg         return ureg->sampler[i];
72501e04c3fSmrg
7264a49301eSmrg   if (i < PIPE_MAX_SAMPLERS) {
7274a49301eSmrg      ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
7284a49301eSmrg      ureg->nr_samplers++;
7294a49301eSmrg      return ureg->sampler[i];
7304a49301eSmrg   }
7314a49301eSmrg
7324a49301eSmrg   assert( 0 );
7334a49301eSmrg   return ureg->sampler[0];
7344a49301eSmrg}
7354a49301eSmrg
7363464ebd5Sriastradh/*
737af69d88dSmrg * Allocate a new shader sampler view.
7383464ebd5Sriastradh */
7393464ebd5Sriastradhstruct ureg_src
740af69d88dSmrgureg_DECL_sampler_view(struct ureg_program *ureg,
741af69d88dSmrg                       unsigned index,
74201e04c3fSmrg                       enum tgsi_texture_type target,
74301e04c3fSmrg                       enum tgsi_return_type return_type_x,
74401e04c3fSmrg                       enum tgsi_return_type return_type_y,
74501e04c3fSmrg                       enum tgsi_return_type return_type_z,
74601e04c3fSmrg                       enum tgsi_return_type return_type_w)
7473464ebd5Sriastradh{
748af69d88dSmrg   struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index);
7493464ebd5Sriastradh   uint i;
7503464ebd5Sriastradh
751af69d88dSmrg   for (i = 0; i < ureg->nr_sampler_views; i++) {
752af69d88dSmrg      if (ureg->sampler_view[i].index == index) {
7533464ebd5Sriastradh         return reg;
7543464ebd5Sriastradh      }
7553464ebd5Sriastradh   }
7563464ebd5Sriastradh
757af69d88dSmrg   if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) {
758af69d88dSmrg      ureg->sampler_view[i].index = index;
759af69d88dSmrg      ureg->sampler_view[i].target = target;
760af69d88dSmrg      ureg->sampler_view[i].return_type_x = return_type_x;
761af69d88dSmrg      ureg->sampler_view[i].return_type_y = return_type_y;
762af69d88dSmrg      ureg->sampler_view[i].return_type_z = return_type_z;
763af69d88dSmrg      ureg->sampler_view[i].return_type_w = return_type_w;
764af69d88dSmrg      ureg->nr_sampler_views++;
7653464ebd5Sriastradh      return reg;
7663464ebd5Sriastradh   }
7673464ebd5Sriastradh
7683464ebd5Sriastradh   assert(0);
7693464ebd5Sriastradh   return reg;
7703464ebd5Sriastradh}
7714a49301eSmrg
77201e04c3fSmrg/* Allocate a new image.
77301e04c3fSmrg */
77401e04c3fSmrgstruct ureg_src
77501e04c3fSmrgureg_DECL_image(struct ureg_program *ureg,
77601e04c3fSmrg                unsigned index,
77701e04c3fSmrg                enum tgsi_texture_type target,
77801e04c3fSmrg                enum pipe_format format,
77901e04c3fSmrg                boolean wr,
78001e04c3fSmrg                boolean raw)
78101e04c3fSmrg{
78201e04c3fSmrg   struct ureg_src reg = ureg_src_register(TGSI_FILE_IMAGE, index);
78301e04c3fSmrg   unsigned i;
78401e04c3fSmrg
78501e04c3fSmrg   for (i = 0; i < ureg->nr_images; i++)
78601e04c3fSmrg      if (ureg->image[i].index == index)
78701e04c3fSmrg         return reg;
78801e04c3fSmrg
78901e04c3fSmrg   if (i < PIPE_MAX_SHADER_IMAGES) {
79001e04c3fSmrg      ureg->image[i].index = index;
79101e04c3fSmrg      ureg->image[i].target = target;
79201e04c3fSmrg      ureg->image[i].wr = wr;
79301e04c3fSmrg      ureg->image[i].raw = raw;
79401e04c3fSmrg      ureg->image[i].format = format;
79501e04c3fSmrg      ureg->nr_images++;
79601e04c3fSmrg      return reg;
79701e04c3fSmrg   }
79801e04c3fSmrg
79901e04c3fSmrg   assert(0);
80001e04c3fSmrg   return reg;
80101e04c3fSmrg}
80201e04c3fSmrg
80301e04c3fSmrg/* Allocate a new buffer.
80401e04c3fSmrg */
80501e04c3fSmrgstruct ureg_src ureg_DECL_buffer(struct ureg_program *ureg, unsigned nr,
80601e04c3fSmrg                                 bool atomic)
80701e04c3fSmrg{
80801e04c3fSmrg   struct ureg_src reg = ureg_src_register(TGSI_FILE_BUFFER, nr);
80901e04c3fSmrg   unsigned i;
81001e04c3fSmrg
81101e04c3fSmrg   for (i = 0; i < ureg->nr_buffers; i++)
81201e04c3fSmrg      if (ureg->buffer[i].index == nr)
81301e04c3fSmrg         return reg;
81401e04c3fSmrg
81501e04c3fSmrg   if (i < PIPE_MAX_SHADER_BUFFERS) {
81601e04c3fSmrg      ureg->buffer[i].index = nr;
81701e04c3fSmrg      ureg->buffer[i].atomic = atomic;
81801e04c3fSmrg      ureg->nr_buffers++;
81901e04c3fSmrg      return reg;
82001e04c3fSmrg   }
82101e04c3fSmrg
82201e04c3fSmrg   assert(0);
82301e04c3fSmrg   return reg;
82401e04c3fSmrg}
82501e04c3fSmrg
82601e04c3fSmrg/* Allocate a memory area.
82701e04c3fSmrg */
82801e04c3fSmrgstruct ureg_src ureg_DECL_memory(struct ureg_program *ureg,
82901e04c3fSmrg                                 unsigned memory_type)
83001e04c3fSmrg{
83101e04c3fSmrg   struct ureg_src reg = ureg_src_register(TGSI_FILE_MEMORY, memory_type);
83201e04c3fSmrg
83301e04c3fSmrg   ureg->use_memory[memory_type] = true;
83401e04c3fSmrg   return reg;
83501e04c3fSmrg}
83601e04c3fSmrg
83701e04c3fSmrgstatic int
83801e04c3fSmrgmatch_or_expand_immediate64( const unsigned *v,
83901e04c3fSmrg                             unsigned nr,
84001e04c3fSmrg                             unsigned *v2,
84101e04c3fSmrg                             unsigned *pnr2,
84201e04c3fSmrg                             unsigned *swizzle )
84301e04c3fSmrg{
84401e04c3fSmrg   unsigned nr2 = *pnr2;
84501e04c3fSmrg   unsigned i, j;
84601e04c3fSmrg   *swizzle = 0;
84701e04c3fSmrg
84801e04c3fSmrg   for (i = 0; i < nr; i += 2) {
84901e04c3fSmrg      boolean found = FALSE;
85001e04c3fSmrg
85101e04c3fSmrg      for (j = 0; j < nr2 && !found; j += 2) {
85201e04c3fSmrg         if (v[i] == v2[j] && v[i + 1] == v2[j + 1]) {
85301e04c3fSmrg            *swizzle |= (j << (i * 2)) | ((j + 1) << ((i + 1) * 2));
85401e04c3fSmrg            found = TRUE;
85501e04c3fSmrg         }
85601e04c3fSmrg      }
85701e04c3fSmrg      if (!found) {
85801e04c3fSmrg         if ((nr2) >= 4) {
85901e04c3fSmrg            return FALSE;
86001e04c3fSmrg         }
86101e04c3fSmrg
86201e04c3fSmrg         v2[nr2] = v[i];
86301e04c3fSmrg         v2[nr2 + 1] = v[i + 1];
86401e04c3fSmrg
86501e04c3fSmrg         *swizzle |= (nr2 << (i * 2)) | ((nr2 + 1) << ((i + 1) * 2));
86601e04c3fSmrg         nr2 += 2;
86701e04c3fSmrg      }
86801e04c3fSmrg   }
86901e04c3fSmrg
87001e04c3fSmrg   /* Actually expand immediate only when fully succeeded.
87101e04c3fSmrg    */
87201e04c3fSmrg   *pnr2 = nr2;
87301e04c3fSmrg   return TRUE;
87401e04c3fSmrg}
87501e04c3fSmrg
876cdc920a0Smrgstatic int
877cdc920a0Smrgmatch_or_expand_immediate( const unsigned *v,
87801e04c3fSmrg                           int type,
879cdc920a0Smrg                           unsigned nr,
880cdc920a0Smrg                           unsigned *v2,
881cdc920a0Smrg                           unsigned *pnr2,
882cdc920a0Smrg                           unsigned *swizzle )
8834a49301eSmrg{
884cdc920a0Smrg   unsigned nr2 = *pnr2;
8854a49301eSmrg   unsigned i, j;
886cdc920a0Smrg
88701e04c3fSmrg   if (type == TGSI_IMM_FLOAT64 ||
88801e04c3fSmrg       type == TGSI_IMM_UINT64 ||
88901e04c3fSmrg       type == TGSI_IMM_INT64)
89001e04c3fSmrg      return match_or_expand_immediate64(v, nr, v2, pnr2, swizzle);
89101e04c3fSmrg
8924a49301eSmrg   *swizzle = 0;
8934a49301eSmrg
8944a49301eSmrg   for (i = 0; i < nr; i++) {
8954a49301eSmrg      boolean found = FALSE;
8964a49301eSmrg
897cdc920a0Smrg      for (j = 0; j < nr2 && !found; j++) {
8984a49301eSmrg         if (v[i] == v2[j]) {
8994a49301eSmrg            *swizzle |= j << (i * 2);
9004a49301eSmrg            found = TRUE;
9014a49301eSmrg         }
9024a49301eSmrg      }
9034a49301eSmrg
9044a49301eSmrg      if (!found) {
905cdc920a0Smrg         if (nr2 >= 4) {
9064a49301eSmrg            return FALSE;
907cdc920a0Smrg         }
9084a49301eSmrg
909cdc920a0Smrg         v2[nr2] = v[i];
910cdc920a0Smrg         *swizzle |= nr2 << (i * 2);
911cdc920a0Smrg         nr2++;
9124a49301eSmrg      }
9134a49301eSmrg   }
9144a49301eSmrg
915cdc920a0Smrg   /* Actually expand immediate only when fully succeeded.
916cdc920a0Smrg    */
917cdc920a0Smrg   *pnr2 = nr2;
9184a49301eSmrg   return TRUE;
9194a49301eSmrg}
9204a49301eSmrg
9214a49301eSmrg
922cdc920a0Smrgstatic struct ureg_src
923cdc920a0Smrgdecl_immediate( struct ureg_program *ureg,
924cdc920a0Smrg                const unsigned *v,
925cdc920a0Smrg                unsigned nr,
926cdc920a0Smrg                unsigned type )
9274a49301eSmrg{
9284a49301eSmrg   unsigned i, j;
929cdc920a0Smrg   unsigned swizzle = 0;
9304a49301eSmrg
9314a49301eSmrg   /* Could do a first pass where we examine all existing immediates
9324a49301eSmrg    * without expanding.
9334a49301eSmrg    */
9344a49301eSmrg
9354a49301eSmrg   for (i = 0; i < ureg->nr_immediates; i++) {
936cdc920a0Smrg      if (ureg->immediate[i].type != type) {
937cdc920a0Smrg         continue;
938cdc920a0Smrg      }
939cdc920a0Smrg      if (match_or_expand_immediate(v,
94001e04c3fSmrg                                    type,
941cdc920a0Smrg                                    nr,
942cdc920a0Smrg                                    ureg->immediate[i].value.u,
943cdc920a0Smrg                                    &ureg->immediate[i].nr,
944cdc920a0Smrg                                    &swizzle)) {
9454a49301eSmrg         goto out;
946cdc920a0Smrg      }
9474a49301eSmrg   }
9484a49301eSmrg
9494a49301eSmrg   if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
9504a49301eSmrg      i = ureg->nr_immediates++;
951cdc920a0Smrg      ureg->immediate[i].type = type;
952cdc920a0Smrg      if (match_or_expand_immediate(v,
95301e04c3fSmrg                                    type,
954cdc920a0Smrg                                    nr,
955cdc920a0Smrg                                    ureg->immediate[i].value.u,
956cdc920a0Smrg                                    &ureg->immediate[i].nr,
957cdc920a0Smrg                                    &swizzle)) {
9584a49301eSmrg         goto out;
959cdc920a0Smrg      }
9604a49301eSmrg   }
9614a49301eSmrg
962cdc920a0Smrg   set_bad(ureg);
9634a49301eSmrg
9644a49301eSmrgout:
9654a49301eSmrg   /* Make sure that all referenced elements are from this immediate.
9664a49301eSmrg    * Has the effect of making size-one immediates into scalars.
9674a49301eSmrg    */
96801e04c3fSmrg   if (type == TGSI_IMM_FLOAT64 ||
96901e04c3fSmrg       type == TGSI_IMM_UINT64 ||
97001e04c3fSmrg       type == TGSI_IMM_INT64) {
97101e04c3fSmrg      for (j = nr; j < 4; j+=2) {
97201e04c3fSmrg         swizzle |= (swizzle & 0xf) << (j * 2);
97301e04c3fSmrg      }
97401e04c3fSmrg   } else {
97501e04c3fSmrg      for (j = nr; j < 4; j++) {
97601e04c3fSmrg         swizzle |= (swizzle & 0x3) << (j * 2);
97701e04c3fSmrg      }
978cdc920a0Smrg   }
979cdc920a0Smrg   return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i),
980cdc920a0Smrg                       (swizzle >> 0) & 0x3,
981cdc920a0Smrg                       (swizzle >> 2) & 0x3,
982cdc920a0Smrg                       (swizzle >> 4) & 0x3,
983cdc920a0Smrg                       (swizzle >> 6) & 0x3);
984cdc920a0Smrg}
985cdc920a0Smrg
986cdc920a0Smrg
987cdc920a0Smrgstruct ureg_src
988cdc920a0Smrgureg_DECL_immediate( struct ureg_program *ureg,
989cdc920a0Smrg                     const float *v,
990cdc920a0Smrg                     unsigned nr )
991cdc920a0Smrg{
992cdc920a0Smrg   union {
993cdc920a0Smrg      float f[4];
994cdc920a0Smrg      unsigned u[4];
995cdc920a0Smrg   } fu;
996cdc920a0Smrg   unsigned int i;
997cdc920a0Smrg
998cdc920a0Smrg   for (i = 0; i < nr; i++) {
999cdc920a0Smrg      fu.f[i] = v[i];
1000cdc920a0Smrg   }
1001cdc920a0Smrg
1002cdc920a0Smrg   return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32);
1003cdc920a0Smrg}
1004cdc920a0Smrg
100501e04c3fSmrgstruct ureg_src
100601e04c3fSmrgureg_DECL_immediate_f64( struct ureg_program *ureg,
100701e04c3fSmrg                         const double *v,
100801e04c3fSmrg                         unsigned nr )
100901e04c3fSmrg{
101001e04c3fSmrg   union {
101101e04c3fSmrg      unsigned u[4];
101201e04c3fSmrg      double d[2];
101301e04c3fSmrg   } fu;
101401e04c3fSmrg   unsigned int i;
101501e04c3fSmrg
101601e04c3fSmrg   assert((nr / 2) < 3);
101701e04c3fSmrg   for (i = 0; i < nr / 2; i++) {
101801e04c3fSmrg      fu.d[i] = v[i];
101901e04c3fSmrg   }
102001e04c3fSmrg
102101e04c3fSmrg   return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT64);
102201e04c3fSmrg}
1023cdc920a0Smrg
1024cdc920a0Smrgstruct ureg_src
1025cdc920a0Smrgureg_DECL_immediate_uint( struct ureg_program *ureg,
1026cdc920a0Smrg                          const unsigned *v,
1027cdc920a0Smrg                          unsigned nr )
1028cdc920a0Smrg{
1029cdc920a0Smrg   return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32);
1030cdc920a0Smrg}
1031cdc920a0Smrg
1032cdc920a0Smrg
1033cdc920a0Smrgstruct ureg_src
1034cdc920a0Smrgureg_DECL_immediate_block_uint( struct ureg_program *ureg,
1035cdc920a0Smrg                                const unsigned *v,
1036cdc920a0Smrg                                unsigned nr )
1037cdc920a0Smrg{
1038cdc920a0Smrg   uint index;
1039cdc920a0Smrg   uint i;
1040cdc920a0Smrg
1041cdc920a0Smrg   if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) {
1042cdc920a0Smrg      set_bad(ureg);
1043cdc920a0Smrg      return ureg_src_register(TGSI_FILE_IMMEDIATE, 0);
1044cdc920a0Smrg   }
1045cdc920a0Smrg
1046cdc920a0Smrg   index = ureg->nr_immediates;
1047cdc920a0Smrg   ureg->nr_immediates += (nr + 3) / 4;
1048cdc920a0Smrg
1049cdc920a0Smrg   for (i = index; i < ureg->nr_immediates; i++) {
1050cdc920a0Smrg      ureg->immediate[i].type = TGSI_IMM_UINT32;
1051cdc920a0Smrg      ureg->immediate[i].nr = nr > 4 ? 4 : nr;
1052cdc920a0Smrg      memcpy(ureg->immediate[i].value.u,
1053cdc920a0Smrg             &v[(i - index) * 4],
1054cdc920a0Smrg             ureg->immediate[i].nr * sizeof(uint));
1055cdc920a0Smrg      nr -= 4;
1056cdc920a0Smrg   }
1057cdc920a0Smrg
1058cdc920a0Smrg   return ureg_src_register(TGSI_FILE_IMMEDIATE, index);
1059cdc920a0Smrg}
1060cdc920a0Smrg
1061cdc920a0Smrg
1062cdc920a0Smrgstruct ureg_src
1063cdc920a0Smrgureg_DECL_immediate_int( struct ureg_program *ureg,
1064cdc920a0Smrg                         const int *v,
1065cdc920a0Smrg                         unsigned nr )
1066cdc920a0Smrg{
1067cdc920a0Smrg   return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32);
10684a49301eSmrg}
10694a49301eSmrg
107001e04c3fSmrgstruct ureg_src
107101e04c3fSmrgureg_DECL_immediate_uint64( struct ureg_program *ureg,
107201e04c3fSmrg                            const uint64_t *v,
107301e04c3fSmrg                            unsigned nr )
107401e04c3fSmrg{
107501e04c3fSmrg   union {
107601e04c3fSmrg      unsigned u[4];
107701e04c3fSmrg      uint64_t u64[2];
107801e04c3fSmrg   } fu;
107901e04c3fSmrg   unsigned int i;
108001e04c3fSmrg
108101e04c3fSmrg   assert((nr / 2) < 3);
108201e04c3fSmrg   for (i = 0; i < nr / 2; i++) {
108301e04c3fSmrg      fu.u64[i] = v[i];
108401e04c3fSmrg   }
108501e04c3fSmrg
108601e04c3fSmrg   return decl_immediate(ureg, fu.u, nr, TGSI_IMM_UINT64);
108701e04c3fSmrg}
108801e04c3fSmrg
108901e04c3fSmrgstruct ureg_src
109001e04c3fSmrgureg_DECL_immediate_int64( struct ureg_program *ureg,
109101e04c3fSmrg                           const int64_t *v,
109201e04c3fSmrg                           unsigned nr )
109301e04c3fSmrg{
109401e04c3fSmrg   union {
109501e04c3fSmrg      unsigned u[4];
109601e04c3fSmrg      int64_t i64[2];
109701e04c3fSmrg   } fu;
109801e04c3fSmrg   unsigned int i;
109901e04c3fSmrg
110001e04c3fSmrg   assert((nr / 2) < 3);
110101e04c3fSmrg   for (i = 0; i < nr / 2; i++) {
110201e04c3fSmrg      fu.i64[i] = v[i];
110301e04c3fSmrg   }
110401e04c3fSmrg
110501e04c3fSmrg   return decl_immediate(ureg, fu.u, nr, TGSI_IMM_INT64);
110601e04c3fSmrg}
11074a49301eSmrg
11083464ebd5Sriastradhvoid
11094a49301eSmrgureg_emit_src( struct ureg_program *ureg,
11104a49301eSmrg               struct ureg_src src )
11114a49301eSmrg{
11123464ebd5Sriastradh   unsigned size = 1 + (src.Indirect ? 1 : 0) +
11133464ebd5Sriastradh                   (src.Dimension ? (src.DimIndirect ? 2 : 1) : 0);
11144a49301eSmrg
11154a49301eSmrg   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
11164a49301eSmrg   unsigned n = 0;
11174a49301eSmrg
11184a49301eSmrg   assert(src.File != TGSI_FILE_NULL);
11194a49301eSmrg   assert(src.File < TGSI_FILE_COUNT);
112001e04c3fSmrg
11214a49301eSmrg   out[n].value = 0;
11224a49301eSmrg   out[n].src.File = src.File;
11234a49301eSmrg   out[n].src.SwizzleX = src.SwizzleX;
11244a49301eSmrg   out[n].src.SwizzleY = src.SwizzleY;
11254a49301eSmrg   out[n].src.SwizzleZ = src.SwizzleZ;
11264a49301eSmrg   out[n].src.SwizzleW = src.SwizzleW;
11274a49301eSmrg   out[n].src.Index = src.Index;
11284a49301eSmrg   out[n].src.Negate = src.Negate;
1129cdc920a0Smrg   out[0].src.Absolute = src.Absolute;
11304a49301eSmrg   n++;
11314a49301eSmrg
11324a49301eSmrg   if (src.Indirect) {
11334a49301eSmrg      out[0].src.Indirect = 1;
11344a49301eSmrg      out[n].value = 0;
1135af69d88dSmrg      out[n].ind.File = src.IndirectFile;
1136af69d88dSmrg      out[n].ind.Swizzle = src.IndirectSwizzle;
1137af69d88dSmrg      out[n].ind.Index = src.IndirectIndex;
113801e04c3fSmrg      if (!ureg->supports_any_inout_decl_range &&
113901e04c3fSmrg          (src.File == TGSI_FILE_INPUT || src.File == TGSI_FILE_OUTPUT))
114001e04c3fSmrg         out[n].ind.ArrayID = 0;
114101e04c3fSmrg      else
114201e04c3fSmrg         out[n].ind.ArrayID = src.ArrayID;
11434a49301eSmrg      n++;
11444a49301eSmrg   }
11454a49301eSmrg
1146cdc920a0Smrg   if (src.Dimension) {
1147af69d88dSmrg      out[0].src.Dimension = 1;
1148af69d88dSmrg      out[n].dim.Dimension = 0;
1149af69d88dSmrg      out[n].dim.Padding = 0;
11503464ebd5Sriastradh      if (src.DimIndirect) {
11513464ebd5Sriastradh         out[n].dim.Indirect = 1;
11523464ebd5Sriastradh         out[n].dim.Index = src.DimensionIndex;
11533464ebd5Sriastradh         n++;
11543464ebd5Sriastradh         out[n].value = 0;
1155af69d88dSmrg         out[n].ind.File = src.DimIndFile;
1156af69d88dSmrg         out[n].ind.Swizzle = src.DimIndSwizzle;
1157af69d88dSmrg         out[n].ind.Index = src.DimIndIndex;
115801e04c3fSmrg         if (!ureg->supports_any_inout_decl_range &&
115901e04c3fSmrg             (src.File == TGSI_FILE_INPUT || src.File == TGSI_FILE_OUTPUT))
116001e04c3fSmrg            out[n].ind.ArrayID = 0;
116101e04c3fSmrg         else
116201e04c3fSmrg            out[n].ind.ArrayID = src.ArrayID;
11633464ebd5Sriastradh      } else {
11643464ebd5Sriastradh         out[n].dim.Indirect = 0;
11653464ebd5Sriastradh         out[n].dim.Index = src.DimensionIndex;
11663464ebd5Sriastradh      }
1167cdc920a0Smrg      n++;
1168cdc920a0Smrg   }
1169cdc920a0Smrg
11704a49301eSmrg   assert(n == size);
11714a49301eSmrg}
11724a49301eSmrg
11734a49301eSmrg
117401e04c3fSmrgvoid
11754a49301eSmrgureg_emit_dst( struct ureg_program *ureg,
11764a49301eSmrg               struct ureg_dst dst )
11774a49301eSmrg{
117801e04c3fSmrg   unsigned size = 1 + (dst.Indirect ? 1 : 0) +
117901e04c3fSmrg                   (dst.Dimension ? (dst.DimIndirect ? 2 : 1) : 0);
11804a49301eSmrg
11814a49301eSmrg   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
11824a49301eSmrg   unsigned n = 0;
11834a49301eSmrg
11844a49301eSmrg   assert(dst.File != TGSI_FILE_NULL);
11854a49301eSmrg   assert(dst.File != TGSI_FILE_SAMPLER);
1186af69d88dSmrg   assert(dst.File != TGSI_FILE_SAMPLER_VIEW);
11874a49301eSmrg   assert(dst.File != TGSI_FILE_IMMEDIATE);
11884a49301eSmrg   assert(dst.File < TGSI_FILE_COUNT);
11893464ebd5Sriastradh
11904a49301eSmrg   out[n].value = 0;
11914a49301eSmrg   out[n].dst.File = dst.File;
11924a49301eSmrg   out[n].dst.WriteMask = dst.WriteMask;
11934a49301eSmrg   out[n].dst.Indirect = dst.Indirect;
11944a49301eSmrg   out[n].dst.Index = dst.Index;
11954a49301eSmrg   n++;
119601e04c3fSmrg
11974a49301eSmrg   if (dst.Indirect) {
11984a49301eSmrg      out[n].value = 0;
1199af69d88dSmrg      out[n].ind.File = dst.IndirectFile;
1200af69d88dSmrg      out[n].ind.Swizzle = dst.IndirectSwizzle;
1201af69d88dSmrg      out[n].ind.Index = dst.IndirectIndex;
120201e04c3fSmrg      if (!ureg->supports_any_inout_decl_range &&
120301e04c3fSmrg          (dst.File == TGSI_FILE_INPUT || dst.File == TGSI_FILE_OUTPUT))
120401e04c3fSmrg         out[n].ind.ArrayID = 0;
120501e04c3fSmrg      else
120601e04c3fSmrg         out[n].ind.ArrayID = dst.ArrayID;
120701e04c3fSmrg      n++;
120801e04c3fSmrg   }
120901e04c3fSmrg
121001e04c3fSmrg   if (dst.Dimension) {
121101e04c3fSmrg      out[0].dst.Dimension = 1;
121201e04c3fSmrg      out[n].dim.Dimension = 0;
121301e04c3fSmrg      out[n].dim.Padding = 0;
121401e04c3fSmrg      if (dst.DimIndirect) {
121501e04c3fSmrg         out[n].dim.Indirect = 1;
121601e04c3fSmrg         out[n].dim.Index = dst.DimensionIndex;
121701e04c3fSmrg         n++;
121801e04c3fSmrg         out[n].value = 0;
121901e04c3fSmrg         out[n].ind.File = dst.DimIndFile;
122001e04c3fSmrg         out[n].ind.Swizzle = dst.DimIndSwizzle;
122101e04c3fSmrg         out[n].ind.Index = dst.DimIndIndex;
122201e04c3fSmrg         if (!ureg->supports_any_inout_decl_range &&
122301e04c3fSmrg             (dst.File == TGSI_FILE_INPUT || dst.File == TGSI_FILE_OUTPUT))
122401e04c3fSmrg            out[n].ind.ArrayID = 0;
122501e04c3fSmrg         else
122601e04c3fSmrg            out[n].ind.ArrayID = dst.ArrayID;
122701e04c3fSmrg      } else {
122801e04c3fSmrg         out[n].dim.Indirect = 0;
122901e04c3fSmrg         out[n].dim.Index = dst.DimensionIndex;
123001e04c3fSmrg      }
12314a49301eSmrg      n++;
12324a49301eSmrg   }
12334a49301eSmrg
12344a49301eSmrg   assert(n == size);
12354a49301eSmrg}
12364a49301eSmrg
12374a49301eSmrg
123801e04c3fSmrgstatic void validate( enum tgsi_opcode opcode,
12394a49301eSmrg                      unsigned nr_dst,
12404a49301eSmrg                      unsigned nr_src )
12414a49301eSmrg{
12427ec681f3Smrg#ifndef NDEBUG
12434a49301eSmrg   const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
12444a49301eSmrg   assert(info);
124501e04c3fSmrg   if (info) {
12464a49301eSmrg      assert(nr_dst == info->num_dst);
12474a49301eSmrg      assert(nr_src == info->num_src);
12484a49301eSmrg   }
12494a49301eSmrg#endif
12504a49301eSmrg}
12514a49301eSmrg
12524a49301eSmrgstruct ureg_emit_insn_result
12534a49301eSmrgureg_emit_insn(struct ureg_program *ureg,
125401e04c3fSmrg               enum tgsi_opcode opcode,
12554a49301eSmrg               boolean saturate,
125601e04c3fSmrg               unsigned precise,
12574a49301eSmrg               unsigned num_dst,
125801e04c3fSmrg               unsigned num_src)
12594a49301eSmrg{
12604a49301eSmrg   union tgsi_any_token *out;
126101e04c3fSmrg   uint count = 1;
12624a49301eSmrg   struct ureg_emit_insn_result result;
12634a49301eSmrg
12644a49301eSmrg   validate( opcode, num_dst, num_src );
126501e04c3fSmrg
12664a49301eSmrg   out = get_tokens( ureg, DOMAIN_INSN, count );
1267cdc920a0Smrg   out[0].insn = tgsi_default_instruction();
12684a49301eSmrg   out[0].insn.Opcode = opcode;
12694a49301eSmrg   out[0].insn.Saturate = saturate;
127001e04c3fSmrg   out[0].insn.Precise = precise;
12714a49301eSmrg   out[0].insn.NumDstRegs = num_dst;
12724a49301eSmrg   out[0].insn.NumSrcRegs = num_src;
12734a49301eSmrg
12744a49301eSmrg   result.insn_token = ureg->domain[DOMAIN_INSN].count - count;
1275cdc920a0Smrg   result.extended_token = result.insn_token;
12764a49301eSmrg
12774a49301eSmrg   ureg->nr_instructions++;
1278cdc920a0Smrg
12794a49301eSmrg   return result;
12804a49301eSmrg}
12814a49301eSmrg
12824a49301eSmrg
128301e04c3fSmrg/**
128401e04c3fSmrg * Emit a label token.
128501e04c3fSmrg * \param label_token returns a token number indicating where the label
128601e04c3fSmrg * needs to be patched later.  Later, this value should be passed to the
128701e04c3fSmrg * ureg_fixup_label() function.
128801e04c3fSmrg */
12894a49301eSmrgvoid
12904a49301eSmrgureg_emit_label(struct ureg_program *ureg,
12914a49301eSmrg                unsigned extended_token,
12924a49301eSmrg                unsigned *label_token )
12934a49301eSmrg{
12944a49301eSmrg   union tgsi_any_token *out, *insn;
12954a49301eSmrg
129601e04c3fSmrg   if (!label_token)
12974a49301eSmrg      return;
12984a49301eSmrg
12994a49301eSmrg   out = get_tokens( ureg, DOMAIN_INSN, 1 );
1300cdc920a0Smrg   out[0].value = 0;
13014a49301eSmrg
1302cdc920a0Smrg   insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
1303cdc920a0Smrg   insn->insn.Label = 1;
13044a49301eSmrg
13054a49301eSmrg   *label_token = ureg->domain[DOMAIN_INSN].count - 1;
13064a49301eSmrg}
13074a49301eSmrg
13084a49301eSmrg/* Will return a number which can be used in a label to point to the
13094a49301eSmrg * next instruction to be emitted.
13104a49301eSmrg */
13114a49301eSmrgunsigned
13124a49301eSmrgureg_get_instruction_number( struct ureg_program *ureg )
13134a49301eSmrg{
13144a49301eSmrg   return ureg->nr_instructions;
13154a49301eSmrg}
13164a49301eSmrg
13174a49301eSmrg/* Patch a given label (expressed as a token number) to point to a
13184a49301eSmrg * given instruction (expressed as an instruction number).
13194a49301eSmrg */
13204a49301eSmrgvoid
13214a49301eSmrgureg_fixup_label(struct ureg_program *ureg,
13224a49301eSmrg                 unsigned label_token,
13234a49301eSmrg                 unsigned instruction_number )
13244a49301eSmrg{
13254a49301eSmrg   union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
13264a49301eSmrg
1327cdc920a0Smrg   out->insn_label.Label = instruction_number;
13284a49301eSmrg}
13294a49301eSmrg
13304a49301eSmrg
13314a49301eSmrgvoid
13324a49301eSmrgureg_emit_texture(struct ureg_program *ureg,
13334a49301eSmrg                  unsigned extended_token,
133401e04c3fSmrg                  enum tgsi_texture_type target,
133501e04c3fSmrg                  enum tgsi_return_type return_type, unsigned num_offsets)
13364a49301eSmrg{
13374a49301eSmrg   union tgsi_any_token *out, *insn;
13384a49301eSmrg
13394a49301eSmrg   out = get_tokens( ureg, DOMAIN_INSN, 1 );
13404a49301eSmrg   insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
13414a49301eSmrg
1342cdc920a0Smrg   insn->insn.Texture = 1;
13434a49301eSmrg
13444a49301eSmrg   out[0].value = 0;
1345cdc920a0Smrg   out[0].insn_texture.Texture = target;
1346af69d88dSmrg   out[0].insn_texture.NumOffsets = num_offsets;
134701e04c3fSmrg   out[0].insn_texture.ReturnType = return_type;
1348af69d88dSmrg}
1349af69d88dSmrg
1350af69d88dSmrgvoid
1351af69d88dSmrgureg_emit_texture_offset(struct ureg_program *ureg,
1352af69d88dSmrg                         const struct tgsi_texture_offset *offset)
1353af69d88dSmrg{
1354af69d88dSmrg   union tgsi_any_token *out;
1355af69d88dSmrg
1356af69d88dSmrg   out = get_tokens( ureg, DOMAIN_INSN, 1);
1357af69d88dSmrg
1358af69d88dSmrg   out[0].value = 0;
1359af69d88dSmrg   out[0].insn_texture_offset = *offset;
13604a49301eSmrg}
13614a49301eSmrg
136201e04c3fSmrgvoid
136301e04c3fSmrgureg_emit_memory(struct ureg_program *ureg,
136401e04c3fSmrg                 unsigned extended_token,
136501e04c3fSmrg                 unsigned qualifier,
136601e04c3fSmrg                 enum tgsi_texture_type texture,
136701e04c3fSmrg                 enum pipe_format format)
136801e04c3fSmrg{
136901e04c3fSmrg   union tgsi_any_token *out, *insn;
137001e04c3fSmrg
137101e04c3fSmrg   out = get_tokens( ureg, DOMAIN_INSN, 1 );
137201e04c3fSmrg   insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
137301e04c3fSmrg
137401e04c3fSmrg   insn->insn.Memory = 1;
137501e04c3fSmrg
137601e04c3fSmrg   out[0].value = 0;
137701e04c3fSmrg   out[0].insn_memory.Qualifier = qualifier;
137801e04c3fSmrg   out[0].insn_memory.Texture = texture;
137901e04c3fSmrg   out[0].insn_memory.Format = format;
138001e04c3fSmrg}
13814a49301eSmrg
13824a49301eSmrgvoid
13834a49301eSmrgureg_fixup_insn_size(struct ureg_program *ureg,
13844a49301eSmrg                     unsigned insn )
13854a49301eSmrg{
13864a49301eSmrg   union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
13874a49301eSmrg
13884a49301eSmrg   assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
13894a49301eSmrg   out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1;
13904a49301eSmrg}
13914a49301eSmrg
13924a49301eSmrg
13934a49301eSmrgvoid
13944a49301eSmrgureg_insn(struct ureg_program *ureg,
139501e04c3fSmrg          enum tgsi_opcode opcode,
13964a49301eSmrg          const struct ureg_dst *dst,
13974a49301eSmrg          unsigned nr_dst,
13984a49301eSmrg          const struct ureg_src *src,
139901e04c3fSmrg          unsigned nr_src,
140001e04c3fSmrg          unsigned precise )
14014a49301eSmrg{
14024a49301eSmrg   struct ureg_emit_insn_result insn;
14034a49301eSmrg   unsigned i;
14044a49301eSmrg   boolean saturate;
14054a49301eSmrg
1406af69d88dSmrg   if (nr_dst && ureg_dst_is_empty(dst[0])) {
1407af69d88dSmrg      return;
1408af69d88dSmrg   }
1409af69d88dSmrg
14104a49301eSmrg   saturate = nr_dst ? dst[0].Saturate : FALSE;
14114a49301eSmrg
14124a49301eSmrg   insn = ureg_emit_insn(ureg,
14134a49301eSmrg                         opcode,
14144a49301eSmrg                         saturate,
141501e04c3fSmrg                         precise,
14164a49301eSmrg                         nr_dst,
14174a49301eSmrg                         nr_src);
14184a49301eSmrg
14194a49301eSmrg   for (i = 0; i < nr_dst; i++)
14204a49301eSmrg      ureg_emit_dst( ureg, dst[i] );
14214a49301eSmrg
14224a49301eSmrg   for (i = 0; i < nr_src; i++)
14234a49301eSmrg      ureg_emit_src( ureg, src[i] );
14244a49301eSmrg
14254a49301eSmrg   ureg_fixup_insn_size( ureg, insn.insn_token );
14264a49301eSmrg}
14274a49301eSmrg
14284a49301eSmrgvoid
14294a49301eSmrgureg_tex_insn(struct ureg_program *ureg,
143001e04c3fSmrg              enum tgsi_opcode opcode,
14314a49301eSmrg              const struct ureg_dst *dst,
14324a49301eSmrg              unsigned nr_dst,
143301e04c3fSmrg              enum tgsi_texture_type target,
143401e04c3fSmrg              enum tgsi_return_type return_type,
1435af69d88dSmrg              const struct tgsi_texture_offset *texoffsets,
1436af69d88dSmrg              unsigned nr_offset,
14374a49301eSmrg              const struct ureg_src *src,
14384a49301eSmrg              unsigned nr_src )
14394a49301eSmrg{
14404a49301eSmrg   struct ureg_emit_insn_result insn;
14414a49301eSmrg   unsigned i;
14424a49301eSmrg   boolean saturate;
14434a49301eSmrg
1444af69d88dSmrg   if (nr_dst && ureg_dst_is_empty(dst[0])) {
1445af69d88dSmrg      return;
1446af69d88dSmrg   }
1447af69d88dSmrg
14484a49301eSmrg   saturate = nr_dst ? dst[0].Saturate : FALSE;
14494a49301eSmrg
14504a49301eSmrg   insn = ureg_emit_insn(ureg,
14514a49301eSmrg                         opcode,
14524a49301eSmrg                         saturate,
145301e04c3fSmrg                         0,
14544a49301eSmrg                         nr_dst,
14554a49301eSmrg                         nr_src);
14564a49301eSmrg
145701e04c3fSmrg   ureg_emit_texture( ureg, insn.extended_token, target, return_type,
145801e04c3fSmrg                      nr_offset );
1459af69d88dSmrg
1460af69d88dSmrg   for (i = 0; i < nr_offset; i++)
1461af69d88dSmrg      ureg_emit_texture_offset( ureg, &texoffsets[i]);
14624a49301eSmrg
14634a49301eSmrg   for (i = 0; i < nr_dst; i++)
14644a49301eSmrg      ureg_emit_dst( ureg, dst[i] );
14654a49301eSmrg
14664a49301eSmrg   for (i = 0; i < nr_src; i++)
14674a49301eSmrg      ureg_emit_src( ureg, src[i] );
14684a49301eSmrg
14694a49301eSmrg   ureg_fixup_insn_size( ureg, insn.insn_token );
14704a49301eSmrg}
14714a49301eSmrg
14724a49301eSmrg
14734a49301eSmrgvoid
147401e04c3fSmrgureg_memory_insn(struct ureg_program *ureg,
147501e04c3fSmrg                 enum tgsi_opcode opcode,
147601e04c3fSmrg                 const struct ureg_dst *dst,
147701e04c3fSmrg                 unsigned nr_dst,
147801e04c3fSmrg                 const struct ureg_src *src,
147901e04c3fSmrg                 unsigned nr_src,
148001e04c3fSmrg                 unsigned qualifier,
148101e04c3fSmrg                 enum tgsi_texture_type texture,
148201e04c3fSmrg                 enum pipe_format format)
14834a49301eSmrg{
14844a49301eSmrg   struct ureg_emit_insn_result insn;
14854a49301eSmrg   unsigned i;
14864a49301eSmrg
14874a49301eSmrg   insn = ureg_emit_insn(ureg,
14884a49301eSmrg                         opcode,
14894a49301eSmrg                         FALSE,
14904a49301eSmrg                         0,
149101e04c3fSmrg                         nr_dst,
14924a49301eSmrg                         nr_src);
14934a49301eSmrg
149401e04c3fSmrg   ureg_emit_memory(ureg, insn.extended_token, qualifier, texture, format);
149501e04c3fSmrg
149601e04c3fSmrg   for (i = 0; i < nr_dst; i++)
149701e04c3fSmrg      ureg_emit_dst(ureg, dst[i]);
14984a49301eSmrg
14994a49301eSmrg   for (i = 0; i < nr_src; i++)
150001e04c3fSmrg      ureg_emit_src(ureg, src[i]);
15014a49301eSmrg
150201e04c3fSmrg   ureg_fixup_insn_size(ureg, insn.insn_token);
15034a49301eSmrg}
15044a49301eSmrg
15054a49301eSmrg
1506cdc920a0Smrgstatic void
1507cdc920a0Smrgemit_decl_semantic(struct ureg_program *ureg,
1508cdc920a0Smrg                   unsigned file,
150901e04c3fSmrg                   unsigned first,
151001e04c3fSmrg                   unsigned last,
151101e04c3fSmrg                   enum tgsi_semantic semantic_name,
1512af69d88dSmrg                   unsigned semantic_index,
151301e04c3fSmrg                   unsigned streams,
151401e04c3fSmrg                   unsigned usage_mask,
151501e04c3fSmrg                   unsigned array_id,
151601e04c3fSmrg                   boolean invariant)
15174a49301eSmrg{
151801e04c3fSmrg   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3);
15194a49301eSmrg
15204a49301eSmrg   out[0].value = 0;
15214a49301eSmrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
15224a49301eSmrg   out[0].decl.NrTokens = 3;
15234a49301eSmrg   out[0].decl.File = file;
1524af69d88dSmrg   out[0].decl.UsageMask = usage_mask;
15254a49301eSmrg   out[0].decl.Semantic = 1;
152601e04c3fSmrg   out[0].decl.Array = array_id != 0;
152701e04c3fSmrg   out[0].decl.Invariant = invariant;
15284a49301eSmrg
15294a49301eSmrg   out[1].value = 0;
153001e04c3fSmrg   out[1].decl_range.First = first;
153101e04c3fSmrg   out[1].decl_range.Last = last;
15324a49301eSmrg
15334a49301eSmrg   out[2].value = 0;
1534cdc920a0Smrg   out[2].decl_semantic.Name = semantic_name;
1535cdc920a0Smrg   out[2].decl_semantic.Index = semantic_index;
153601e04c3fSmrg   out[2].decl_semantic.StreamX = streams & 3;
153701e04c3fSmrg   out[2].decl_semantic.StreamY = (streams >> 2) & 3;
153801e04c3fSmrg   out[2].decl_semantic.StreamZ = (streams >> 4) & 3;
153901e04c3fSmrg   out[2].decl_semantic.StreamW = (streams >> 6) & 3;
154001e04c3fSmrg
154101e04c3fSmrg   if (array_id) {
154201e04c3fSmrg      out[3].value = 0;
154301e04c3fSmrg      out[3].array.ArrayID = array_id;
154401e04c3fSmrg   }
1545cdc920a0Smrg}
15464a49301eSmrg
154701e04c3fSmrgstatic void
154801e04c3fSmrgemit_decl_atomic_2d(struct ureg_program *ureg,
154901e04c3fSmrg                    unsigned first,
155001e04c3fSmrg                    unsigned last,
155101e04c3fSmrg                    unsigned index2D,
155201e04c3fSmrg                    unsigned array_id)
155301e04c3fSmrg{
155401e04c3fSmrg   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3);
155501e04c3fSmrg
155601e04c3fSmrg   out[0].value = 0;
155701e04c3fSmrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
155801e04c3fSmrg   out[0].decl.NrTokens = 3;
155901e04c3fSmrg   out[0].decl.File = TGSI_FILE_HW_ATOMIC;
156001e04c3fSmrg   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
156101e04c3fSmrg   out[0].decl.Dimension = 1;
156201e04c3fSmrg   out[0].decl.Array = array_id != 0;
156301e04c3fSmrg
156401e04c3fSmrg   out[1].value = 0;
156501e04c3fSmrg   out[1].decl_range.First = first;
156601e04c3fSmrg   out[1].decl_range.Last = last;
156701e04c3fSmrg
156801e04c3fSmrg   out[2].value = 0;
156901e04c3fSmrg   out[2].decl_dim.Index2D = index2D;
157001e04c3fSmrg
157101e04c3fSmrg   if (array_id) {
157201e04c3fSmrg      out[3].value = 0;
157301e04c3fSmrg      out[3].array.ArrayID = array_id;
157401e04c3fSmrg   }
157501e04c3fSmrg}
1576cdc920a0Smrg
1577cdc920a0Smrgstatic void
1578cdc920a0Smrgemit_decl_fs(struct ureg_program *ureg,
1579cdc920a0Smrg             unsigned file,
158001e04c3fSmrg             unsigned first,
158101e04c3fSmrg             unsigned last,
158201e04c3fSmrg             enum tgsi_semantic semantic_name,
1583cdc920a0Smrg             unsigned semantic_index,
158401e04c3fSmrg             enum tgsi_interpolate_mode interpolate,
158501e04c3fSmrg             enum tgsi_interpolate_loc interpolate_location,
158601e04c3fSmrg             unsigned array_id,
158701e04c3fSmrg             unsigned usage_mask)
1588cdc920a0Smrg{
158901e04c3fSmrg   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL,
159001e04c3fSmrg                                          array_id ? 5 : 4);
1591cdc920a0Smrg
1592cdc920a0Smrg   out[0].value = 0;
1593cdc920a0Smrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1594af69d88dSmrg   out[0].decl.NrTokens = 4;
1595cdc920a0Smrg   out[0].decl.File = file;
159601e04c3fSmrg   out[0].decl.UsageMask = usage_mask;
1597af69d88dSmrg   out[0].decl.Interpolate = 1;
1598cdc920a0Smrg   out[0].decl.Semantic = 1;
159901e04c3fSmrg   out[0].decl.Array = array_id != 0;
1600cdc920a0Smrg
1601cdc920a0Smrg   out[1].value = 0;
160201e04c3fSmrg   out[1].decl_range.First = first;
160301e04c3fSmrg   out[1].decl_range.Last = last;
1604cdc920a0Smrg
1605cdc920a0Smrg   out[2].value = 0;
1606af69d88dSmrg   out[2].decl_interp.Interpolate = interpolate;
1607af69d88dSmrg   out[2].decl_interp.Location = interpolate_location;
1608af69d88dSmrg
1609af69d88dSmrg   out[3].value = 0;
1610af69d88dSmrg   out[3].decl_semantic.Name = semantic_name;
1611af69d88dSmrg   out[3].decl_semantic.Index = semantic_index;
161201e04c3fSmrg
161301e04c3fSmrg   if (array_id) {
161401e04c3fSmrg      out[4].value = 0;
161501e04c3fSmrg      out[4].array.ArrayID = array_id;
161601e04c3fSmrg   }
16174a49301eSmrg}
16184a49301eSmrg
1619af69d88dSmrgstatic void
1620af69d88dSmrgemit_decl_temps( struct ureg_program *ureg,
1621af69d88dSmrg                 unsigned first, unsigned last,
1622af69d88dSmrg                 boolean local,
1623af69d88dSmrg                 unsigned arrayid )
1624af69d88dSmrg{
1625af69d88dSmrg   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL,
1626af69d88dSmrg                                           arrayid ? 3 : 2 );
1627af69d88dSmrg
1628af69d88dSmrg   out[0].value = 0;
1629af69d88dSmrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1630af69d88dSmrg   out[0].decl.NrTokens = 2;
1631af69d88dSmrg   out[0].decl.File = TGSI_FILE_TEMPORARY;
1632af69d88dSmrg   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
1633af69d88dSmrg   out[0].decl.Local = local;
1634af69d88dSmrg
1635af69d88dSmrg   out[1].value = 0;
1636af69d88dSmrg   out[1].decl_range.First = first;
1637af69d88dSmrg   out[1].decl_range.Last = last;
1638af69d88dSmrg
1639af69d88dSmrg   if (arrayid) {
1640af69d88dSmrg      out[0].decl.Array = 1;
1641af69d88dSmrg      out[2].value = 0;
1642af69d88dSmrg      out[2].array.ArrayID = arrayid;
1643af69d88dSmrg   }
1644af69d88dSmrg}
16454a49301eSmrg
16464a49301eSmrgstatic void emit_decl_range( struct ureg_program *ureg,
16474a49301eSmrg                             unsigned file,
16484a49301eSmrg                             unsigned first,
16494a49301eSmrg                             unsigned count )
16504a49301eSmrg{
16514a49301eSmrg   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
16524a49301eSmrg
16534a49301eSmrg   out[0].value = 0;
16544a49301eSmrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
16554a49301eSmrg   out[0].decl.NrTokens = 2;
16564a49301eSmrg   out[0].decl.File = file;
16573464ebd5Sriastradh   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
16584a49301eSmrg   out[0].decl.Semantic = 0;
16594a49301eSmrg
16604a49301eSmrg   out[1].value = 0;
16614a49301eSmrg   out[1].decl_range.First = first;
16624a49301eSmrg   out[1].decl_range.Last = first + count - 1;
16634a49301eSmrg}
16644a49301eSmrg
1665cdc920a0Smrgstatic void
1666cdc920a0Smrgemit_decl_range2D(struct ureg_program *ureg,
1667cdc920a0Smrg                  unsigned file,
1668cdc920a0Smrg                  unsigned first,
1669cdc920a0Smrg                  unsigned last,
1670cdc920a0Smrg                  unsigned index2D)
1671cdc920a0Smrg{
1672cdc920a0Smrg   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
1673cdc920a0Smrg
1674cdc920a0Smrg   out[0].value = 0;
1675cdc920a0Smrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
1676cdc920a0Smrg   out[0].decl.NrTokens = 3;
1677cdc920a0Smrg   out[0].decl.File = file;
16783464ebd5Sriastradh   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
1679cdc920a0Smrg   out[0].decl.Dimension = 1;
1680cdc920a0Smrg
1681cdc920a0Smrg   out[1].value = 0;
1682cdc920a0Smrg   out[1].decl_range.First = first;
1683cdc920a0Smrg   out[1].decl_range.Last = last;
1684cdc920a0Smrg
1685cdc920a0Smrg   out[2].value = 0;
1686cdc920a0Smrg   out[2].decl_dim.Index2D = index2D;
1687cdc920a0Smrg}
1688cdc920a0Smrg
16893464ebd5Sriastradhstatic void
1690af69d88dSmrgemit_decl_sampler_view(struct ureg_program *ureg,
1691af69d88dSmrg                       unsigned index,
169201e04c3fSmrg                       enum tgsi_texture_type target,
169301e04c3fSmrg                       enum tgsi_return_type return_type_x,
169401e04c3fSmrg                       enum tgsi_return_type return_type_y,
169501e04c3fSmrg                       enum tgsi_return_type return_type_z,
169601e04c3fSmrg                       enum tgsi_return_type return_type_w )
16973464ebd5Sriastradh{
16983464ebd5Sriastradh   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
16993464ebd5Sriastradh
17003464ebd5Sriastradh   out[0].value = 0;
17013464ebd5Sriastradh   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
17023464ebd5Sriastradh   out[0].decl.NrTokens = 3;
1703af69d88dSmrg   out[0].decl.File = TGSI_FILE_SAMPLER_VIEW;
170401e04c3fSmrg   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
17053464ebd5Sriastradh
17063464ebd5Sriastradh   out[1].value = 0;
17073464ebd5Sriastradh   out[1].decl_range.First = index;
17083464ebd5Sriastradh   out[1].decl_range.Last = index;
17093464ebd5Sriastradh
17103464ebd5Sriastradh   out[2].value = 0;
1711af69d88dSmrg   out[2].decl_sampler_view.Resource    = target;
1712af69d88dSmrg   out[2].decl_sampler_view.ReturnTypeX = return_type_x;
1713af69d88dSmrg   out[2].decl_sampler_view.ReturnTypeY = return_type_y;
1714af69d88dSmrg   out[2].decl_sampler_view.ReturnTypeZ = return_type_z;
1715af69d88dSmrg   out[2].decl_sampler_view.ReturnTypeW = return_type_w;
17163464ebd5Sriastradh}
17173464ebd5Sriastradh
171801e04c3fSmrgstatic void
171901e04c3fSmrgemit_decl_image(struct ureg_program *ureg,
172001e04c3fSmrg                unsigned index,
172101e04c3fSmrg                enum tgsi_texture_type target,
172201e04c3fSmrg                enum pipe_format format,
172301e04c3fSmrg                boolean wr,
172401e04c3fSmrg                boolean raw)
172501e04c3fSmrg{
172601e04c3fSmrg   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
172701e04c3fSmrg
172801e04c3fSmrg   out[0].value = 0;
172901e04c3fSmrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
173001e04c3fSmrg   out[0].decl.NrTokens = 3;
173101e04c3fSmrg   out[0].decl.File = TGSI_FILE_IMAGE;
173201e04c3fSmrg   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
173301e04c3fSmrg
173401e04c3fSmrg   out[1].value = 0;
173501e04c3fSmrg   out[1].decl_range.First = index;
173601e04c3fSmrg   out[1].decl_range.Last = index;
173701e04c3fSmrg
173801e04c3fSmrg   out[2].value = 0;
173901e04c3fSmrg   out[2].decl_image.Resource = target;
174001e04c3fSmrg   out[2].decl_image.Writable = wr;
174101e04c3fSmrg   out[2].decl_image.Raw      = raw;
174201e04c3fSmrg   out[2].decl_image.Format   = format;
174301e04c3fSmrg}
174401e04c3fSmrg
174501e04c3fSmrgstatic void
174601e04c3fSmrgemit_decl_buffer(struct ureg_program *ureg,
174701e04c3fSmrg                 unsigned index,
174801e04c3fSmrg                 bool atomic)
174901e04c3fSmrg{
175001e04c3fSmrg   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
175101e04c3fSmrg
175201e04c3fSmrg   out[0].value = 0;
175301e04c3fSmrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
175401e04c3fSmrg   out[0].decl.NrTokens = 2;
175501e04c3fSmrg   out[0].decl.File = TGSI_FILE_BUFFER;
175601e04c3fSmrg   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
175701e04c3fSmrg   out[0].decl.Atomic = atomic;
175801e04c3fSmrg
175901e04c3fSmrg   out[1].value = 0;
176001e04c3fSmrg   out[1].decl_range.First = index;
176101e04c3fSmrg   out[1].decl_range.Last = index;
176201e04c3fSmrg}
176301e04c3fSmrg
176401e04c3fSmrgstatic void
176501e04c3fSmrgemit_decl_memory(struct ureg_program *ureg, unsigned memory_type)
176601e04c3fSmrg{
176701e04c3fSmrg   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
176801e04c3fSmrg
176901e04c3fSmrg   out[0].value = 0;
177001e04c3fSmrg   out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
177101e04c3fSmrg   out[0].decl.NrTokens = 2;
177201e04c3fSmrg   out[0].decl.File = TGSI_FILE_MEMORY;
177301e04c3fSmrg   out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
177401e04c3fSmrg   out[0].decl.MemType = memory_type;
177501e04c3fSmrg
177601e04c3fSmrg   out[1].value = 0;
177701e04c3fSmrg   out[1].decl_range.First = memory_type;
177801e04c3fSmrg   out[1].decl_range.Last = memory_type;
177901e04c3fSmrg}
178001e04c3fSmrg
1781cdc920a0Smrgstatic void
1782cdc920a0Smrgemit_immediate( struct ureg_program *ureg,
1783cdc920a0Smrg                const unsigned *v,
1784cdc920a0Smrg                unsigned type )
17854a49301eSmrg{
17864a49301eSmrg   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
17874a49301eSmrg
17884a49301eSmrg   out[0].value = 0;
17894a49301eSmrg   out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
17904a49301eSmrg   out[0].imm.NrTokens = 5;
1791cdc920a0Smrg   out[0].imm.DataType = type;
17924a49301eSmrg   out[0].imm.Padding = 0;
17934a49301eSmrg
1794cdc920a0Smrg   out[1].imm_data.Uint = v[0];
1795cdc920a0Smrg   out[2].imm_data.Uint = v[1];
1796cdc920a0Smrg   out[3].imm_data.Uint = v[2];
1797cdc920a0Smrg   out[4].imm_data.Uint = v[3];
17984a49301eSmrg}
17994a49301eSmrg
1800cdc920a0Smrgstatic void
1801cdc920a0Smrgemit_property(struct ureg_program *ureg,
1802cdc920a0Smrg              unsigned name,
1803cdc920a0Smrg              unsigned data)
1804cdc920a0Smrg{
1805cdc920a0Smrg   union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
18064a49301eSmrg
1807cdc920a0Smrg   out[0].value = 0;
1808cdc920a0Smrg   out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY;
1809cdc920a0Smrg   out[0].prop.NrTokens = 2;
1810cdc920a0Smrg   out[0].prop.PropertyName = name;
1811cdc920a0Smrg
1812cdc920a0Smrg   out[1].prop_data.Data = data;
1813cdc920a0Smrg}
18144a49301eSmrg
18157ec681f3Smrgstatic int
18167ec681f3Smrginput_sort(const void *in_a, const void *in_b)
18177ec681f3Smrg{
18187ec681f3Smrg   const struct ureg_input_decl *a = in_a, *b = in_b;
18197ec681f3Smrg
18207ec681f3Smrg   return a->first - b->first;
18217ec681f3Smrg}
18227ec681f3Smrg
18237ec681f3Smrgstatic int
18247ec681f3Smrgoutput_sort(const void *in_a, const void *in_b)
18257ec681f3Smrg{
18267ec681f3Smrg   const struct ureg_output_decl *a = in_a, *b = in_b;
18277ec681f3Smrg
18287ec681f3Smrg   return a->first - b->first;
18297ec681f3Smrg}
18304a49301eSmrg
18314a49301eSmrgstatic void emit_decls( struct ureg_program *ureg )
18324a49301eSmrg{
183301e04c3fSmrg   unsigned i,j;
1834cdc920a0Smrg
183501e04c3fSmrg   for (i = 0; i < ARRAY_SIZE(ureg->properties); i++)
183601e04c3fSmrg      if (ureg->properties[i] != ~0u)
183701e04c3fSmrg         emit_property(ureg, i, ureg->properties[i]);
18383464ebd5Sriastradh
18397ec681f3Smrg   /* While not required by TGSI spec, virglrenderer has a dependency on the
18407ec681f3Smrg    * inputs being sorted.
18417ec681f3Smrg    */
18427ec681f3Smrg   qsort(ureg->input, ureg->nr_inputs, sizeof(ureg->input[0]), input_sort);
18437ec681f3Smrg
184401e04c3fSmrg   if (ureg->processor == PIPE_SHADER_VERTEX) {
184501e04c3fSmrg      for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
184601e04c3fSmrg         if (ureg->vs_inputs[i/32] & (1u << (i%32))) {
18474a49301eSmrg            emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 );
18484a49301eSmrg         }
18494a49301eSmrg      }
185001e04c3fSmrg   } else if (ureg->processor == PIPE_SHADER_FRAGMENT) {
185101e04c3fSmrg      if (ureg->supports_any_inout_decl_range) {
185201e04c3fSmrg         for (i = 0; i < ureg->nr_inputs; i++) {
185301e04c3fSmrg            emit_decl_fs(ureg,
185401e04c3fSmrg                         TGSI_FILE_INPUT,
185501e04c3fSmrg                         ureg->input[i].first,
185601e04c3fSmrg                         ureg->input[i].last,
185701e04c3fSmrg                         ureg->input[i].semantic_name,
185801e04c3fSmrg                         ureg->input[i].semantic_index,
185901e04c3fSmrg                         ureg->input[i].interp,
186001e04c3fSmrg                         ureg->input[i].interp_location,
186101e04c3fSmrg                         ureg->input[i].array_id,
186201e04c3fSmrg                         ureg->input[i].usage_mask);
186301e04c3fSmrg         }
18644a49301eSmrg      }
186501e04c3fSmrg      else {
186601e04c3fSmrg         for (i = 0; i < ureg->nr_inputs; i++) {
186701e04c3fSmrg            for (j = ureg->input[i].first; j <= ureg->input[i].last; j++) {
186801e04c3fSmrg               emit_decl_fs(ureg,
1869cdc920a0Smrg                            TGSI_FILE_INPUT,
187001e04c3fSmrg                            j, j,
187101e04c3fSmrg                            ureg->input[i].semantic_name,
187201e04c3fSmrg                            ureg->input[i].semantic_index +
187301e04c3fSmrg                            (j - ureg->input[i].first),
187401e04c3fSmrg                            ureg->input[i].interp,
187501e04c3fSmrg                            ureg->input[i].interp_location, 0,
187601e04c3fSmrg                            ureg->input[i].usage_mask);
187701e04c3fSmrg            }
187801e04c3fSmrg         }
187901e04c3fSmrg      }
188001e04c3fSmrg   } else {
188101e04c3fSmrg      if (ureg->supports_any_inout_decl_range) {
188201e04c3fSmrg         for (i = 0; i < ureg->nr_inputs; i++) {
188301e04c3fSmrg            emit_decl_semantic(ureg,
188401e04c3fSmrg                               TGSI_FILE_INPUT,
188501e04c3fSmrg                               ureg->input[i].first,
188601e04c3fSmrg                               ureg->input[i].last,
188701e04c3fSmrg                               ureg->input[i].semantic_name,
188801e04c3fSmrg                               ureg->input[i].semantic_index,
188901e04c3fSmrg                               0,
189001e04c3fSmrg                               TGSI_WRITEMASK_XYZW,
189101e04c3fSmrg                               ureg->input[i].array_id,
189201e04c3fSmrg                               FALSE);
189301e04c3fSmrg         }
189401e04c3fSmrg      }
189501e04c3fSmrg      else {
189601e04c3fSmrg         for (i = 0; i < ureg->nr_inputs; i++) {
189701e04c3fSmrg            for (j = ureg->input[i].first; j <= ureg->input[i].last; j++) {
189801e04c3fSmrg               emit_decl_semantic(ureg,
189901e04c3fSmrg                                  TGSI_FILE_INPUT,
190001e04c3fSmrg                                  j, j,
190101e04c3fSmrg                                  ureg->input[i].semantic_name,
190201e04c3fSmrg                                  ureg->input[i].semantic_index +
190301e04c3fSmrg                                  (j - ureg->input[i].first),
190401e04c3fSmrg                                  0,
190501e04c3fSmrg                                  TGSI_WRITEMASK_XYZW, 0, FALSE);
190601e04c3fSmrg            }
190701e04c3fSmrg         }
1908cdc920a0Smrg      }
1909cdc920a0Smrg   }
1910cdc920a0Smrg
1911cdc920a0Smrg   for (i = 0; i < ureg->nr_system_values; i++) {
1912cdc920a0Smrg      emit_decl_semantic(ureg,
1913cdc920a0Smrg                         TGSI_FILE_SYSTEM_VALUE,
191401e04c3fSmrg                         i,
191501e04c3fSmrg                         i,
1916cdc920a0Smrg                         ureg->system_value[i].semantic_name,
1917af69d88dSmrg                         ureg->system_value[i].semantic_index,
191801e04c3fSmrg                         0,
191901e04c3fSmrg                         TGSI_WRITEMASK_XYZW, 0, FALSE);
19204a49301eSmrg   }
19214a49301eSmrg
19227ec681f3Smrg   /* While not required by TGSI spec, virglrenderer has a dependency on the
19237ec681f3Smrg    * outputs being sorted.
19247ec681f3Smrg    */
19257ec681f3Smrg   qsort(ureg->output, ureg->nr_outputs, sizeof(ureg->output[0]), output_sort);
19267ec681f3Smrg
192701e04c3fSmrg   if (ureg->supports_any_inout_decl_range) {
192801e04c3fSmrg      for (i = 0; i < ureg->nr_outputs; i++) {
192901e04c3fSmrg         emit_decl_semantic(ureg,
193001e04c3fSmrg                            TGSI_FILE_OUTPUT,
193101e04c3fSmrg                            ureg->output[i].first,
193201e04c3fSmrg                            ureg->output[i].last,
193301e04c3fSmrg                            ureg->output[i].semantic_name,
193401e04c3fSmrg                            ureg->output[i].semantic_index,
193501e04c3fSmrg                            ureg->output[i].streams,
193601e04c3fSmrg                            ureg->output[i].usage_mask,
193701e04c3fSmrg                            ureg->output[i].array_id,
193801e04c3fSmrg                            ureg->output[i].invariant);
193901e04c3fSmrg      }
194001e04c3fSmrg   }
194101e04c3fSmrg   else {
194201e04c3fSmrg      for (i = 0; i < ureg->nr_outputs; i++) {
194301e04c3fSmrg         for (j = ureg->output[i].first; j <= ureg->output[i].last; j++) {
194401e04c3fSmrg            emit_decl_semantic(ureg,
194501e04c3fSmrg                               TGSI_FILE_OUTPUT,
194601e04c3fSmrg                               j, j,
194701e04c3fSmrg                               ureg->output[i].semantic_name,
194801e04c3fSmrg                               ureg->output[i].semantic_index +
194901e04c3fSmrg                               (j - ureg->output[i].first),
195001e04c3fSmrg                               ureg->output[i].streams,
195101e04c3fSmrg                               ureg->output[i].usage_mask,
195201e04c3fSmrg                               0,
195301e04c3fSmrg                               ureg->output[i].invariant);
195401e04c3fSmrg         }
195501e04c3fSmrg      }
19564a49301eSmrg   }
19574a49301eSmrg
19584a49301eSmrg   for (i = 0; i < ureg->nr_samplers; i++) {
195901e04c3fSmrg      emit_decl_range( ureg,
19604a49301eSmrg                       TGSI_FILE_SAMPLER,
19614a49301eSmrg                       ureg->sampler[i].Index, 1 );
19624a49301eSmrg   }
19634a49301eSmrg
1964af69d88dSmrg   for (i = 0; i < ureg->nr_sampler_views; i++) {
1965af69d88dSmrg      emit_decl_sampler_view(ureg,
1966af69d88dSmrg                             ureg->sampler_view[i].index,
1967af69d88dSmrg                             ureg->sampler_view[i].target,
1968af69d88dSmrg                             ureg->sampler_view[i].return_type_x,
1969af69d88dSmrg                             ureg->sampler_view[i].return_type_y,
1970af69d88dSmrg                             ureg->sampler_view[i].return_type_z,
1971af69d88dSmrg                             ureg->sampler_view[i].return_type_w);
19723464ebd5Sriastradh   }
19733464ebd5Sriastradh
197401e04c3fSmrg   for (i = 0; i < ureg->nr_images; i++) {
197501e04c3fSmrg      emit_decl_image(ureg,
197601e04c3fSmrg                      ureg->image[i].index,
197701e04c3fSmrg                      ureg->image[i].target,
197801e04c3fSmrg                      ureg->image[i].format,
197901e04c3fSmrg                      ureg->image[i].wr,
198001e04c3fSmrg                      ureg->image[i].raw);
198101e04c3fSmrg   }
198201e04c3fSmrg
198301e04c3fSmrg   for (i = 0; i < ureg->nr_buffers; i++) {
198401e04c3fSmrg      emit_decl_buffer(ureg, ureg->buffer[i].index, ureg->buffer[i].atomic);
198501e04c3fSmrg   }
198601e04c3fSmrg
198701e04c3fSmrg   for (i = 0; i < TGSI_MEMORY_TYPE_COUNT; i++) {
198801e04c3fSmrg      if (ureg->use_memory[i])
198901e04c3fSmrg         emit_decl_memory(ureg, i);
1990cdc920a0Smrg   }
1991cdc920a0Smrg
1992cdc920a0Smrg   for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
199301e04c3fSmrg      struct const_decl *decl = &ureg->const_decls[i];
1994cdc920a0Smrg
1995cdc920a0Smrg      if (decl->nr_constant_ranges) {
1996cdc920a0Smrg         uint j;
1997cdc920a0Smrg
1998cdc920a0Smrg         for (j = 0; j < decl->nr_constant_ranges; j++) {
1999cdc920a0Smrg            emit_decl_range2D(ureg,
2000cdc920a0Smrg                              TGSI_FILE_CONSTANT,
2001cdc920a0Smrg                              decl->constant_range[j].first,
2002cdc920a0Smrg                              decl->constant_range[j].last,
2003cdc920a0Smrg                              i);
2004cdc920a0Smrg         }
2005cdc920a0Smrg      }
20064a49301eSmrg   }
20074a49301eSmrg
200801e04c3fSmrg   for (i = 0; i < PIPE_MAX_HW_ATOMIC_BUFFERS; i++) {
200901e04c3fSmrg      struct hw_atomic_decl *decl = &ureg->hw_atomic_decls[i];
201001e04c3fSmrg
201101e04c3fSmrg      if (decl->nr_hw_atomic_ranges) {
201201e04c3fSmrg         uint j;
201301e04c3fSmrg
201401e04c3fSmrg         for (j = 0; j < decl->nr_hw_atomic_ranges; j++) {
201501e04c3fSmrg            emit_decl_atomic_2d(ureg,
201601e04c3fSmrg                                decl->hw_atomic_range[j].first,
201701e04c3fSmrg                                decl->hw_atomic_range[j].last,
201801e04c3fSmrg                                i,
201901e04c3fSmrg                                decl->hw_atomic_range[j].array_id);
202001e04c3fSmrg         }
202101e04c3fSmrg      }
202201e04c3fSmrg   }
202301e04c3fSmrg
20244a49301eSmrg   if (ureg->nr_temps) {
2025af69d88dSmrg      unsigned array = 0;
2026af69d88dSmrg      for (i = 0; i < ureg->nr_temps;) {
2027af69d88dSmrg         boolean local = util_bitmask_get(ureg->local_temps, i);
2028af69d88dSmrg         unsigned first = i;
2029af69d88dSmrg         i = util_bitmask_get_next_index(ureg->decl_temps, i + 1);
2030af69d88dSmrg         if (i == UTIL_BITMASK_INVALID_INDEX)
2031af69d88dSmrg            i = ureg->nr_temps;
2032af69d88dSmrg
2033af69d88dSmrg         if (array < ureg->nr_array_temps && ureg->array_temps[array] == first)
2034af69d88dSmrg            emit_decl_temps( ureg, first, i - 1, local, ++array );
2035af69d88dSmrg         else
2036af69d88dSmrg            emit_decl_temps( ureg, first, i - 1, local, 0 );
2037af69d88dSmrg      }
20384a49301eSmrg   }
20394a49301eSmrg
20404a49301eSmrg   if (ureg->nr_addrs) {
20414a49301eSmrg      emit_decl_range( ureg,
20424a49301eSmrg                       TGSI_FILE_ADDRESS,
20434a49301eSmrg                       0, ureg->nr_addrs );
20444a49301eSmrg   }
20454a49301eSmrg
20464a49301eSmrg   for (i = 0; i < ureg->nr_immediates; i++) {
20474a49301eSmrg      emit_immediate( ureg,
2048cdc920a0Smrg                      ureg->immediate[i].value.u,
2049cdc920a0Smrg                      ureg->immediate[i].type );
20504a49301eSmrg   }
20514a49301eSmrg}
20524a49301eSmrg
20534a49301eSmrg/* Append the instruction tokens onto the declarations to build a
20544a49301eSmrg * contiguous stream suitable to send to the driver.
20554a49301eSmrg */
20564a49301eSmrgstatic void copy_instructions( struct ureg_program *ureg )
20574a49301eSmrg{
20584a49301eSmrg   unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
205901e04c3fSmrg   union tgsi_any_token *out = get_tokens( ureg,
206001e04c3fSmrg                                           DOMAIN_DECL,
20614a49301eSmrg                                           nr_tokens );
20624a49301eSmrg
206301e04c3fSmrg   memcpy(out,
206401e04c3fSmrg          ureg->domain[DOMAIN_INSN].tokens,
20654a49301eSmrg          nr_tokens * sizeof out[0] );
20664a49301eSmrg}
20674a49301eSmrg
20684a49301eSmrg
20694a49301eSmrgstatic void
20704a49301eSmrgfixup_header_size(struct ureg_program *ureg)
20714a49301eSmrg{
2072cdc920a0Smrg   union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 );
20734a49301eSmrg
2074cdc920a0Smrg   out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2;
20754a49301eSmrg}
20764a49301eSmrg
20774a49301eSmrg
20784a49301eSmrgstatic void
20794a49301eSmrgemit_header( struct ureg_program *ureg )
20804a49301eSmrg{
2081cdc920a0Smrg   union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
20824a49301eSmrg
2083cdc920a0Smrg   out[0].header.HeaderSize = 2;
2084cdc920a0Smrg   out[0].header.BodySize = 0;
20854a49301eSmrg
2086cdc920a0Smrg   out[1].processor.Processor = ureg->processor;
2087cdc920a0Smrg   out[1].processor.Padding = 0;
20884a49301eSmrg}
20894a49301eSmrg
20904a49301eSmrg
20914a49301eSmrgconst struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
20924a49301eSmrg{
20934a49301eSmrg   const struct tgsi_token *tokens;
20944a49301eSmrg
209501e04c3fSmrg   switch (ureg->processor) {
209601e04c3fSmrg   case PIPE_SHADER_VERTEX:
209701e04c3fSmrg   case PIPE_SHADER_TESS_EVAL:
209801e04c3fSmrg      ureg_property(ureg, TGSI_PROPERTY_NEXT_SHADER,
209901e04c3fSmrg                    ureg->next_shader_processor == -1 ?
210001e04c3fSmrg                       PIPE_SHADER_FRAGMENT :
210101e04c3fSmrg                       ureg->next_shader_processor);
210201e04c3fSmrg      break;
210301e04c3fSmrg   default:
210401e04c3fSmrg      ; /* nothing */
210501e04c3fSmrg   }
210601e04c3fSmrg
21074a49301eSmrg   emit_header( ureg );
21084a49301eSmrg   emit_decls( ureg );
21094a49301eSmrg   copy_instructions( ureg );
21104a49301eSmrg   fixup_header_size( ureg );
211101e04c3fSmrg
21124a49301eSmrg   if (ureg->domain[0].tokens == error_tokens ||
21134a49301eSmrg       ureg->domain[1].tokens == error_tokens) {
21144a49301eSmrg      debug_printf("%s: error in generated shader\n", __FUNCTION__);
21154a49301eSmrg      assert(0);
21164a49301eSmrg      return NULL;
21174a49301eSmrg   }
21184a49301eSmrg
21194a49301eSmrg   tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
21204a49301eSmrg
21214a49301eSmrg   if (0) {
212201e04c3fSmrg      debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
21234a49301eSmrg                   ureg->domain[DOMAIN_DECL].count);
21244a49301eSmrg      tgsi_dump( tokens, 0 );
21254a49301eSmrg   }
21264a49301eSmrg
21274a49301eSmrg#if DEBUG
212801e04c3fSmrg   /* tgsi_sanity doesn't seem to return if there are too many constants. */
212901e04c3fSmrg   bool too_many_constants = false;
213001e04c3fSmrg   for (unsigned i = 0; i < ARRAY_SIZE(ureg->const_decls); i++) {
213101e04c3fSmrg      for (unsigned j = 0; j < ureg->const_decls[i].nr_constant_ranges; j++) {
213201e04c3fSmrg         if (ureg->const_decls[i].constant_range[j].last > 4096) {
213301e04c3fSmrg            too_many_constants = true;
213401e04c3fSmrg            break;
213501e04c3fSmrg         }
213601e04c3fSmrg      }
213701e04c3fSmrg   }
213801e04c3fSmrg
213901e04c3fSmrg   if (tokens && !too_many_constants && !tgsi_sanity_check(tokens)) {
21404a49301eSmrg      debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n");
21414a49301eSmrg      tgsi_dump(tokens, 0);
21424a49301eSmrg      assert(0);
21434a49301eSmrg   }
21444a49301eSmrg#endif
21454a49301eSmrg
214601e04c3fSmrg
21474a49301eSmrg   return tokens;
21484a49301eSmrg}
21494a49301eSmrg
21504a49301eSmrg
21514a49301eSmrgvoid *ureg_create_shader( struct ureg_program *ureg,
2152af69d88dSmrg                          struct pipe_context *pipe,
2153af69d88dSmrg                          const struct pipe_stream_output_info *so )
21544a49301eSmrg{
21557ec681f3Smrg   struct pipe_shader_state state = {0};
21564a49301eSmrg
215701e04c3fSmrg   pipe_shader_state_from_tgsi(&state, ureg_finalize(ureg));
21584a49301eSmrg   if(!state.tokens)
21594a49301eSmrg      return NULL;
21604a49301eSmrg
2161af69d88dSmrg   if (so)
2162af69d88dSmrg      state.stream_output = *so;
2163af69d88dSmrg
216401e04c3fSmrg   switch (ureg->processor) {
216501e04c3fSmrg   case PIPE_SHADER_VERTEX:
216601e04c3fSmrg      return pipe->create_vs_state(pipe, &state);
216701e04c3fSmrg   case PIPE_SHADER_TESS_CTRL:
216801e04c3fSmrg      return pipe->create_tcs_state(pipe, &state);
216901e04c3fSmrg   case PIPE_SHADER_TESS_EVAL:
217001e04c3fSmrg      return pipe->create_tes_state(pipe, &state);
217101e04c3fSmrg   case PIPE_SHADER_GEOMETRY:
217201e04c3fSmrg      return pipe->create_gs_state(pipe, &state);
217301e04c3fSmrg   case PIPE_SHADER_FRAGMENT:
217401e04c3fSmrg      return pipe->create_fs_state(pipe, &state);
217501e04c3fSmrg   default:
217601e04c3fSmrg      return NULL;
217701e04c3fSmrg   }
21784a49301eSmrg}
21794a49301eSmrg
21804a49301eSmrg
21814a49301eSmrgconst struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg,
21824a49301eSmrg                                          unsigned *nr_tokens )
21834a49301eSmrg{
21844a49301eSmrg   const struct tgsi_token *tokens;
21854a49301eSmrg
21864a49301eSmrg   ureg_finalize(ureg);
21874a49301eSmrg
21884a49301eSmrg   tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
21894a49301eSmrg
219001e04c3fSmrg   if (nr_tokens)
219101e04c3fSmrg      *nr_tokens = ureg->domain[DOMAIN_DECL].count;
21924a49301eSmrg
21934a49301eSmrg   ureg->domain[DOMAIN_DECL].tokens = 0;
21944a49301eSmrg   ureg->domain[DOMAIN_DECL].size = 0;
21954a49301eSmrg   ureg->domain[DOMAIN_DECL].order = 0;
21964a49301eSmrg   ureg->domain[DOMAIN_DECL].count = 0;
21974a49301eSmrg
21984a49301eSmrg   return tokens;
21994a49301eSmrg}
22004a49301eSmrg
22014a49301eSmrg
22023464ebd5Sriastradhvoid ureg_free_tokens( const struct tgsi_token *tokens )
22033464ebd5Sriastradh{
22043464ebd5Sriastradh   FREE((struct tgsi_token *)tokens);
22053464ebd5Sriastradh}
22063464ebd5Sriastradh
22073464ebd5Sriastradh
220801e04c3fSmrgstruct ureg_program *
220901e04c3fSmrgureg_create(enum pipe_shader_type processor)
22104a49301eSmrg{
221101e04c3fSmrg   return ureg_create_with_screen(processor, NULL);
221201e04c3fSmrg}
221301e04c3fSmrg
221401e04c3fSmrg
221501e04c3fSmrgstruct ureg_program *
221601e04c3fSmrgureg_create_with_screen(enum pipe_shader_type processor,
221701e04c3fSmrg                        struct pipe_screen *screen)
221801e04c3fSmrg{
221901e04c3fSmrg   uint i;
22204a49301eSmrg   struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
222101e04c3fSmrg   if (!ureg)
2222af69d88dSmrg      goto no_ureg;
22234a49301eSmrg
22244a49301eSmrg   ureg->processor = processor;
222501e04c3fSmrg   ureg->supports_any_inout_decl_range =
222601e04c3fSmrg      screen &&
222701e04c3fSmrg      screen->get_shader_param(screen, processor,
222801e04c3fSmrg                               PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE) != 0;
222901e04c3fSmrg   ureg->next_shader_processor = -1;
223001e04c3fSmrg
223101e04c3fSmrg   for (i = 0; i < ARRAY_SIZE(ureg->properties); i++)
223201e04c3fSmrg      ureg->properties[i] = ~0;
2233af69d88dSmrg
2234af69d88dSmrg   ureg->free_temps = util_bitmask_create();
2235af69d88dSmrg   if (ureg->free_temps == NULL)
2236af69d88dSmrg      goto no_free_temps;
2237af69d88dSmrg
2238af69d88dSmrg   ureg->local_temps = util_bitmask_create();
2239af69d88dSmrg   if (ureg->local_temps == NULL)
2240af69d88dSmrg      goto no_local_temps;
2241af69d88dSmrg
2242af69d88dSmrg   ureg->decl_temps = util_bitmask_create();
2243af69d88dSmrg   if (ureg->decl_temps == NULL)
2244af69d88dSmrg      goto no_decl_temps;
2245af69d88dSmrg
22464a49301eSmrg   return ureg;
2247af69d88dSmrg
2248af69d88dSmrgno_decl_temps:
2249af69d88dSmrg   util_bitmask_destroy(ureg->local_temps);
2250af69d88dSmrgno_local_temps:
2251af69d88dSmrg   util_bitmask_destroy(ureg->free_temps);
2252af69d88dSmrgno_free_temps:
2253af69d88dSmrg   FREE(ureg);
2254af69d88dSmrgno_ureg:
2255af69d88dSmrg   return NULL;
2256af69d88dSmrg}
2257af69d88dSmrg
2258af69d88dSmrg
225901e04c3fSmrgvoid
226001e04c3fSmrgureg_set_next_shader_processor(struct ureg_program *ureg, unsigned processor)
226101e04c3fSmrg{
226201e04c3fSmrg   ureg->next_shader_processor = processor;
226301e04c3fSmrg}
226401e04c3fSmrg
226501e04c3fSmrg
2266af69d88dSmrgunsigned
2267af69d88dSmrgureg_get_nr_outputs( const struct ureg_program *ureg )
2268af69d88dSmrg{
2269af69d88dSmrg   if (!ureg)
2270af69d88dSmrg      return 0;
2271af69d88dSmrg   return ureg->nr_outputs;
22724a49301eSmrg}
22734a49301eSmrg
22747ec681f3Smrgstatic void
22757ec681f3Smrgureg_setup_clipdist_info(struct ureg_program *ureg,
22767ec681f3Smrg                         const struct shader_info *info)
22777ec681f3Smrg{
22787ec681f3Smrg   if (info->clip_distance_array_size)
22797ec681f3Smrg      ureg_property(ureg, TGSI_PROPERTY_NUM_CLIPDIST_ENABLED,
22807ec681f3Smrg                    info->clip_distance_array_size);
22817ec681f3Smrg   if (info->cull_distance_array_size)
22827ec681f3Smrg      ureg_property(ureg, TGSI_PROPERTY_NUM_CULLDIST_ENABLED,
22837ec681f3Smrg                    info->cull_distance_array_size);
22847ec681f3Smrg}
22857ec681f3Smrg
22867ec681f3Smrgstatic void
22877ec681f3Smrgureg_setup_tess_ctrl_shader(struct ureg_program *ureg,
22887ec681f3Smrg                            const struct shader_info *info)
22897ec681f3Smrg{
22907ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT,
22917ec681f3Smrg                 info->tess.tcs_vertices_out);
22927ec681f3Smrg}
22937ec681f3Smrg
22947ec681f3Smrgstatic void
22957ec681f3Smrgureg_setup_tess_eval_shader(struct ureg_program *ureg,
22967ec681f3Smrg                            const struct shader_info *info)
22977ec681f3Smrg{
22987ec681f3Smrg   if (info->tess.primitive_mode == GL_ISOLINES)
22997ec681f3Smrg      ureg_property(ureg, TGSI_PROPERTY_TES_PRIM_MODE, GL_LINES);
23007ec681f3Smrg   else
23017ec681f3Smrg      ureg_property(ureg, TGSI_PROPERTY_TES_PRIM_MODE,
23027ec681f3Smrg                    info->tess.primitive_mode);
23037ec681f3Smrg
23047ec681f3Smrg   STATIC_ASSERT((TESS_SPACING_EQUAL + 1) % 3 == PIPE_TESS_SPACING_EQUAL);
23057ec681f3Smrg   STATIC_ASSERT((TESS_SPACING_FRACTIONAL_ODD + 1) % 3 ==
23067ec681f3Smrg                 PIPE_TESS_SPACING_FRACTIONAL_ODD);
23077ec681f3Smrg   STATIC_ASSERT((TESS_SPACING_FRACTIONAL_EVEN + 1) % 3 ==
23087ec681f3Smrg                 PIPE_TESS_SPACING_FRACTIONAL_EVEN);
23097ec681f3Smrg
23107ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_TES_SPACING,
23117ec681f3Smrg                 (info->tess.spacing + 1) % 3);
23127ec681f3Smrg
23137ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_TES_VERTEX_ORDER_CW,
23147ec681f3Smrg                 !info->tess.ccw);
23157ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_TES_POINT_MODE,
23167ec681f3Smrg                 info->tess.point_mode);
23177ec681f3Smrg}
23187ec681f3Smrg
23197ec681f3Smrgstatic void
23207ec681f3Smrgureg_setup_geometry_shader(struct ureg_program *ureg,
23217ec681f3Smrg                           const struct shader_info *info)
23227ec681f3Smrg{
23237ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM,
23247ec681f3Smrg                 info->gs.input_primitive);
23257ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM,
23267ec681f3Smrg                 info->gs.output_primitive);
23277ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES,
23287ec681f3Smrg                 info->gs.vertices_out);
23297ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS,
23307ec681f3Smrg                 info->gs.invocations);
23317ec681f3Smrg}
23327ec681f3Smrg
23337ec681f3Smrgstatic void
23347ec681f3Smrgureg_setup_fragment_shader(struct ureg_program *ureg,
23357ec681f3Smrg                           const struct shader_info *info)
23367ec681f3Smrg{
23377ec681f3Smrg   if (info->fs.early_fragment_tests || info->fs.post_depth_coverage) {
23387ec681f3Smrg      ureg_property(ureg, TGSI_PROPERTY_FS_EARLY_DEPTH_STENCIL, 1);
23397ec681f3Smrg
23407ec681f3Smrg      if (info->fs.post_depth_coverage)
23417ec681f3Smrg         ureg_property(ureg, TGSI_PROPERTY_FS_POST_DEPTH_COVERAGE, 1);
23427ec681f3Smrg   }
23437ec681f3Smrg
23447ec681f3Smrg   if (info->fs.depth_layout != FRAG_DEPTH_LAYOUT_NONE) {
23457ec681f3Smrg      switch (info->fs.depth_layout) {
23467ec681f3Smrg      case FRAG_DEPTH_LAYOUT_ANY:
23477ec681f3Smrg         ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT,
23487ec681f3Smrg                       TGSI_FS_DEPTH_LAYOUT_ANY);
23497ec681f3Smrg         break;
23507ec681f3Smrg      case FRAG_DEPTH_LAYOUT_GREATER:
23517ec681f3Smrg         ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT,
23527ec681f3Smrg                       TGSI_FS_DEPTH_LAYOUT_GREATER);
23537ec681f3Smrg         break;
23547ec681f3Smrg      case FRAG_DEPTH_LAYOUT_LESS:
23557ec681f3Smrg         ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT,
23567ec681f3Smrg                       TGSI_FS_DEPTH_LAYOUT_LESS);
23577ec681f3Smrg         break;
23587ec681f3Smrg      case FRAG_DEPTH_LAYOUT_UNCHANGED:
23597ec681f3Smrg         ureg_property(ureg, TGSI_PROPERTY_FS_DEPTH_LAYOUT,
23607ec681f3Smrg                       TGSI_FS_DEPTH_LAYOUT_UNCHANGED);
23617ec681f3Smrg         break;
23627ec681f3Smrg      default:
23637ec681f3Smrg         assert(0);
23647ec681f3Smrg      }
23657ec681f3Smrg   }
23667ec681f3Smrg
23677ec681f3Smrg   if (info->fs.advanced_blend_modes) {
23687ec681f3Smrg      ureg_property(ureg, TGSI_PROPERTY_FS_BLEND_EQUATION_ADVANCED,
23697ec681f3Smrg                    info->fs.advanced_blend_modes);
23707ec681f3Smrg   }
23717ec681f3Smrg}
23727ec681f3Smrg
23737ec681f3Smrgstatic void
23747ec681f3Smrgureg_setup_compute_shader(struct ureg_program *ureg,
23757ec681f3Smrg                          const struct shader_info *info)
23767ec681f3Smrg{
23777ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH,
23787ec681f3Smrg                 info->workgroup_size[0]);
23797ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT,
23807ec681f3Smrg                 info->workgroup_size[1]);
23817ec681f3Smrg   ureg_property(ureg, TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH,
23827ec681f3Smrg                 info->workgroup_size[2]);
23837ec681f3Smrg
23847ec681f3Smrg   if (info->shared_size)
23857ec681f3Smrg      ureg_DECL_memory(ureg, TGSI_MEMORY_TYPE_SHARED);
23867ec681f3Smrg}
23877ec681f3Smrg
23887ec681f3Smrgvoid
23897ec681f3Smrgureg_setup_shader_info(struct ureg_program *ureg,
23907ec681f3Smrg                       const struct shader_info *info)
23917ec681f3Smrg{
23927ec681f3Smrg   if (info->layer_viewport_relative)
23937ec681f3Smrg      ureg_property(ureg, TGSI_PROPERTY_LAYER_VIEWPORT_RELATIVE, 1);
23947ec681f3Smrg
23957ec681f3Smrg   switch (info->stage) {
23967ec681f3Smrg   case MESA_SHADER_VERTEX:
23977ec681f3Smrg      ureg_setup_clipdist_info(ureg, info);
23987ec681f3Smrg      ureg_set_next_shader_processor(ureg, pipe_shader_type_from_mesa(info->next_stage));
23997ec681f3Smrg      break;
24007ec681f3Smrg   case MESA_SHADER_TESS_CTRL:
24017ec681f3Smrg      ureg_setup_tess_ctrl_shader(ureg, info);
24027ec681f3Smrg      break;
24037ec681f3Smrg   case MESA_SHADER_TESS_EVAL:
24047ec681f3Smrg      ureg_setup_tess_eval_shader(ureg, info);
24057ec681f3Smrg      ureg_setup_clipdist_info(ureg, info);
24067ec681f3Smrg      ureg_set_next_shader_processor(ureg, pipe_shader_type_from_mesa(info->next_stage));
24077ec681f3Smrg      break;
24087ec681f3Smrg   case MESA_SHADER_GEOMETRY:
24097ec681f3Smrg      ureg_setup_geometry_shader(ureg, info);
24107ec681f3Smrg      ureg_setup_clipdist_info(ureg, info);
24117ec681f3Smrg      break;
24127ec681f3Smrg   case MESA_SHADER_FRAGMENT:
24137ec681f3Smrg      ureg_setup_fragment_shader(ureg, info);
24147ec681f3Smrg      break;
24157ec681f3Smrg   case MESA_SHADER_COMPUTE:
24167ec681f3Smrg      ureg_setup_compute_shader(ureg, info);
24177ec681f3Smrg      break;
24187ec681f3Smrg   default:
24197ec681f3Smrg      break;
24207ec681f3Smrg   }
24217ec681f3Smrg}
24227ec681f3Smrg
24234a49301eSmrg
24244a49301eSmrgvoid ureg_destroy( struct ureg_program *ureg )
24254a49301eSmrg{
24264a49301eSmrg   unsigned i;
24274a49301eSmrg
242801e04c3fSmrg   for (i = 0; i < ARRAY_SIZE(ureg->domain); i++) {
242901e04c3fSmrg      if (ureg->domain[i].tokens &&
24304a49301eSmrg          ureg->domain[i].tokens != error_tokens)
24314a49301eSmrg         FREE(ureg->domain[i].tokens);
24324a49301eSmrg   }
2433af69d88dSmrg
2434af69d88dSmrg   util_bitmask_destroy(ureg->free_temps);
2435af69d88dSmrg   util_bitmask_destroy(ureg->local_temps);
2436af69d88dSmrg   util_bitmask_destroy(ureg->decl_temps);
2437af69d88dSmrg
24384a49301eSmrg   FREE(ureg);
24394a49301eSmrg}
2440