1848b8605Smrg/************************************************************************** 2b8e80941Smrg * 3848b8605Smrg * Copyright 2009-2010 VMware, Inc. 4848b8605Smrg * All Rights Reserved. 5b8e80941Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13b8e80941Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17b8e80941Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b8e80941Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg 29b8e80941Smrg#include "pipe/p_screen.h" 30848b8605Smrg#include "pipe/p_context.h" 31848b8605Smrg#include "pipe/p_state.h" 32848b8605Smrg#include "tgsi/tgsi_ureg.h" 33848b8605Smrg#include "tgsi/tgsi_build.h" 34848b8605Smrg#include "tgsi/tgsi_info.h" 35848b8605Smrg#include "tgsi/tgsi_dump.h" 36848b8605Smrg#include "tgsi/tgsi_sanity.h" 37848b8605Smrg#include "util/u_debug.h" 38b8e80941Smrg#include "util/u_inlines.h" 39848b8605Smrg#include "util/u_memory.h" 40848b8605Smrg#include "util/u_math.h" 41848b8605Smrg#include "util/u_bitmask.h" 42848b8605Smrg 43848b8605Smrgunion tgsi_any_token { 44848b8605Smrg struct tgsi_header header; 45848b8605Smrg struct tgsi_processor processor; 46848b8605Smrg struct tgsi_token token; 47848b8605Smrg struct tgsi_property prop; 48848b8605Smrg struct tgsi_property_data prop_data; 49848b8605Smrg struct tgsi_declaration decl; 50848b8605Smrg struct tgsi_declaration_range decl_range; 51848b8605Smrg struct tgsi_declaration_dimension decl_dim; 52848b8605Smrg struct tgsi_declaration_interp decl_interp; 53b8e80941Smrg struct tgsi_declaration_image decl_image; 54848b8605Smrg struct tgsi_declaration_semantic decl_semantic; 55848b8605Smrg struct tgsi_declaration_sampler_view decl_sampler_view; 56848b8605Smrg struct tgsi_declaration_array array; 57848b8605Smrg struct tgsi_immediate imm; 58848b8605Smrg union tgsi_immediate_data imm_data; 59848b8605Smrg struct tgsi_instruction insn; 60848b8605Smrg struct tgsi_instruction_label insn_label; 61848b8605Smrg struct tgsi_instruction_texture insn_texture; 62b8e80941Smrg struct tgsi_instruction_memory insn_memory; 63848b8605Smrg struct tgsi_texture_offset insn_texture_offset; 64848b8605Smrg struct tgsi_src_register src; 65848b8605Smrg struct tgsi_ind_register ind; 66848b8605Smrg struct tgsi_dimension dim; 67848b8605Smrg struct tgsi_dst_register dst; 68848b8605Smrg unsigned value; 69848b8605Smrg}; 70848b8605Smrg 71848b8605Smrg 72848b8605Smrgstruct ureg_tokens { 73848b8605Smrg union tgsi_any_token *tokens; 74848b8605Smrg unsigned size; 75848b8605Smrg unsigned order; 76848b8605Smrg unsigned count; 77848b8605Smrg}; 78848b8605Smrg 79b8e80941Smrg#define UREG_MAX_INPUT (4 * PIPE_MAX_SHADER_INPUTS) 80848b8605Smrg#define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS 81b8e80941Smrg#define UREG_MAX_OUTPUT (4 * PIPE_MAX_SHADER_OUTPUTS) 82848b8605Smrg#define UREG_MAX_CONSTANT_RANGE 32 83b8e80941Smrg#define UREG_MAX_HW_ATOMIC_RANGE 32 84848b8605Smrg#define UREG_MAX_IMMEDIATE 4096 85848b8605Smrg#define UREG_MAX_ADDR 3 86848b8605Smrg#define UREG_MAX_ARRAY_TEMPS 256 87848b8605Smrg 88848b8605Smrgstruct const_decl { 89848b8605Smrg struct { 90848b8605Smrg unsigned first; 91848b8605Smrg unsigned last; 92848b8605Smrg } constant_range[UREG_MAX_CONSTANT_RANGE]; 93848b8605Smrg unsigned nr_constant_ranges; 94848b8605Smrg}; 95848b8605Smrg 96b8e80941Smrgstruct hw_atomic_decl { 97b8e80941Smrg struct { 98b8e80941Smrg unsigned first; 99b8e80941Smrg unsigned last; 100b8e80941Smrg unsigned array_id; 101b8e80941Smrg } hw_atomic_range[UREG_MAX_HW_ATOMIC_RANGE]; 102b8e80941Smrg unsigned nr_hw_atomic_ranges; 103b8e80941Smrg}; 104b8e80941Smrg 105848b8605Smrg#define DOMAIN_DECL 0 106848b8605Smrg#define DOMAIN_INSN 1 107848b8605Smrg 108848b8605Smrgstruct ureg_program 109848b8605Smrg{ 110b8e80941Smrg enum pipe_shader_type processor; 111b8e80941Smrg bool supports_any_inout_decl_range; 112b8e80941Smrg int next_shader_processor; 113848b8605Smrg 114848b8605Smrg struct { 115b8e80941Smrg enum tgsi_semantic semantic_name; 116848b8605Smrg unsigned semantic_index; 117b8e80941Smrg enum tgsi_interpolate_mode interp; 118848b8605Smrg unsigned char cylindrical_wrap; 119b8e80941Smrg unsigned char usage_mask; 120b8e80941Smrg enum tgsi_interpolate_loc interp_location; 121b8e80941Smrg unsigned first; 122b8e80941Smrg unsigned last; 123b8e80941Smrg unsigned array_id; 124b8e80941Smrg } input[UREG_MAX_INPUT]; 125b8e80941Smrg unsigned nr_inputs, nr_input_regs; 126848b8605Smrg 127b8e80941Smrg unsigned vs_inputs[PIPE_MAX_ATTRIBS/32]; 128848b8605Smrg 129848b8605Smrg struct { 130b8e80941Smrg enum tgsi_semantic semantic_name; 131848b8605Smrg unsigned semantic_index; 132848b8605Smrg } system_value[UREG_MAX_SYSTEM_VALUE]; 133848b8605Smrg unsigned nr_system_values; 134848b8605Smrg 135848b8605Smrg struct { 136b8e80941Smrg enum tgsi_semantic semantic_name; 137848b8605Smrg unsigned semantic_index; 138b8e80941Smrg unsigned streams; 139848b8605Smrg unsigned usage_mask; /* = TGSI_WRITEMASK_* */ 140b8e80941Smrg unsigned first; 141b8e80941Smrg unsigned last; 142b8e80941Smrg unsigned array_id; 143b8e80941Smrg boolean invariant; 144848b8605Smrg } output[UREG_MAX_OUTPUT]; 145b8e80941Smrg unsigned nr_outputs, nr_output_regs; 146848b8605Smrg 147848b8605Smrg struct { 148848b8605Smrg union { 149848b8605Smrg float f[4]; 150848b8605Smrg unsigned u[4]; 151848b8605Smrg int i[4]; 152848b8605Smrg } value; 153848b8605Smrg unsigned nr; 154848b8605Smrg unsigned type; 155848b8605Smrg } immediate[UREG_MAX_IMMEDIATE]; 156848b8605Smrg unsigned nr_immediates; 157848b8605Smrg 158848b8605Smrg struct ureg_src sampler[PIPE_MAX_SAMPLERS]; 159848b8605Smrg unsigned nr_samplers; 160848b8605Smrg 161848b8605Smrg struct { 162848b8605Smrg unsigned index; 163b8e80941Smrg enum tgsi_texture_type target; 164b8e80941Smrg enum tgsi_return_type return_type_x; 165b8e80941Smrg enum tgsi_return_type return_type_y; 166b8e80941Smrg enum tgsi_return_type return_type_z; 167b8e80941Smrg enum tgsi_return_type return_type_w; 168848b8605Smrg } sampler_view[PIPE_MAX_SHADER_SAMPLER_VIEWS]; 169848b8605Smrg unsigned nr_sampler_views; 170848b8605Smrg 171b8e80941Smrg struct { 172b8e80941Smrg unsigned index; 173b8e80941Smrg enum tgsi_texture_type target; 174b8e80941Smrg enum pipe_format format; 175b8e80941Smrg boolean wr; 176b8e80941Smrg boolean raw; 177b8e80941Smrg } image[PIPE_MAX_SHADER_IMAGES]; 178b8e80941Smrg unsigned nr_images; 179b8e80941Smrg 180b8e80941Smrg struct { 181b8e80941Smrg unsigned index; 182b8e80941Smrg bool atomic; 183b8e80941Smrg } buffer[PIPE_MAX_SHADER_BUFFERS]; 184b8e80941Smrg unsigned nr_buffers; 185b8e80941Smrg 186848b8605Smrg struct util_bitmask *free_temps; 187848b8605Smrg struct util_bitmask *local_temps; 188848b8605Smrg struct util_bitmask *decl_temps; 189848b8605Smrg unsigned nr_temps; 190848b8605Smrg 191848b8605Smrg unsigned array_temps[UREG_MAX_ARRAY_TEMPS]; 192848b8605Smrg unsigned nr_array_temps; 193848b8605Smrg 194b8e80941Smrg struct const_decl const_decls[PIPE_MAX_CONSTANT_BUFFERS]; 195b8e80941Smrg 196b8e80941Smrg struct hw_atomic_decl hw_atomic_decls[PIPE_MAX_HW_ATOMIC_BUFFERS]; 197848b8605Smrg 198b8e80941Smrg unsigned properties[TGSI_PROPERTY_COUNT]; 199848b8605Smrg 200848b8605Smrg unsigned nr_addrs; 201848b8605Smrg unsigned nr_instructions; 202848b8605Smrg 203848b8605Smrg struct ureg_tokens domain[2]; 204b8e80941Smrg 205b8e80941Smrg bool use_memory[TGSI_MEMORY_TYPE_COUNT]; 206848b8605Smrg}; 207848b8605Smrg 208848b8605Smrgstatic union tgsi_any_token error_tokens[32]; 209848b8605Smrg 210848b8605Smrgstatic void tokens_error( struct ureg_tokens *tokens ) 211848b8605Smrg{ 212848b8605Smrg if (tokens->tokens && tokens->tokens != error_tokens) 213848b8605Smrg FREE(tokens->tokens); 214848b8605Smrg 215848b8605Smrg tokens->tokens = error_tokens; 216b8e80941Smrg tokens->size = ARRAY_SIZE(error_tokens); 217848b8605Smrg tokens->count = 0; 218848b8605Smrg} 219848b8605Smrg 220848b8605Smrg 221848b8605Smrgstatic void tokens_expand( struct ureg_tokens *tokens, 222848b8605Smrg unsigned count ) 223848b8605Smrg{ 224848b8605Smrg unsigned old_size = tokens->size * sizeof(unsigned); 225848b8605Smrg 226848b8605Smrg if (tokens->tokens == error_tokens) { 227848b8605Smrg return; 228848b8605Smrg } 229848b8605Smrg 230848b8605Smrg while (tokens->count + count > tokens->size) { 231848b8605Smrg tokens->size = (1 << ++tokens->order); 232848b8605Smrg } 233848b8605Smrg 234848b8605Smrg tokens->tokens = REALLOC(tokens->tokens, 235848b8605Smrg old_size, 236848b8605Smrg tokens->size * sizeof(unsigned)); 237848b8605Smrg if (tokens->tokens == NULL) { 238848b8605Smrg tokens_error(tokens); 239848b8605Smrg } 240848b8605Smrg} 241848b8605Smrg 242848b8605Smrgstatic void set_bad( struct ureg_program *ureg ) 243848b8605Smrg{ 244848b8605Smrg tokens_error(&ureg->domain[0]); 245848b8605Smrg} 246848b8605Smrg 247848b8605Smrg 248848b8605Smrg 249848b8605Smrgstatic union tgsi_any_token *get_tokens( struct ureg_program *ureg, 250848b8605Smrg unsigned domain, 251848b8605Smrg unsigned count ) 252848b8605Smrg{ 253848b8605Smrg struct ureg_tokens *tokens = &ureg->domain[domain]; 254848b8605Smrg union tgsi_any_token *result; 255848b8605Smrg 256848b8605Smrg if (tokens->count + count > tokens->size) 257848b8605Smrg tokens_expand(tokens, count); 258848b8605Smrg 259848b8605Smrg result = &tokens->tokens[tokens->count]; 260848b8605Smrg tokens->count += count; 261848b8605Smrg return result; 262848b8605Smrg} 263848b8605Smrg 264848b8605Smrg 265848b8605Smrgstatic union tgsi_any_token *retrieve_token( struct ureg_program *ureg, 266848b8605Smrg unsigned domain, 267848b8605Smrg unsigned nr ) 268848b8605Smrg{ 269848b8605Smrg if (ureg->domain[domain].tokens == error_tokens) 270848b8605Smrg return &error_tokens[0]; 271848b8605Smrg 272848b8605Smrg return &ureg->domain[domain].tokens[nr]; 273848b8605Smrg} 274848b8605Smrg 275848b8605Smrg 276848b8605Smrgvoid 277b8e80941Smrgureg_property(struct ureg_program *ureg, unsigned name, unsigned value) 278848b8605Smrg{ 279b8e80941Smrg assert(name < ARRAY_SIZE(ureg->properties)); 280b8e80941Smrg ureg->properties[name] = value; 281848b8605Smrg} 282848b8605Smrg 283848b8605Smrgstruct ureg_src 284b8e80941Smrgureg_DECL_fs_input_cyl_centroid_layout(struct ureg_program *ureg, 285b8e80941Smrg enum tgsi_semantic semantic_name, 286848b8605Smrg unsigned semantic_index, 287b8e80941Smrg enum tgsi_interpolate_mode interp_mode, 288848b8605Smrg unsigned cylindrical_wrap, 289b8e80941Smrg enum tgsi_interpolate_loc interp_location, 290b8e80941Smrg unsigned index, 291b8e80941Smrg unsigned usage_mask, 292b8e80941Smrg unsigned array_id, 293b8e80941Smrg unsigned array_size) 294848b8605Smrg{ 295848b8605Smrg unsigned i; 296848b8605Smrg 297b8e80941Smrg assert(usage_mask != 0); 298b8e80941Smrg assert(usage_mask <= TGSI_WRITEMASK_XYZW); 299b8e80941Smrg 300b8e80941Smrg for (i = 0; i < ureg->nr_inputs; i++) { 301b8e80941Smrg if (ureg->input[i].semantic_name == semantic_name && 302b8e80941Smrg ureg->input[i].semantic_index == semantic_index) { 303b8e80941Smrg assert(ureg->input[i].interp == interp_mode); 304b8e80941Smrg assert(ureg->input[i].cylindrical_wrap == cylindrical_wrap); 305b8e80941Smrg assert(ureg->input[i].interp_location == interp_location); 306b8e80941Smrg if (ureg->input[i].array_id == array_id) { 307b8e80941Smrg ureg->input[i].usage_mask |= usage_mask; 308b8e80941Smrg goto out; 309b8e80941Smrg } 310b8e80941Smrg assert((ureg->input[i].usage_mask & usage_mask) == 0); 311848b8605Smrg } 312848b8605Smrg } 313848b8605Smrg 314b8e80941Smrg if (ureg->nr_inputs < UREG_MAX_INPUT) { 315b8e80941Smrg assert(array_size >= 1); 316b8e80941Smrg ureg->input[i].semantic_name = semantic_name; 317b8e80941Smrg ureg->input[i].semantic_index = semantic_index; 318b8e80941Smrg ureg->input[i].interp = interp_mode; 319b8e80941Smrg ureg->input[i].cylindrical_wrap = cylindrical_wrap; 320b8e80941Smrg ureg->input[i].interp_location = interp_location; 321b8e80941Smrg ureg->input[i].first = index; 322b8e80941Smrg ureg->input[i].last = index + array_size - 1; 323b8e80941Smrg ureg->input[i].array_id = array_id; 324b8e80941Smrg ureg->input[i].usage_mask = usage_mask; 325b8e80941Smrg ureg->nr_input_regs = MAX2(ureg->nr_input_regs, index + array_size); 326b8e80941Smrg ureg->nr_inputs++; 327848b8605Smrg } else { 328848b8605Smrg set_bad(ureg); 329848b8605Smrg } 330848b8605Smrg 331848b8605Smrgout: 332b8e80941Smrg return ureg_src_array_register(TGSI_FILE_INPUT, ureg->input[i].first, 333b8e80941Smrg array_id); 334b8e80941Smrg} 335b8e80941Smrg 336b8e80941Smrgstruct ureg_src 337b8e80941Smrgureg_DECL_fs_input_cyl_centroid(struct ureg_program *ureg, 338b8e80941Smrg enum tgsi_semantic semantic_name, 339b8e80941Smrg unsigned semantic_index, 340b8e80941Smrg enum tgsi_interpolate_mode interp_mode, 341b8e80941Smrg unsigned cylindrical_wrap, 342b8e80941Smrg enum tgsi_interpolate_loc interp_location, 343b8e80941Smrg unsigned array_id, 344b8e80941Smrg unsigned array_size) 345b8e80941Smrg{ 346b8e80941Smrg return ureg_DECL_fs_input_cyl_centroid_layout(ureg, 347b8e80941Smrg semantic_name, semantic_index, interp_mode, 348b8e80941Smrg cylindrical_wrap, interp_location, 349b8e80941Smrg ureg->nr_input_regs, TGSI_WRITEMASK_XYZW, array_id, array_size); 350848b8605Smrg} 351848b8605Smrg 352848b8605Smrg 353b8e80941Smrgstruct ureg_src 354848b8605Smrgureg_DECL_vs_input( struct ureg_program *ureg, 355848b8605Smrg unsigned index ) 356848b8605Smrg{ 357b8e80941Smrg assert(ureg->processor == PIPE_SHADER_VERTEX); 358b8e80941Smrg assert(index / 32 < ARRAY_SIZE(ureg->vs_inputs)); 359b8e80941Smrg 360848b8605Smrg ureg->vs_inputs[index/32] |= 1 << (index % 32); 361848b8605Smrg return ureg_src_register( TGSI_FILE_INPUT, index ); 362848b8605Smrg} 363848b8605Smrg 364848b8605Smrg 365848b8605Smrgstruct ureg_src 366b8e80941Smrgureg_DECL_input_layout(struct ureg_program *ureg, 367b8e80941Smrg enum tgsi_semantic semantic_name, 368b8e80941Smrg unsigned semantic_index, 369b8e80941Smrg unsigned index, 370b8e80941Smrg unsigned usage_mask, 371b8e80941Smrg unsigned array_id, 372b8e80941Smrg unsigned array_size) 373b8e80941Smrg{ 374b8e80941Smrg return ureg_DECL_fs_input_cyl_centroid_layout(ureg, 375b8e80941Smrg semantic_name, semantic_index, 376b8e80941Smrg TGSI_INTERPOLATE_CONSTANT, 0, TGSI_INTERPOLATE_LOC_CENTER, 377b8e80941Smrg index, usage_mask, array_id, array_size); 378b8e80941Smrg} 379848b8605Smrg 380b8e80941Smrg 381b8e80941Smrgstruct ureg_src 382b8e80941Smrgureg_DECL_input(struct ureg_program *ureg, 383b8e80941Smrg enum tgsi_semantic semantic_name, 384b8e80941Smrg unsigned semantic_index, 385b8e80941Smrg unsigned array_id, 386b8e80941Smrg unsigned array_size) 387b8e80941Smrg{ 388b8e80941Smrg return ureg_DECL_fs_input_cyl_centroid(ureg, semantic_name, semantic_index, 389b8e80941Smrg TGSI_INTERPOLATE_CONSTANT, 0, 390b8e80941Smrg TGSI_INTERPOLATE_LOC_CENTER, 391b8e80941Smrg array_id, array_size); 392848b8605Smrg} 393848b8605Smrg 394848b8605Smrg 395848b8605Smrgstruct ureg_src 396848b8605Smrgureg_DECL_system_value(struct ureg_program *ureg, 397b8e80941Smrg enum tgsi_semantic semantic_name, 398848b8605Smrg unsigned semantic_index) 399848b8605Smrg{ 400b8e80941Smrg unsigned i; 401b8e80941Smrg 402b8e80941Smrg for (i = 0; i < ureg->nr_system_values; i++) { 403b8e80941Smrg if (ureg->system_value[i].semantic_name == semantic_name && 404b8e80941Smrg ureg->system_value[i].semantic_index == semantic_index) { 405b8e80941Smrg goto out; 406b8e80941Smrg } 407b8e80941Smrg } 408b8e80941Smrg 409848b8605Smrg if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) { 410848b8605Smrg ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name; 411848b8605Smrg ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index; 412b8e80941Smrg i = ureg->nr_system_values; 413848b8605Smrg ureg->nr_system_values++; 414848b8605Smrg } else { 415848b8605Smrg set_bad(ureg); 416848b8605Smrg } 417848b8605Smrg 418b8e80941Smrgout: 419b8e80941Smrg return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, i); 420848b8605Smrg} 421848b8605Smrg 422848b8605Smrg 423b8e80941Smrgstruct ureg_dst 424b8e80941Smrgureg_DECL_output_layout(struct ureg_program *ureg, 425b8e80941Smrg enum tgsi_semantic semantic_name, 426b8e80941Smrg unsigned semantic_index, 427b8e80941Smrg unsigned streams, 428b8e80941Smrg unsigned index, 429b8e80941Smrg unsigned usage_mask, 430b8e80941Smrg unsigned array_id, 431b8e80941Smrg unsigned array_size, 432b8e80941Smrg boolean invariant) 433848b8605Smrg{ 434848b8605Smrg unsigned i; 435848b8605Smrg 436848b8605Smrg assert(usage_mask != 0); 437b8e80941Smrg assert(!(streams & 0x03) || (usage_mask & 1)); 438b8e80941Smrg assert(!(streams & 0x0c) || (usage_mask & 2)); 439b8e80941Smrg assert(!(streams & 0x30) || (usage_mask & 4)); 440b8e80941Smrg assert(!(streams & 0xc0) || (usage_mask & 8)); 441848b8605Smrg 442848b8605Smrg for (i = 0; i < ureg->nr_outputs; i++) { 443b8e80941Smrg if (ureg->output[i].semantic_name == semantic_name && 444b8e80941Smrg ureg->output[i].semantic_index == semantic_index) { 445b8e80941Smrg if (ureg->output[i].array_id == array_id) { 446b8e80941Smrg ureg->output[i].usage_mask |= usage_mask; 447b8e80941Smrg goto out; 448b8e80941Smrg } 449b8e80941Smrg assert((ureg->output[i].usage_mask & usage_mask) == 0); 450848b8605Smrg } 451848b8605Smrg } 452848b8605Smrg 453848b8605Smrg if (ureg->nr_outputs < UREG_MAX_OUTPUT) { 454b8e80941Smrg ureg->output[i].semantic_name = semantic_name; 455b8e80941Smrg ureg->output[i].semantic_index = semantic_index; 456848b8605Smrg ureg->output[i].usage_mask = usage_mask; 457b8e80941Smrg ureg->output[i].first = index; 458b8e80941Smrg ureg->output[i].last = index + array_size - 1; 459b8e80941Smrg ureg->output[i].array_id = array_id; 460b8e80941Smrg ureg->output[i].invariant = invariant; 461b8e80941Smrg ureg->nr_output_regs = MAX2(ureg->nr_output_regs, index + array_size); 462848b8605Smrg ureg->nr_outputs++; 463848b8605Smrg } 464848b8605Smrg else { 465848b8605Smrg set_bad( ureg ); 466b8e80941Smrg i = 0; 467848b8605Smrg } 468848b8605Smrg 469848b8605Smrgout: 470b8e80941Smrg ureg->output[i].streams |= streams; 471b8e80941Smrg 472b8e80941Smrg return ureg_dst_array_register(TGSI_FILE_OUTPUT, ureg->output[i].first, 473b8e80941Smrg array_id); 474848b8605Smrg} 475848b8605Smrg 476848b8605Smrg 477b8e80941Smrgstruct ureg_dst 478b8e80941Smrgureg_DECL_output_masked(struct ureg_program *ureg, 479b8e80941Smrg unsigned name, 480b8e80941Smrg unsigned index, 481b8e80941Smrg unsigned usage_mask, 482b8e80941Smrg unsigned array_id, 483b8e80941Smrg unsigned array_size) 484b8e80941Smrg{ 485b8e80941Smrg return ureg_DECL_output_layout(ureg, name, index, 0, 486b8e80941Smrg ureg->nr_output_regs, usage_mask, array_id, 487b8e80941Smrg array_size, FALSE); 488b8e80941Smrg} 489b8e80941Smrg 490b8e80941Smrg 491b8e80941Smrgstruct ureg_dst 492b8e80941Smrgureg_DECL_output(struct ureg_program *ureg, 493b8e80941Smrg enum tgsi_semantic name, 494b8e80941Smrg unsigned index) 495b8e80941Smrg{ 496b8e80941Smrg return ureg_DECL_output_masked(ureg, name, index, TGSI_WRITEMASK_XYZW, 497b8e80941Smrg 0, 1); 498b8e80941Smrg} 499b8e80941Smrg 500b8e80941Smrgstruct ureg_dst 501b8e80941Smrgureg_DECL_output_array(struct ureg_program *ureg, 502b8e80941Smrg enum tgsi_semantic semantic_name, 503b8e80941Smrg unsigned semantic_index, 504b8e80941Smrg unsigned array_id, 505b8e80941Smrg unsigned array_size) 506848b8605Smrg{ 507b8e80941Smrg return ureg_DECL_output_masked(ureg, semantic_name, semantic_index, 508b8e80941Smrg TGSI_WRITEMASK_XYZW, 509b8e80941Smrg array_id, array_size); 510848b8605Smrg} 511848b8605Smrg 512848b8605Smrg 513848b8605Smrg/* Returns a new constant register. Keep track of which have been 514848b8605Smrg * referred to so that we can emit decls later. 515848b8605Smrg * 516848b8605Smrg * Constant operands declared with this function must be addressed 517848b8605Smrg * with a two-dimensional index. 518848b8605Smrg * 519848b8605Smrg * There is nothing in this code to bind this constant to any tracked 520848b8605Smrg * value or manage any constant_buffer contents -- that's the 521848b8605Smrg * resposibility of the calling code. 522848b8605Smrg */ 523848b8605Smrgvoid 524848b8605Smrgureg_DECL_constant2D(struct ureg_program *ureg, 525848b8605Smrg unsigned first, 526848b8605Smrg unsigned last, 527848b8605Smrg unsigned index2D) 528848b8605Smrg{ 529b8e80941Smrg struct const_decl *decl = &ureg->const_decls[index2D]; 530848b8605Smrg 531848b8605Smrg assert(index2D < PIPE_MAX_CONSTANT_BUFFERS); 532848b8605Smrg 533848b8605Smrg if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { 534848b8605Smrg uint i = decl->nr_constant_ranges++; 535848b8605Smrg 536848b8605Smrg decl->constant_range[i].first = first; 537848b8605Smrg decl->constant_range[i].last = last; 538848b8605Smrg } 539848b8605Smrg} 540848b8605Smrg 541848b8605Smrg 542b8e80941Smrg/* A one-dimensional, deprecated version of ureg_DECL_constant2D(). 543848b8605Smrg * 544848b8605Smrg * Constant operands declared with this function must be addressed 545848b8605Smrg * with a one-dimensional index. 546848b8605Smrg */ 547848b8605Smrgstruct ureg_src 548848b8605Smrgureg_DECL_constant(struct ureg_program *ureg, 549848b8605Smrg unsigned index) 550848b8605Smrg{ 551b8e80941Smrg struct const_decl *decl = &ureg->const_decls[0]; 552848b8605Smrg unsigned minconst = index, maxconst = index; 553848b8605Smrg unsigned i; 554848b8605Smrg 555848b8605Smrg /* Inside existing range? 556848b8605Smrg */ 557848b8605Smrg for (i = 0; i < decl->nr_constant_ranges; i++) { 558848b8605Smrg if (decl->constant_range[i].first <= index && 559848b8605Smrg decl->constant_range[i].last >= index) { 560848b8605Smrg goto out; 561848b8605Smrg } 562848b8605Smrg } 563848b8605Smrg 564848b8605Smrg /* Extend existing range? 565848b8605Smrg */ 566848b8605Smrg for (i = 0; i < decl->nr_constant_ranges; i++) { 567848b8605Smrg if (decl->constant_range[i].last == index - 1) { 568848b8605Smrg decl->constant_range[i].last = index; 569848b8605Smrg goto out; 570848b8605Smrg } 571848b8605Smrg 572848b8605Smrg if (decl->constant_range[i].first == index + 1) { 573848b8605Smrg decl->constant_range[i].first = index; 574848b8605Smrg goto out; 575848b8605Smrg } 576848b8605Smrg 577848b8605Smrg minconst = MIN2(minconst, decl->constant_range[i].first); 578848b8605Smrg maxconst = MAX2(maxconst, decl->constant_range[i].last); 579848b8605Smrg } 580848b8605Smrg 581848b8605Smrg /* Create new range? 582848b8605Smrg */ 583848b8605Smrg if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) { 584848b8605Smrg i = decl->nr_constant_ranges++; 585848b8605Smrg decl->constant_range[i].first = index; 586848b8605Smrg decl->constant_range[i].last = index; 587848b8605Smrg goto out; 588848b8605Smrg } 589848b8605Smrg 590848b8605Smrg /* Collapse all ranges down to one: 591848b8605Smrg */ 592848b8605Smrg i = 0; 593848b8605Smrg decl->constant_range[0].first = minconst; 594848b8605Smrg decl->constant_range[0].last = maxconst; 595848b8605Smrg decl->nr_constant_ranges = 1; 596848b8605Smrg 597848b8605Smrgout: 598848b8605Smrg assert(i < decl->nr_constant_ranges); 599848b8605Smrg assert(decl->constant_range[i].first <= index); 600848b8605Smrg assert(decl->constant_range[i].last >= index); 601b8e80941Smrg 602b8e80941Smrg struct ureg_src src = ureg_src_register(TGSI_FILE_CONSTANT, index); 603b8e80941Smrg return ureg_src_dimension(src, 0); 604b8e80941Smrg} 605b8e80941Smrg 606b8e80941Smrg 607b8e80941Smrg/* Returns a new hw atomic register. Keep track of which have been 608b8e80941Smrg * referred to so that we can emit decls later. 609b8e80941Smrg */ 610b8e80941Smrgvoid 611b8e80941Smrgureg_DECL_hw_atomic(struct ureg_program *ureg, 612b8e80941Smrg unsigned first, 613b8e80941Smrg unsigned last, 614b8e80941Smrg unsigned buffer_id, 615b8e80941Smrg unsigned array_id) 616b8e80941Smrg{ 617b8e80941Smrg struct hw_atomic_decl *decl = &ureg->hw_atomic_decls[buffer_id]; 618b8e80941Smrg 619b8e80941Smrg if (decl->nr_hw_atomic_ranges < UREG_MAX_HW_ATOMIC_RANGE) { 620b8e80941Smrg uint i = decl->nr_hw_atomic_ranges++; 621b8e80941Smrg 622b8e80941Smrg decl->hw_atomic_range[i].first = first; 623b8e80941Smrg decl->hw_atomic_range[i].last = last; 624b8e80941Smrg decl->hw_atomic_range[i].array_id = array_id; 625b8e80941Smrg } else { 626b8e80941Smrg set_bad(ureg); 627b8e80941Smrg } 628848b8605Smrg} 629848b8605Smrg 630848b8605Smrgstatic struct ureg_dst alloc_temporary( struct ureg_program *ureg, 631848b8605Smrg boolean local ) 632848b8605Smrg{ 633848b8605Smrg unsigned i; 634848b8605Smrg 635848b8605Smrg /* Look for a released temporary. 636848b8605Smrg */ 637848b8605Smrg for (i = util_bitmask_get_first_index(ureg->free_temps); 638848b8605Smrg i != UTIL_BITMASK_INVALID_INDEX; 639848b8605Smrg i = util_bitmask_get_next_index(ureg->free_temps, i + 1)) { 640848b8605Smrg if (util_bitmask_get(ureg->local_temps, i) == local) 641848b8605Smrg break; 642848b8605Smrg } 643848b8605Smrg 644848b8605Smrg /* Or allocate a new one. 645848b8605Smrg */ 646848b8605Smrg if (i == UTIL_BITMASK_INVALID_INDEX) { 647848b8605Smrg i = ureg->nr_temps++; 648848b8605Smrg 649848b8605Smrg if (local) 650848b8605Smrg util_bitmask_set(ureg->local_temps, i); 651848b8605Smrg 652848b8605Smrg /* Start a new declaration when the local flag changes */ 653848b8605Smrg if (!i || util_bitmask_get(ureg->local_temps, i - 1) != local) 654848b8605Smrg util_bitmask_set(ureg->decl_temps, i); 655848b8605Smrg } 656848b8605Smrg 657848b8605Smrg util_bitmask_clear(ureg->free_temps, i); 658848b8605Smrg 659848b8605Smrg return ureg_dst_register( TGSI_FILE_TEMPORARY, i ); 660848b8605Smrg} 661848b8605Smrg 662848b8605Smrgstruct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg ) 663848b8605Smrg{ 664848b8605Smrg return alloc_temporary(ureg, FALSE); 665848b8605Smrg} 666848b8605Smrg 667848b8605Smrgstruct ureg_dst ureg_DECL_local_temporary( struct ureg_program *ureg ) 668848b8605Smrg{ 669848b8605Smrg return alloc_temporary(ureg, TRUE); 670848b8605Smrg} 671848b8605Smrg 672848b8605Smrgstruct ureg_dst ureg_DECL_array_temporary( struct ureg_program *ureg, 673848b8605Smrg unsigned size, 674848b8605Smrg boolean local ) 675848b8605Smrg{ 676848b8605Smrg unsigned i = ureg->nr_temps; 677848b8605Smrg struct ureg_dst dst = ureg_dst_register( TGSI_FILE_TEMPORARY, i ); 678848b8605Smrg 679848b8605Smrg if (local) 680848b8605Smrg util_bitmask_set(ureg->local_temps, i); 681848b8605Smrg 682848b8605Smrg /* Always start a new declaration at the start */ 683848b8605Smrg util_bitmask_set(ureg->decl_temps, i); 684848b8605Smrg 685848b8605Smrg ureg->nr_temps += size; 686848b8605Smrg 687848b8605Smrg /* and also at the end of the array */ 688848b8605Smrg util_bitmask_set(ureg->decl_temps, ureg->nr_temps); 689848b8605Smrg 690848b8605Smrg if (ureg->nr_array_temps < UREG_MAX_ARRAY_TEMPS) { 691848b8605Smrg ureg->array_temps[ureg->nr_array_temps++] = i; 692848b8605Smrg dst.ArrayID = ureg->nr_array_temps; 693848b8605Smrg } 694848b8605Smrg 695848b8605Smrg return dst; 696848b8605Smrg} 697848b8605Smrg 698848b8605Smrgvoid ureg_release_temporary( struct ureg_program *ureg, 699848b8605Smrg struct ureg_dst tmp ) 700848b8605Smrg{ 701848b8605Smrg if(tmp.File == TGSI_FILE_TEMPORARY) 702848b8605Smrg util_bitmask_set(ureg->free_temps, tmp.Index); 703848b8605Smrg} 704848b8605Smrg 705848b8605Smrg 706848b8605Smrg/* Allocate a new address register. 707848b8605Smrg */ 708848b8605Smrgstruct ureg_dst ureg_DECL_address( struct ureg_program *ureg ) 709848b8605Smrg{ 710848b8605Smrg if (ureg->nr_addrs < UREG_MAX_ADDR) 711848b8605Smrg return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ ); 712848b8605Smrg 713848b8605Smrg assert( 0 ); 714848b8605Smrg return ureg_dst_register( TGSI_FILE_ADDRESS, 0 ); 715848b8605Smrg} 716848b8605Smrg 717848b8605Smrg/* Allocate a new sampler. 718848b8605Smrg */ 719848b8605Smrgstruct ureg_src ureg_DECL_sampler( struct ureg_program *ureg, 720848b8605Smrg unsigned nr ) 721848b8605Smrg{ 722848b8605Smrg unsigned i; 723848b8605Smrg 724848b8605Smrg for (i = 0; i < ureg->nr_samplers; i++) 725b8e80941Smrg if (ureg->sampler[i].Index == (int)nr) 726848b8605Smrg return ureg->sampler[i]; 727b8e80941Smrg 728848b8605Smrg if (i < PIPE_MAX_SAMPLERS) { 729848b8605Smrg ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr ); 730848b8605Smrg ureg->nr_samplers++; 731848b8605Smrg return ureg->sampler[i]; 732848b8605Smrg } 733848b8605Smrg 734848b8605Smrg assert( 0 ); 735848b8605Smrg return ureg->sampler[0]; 736848b8605Smrg} 737848b8605Smrg 738848b8605Smrg/* 739848b8605Smrg * Allocate a new shader sampler view. 740848b8605Smrg */ 741848b8605Smrgstruct ureg_src 742848b8605Smrgureg_DECL_sampler_view(struct ureg_program *ureg, 743848b8605Smrg unsigned index, 744b8e80941Smrg enum tgsi_texture_type target, 745b8e80941Smrg enum tgsi_return_type return_type_x, 746b8e80941Smrg enum tgsi_return_type return_type_y, 747b8e80941Smrg enum tgsi_return_type return_type_z, 748b8e80941Smrg enum tgsi_return_type return_type_w) 749848b8605Smrg{ 750848b8605Smrg struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index); 751848b8605Smrg uint i; 752848b8605Smrg 753848b8605Smrg for (i = 0; i < ureg->nr_sampler_views; i++) { 754848b8605Smrg if (ureg->sampler_view[i].index == index) { 755848b8605Smrg return reg; 756848b8605Smrg } 757848b8605Smrg } 758848b8605Smrg 759848b8605Smrg if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) { 760848b8605Smrg ureg->sampler_view[i].index = index; 761848b8605Smrg ureg->sampler_view[i].target = target; 762848b8605Smrg ureg->sampler_view[i].return_type_x = return_type_x; 763848b8605Smrg ureg->sampler_view[i].return_type_y = return_type_y; 764848b8605Smrg ureg->sampler_view[i].return_type_z = return_type_z; 765848b8605Smrg ureg->sampler_view[i].return_type_w = return_type_w; 766848b8605Smrg ureg->nr_sampler_views++; 767848b8605Smrg return reg; 768848b8605Smrg } 769848b8605Smrg 770848b8605Smrg assert(0); 771848b8605Smrg return reg; 772848b8605Smrg} 773848b8605Smrg 774b8e80941Smrg/* Allocate a new image. 775b8e80941Smrg */ 776b8e80941Smrgstruct ureg_src 777b8e80941Smrgureg_DECL_image(struct ureg_program *ureg, 778b8e80941Smrg unsigned index, 779b8e80941Smrg enum tgsi_texture_type target, 780b8e80941Smrg enum pipe_format format, 781b8e80941Smrg boolean wr, 782b8e80941Smrg boolean raw) 783b8e80941Smrg{ 784b8e80941Smrg struct ureg_src reg = ureg_src_register(TGSI_FILE_IMAGE, index); 785b8e80941Smrg unsigned i; 786b8e80941Smrg 787b8e80941Smrg for (i = 0; i < ureg->nr_images; i++) 788b8e80941Smrg if (ureg->image[i].index == index) 789b8e80941Smrg return reg; 790b8e80941Smrg 791b8e80941Smrg if (i < PIPE_MAX_SHADER_IMAGES) { 792b8e80941Smrg ureg->image[i].index = index; 793b8e80941Smrg ureg->image[i].target = target; 794b8e80941Smrg ureg->image[i].wr = wr; 795b8e80941Smrg ureg->image[i].raw = raw; 796b8e80941Smrg ureg->image[i].format = format; 797b8e80941Smrg ureg->nr_images++; 798b8e80941Smrg return reg; 799b8e80941Smrg } 800b8e80941Smrg 801b8e80941Smrg assert(0); 802b8e80941Smrg return reg; 803b8e80941Smrg} 804b8e80941Smrg 805b8e80941Smrg/* Allocate a new buffer. 806b8e80941Smrg */ 807b8e80941Smrgstruct ureg_src ureg_DECL_buffer(struct ureg_program *ureg, unsigned nr, 808b8e80941Smrg bool atomic) 809b8e80941Smrg{ 810b8e80941Smrg struct ureg_src reg = ureg_src_register(TGSI_FILE_BUFFER, nr); 811b8e80941Smrg unsigned i; 812b8e80941Smrg 813b8e80941Smrg for (i = 0; i < ureg->nr_buffers; i++) 814b8e80941Smrg if (ureg->buffer[i].index == nr) 815b8e80941Smrg return reg; 816b8e80941Smrg 817b8e80941Smrg if (i < PIPE_MAX_SHADER_BUFFERS) { 818b8e80941Smrg ureg->buffer[i].index = nr; 819b8e80941Smrg ureg->buffer[i].atomic = atomic; 820b8e80941Smrg ureg->nr_buffers++; 821b8e80941Smrg return reg; 822b8e80941Smrg } 823b8e80941Smrg 824b8e80941Smrg assert(0); 825b8e80941Smrg return reg; 826b8e80941Smrg} 827b8e80941Smrg 828b8e80941Smrg/* Allocate a memory area. 829b8e80941Smrg */ 830b8e80941Smrgstruct ureg_src ureg_DECL_memory(struct ureg_program *ureg, 831b8e80941Smrg unsigned memory_type) 832b8e80941Smrg{ 833b8e80941Smrg struct ureg_src reg = ureg_src_register(TGSI_FILE_MEMORY, memory_type); 834b8e80941Smrg 835b8e80941Smrg ureg->use_memory[memory_type] = true; 836b8e80941Smrg return reg; 837b8e80941Smrg} 838b8e80941Smrg 839b8e80941Smrgstatic int 840b8e80941Smrgmatch_or_expand_immediate64( const unsigned *v, 841b8e80941Smrg unsigned nr, 842b8e80941Smrg unsigned *v2, 843b8e80941Smrg unsigned *pnr2, 844b8e80941Smrg unsigned *swizzle ) 845b8e80941Smrg{ 846b8e80941Smrg unsigned nr2 = *pnr2; 847b8e80941Smrg unsigned i, j; 848b8e80941Smrg *swizzle = 0; 849b8e80941Smrg 850b8e80941Smrg for (i = 0; i < nr; i += 2) { 851b8e80941Smrg boolean found = FALSE; 852b8e80941Smrg 853b8e80941Smrg for (j = 0; j < nr2 && !found; j += 2) { 854b8e80941Smrg if (v[i] == v2[j] && v[i + 1] == v2[j + 1]) { 855b8e80941Smrg *swizzle |= (j << (i * 2)) | ((j + 1) << ((i + 1) * 2)); 856b8e80941Smrg found = TRUE; 857b8e80941Smrg } 858b8e80941Smrg } 859b8e80941Smrg if (!found) { 860b8e80941Smrg if ((nr2) >= 4) { 861b8e80941Smrg return FALSE; 862b8e80941Smrg } 863b8e80941Smrg 864b8e80941Smrg v2[nr2] = v[i]; 865b8e80941Smrg v2[nr2 + 1] = v[i + 1]; 866b8e80941Smrg 867b8e80941Smrg *swizzle |= (nr2 << (i * 2)) | ((nr2 + 1) << ((i + 1) * 2)); 868b8e80941Smrg nr2 += 2; 869b8e80941Smrg } 870b8e80941Smrg } 871b8e80941Smrg 872b8e80941Smrg /* Actually expand immediate only when fully succeeded. 873b8e80941Smrg */ 874b8e80941Smrg *pnr2 = nr2; 875b8e80941Smrg return TRUE; 876b8e80941Smrg} 877b8e80941Smrg 878848b8605Smrgstatic int 879848b8605Smrgmatch_or_expand_immediate( const unsigned *v, 880b8e80941Smrg int type, 881848b8605Smrg unsigned nr, 882848b8605Smrg unsigned *v2, 883848b8605Smrg unsigned *pnr2, 884848b8605Smrg unsigned *swizzle ) 885848b8605Smrg{ 886848b8605Smrg unsigned nr2 = *pnr2; 887848b8605Smrg unsigned i, j; 888848b8605Smrg 889b8e80941Smrg if (type == TGSI_IMM_FLOAT64 || 890b8e80941Smrg type == TGSI_IMM_UINT64 || 891b8e80941Smrg type == TGSI_IMM_INT64) 892b8e80941Smrg return match_or_expand_immediate64(v, nr, v2, pnr2, swizzle); 893b8e80941Smrg 894848b8605Smrg *swizzle = 0; 895848b8605Smrg 896848b8605Smrg for (i = 0; i < nr; i++) { 897848b8605Smrg boolean found = FALSE; 898848b8605Smrg 899848b8605Smrg for (j = 0; j < nr2 && !found; j++) { 900848b8605Smrg if (v[i] == v2[j]) { 901848b8605Smrg *swizzle |= j << (i * 2); 902848b8605Smrg found = TRUE; 903848b8605Smrg } 904848b8605Smrg } 905848b8605Smrg 906848b8605Smrg if (!found) { 907848b8605Smrg if (nr2 >= 4) { 908848b8605Smrg return FALSE; 909848b8605Smrg } 910848b8605Smrg 911848b8605Smrg v2[nr2] = v[i]; 912848b8605Smrg *swizzle |= nr2 << (i * 2); 913848b8605Smrg nr2++; 914848b8605Smrg } 915848b8605Smrg } 916848b8605Smrg 917848b8605Smrg /* Actually expand immediate only when fully succeeded. 918848b8605Smrg */ 919848b8605Smrg *pnr2 = nr2; 920848b8605Smrg return TRUE; 921848b8605Smrg} 922848b8605Smrg 923848b8605Smrg 924848b8605Smrgstatic struct ureg_src 925848b8605Smrgdecl_immediate( struct ureg_program *ureg, 926848b8605Smrg const unsigned *v, 927848b8605Smrg unsigned nr, 928848b8605Smrg unsigned type ) 929848b8605Smrg{ 930848b8605Smrg unsigned i, j; 931848b8605Smrg unsigned swizzle = 0; 932848b8605Smrg 933848b8605Smrg /* Could do a first pass where we examine all existing immediates 934848b8605Smrg * without expanding. 935848b8605Smrg */ 936848b8605Smrg 937848b8605Smrg for (i = 0; i < ureg->nr_immediates; i++) { 938848b8605Smrg if (ureg->immediate[i].type != type) { 939848b8605Smrg continue; 940848b8605Smrg } 941848b8605Smrg if (match_or_expand_immediate(v, 942b8e80941Smrg type, 943848b8605Smrg nr, 944848b8605Smrg ureg->immediate[i].value.u, 945848b8605Smrg &ureg->immediate[i].nr, 946848b8605Smrg &swizzle)) { 947848b8605Smrg goto out; 948848b8605Smrg } 949848b8605Smrg } 950848b8605Smrg 951848b8605Smrg if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) { 952848b8605Smrg i = ureg->nr_immediates++; 953848b8605Smrg ureg->immediate[i].type = type; 954848b8605Smrg if (match_or_expand_immediate(v, 955b8e80941Smrg type, 956848b8605Smrg nr, 957848b8605Smrg ureg->immediate[i].value.u, 958848b8605Smrg &ureg->immediate[i].nr, 959848b8605Smrg &swizzle)) { 960848b8605Smrg goto out; 961848b8605Smrg } 962848b8605Smrg } 963848b8605Smrg 964848b8605Smrg set_bad(ureg); 965848b8605Smrg 966848b8605Smrgout: 967848b8605Smrg /* Make sure that all referenced elements are from this immediate. 968848b8605Smrg * Has the effect of making size-one immediates into scalars. 969848b8605Smrg */ 970b8e80941Smrg if (type == TGSI_IMM_FLOAT64 || 971b8e80941Smrg type == TGSI_IMM_UINT64 || 972b8e80941Smrg type == TGSI_IMM_INT64) { 973b8e80941Smrg for (j = nr; j < 4; j+=2) { 974b8e80941Smrg swizzle |= (swizzle & 0xf) << (j * 2); 975b8e80941Smrg } 976b8e80941Smrg } else { 977b8e80941Smrg for (j = nr; j < 4; j++) { 978b8e80941Smrg swizzle |= (swizzle & 0x3) << (j * 2); 979b8e80941Smrg } 980848b8605Smrg } 981848b8605Smrg return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i), 982848b8605Smrg (swizzle >> 0) & 0x3, 983848b8605Smrg (swizzle >> 2) & 0x3, 984848b8605Smrg (swizzle >> 4) & 0x3, 985848b8605Smrg (swizzle >> 6) & 0x3); 986848b8605Smrg} 987848b8605Smrg 988848b8605Smrg 989848b8605Smrgstruct ureg_src 990848b8605Smrgureg_DECL_immediate( struct ureg_program *ureg, 991848b8605Smrg const float *v, 992848b8605Smrg unsigned nr ) 993848b8605Smrg{ 994848b8605Smrg union { 995848b8605Smrg float f[4]; 996848b8605Smrg unsigned u[4]; 997848b8605Smrg } fu; 998848b8605Smrg unsigned int i; 999848b8605Smrg 1000848b8605Smrg for (i = 0; i < nr; i++) { 1001848b8605Smrg fu.f[i] = v[i]; 1002848b8605Smrg } 1003848b8605Smrg 1004848b8605Smrg return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32); 1005848b8605Smrg} 1006848b8605Smrg 1007b8e80941Smrgstruct ureg_src 1008b8e80941Smrgureg_DECL_immediate_f64( struct ureg_program *ureg, 1009b8e80941Smrg const double *v, 1010b8e80941Smrg unsigned nr ) 1011b8e80941Smrg{ 1012b8e80941Smrg union { 1013b8e80941Smrg unsigned u[4]; 1014b8e80941Smrg double d[2]; 1015b8e80941Smrg } fu; 1016b8e80941Smrg unsigned int i; 1017b8e80941Smrg 1018b8e80941Smrg assert((nr / 2) < 3); 1019b8e80941Smrg for (i = 0; i < nr / 2; i++) { 1020b8e80941Smrg fu.d[i] = v[i]; 1021b8e80941Smrg } 1022b8e80941Smrg 1023b8e80941Smrg return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT64); 1024b8e80941Smrg} 1025848b8605Smrg 1026848b8605Smrgstruct ureg_src 1027848b8605Smrgureg_DECL_immediate_uint( struct ureg_program *ureg, 1028848b8605Smrg const unsigned *v, 1029848b8605Smrg unsigned nr ) 1030848b8605Smrg{ 1031848b8605Smrg return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32); 1032848b8605Smrg} 1033848b8605Smrg 1034848b8605Smrg 1035848b8605Smrgstruct ureg_src 1036848b8605Smrgureg_DECL_immediate_block_uint( struct ureg_program *ureg, 1037848b8605Smrg const unsigned *v, 1038848b8605Smrg unsigned nr ) 1039848b8605Smrg{ 1040848b8605Smrg uint index; 1041848b8605Smrg uint i; 1042848b8605Smrg 1043848b8605Smrg if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) { 1044848b8605Smrg set_bad(ureg); 1045848b8605Smrg return ureg_src_register(TGSI_FILE_IMMEDIATE, 0); 1046848b8605Smrg } 1047848b8605Smrg 1048848b8605Smrg index = ureg->nr_immediates; 1049848b8605Smrg ureg->nr_immediates += (nr + 3) / 4; 1050848b8605Smrg 1051848b8605Smrg for (i = index; i < ureg->nr_immediates; i++) { 1052848b8605Smrg ureg->immediate[i].type = TGSI_IMM_UINT32; 1053848b8605Smrg ureg->immediate[i].nr = nr > 4 ? 4 : nr; 1054848b8605Smrg memcpy(ureg->immediate[i].value.u, 1055848b8605Smrg &v[(i - index) * 4], 1056848b8605Smrg ureg->immediate[i].nr * sizeof(uint)); 1057848b8605Smrg nr -= 4; 1058848b8605Smrg } 1059848b8605Smrg 1060848b8605Smrg return ureg_src_register(TGSI_FILE_IMMEDIATE, index); 1061848b8605Smrg} 1062848b8605Smrg 1063848b8605Smrg 1064848b8605Smrgstruct ureg_src 1065848b8605Smrgureg_DECL_immediate_int( struct ureg_program *ureg, 1066848b8605Smrg const int *v, 1067848b8605Smrg unsigned nr ) 1068848b8605Smrg{ 1069848b8605Smrg return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32); 1070848b8605Smrg} 1071848b8605Smrg 1072b8e80941Smrgstruct ureg_src 1073b8e80941Smrgureg_DECL_immediate_uint64( struct ureg_program *ureg, 1074b8e80941Smrg const uint64_t *v, 1075b8e80941Smrg unsigned nr ) 1076b8e80941Smrg{ 1077b8e80941Smrg union { 1078b8e80941Smrg unsigned u[4]; 1079b8e80941Smrg uint64_t u64[2]; 1080b8e80941Smrg } fu; 1081b8e80941Smrg unsigned int i; 1082b8e80941Smrg 1083b8e80941Smrg assert((nr / 2) < 3); 1084b8e80941Smrg for (i = 0; i < nr / 2; i++) { 1085b8e80941Smrg fu.u64[i] = v[i]; 1086b8e80941Smrg } 1087b8e80941Smrg 1088b8e80941Smrg return decl_immediate(ureg, fu.u, nr, TGSI_IMM_UINT64); 1089b8e80941Smrg} 1090b8e80941Smrg 1091b8e80941Smrgstruct ureg_src 1092b8e80941Smrgureg_DECL_immediate_int64( struct ureg_program *ureg, 1093b8e80941Smrg const int64_t *v, 1094b8e80941Smrg unsigned nr ) 1095b8e80941Smrg{ 1096b8e80941Smrg union { 1097b8e80941Smrg unsigned u[4]; 1098b8e80941Smrg int64_t i64[2]; 1099b8e80941Smrg } fu; 1100b8e80941Smrg unsigned int i; 1101b8e80941Smrg 1102b8e80941Smrg assert((nr / 2) < 3); 1103b8e80941Smrg for (i = 0; i < nr / 2; i++) { 1104b8e80941Smrg fu.i64[i] = v[i]; 1105b8e80941Smrg } 1106b8e80941Smrg 1107b8e80941Smrg return decl_immediate(ureg, fu.u, nr, TGSI_IMM_INT64); 1108b8e80941Smrg} 1109848b8605Smrg 1110848b8605Smrgvoid 1111848b8605Smrgureg_emit_src( struct ureg_program *ureg, 1112848b8605Smrg struct ureg_src src ) 1113848b8605Smrg{ 1114848b8605Smrg unsigned size = 1 + (src.Indirect ? 1 : 0) + 1115848b8605Smrg (src.Dimension ? (src.DimIndirect ? 2 : 1) : 0); 1116848b8605Smrg 1117848b8605Smrg union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); 1118848b8605Smrg unsigned n = 0; 1119848b8605Smrg 1120848b8605Smrg assert(src.File != TGSI_FILE_NULL); 1121848b8605Smrg assert(src.File < TGSI_FILE_COUNT); 1122b8e80941Smrg 1123848b8605Smrg out[n].value = 0; 1124848b8605Smrg out[n].src.File = src.File; 1125848b8605Smrg out[n].src.SwizzleX = src.SwizzleX; 1126848b8605Smrg out[n].src.SwizzleY = src.SwizzleY; 1127848b8605Smrg out[n].src.SwizzleZ = src.SwizzleZ; 1128848b8605Smrg out[n].src.SwizzleW = src.SwizzleW; 1129848b8605Smrg out[n].src.Index = src.Index; 1130848b8605Smrg out[n].src.Negate = src.Negate; 1131848b8605Smrg out[0].src.Absolute = src.Absolute; 1132848b8605Smrg n++; 1133848b8605Smrg 1134848b8605Smrg if (src.Indirect) { 1135848b8605Smrg out[0].src.Indirect = 1; 1136848b8605Smrg out[n].value = 0; 1137848b8605Smrg out[n].ind.File = src.IndirectFile; 1138848b8605Smrg out[n].ind.Swizzle = src.IndirectSwizzle; 1139848b8605Smrg out[n].ind.Index = src.IndirectIndex; 1140b8e80941Smrg if (!ureg->supports_any_inout_decl_range && 1141b8e80941Smrg (src.File == TGSI_FILE_INPUT || src.File == TGSI_FILE_OUTPUT)) 1142b8e80941Smrg out[n].ind.ArrayID = 0; 1143b8e80941Smrg else 1144b8e80941Smrg out[n].ind.ArrayID = src.ArrayID; 1145848b8605Smrg n++; 1146848b8605Smrg } 1147848b8605Smrg 1148848b8605Smrg if (src.Dimension) { 1149848b8605Smrg out[0].src.Dimension = 1; 1150848b8605Smrg out[n].dim.Dimension = 0; 1151848b8605Smrg out[n].dim.Padding = 0; 1152848b8605Smrg if (src.DimIndirect) { 1153848b8605Smrg out[n].dim.Indirect = 1; 1154848b8605Smrg out[n].dim.Index = src.DimensionIndex; 1155848b8605Smrg n++; 1156848b8605Smrg out[n].value = 0; 1157848b8605Smrg out[n].ind.File = src.DimIndFile; 1158848b8605Smrg out[n].ind.Swizzle = src.DimIndSwizzle; 1159848b8605Smrg out[n].ind.Index = src.DimIndIndex; 1160b8e80941Smrg if (!ureg->supports_any_inout_decl_range && 1161b8e80941Smrg (src.File == TGSI_FILE_INPUT || src.File == TGSI_FILE_OUTPUT)) 1162b8e80941Smrg out[n].ind.ArrayID = 0; 1163b8e80941Smrg else 1164b8e80941Smrg out[n].ind.ArrayID = src.ArrayID; 1165848b8605Smrg } else { 1166848b8605Smrg out[n].dim.Indirect = 0; 1167848b8605Smrg out[n].dim.Index = src.DimensionIndex; 1168848b8605Smrg } 1169848b8605Smrg n++; 1170848b8605Smrg } 1171848b8605Smrg 1172848b8605Smrg assert(n == size); 1173848b8605Smrg} 1174848b8605Smrg 1175848b8605Smrg 1176b8e80941Smrgvoid 1177848b8605Smrgureg_emit_dst( struct ureg_program *ureg, 1178848b8605Smrg struct ureg_dst dst ) 1179848b8605Smrg{ 1180b8e80941Smrg unsigned size = 1 + (dst.Indirect ? 1 : 0) + 1181b8e80941Smrg (dst.Dimension ? (dst.DimIndirect ? 2 : 1) : 0); 1182848b8605Smrg 1183848b8605Smrg union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); 1184848b8605Smrg unsigned n = 0; 1185848b8605Smrg 1186848b8605Smrg assert(dst.File != TGSI_FILE_NULL); 1187848b8605Smrg assert(dst.File != TGSI_FILE_SAMPLER); 1188848b8605Smrg assert(dst.File != TGSI_FILE_SAMPLER_VIEW); 1189848b8605Smrg assert(dst.File != TGSI_FILE_IMMEDIATE); 1190848b8605Smrg assert(dst.File < TGSI_FILE_COUNT); 1191848b8605Smrg 1192848b8605Smrg out[n].value = 0; 1193848b8605Smrg out[n].dst.File = dst.File; 1194848b8605Smrg out[n].dst.WriteMask = dst.WriteMask; 1195848b8605Smrg out[n].dst.Indirect = dst.Indirect; 1196848b8605Smrg out[n].dst.Index = dst.Index; 1197848b8605Smrg n++; 1198b8e80941Smrg 1199848b8605Smrg if (dst.Indirect) { 1200848b8605Smrg out[n].value = 0; 1201848b8605Smrg out[n].ind.File = dst.IndirectFile; 1202848b8605Smrg out[n].ind.Swizzle = dst.IndirectSwizzle; 1203848b8605Smrg out[n].ind.Index = dst.IndirectIndex; 1204b8e80941Smrg if (!ureg->supports_any_inout_decl_range && 1205b8e80941Smrg (dst.File == TGSI_FILE_INPUT || dst.File == TGSI_FILE_OUTPUT)) 1206b8e80941Smrg out[n].ind.ArrayID = 0; 1207b8e80941Smrg else 1208b8e80941Smrg out[n].ind.ArrayID = dst.ArrayID; 1209b8e80941Smrg n++; 1210b8e80941Smrg } 1211b8e80941Smrg 1212b8e80941Smrg if (dst.Dimension) { 1213b8e80941Smrg out[0].dst.Dimension = 1; 1214b8e80941Smrg out[n].dim.Dimension = 0; 1215b8e80941Smrg out[n].dim.Padding = 0; 1216b8e80941Smrg if (dst.DimIndirect) { 1217b8e80941Smrg out[n].dim.Indirect = 1; 1218b8e80941Smrg out[n].dim.Index = dst.DimensionIndex; 1219b8e80941Smrg n++; 1220b8e80941Smrg out[n].value = 0; 1221b8e80941Smrg out[n].ind.File = dst.DimIndFile; 1222b8e80941Smrg out[n].ind.Swizzle = dst.DimIndSwizzle; 1223b8e80941Smrg out[n].ind.Index = dst.DimIndIndex; 1224b8e80941Smrg if (!ureg->supports_any_inout_decl_range && 1225b8e80941Smrg (dst.File == TGSI_FILE_INPUT || dst.File == TGSI_FILE_OUTPUT)) 1226b8e80941Smrg out[n].ind.ArrayID = 0; 1227b8e80941Smrg else 1228b8e80941Smrg out[n].ind.ArrayID = dst.ArrayID; 1229b8e80941Smrg } else { 1230b8e80941Smrg out[n].dim.Indirect = 0; 1231b8e80941Smrg out[n].dim.Index = dst.DimensionIndex; 1232b8e80941Smrg } 1233848b8605Smrg n++; 1234848b8605Smrg } 1235848b8605Smrg 1236848b8605Smrg assert(n == size); 1237848b8605Smrg} 1238848b8605Smrg 1239848b8605Smrg 1240b8e80941Smrgstatic void validate( enum tgsi_opcode opcode, 1241848b8605Smrg unsigned nr_dst, 1242848b8605Smrg unsigned nr_src ) 1243848b8605Smrg{ 1244848b8605Smrg#ifdef DEBUG 1245848b8605Smrg const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode ); 1246848b8605Smrg assert(info); 1247b8e80941Smrg if (info) { 1248848b8605Smrg assert(nr_dst == info->num_dst); 1249848b8605Smrg assert(nr_src == info->num_src); 1250848b8605Smrg } 1251848b8605Smrg#endif 1252848b8605Smrg} 1253848b8605Smrg 1254848b8605Smrgstruct ureg_emit_insn_result 1255848b8605Smrgureg_emit_insn(struct ureg_program *ureg, 1256b8e80941Smrg enum tgsi_opcode opcode, 1257848b8605Smrg boolean saturate, 1258b8e80941Smrg unsigned precise, 1259848b8605Smrg unsigned num_dst, 1260b8e80941Smrg unsigned num_src) 1261848b8605Smrg{ 1262848b8605Smrg union tgsi_any_token *out; 1263b8e80941Smrg uint count = 1; 1264848b8605Smrg struct ureg_emit_insn_result result; 1265848b8605Smrg 1266848b8605Smrg validate( opcode, num_dst, num_src ); 1267b8e80941Smrg 1268848b8605Smrg out = get_tokens( ureg, DOMAIN_INSN, count ); 1269848b8605Smrg out[0].insn = tgsi_default_instruction(); 1270848b8605Smrg out[0].insn.Opcode = opcode; 1271848b8605Smrg out[0].insn.Saturate = saturate; 1272b8e80941Smrg out[0].insn.Precise = precise; 1273848b8605Smrg out[0].insn.NumDstRegs = num_dst; 1274848b8605Smrg out[0].insn.NumSrcRegs = num_src; 1275848b8605Smrg 1276848b8605Smrg result.insn_token = ureg->domain[DOMAIN_INSN].count - count; 1277848b8605Smrg result.extended_token = result.insn_token; 1278848b8605Smrg 1279848b8605Smrg ureg->nr_instructions++; 1280848b8605Smrg 1281848b8605Smrg return result; 1282848b8605Smrg} 1283848b8605Smrg 1284848b8605Smrg 1285b8e80941Smrg/** 1286b8e80941Smrg * Emit a label token. 1287b8e80941Smrg * \param label_token returns a token number indicating where the label 1288b8e80941Smrg * needs to be patched later. Later, this value should be passed to the 1289b8e80941Smrg * ureg_fixup_label() function. 1290b8e80941Smrg */ 1291848b8605Smrgvoid 1292848b8605Smrgureg_emit_label(struct ureg_program *ureg, 1293848b8605Smrg unsigned extended_token, 1294848b8605Smrg unsigned *label_token ) 1295848b8605Smrg{ 1296848b8605Smrg union tgsi_any_token *out, *insn; 1297848b8605Smrg 1298b8e80941Smrg if (!label_token) 1299848b8605Smrg return; 1300848b8605Smrg 1301848b8605Smrg out = get_tokens( ureg, DOMAIN_INSN, 1 ); 1302848b8605Smrg out[0].value = 0; 1303848b8605Smrg 1304848b8605Smrg insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); 1305848b8605Smrg insn->insn.Label = 1; 1306848b8605Smrg 1307848b8605Smrg *label_token = ureg->domain[DOMAIN_INSN].count - 1; 1308848b8605Smrg} 1309848b8605Smrg 1310848b8605Smrg/* Will return a number which can be used in a label to point to the 1311848b8605Smrg * next instruction to be emitted. 1312848b8605Smrg */ 1313848b8605Smrgunsigned 1314848b8605Smrgureg_get_instruction_number( struct ureg_program *ureg ) 1315848b8605Smrg{ 1316848b8605Smrg return ureg->nr_instructions; 1317848b8605Smrg} 1318848b8605Smrg 1319848b8605Smrg/* Patch a given label (expressed as a token number) to point to a 1320848b8605Smrg * given instruction (expressed as an instruction number). 1321848b8605Smrg */ 1322848b8605Smrgvoid 1323848b8605Smrgureg_fixup_label(struct ureg_program *ureg, 1324848b8605Smrg unsigned label_token, 1325848b8605Smrg unsigned instruction_number ) 1326848b8605Smrg{ 1327848b8605Smrg union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token ); 1328848b8605Smrg 1329848b8605Smrg out->insn_label.Label = instruction_number; 1330848b8605Smrg} 1331848b8605Smrg 1332848b8605Smrg 1333848b8605Smrgvoid 1334848b8605Smrgureg_emit_texture(struct ureg_program *ureg, 1335848b8605Smrg unsigned extended_token, 1336b8e80941Smrg enum tgsi_texture_type target, 1337b8e80941Smrg enum tgsi_return_type return_type, unsigned num_offsets) 1338848b8605Smrg{ 1339848b8605Smrg union tgsi_any_token *out, *insn; 1340848b8605Smrg 1341848b8605Smrg out = get_tokens( ureg, DOMAIN_INSN, 1 ); 1342848b8605Smrg insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); 1343848b8605Smrg 1344848b8605Smrg insn->insn.Texture = 1; 1345848b8605Smrg 1346848b8605Smrg out[0].value = 0; 1347848b8605Smrg out[0].insn_texture.Texture = target; 1348848b8605Smrg out[0].insn_texture.NumOffsets = num_offsets; 1349b8e80941Smrg out[0].insn_texture.ReturnType = return_type; 1350848b8605Smrg} 1351848b8605Smrg 1352848b8605Smrgvoid 1353848b8605Smrgureg_emit_texture_offset(struct ureg_program *ureg, 1354848b8605Smrg const struct tgsi_texture_offset *offset) 1355848b8605Smrg{ 1356848b8605Smrg union tgsi_any_token *out; 1357848b8605Smrg 1358848b8605Smrg out = get_tokens( ureg, DOMAIN_INSN, 1); 1359848b8605Smrg 1360848b8605Smrg out[0].value = 0; 1361848b8605Smrg out[0].insn_texture_offset = *offset; 1362848b8605Smrg} 1363848b8605Smrg 1364b8e80941Smrgvoid 1365b8e80941Smrgureg_emit_memory(struct ureg_program *ureg, 1366b8e80941Smrg unsigned extended_token, 1367b8e80941Smrg unsigned qualifier, 1368b8e80941Smrg enum tgsi_texture_type texture, 1369b8e80941Smrg enum pipe_format format) 1370b8e80941Smrg{ 1371b8e80941Smrg union tgsi_any_token *out, *insn; 1372b8e80941Smrg 1373b8e80941Smrg out = get_tokens( ureg, DOMAIN_INSN, 1 ); 1374b8e80941Smrg insn = retrieve_token( ureg, DOMAIN_INSN, extended_token ); 1375b8e80941Smrg 1376b8e80941Smrg insn->insn.Memory = 1; 1377b8e80941Smrg 1378b8e80941Smrg out[0].value = 0; 1379b8e80941Smrg out[0].insn_memory.Qualifier = qualifier; 1380b8e80941Smrg out[0].insn_memory.Texture = texture; 1381b8e80941Smrg out[0].insn_memory.Format = format; 1382b8e80941Smrg} 1383848b8605Smrg 1384848b8605Smrgvoid 1385848b8605Smrgureg_fixup_insn_size(struct ureg_program *ureg, 1386848b8605Smrg unsigned insn ) 1387848b8605Smrg{ 1388848b8605Smrg union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn ); 1389848b8605Smrg 1390848b8605Smrg assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION); 1391848b8605Smrg out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1; 1392848b8605Smrg} 1393848b8605Smrg 1394848b8605Smrg 1395848b8605Smrgvoid 1396848b8605Smrgureg_insn(struct ureg_program *ureg, 1397b8e80941Smrg enum tgsi_opcode opcode, 1398848b8605Smrg const struct ureg_dst *dst, 1399848b8605Smrg unsigned nr_dst, 1400848b8605Smrg const struct ureg_src *src, 1401b8e80941Smrg unsigned nr_src, 1402b8e80941Smrg unsigned precise ) 1403848b8605Smrg{ 1404848b8605Smrg struct ureg_emit_insn_result insn; 1405848b8605Smrg unsigned i; 1406848b8605Smrg boolean saturate; 1407848b8605Smrg 1408848b8605Smrg if (nr_dst && ureg_dst_is_empty(dst[0])) { 1409848b8605Smrg return; 1410848b8605Smrg } 1411848b8605Smrg 1412848b8605Smrg saturate = nr_dst ? dst[0].Saturate : FALSE; 1413848b8605Smrg 1414848b8605Smrg insn = ureg_emit_insn(ureg, 1415848b8605Smrg opcode, 1416848b8605Smrg saturate, 1417b8e80941Smrg precise, 1418848b8605Smrg nr_dst, 1419848b8605Smrg nr_src); 1420848b8605Smrg 1421848b8605Smrg for (i = 0; i < nr_dst; i++) 1422848b8605Smrg ureg_emit_dst( ureg, dst[i] ); 1423848b8605Smrg 1424848b8605Smrg for (i = 0; i < nr_src; i++) 1425848b8605Smrg ureg_emit_src( ureg, src[i] ); 1426848b8605Smrg 1427848b8605Smrg ureg_fixup_insn_size( ureg, insn.insn_token ); 1428848b8605Smrg} 1429848b8605Smrg 1430848b8605Smrgvoid 1431848b8605Smrgureg_tex_insn(struct ureg_program *ureg, 1432b8e80941Smrg enum tgsi_opcode opcode, 1433848b8605Smrg const struct ureg_dst *dst, 1434848b8605Smrg unsigned nr_dst, 1435b8e80941Smrg enum tgsi_texture_type target, 1436b8e80941Smrg enum tgsi_return_type return_type, 1437848b8605Smrg const struct tgsi_texture_offset *texoffsets, 1438848b8605Smrg unsigned nr_offset, 1439848b8605Smrg const struct ureg_src *src, 1440848b8605Smrg unsigned nr_src ) 1441848b8605Smrg{ 1442848b8605Smrg struct ureg_emit_insn_result insn; 1443848b8605Smrg unsigned i; 1444848b8605Smrg boolean saturate; 1445848b8605Smrg 1446848b8605Smrg if (nr_dst && ureg_dst_is_empty(dst[0])) { 1447848b8605Smrg return; 1448848b8605Smrg } 1449848b8605Smrg 1450848b8605Smrg saturate = nr_dst ? dst[0].Saturate : FALSE; 1451848b8605Smrg 1452848b8605Smrg insn = ureg_emit_insn(ureg, 1453848b8605Smrg opcode, 1454848b8605Smrg saturate, 1455b8e80941Smrg 0, 1456848b8605Smrg nr_dst, 1457848b8605Smrg nr_src); 1458848b8605Smrg 1459b8e80941Smrg ureg_emit_texture( ureg, insn.extended_token, target, return_type, 1460b8e80941Smrg nr_offset ); 1461848b8605Smrg 1462848b8605Smrg for (i = 0; i < nr_offset; i++) 1463848b8605Smrg ureg_emit_texture_offset( ureg, &texoffsets[i]); 1464848b8605Smrg 1465848b8605Smrg for (i = 0; i < nr_dst; i++) 1466848b8605Smrg ureg_emit_dst( ureg, dst[i] ); 1467848b8605Smrg 1468848b8605Smrg for (i = 0; i < nr_src; i++) 1469848b8605Smrg ureg_emit_src( ureg, src[i] ); 1470848b8605Smrg 1471848b8605Smrg ureg_fixup_insn_size( ureg, insn.insn_token ); 1472848b8605Smrg} 1473848b8605Smrg 1474848b8605Smrg 1475848b8605Smrgvoid 1476b8e80941Smrgureg_memory_insn(struct ureg_program *ureg, 1477b8e80941Smrg enum tgsi_opcode opcode, 1478b8e80941Smrg const struct ureg_dst *dst, 1479b8e80941Smrg unsigned nr_dst, 1480b8e80941Smrg const struct ureg_src *src, 1481b8e80941Smrg unsigned nr_src, 1482b8e80941Smrg unsigned qualifier, 1483b8e80941Smrg enum tgsi_texture_type texture, 1484b8e80941Smrg enum pipe_format format) 1485848b8605Smrg{ 1486848b8605Smrg struct ureg_emit_insn_result insn; 1487848b8605Smrg unsigned i; 1488848b8605Smrg 1489848b8605Smrg insn = ureg_emit_insn(ureg, 1490848b8605Smrg opcode, 1491848b8605Smrg FALSE, 1492848b8605Smrg 0, 1493b8e80941Smrg nr_dst, 1494848b8605Smrg nr_src); 1495848b8605Smrg 1496b8e80941Smrg ureg_emit_memory(ureg, insn.extended_token, qualifier, texture, format); 1497b8e80941Smrg 1498b8e80941Smrg for (i = 0; i < nr_dst; i++) 1499b8e80941Smrg ureg_emit_dst(ureg, dst[i]); 1500848b8605Smrg 1501848b8605Smrg for (i = 0; i < nr_src; i++) 1502b8e80941Smrg ureg_emit_src(ureg, src[i]); 1503848b8605Smrg 1504b8e80941Smrg ureg_fixup_insn_size(ureg, insn.insn_token); 1505848b8605Smrg} 1506848b8605Smrg 1507848b8605Smrg 1508848b8605Smrgstatic void 1509848b8605Smrgemit_decl_semantic(struct ureg_program *ureg, 1510848b8605Smrg unsigned file, 1511b8e80941Smrg unsigned first, 1512b8e80941Smrg unsigned last, 1513b8e80941Smrg enum tgsi_semantic semantic_name, 1514848b8605Smrg unsigned semantic_index, 1515b8e80941Smrg unsigned streams, 1516b8e80941Smrg unsigned usage_mask, 1517b8e80941Smrg unsigned array_id, 1518b8e80941Smrg boolean invariant) 1519848b8605Smrg{ 1520b8e80941Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3); 1521848b8605Smrg 1522848b8605Smrg out[0].value = 0; 1523848b8605Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1524848b8605Smrg out[0].decl.NrTokens = 3; 1525848b8605Smrg out[0].decl.File = file; 1526848b8605Smrg out[0].decl.UsageMask = usage_mask; 1527848b8605Smrg out[0].decl.Semantic = 1; 1528b8e80941Smrg out[0].decl.Array = array_id != 0; 1529b8e80941Smrg out[0].decl.Invariant = invariant; 1530848b8605Smrg 1531848b8605Smrg out[1].value = 0; 1532b8e80941Smrg out[1].decl_range.First = first; 1533b8e80941Smrg out[1].decl_range.Last = last; 1534848b8605Smrg 1535848b8605Smrg out[2].value = 0; 1536848b8605Smrg out[2].decl_semantic.Name = semantic_name; 1537848b8605Smrg out[2].decl_semantic.Index = semantic_index; 1538b8e80941Smrg out[2].decl_semantic.StreamX = streams & 3; 1539b8e80941Smrg out[2].decl_semantic.StreamY = (streams >> 2) & 3; 1540b8e80941Smrg out[2].decl_semantic.StreamZ = (streams >> 4) & 3; 1541b8e80941Smrg out[2].decl_semantic.StreamW = (streams >> 6) & 3; 1542b8e80941Smrg 1543b8e80941Smrg if (array_id) { 1544b8e80941Smrg out[3].value = 0; 1545b8e80941Smrg out[3].array.ArrayID = array_id; 1546b8e80941Smrg } 1547848b8605Smrg} 1548848b8605Smrg 1549b8e80941Smrgstatic void 1550b8e80941Smrgemit_decl_atomic_2d(struct ureg_program *ureg, 1551b8e80941Smrg unsigned first, 1552b8e80941Smrg unsigned last, 1553b8e80941Smrg unsigned index2D, 1554b8e80941Smrg unsigned array_id) 1555b8e80941Smrg{ 1556b8e80941Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3); 1557b8e80941Smrg 1558b8e80941Smrg out[0].value = 0; 1559b8e80941Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1560b8e80941Smrg out[0].decl.NrTokens = 3; 1561b8e80941Smrg out[0].decl.File = TGSI_FILE_HW_ATOMIC; 1562b8e80941Smrg out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1563b8e80941Smrg out[0].decl.Dimension = 1; 1564b8e80941Smrg out[0].decl.Array = array_id != 0; 1565b8e80941Smrg 1566b8e80941Smrg out[1].value = 0; 1567b8e80941Smrg out[1].decl_range.First = first; 1568b8e80941Smrg out[1].decl_range.Last = last; 1569b8e80941Smrg 1570b8e80941Smrg out[2].value = 0; 1571b8e80941Smrg out[2].decl_dim.Index2D = index2D; 1572b8e80941Smrg 1573b8e80941Smrg if (array_id) { 1574b8e80941Smrg out[3].value = 0; 1575b8e80941Smrg out[3].array.ArrayID = array_id; 1576b8e80941Smrg } 1577b8e80941Smrg} 1578848b8605Smrg 1579848b8605Smrgstatic void 1580848b8605Smrgemit_decl_fs(struct ureg_program *ureg, 1581848b8605Smrg unsigned file, 1582b8e80941Smrg unsigned first, 1583b8e80941Smrg unsigned last, 1584b8e80941Smrg enum tgsi_semantic semantic_name, 1585848b8605Smrg unsigned semantic_index, 1586b8e80941Smrg enum tgsi_interpolate_mode interpolate, 1587848b8605Smrg unsigned cylindrical_wrap, 1588b8e80941Smrg enum tgsi_interpolate_loc interpolate_location, 1589b8e80941Smrg unsigned array_id, 1590b8e80941Smrg unsigned usage_mask) 1591848b8605Smrg{ 1592b8e80941Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 1593b8e80941Smrg array_id ? 5 : 4); 1594848b8605Smrg 1595848b8605Smrg out[0].value = 0; 1596848b8605Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1597848b8605Smrg out[0].decl.NrTokens = 4; 1598848b8605Smrg out[0].decl.File = file; 1599b8e80941Smrg out[0].decl.UsageMask = usage_mask; 1600848b8605Smrg out[0].decl.Interpolate = 1; 1601848b8605Smrg out[0].decl.Semantic = 1; 1602b8e80941Smrg out[0].decl.Array = array_id != 0; 1603848b8605Smrg 1604848b8605Smrg out[1].value = 0; 1605b8e80941Smrg out[1].decl_range.First = first; 1606b8e80941Smrg out[1].decl_range.Last = last; 1607848b8605Smrg 1608848b8605Smrg out[2].value = 0; 1609848b8605Smrg out[2].decl_interp.Interpolate = interpolate; 1610848b8605Smrg out[2].decl_interp.CylindricalWrap = cylindrical_wrap; 1611848b8605Smrg out[2].decl_interp.Location = interpolate_location; 1612848b8605Smrg 1613848b8605Smrg out[3].value = 0; 1614848b8605Smrg out[3].decl_semantic.Name = semantic_name; 1615848b8605Smrg out[3].decl_semantic.Index = semantic_index; 1616b8e80941Smrg 1617b8e80941Smrg if (array_id) { 1618b8e80941Smrg out[4].value = 0; 1619b8e80941Smrg out[4].array.ArrayID = array_id; 1620b8e80941Smrg } 1621848b8605Smrg} 1622848b8605Smrg 1623848b8605Smrgstatic void 1624848b8605Smrgemit_decl_temps( struct ureg_program *ureg, 1625848b8605Smrg unsigned first, unsigned last, 1626848b8605Smrg boolean local, 1627848b8605Smrg unsigned arrayid ) 1628848b8605Smrg{ 1629848b8605Smrg union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 1630848b8605Smrg arrayid ? 3 : 2 ); 1631848b8605Smrg 1632848b8605Smrg out[0].value = 0; 1633848b8605Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1634848b8605Smrg out[0].decl.NrTokens = 2; 1635848b8605Smrg out[0].decl.File = TGSI_FILE_TEMPORARY; 1636848b8605Smrg out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1637848b8605Smrg out[0].decl.Local = local; 1638848b8605Smrg 1639848b8605Smrg out[1].value = 0; 1640848b8605Smrg out[1].decl_range.First = first; 1641848b8605Smrg out[1].decl_range.Last = last; 1642848b8605Smrg 1643848b8605Smrg if (arrayid) { 1644848b8605Smrg out[0].decl.Array = 1; 1645848b8605Smrg out[2].value = 0; 1646848b8605Smrg out[2].array.ArrayID = arrayid; 1647848b8605Smrg } 1648848b8605Smrg} 1649848b8605Smrg 1650848b8605Smrgstatic void emit_decl_range( struct ureg_program *ureg, 1651848b8605Smrg unsigned file, 1652848b8605Smrg unsigned first, 1653848b8605Smrg unsigned count ) 1654848b8605Smrg{ 1655848b8605Smrg union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); 1656848b8605Smrg 1657848b8605Smrg out[0].value = 0; 1658848b8605Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1659848b8605Smrg out[0].decl.NrTokens = 2; 1660848b8605Smrg out[0].decl.File = file; 1661848b8605Smrg out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1662848b8605Smrg out[0].decl.Semantic = 0; 1663848b8605Smrg 1664848b8605Smrg out[1].value = 0; 1665848b8605Smrg out[1].decl_range.First = first; 1666848b8605Smrg out[1].decl_range.Last = first + count - 1; 1667848b8605Smrg} 1668848b8605Smrg 1669848b8605Smrgstatic void 1670848b8605Smrgemit_decl_range2D(struct ureg_program *ureg, 1671848b8605Smrg unsigned file, 1672848b8605Smrg unsigned first, 1673848b8605Smrg unsigned last, 1674848b8605Smrg unsigned index2D) 1675848b8605Smrg{ 1676848b8605Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1677848b8605Smrg 1678848b8605Smrg out[0].value = 0; 1679848b8605Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1680848b8605Smrg out[0].decl.NrTokens = 3; 1681848b8605Smrg out[0].decl.File = file; 1682848b8605Smrg out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1683848b8605Smrg out[0].decl.Dimension = 1; 1684848b8605Smrg 1685848b8605Smrg out[1].value = 0; 1686848b8605Smrg out[1].decl_range.First = first; 1687848b8605Smrg out[1].decl_range.Last = last; 1688848b8605Smrg 1689848b8605Smrg out[2].value = 0; 1690848b8605Smrg out[2].decl_dim.Index2D = index2D; 1691848b8605Smrg} 1692848b8605Smrg 1693848b8605Smrgstatic void 1694848b8605Smrgemit_decl_sampler_view(struct ureg_program *ureg, 1695848b8605Smrg unsigned index, 1696b8e80941Smrg enum tgsi_texture_type target, 1697b8e80941Smrg enum tgsi_return_type return_type_x, 1698b8e80941Smrg enum tgsi_return_type return_type_y, 1699b8e80941Smrg enum tgsi_return_type return_type_z, 1700b8e80941Smrg enum tgsi_return_type return_type_w ) 1701848b8605Smrg{ 1702848b8605Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1703848b8605Smrg 1704848b8605Smrg out[0].value = 0; 1705848b8605Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1706848b8605Smrg out[0].decl.NrTokens = 3; 1707848b8605Smrg out[0].decl.File = TGSI_FILE_SAMPLER_VIEW; 1708b8e80941Smrg out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1709848b8605Smrg 1710848b8605Smrg out[1].value = 0; 1711848b8605Smrg out[1].decl_range.First = index; 1712848b8605Smrg out[1].decl_range.Last = index; 1713848b8605Smrg 1714848b8605Smrg out[2].value = 0; 1715848b8605Smrg out[2].decl_sampler_view.Resource = target; 1716848b8605Smrg out[2].decl_sampler_view.ReturnTypeX = return_type_x; 1717848b8605Smrg out[2].decl_sampler_view.ReturnTypeY = return_type_y; 1718848b8605Smrg out[2].decl_sampler_view.ReturnTypeZ = return_type_z; 1719848b8605Smrg out[2].decl_sampler_view.ReturnTypeW = return_type_w; 1720848b8605Smrg} 1721848b8605Smrg 1722b8e80941Smrgstatic void 1723b8e80941Smrgemit_decl_image(struct ureg_program *ureg, 1724b8e80941Smrg unsigned index, 1725b8e80941Smrg enum tgsi_texture_type target, 1726b8e80941Smrg enum pipe_format format, 1727b8e80941Smrg boolean wr, 1728b8e80941Smrg boolean raw) 1729b8e80941Smrg{ 1730b8e80941Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3); 1731b8e80941Smrg 1732b8e80941Smrg out[0].value = 0; 1733b8e80941Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1734b8e80941Smrg out[0].decl.NrTokens = 3; 1735b8e80941Smrg out[0].decl.File = TGSI_FILE_IMAGE; 1736b8e80941Smrg out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1737b8e80941Smrg 1738b8e80941Smrg out[1].value = 0; 1739b8e80941Smrg out[1].decl_range.First = index; 1740b8e80941Smrg out[1].decl_range.Last = index; 1741b8e80941Smrg 1742b8e80941Smrg out[2].value = 0; 1743b8e80941Smrg out[2].decl_image.Resource = target; 1744b8e80941Smrg out[2].decl_image.Writable = wr; 1745b8e80941Smrg out[2].decl_image.Raw = raw; 1746b8e80941Smrg out[2].decl_image.Format = format; 1747b8e80941Smrg} 1748b8e80941Smrg 1749b8e80941Smrgstatic void 1750b8e80941Smrgemit_decl_buffer(struct ureg_program *ureg, 1751b8e80941Smrg unsigned index, 1752b8e80941Smrg bool atomic) 1753b8e80941Smrg{ 1754b8e80941Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2); 1755b8e80941Smrg 1756b8e80941Smrg out[0].value = 0; 1757b8e80941Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1758b8e80941Smrg out[0].decl.NrTokens = 2; 1759b8e80941Smrg out[0].decl.File = TGSI_FILE_BUFFER; 1760b8e80941Smrg out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1761b8e80941Smrg out[0].decl.Atomic = atomic; 1762b8e80941Smrg 1763b8e80941Smrg out[1].value = 0; 1764b8e80941Smrg out[1].decl_range.First = index; 1765b8e80941Smrg out[1].decl_range.Last = index; 1766b8e80941Smrg} 1767b8e80941Smrg 1768b8e80941Smrgstatic void 1769b8e80941Smrgemit_decl_memory(struct ureg_program *ureg, unsigned memory_type) 1770b8e80941Smrg{ 1771b8e80941Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2); 1772b8e80941Smrg 1773b8e80941Smrg out[0].value = 0; 1774b8e80941Smrg out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; 1775b8e80941Smrg out[0].decl.NrTokens = 2; 1776b8e80941Smrg out[0].decl.File = TGSI_FILE_MEMORY; 1777b8e80941Smrg out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; 1778b8e80941Smrg out[0].decl.MemType = memory_type; 1779b8e80941Smrg 1780b8e80941Smrg out[1].value = 0; 1781b8e80941Smrg out[1].decl_range.First = memory_type; 1782b8e80941Smrg out[1].decl_range.Last = memory_type; 1783b8e80941Smrg} 1784b8e80941Smrg 1785848b8605Smrgstatic void 1786848b8605Smrgemit_immediate( struct ureg_program *ureg, 1787848b8605Smrg const unsigned *v, 1788848b8605Smrg unsigned type ) 1789848b8605Smrg{ 1790848b8605Smrg union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 ); 1791848b8605Smrg 1792848b8605Smrg out[0].value = 0; 1793848b8605Smrg out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE; 1794848b8605Smrg out[0].imm.NrTokens = 5; 1795848b8605Smrg out[0].imm.DataType = type; 1796848b8605Smrg out[0].imm.Padding = 0; 1797848b8605Smrg 1798848b8605Smrg out[1].imm_data.Uint = v[0]; 1799848b8605Smrg out[2].imm_data.Uint = v[1]; 1800848b8605Smrg out[3].imm_data.Uint = v[2]; 1801848b8605Smrg out[4].imm_data.Uint = v[3]; 1802848b8605Smrg} 1803848b8605Smrg 1804848b8605Smrgstatic void 1805848b8605Smrgemit_property(struct ureg_program *ureg, 1806848b8605Smrg unsigned name, 1807848b8605Smrg unsigned data) 1808848b8605Smrg{ 1809848b8605Smrg union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2); 1810848b8605Smrg 1811848b8605Smrg out[0].value = 0; 1812848b8605Smrg out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY; 1813848b8605Smrg out[0].prop.NrTokens = 2; 1814848b8605Smrg out[0].prop.PropertyName = name; 1815848b8605Smrg 1816848b8605Smrg out[1].prop_data.Data = data; 1817848b8605Smrg} 1818848b8605Smrg 1819848b8605Smrg 1820848b8605Smrgstatic void emit_decls( struct ureg_program *ureg ) 1821848b8605Smrg{ 1822b8e80941Smrg unsigned i,j; 1823848b8605Smrg 1824b8e80941Smrg for (i = 0; i < ARRAY_SIZE(ureg->properties); i++) 1825b8e80941Smrg if (ureg->properties[i] != ~0u) 1826b8e80941Smrg emit_property(ureg, i, ureg->properties[i]); 1827848b8605Smrg 1828b8e80941Smrg if (ureg->processor == PIPE_SHADER_VERTEX) { 1829b8e80941Smrg for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { 1830b8e80941Smrg if (ureg->vs_inputs[i/32] & (1u << (i%32))) { 1831848b8605Smrg emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 ); 1832848b8605Smrg } 1833848b8605Smrg } 1834b8e80941Smrg } else if (ureg->processor == PIPE_SHADER_FRAGMENT) { 1835b8e80941Smrg if (ureg->supports_any_inout_decl_range) { 1836b8e80941Smrg for (i = 0; i < ureg->nr_inputs; i++) { 1837b8e80941Smrg emit_decl_fs(ureg, 1838b8e80941Smrg TGSI_FILE_INPUT, 1839b8e80941Smrg ureg->input[i].first, 1840b8e80941Smrg ureg->input[i].last, 1841b8e80941Smrg ureg->input[i].semantic_name, 1842b8e80941Smrg ureg->input[i].semantic_index, 1843b8e80941Smrg ureg->input[i].interp, 1844b8e80941Smrg ureg->input[i].cylindrical_wrap, 1845b8e80941Smrg ureg->input[i].interp_location, 1846b8e80941Smrg ureg->input[i].array_id, 1847b8e80941Smrg ureg->input[i].usage_mask); 1848b8e80941Smrg } 1849848b8605Smrg } 1850b8e80941Smrg else { 1851b8e80941Smrg for (i = 0; i < ureg->nr_inputs; i++) { 1852b8e80941Smrg for (j = ureg->input[i].first; j <= ureg->input[i].last; j++) { 1853b8e80941Smrg emit_decl_fs(ureg, 1854848b8605Smrg TGSI_FILE_INPUT, 1855b8e80941Smrg j, j, 1856b8e80941Smrg ureg->input[i].semantic_name, 1857b8e80941Smrg ureg->input[i].semantic_index + 1858b8e80941Smrg (j - ureg->input[i].first), 1859b8e80941Smrg ureg->input[i].interp, 1860b8e80941Smrg ureg->input[i].cylindrical_wrap, 1861b8e80941Smrg ureg->input[i].interp_location, 0, 1862b8e80941Smrg ureg->input[i].usage_mask); 1863b8e80941Smrg } 1864b8e80941Smrg } 1865b8e80941Smrg } 1866b8e80941Smrg } else { 1867b8e80941Smrg if (ureg->supports_any_inout_decl_range) { 1868b8e80941Smrg for (i = 0; i < ureg->nr_inputs; i++) { 1869b8e80941Smrg emit_decl_semantic(ureg, 1870b8e80941Smrg TGSI_FILE_INPUT, 1871b8e80941Smrg ureg->input[i].first, 1872b8e80941Smrg ureg->input[i].last, 1873b8e80941Smrg ureg->input[i].semantic_name, 1874b8e80941Smrg ureg->input[i].semantic_index, 1875b8e80941Smrg 0, 1876b8e80941Smrg TGSI_WRITEMASK_XYZW, 1877b8e80941Smrg ureg->input[i].array_id, 1878b8e80941Smrg FALSE); 1879b8e80941Smrg } 1880b8e80941Smrg } 1881b8e80941Smrg else { 1882b8e80941Smrg for (i = 0; i < ureg->nr_inputs; i++) { 1883b8e80941Smrg for (j = ureg->input[i].first; j <= ureg->input[i].last; j++) { 1884b8e80941Smrg emit_decl_semantic(ureg, 1885b8e80941Smrg TGSI_FILE_INPUT, 1886b8e80941Smrg j, j, 1887b8e80941Smrg ureg->input[i].semantic_name, 1888b8e80941Smrg ureg->input[i].semantic_index + 1889b8e80941Smrg (j - ureg->input[i].first), 1890b8e80941Smrg 0, 1891b8e80941Smrg TGSI_WRITEMASK_XYZW, 0, FALSE); 1892b8e80941Smrg } 1893b8e80941Smrg } 1894848b8605Smrg } 1895848b8605Smrg } 1896848b8605Smrg 1897848b8605Smrg for (i = 0; i < ureg->nr_system_values; i++) { 1898848b8605Smrg emit_decl_semantic(ureg, 1899848b8605Smrg TGSI_FILE_SYSTEM_VALUE, 1900b8e80941Smrg i, 1901b8e80941Smrg i, 1902848b8605Smrg ureg->system_value[i].semantic_name, 1903848b8605Smrg ureg->system_value[i].semantic_index, 1904b8e80941Smrg 0, 1905b8e80941Smrg TGSI_WRITEMASK_XYZW, 0, FALSE); 1906848b8605Smrg } 1907848b8605Smrg 1908b8e80941Smrg if (ureg->supports_any_inout_decl_range) { 1909b8e80941Smrg for (i = 0; i < ureg->nr_outputs; i++) { 1910b8e80941Smrg emit_decl_semantic(ureg, 1911b8e80941Smrg TGSI_FILE_OUTPUT, 1912b8e80941Smrg ureg->output[i].first, 1913b8e80941Smrg ureg->output[i].last, 1914b8e80941Smrg ureg->output[i].semantic_name, 1915b8e80941Smrg ureg->output[i].semantic_index, 1916b8e80941Smrg ureg->output[i].streams, 1917b8e80941Smrg ureg->output[i].usage_mask, 1918b8e80941Smrg ureg->output[i].array_id, 1919b8e80941Smrg ureg->output[i].invariant); 1920b8e80941Smrg } 1921b8e80941Smrg } 1922b8e80941Smrg else { 1923b8e80941Smrg for (i = 0; i < ureg->nr_outputs; i++) { 1924b8e80941Smrg for (j = ureg->output[i].first; j <= ureg->output[i].last; j++) { 1925b8e80941Smrg emit_decl_semantic(ureg, 1926b8e80941Smrg TGSI_FILE_OUTPUT, 1927b8e80941Smrg j, j, 1928b8e80941Smrg ureg->output[i].semantic_name, 1929b8e80941Smrg ureg->output[i].semantic_index + 1930b8e80941Smrg (j - ureg->output[i].first), 1931b8e80941Smrg ureg->output[i].streams, 1932b8e80941Smrg ureg->output[i].usage_mask, 1933b8e80941Smrg 0, 1934b8e80941Smrg ureg->output[i].invariant); 1935b8e80941Smrg } 1936b8e80941Smrg } 1937848b8605Smrg } 1938848b8605Smrg 1939848b8605Smrg for (i = 0; i < ureg->nr_samplers; i++) { 1940b8e80941Smrg emit_decl_range( ureg, 1941848b8605Smrg TGSI_FILE_SAMPLER, 1942848b8605Smrg ureg->sampler[i].Index, 1 ); 1943848b8605Smrg } 1944848b8605Smrg 1945848b8605Smrg for (i = 0; i < ureg->nr_sampler_views; i++) { 1946848b8605Smrg emit_decl_sampler_view(ureg, 1947848b8605Smrg ureg->sampler_view[i].index, 1948848b8605Smrg ureg->sampler_view[i].target, 1949848b8605Smrg ureg->sampler_view[i].return_type_x, 1950848b8605Smrg ureg->sampler_view[i].return_type_y, 1951848b8605Smrg ureg->sampler_view[i].return_type_z, 1952848b8605Smrg ureg->sampler_view[i].return_type_w); 1953848b8605Smrg } 1954848b8605Smrg 1955b8e80941Smrg for (i = 0; i < ureg->nr_images; i++) { 1956b8e80941Smrg emit_decl_image(ureg, 1957b8e80941Smrg ureg->image[i].index, 1958b8e80941Smrg ureg->image[i].target, 1959b8e80941Smrg ureg->image[i].format, 1960b8e80941Smrg ureg->image[i].wr, 1961b8e80941Smrg ureg->image[i].raw); 1962b8e80941Smrg } 1963b8e80941Smrg 1964b8e80941Smrg for (i = 0; i < ureg->nr_buffers; i++) { 1965b8e80941Smrg emit_decl_buffer(ureg, ureg->buffer[i].index, ureg->buffer[i].atomic); 1966b8e80941Smrg } 1967b8e80941Smrg 1968b8e80941Smrg for (i = 0; i < TGSI_MEMORY_TYPE_COUNT; i++) { 1969b8e80941Smrg if (ureg->use_memory[i]) 1970b8e80941Smrg emit_decl_memory(ureg, i); 1971848b8605Smrg } 1972848b8605Smrg 1973848b8605Smrg for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { 1974b8e80941Smrg struct const_decl *decl = &ureg->const_decls[i]; 1975848b8605Smrg 1976848b8605Smrg if (decl->nr_constant_ranges) { 1977848b8605Smrg uint j; 1978848b8605Smrg 1979848b8605Smrg for (j = 0; j < decl->nr_constant_ranges; j++) { 1980848b8605Smrg emit_decl_range2D(ureg, 1981848b8605Smrg TGSI_FILE_CONSTANT, 1982848b8605Smrg decl->constant_range[j].first, 1983848b8605Smrg decl->constant_range[j].last, 1984848b8605Smrg i); 1985848b8605Smrg } 1986848b8605Smrg } 1987848b8605Smrg } 1988848b8605Smrg 1989b8e80941Smrg for (i = 0; i < PIPE_MAX_HW_ATOMIC_BUFFERS; i++) { 1990b8e80941Smrg struct hw_atomic_decl *decl = &ureg->hw_atomic_decls[i]; 1991b8e80941Smrg 1992b8e80941Smrg if (decl->nr_hw_atomic_ranges) { 1993b8e80941Smrg uint j; 1994b8e80941Smrg 1995b8e80941Smrg for (j = 0; j < decl->nr_hw_atomic_ranges; j++) { 1996b8e80941Smrg emit_decl_atomic_2d(ureg, 1997b8e80941Smrg decl->hw_atomic_range[j].first, 1998b8e80941Smrg decl->hw_atomic_range[j].last, 1999b8e80941Smrg i, 2000b8e80941Smrg decl->hw_atomic_range[j].array_id); 2001b8e80941Smrg } 2002b8e80941Smrg } 2003b8e80941Smrg } 2004b8e80941Smrg 2005848b8605Smrg if (ureg->nr_temps) { 2006848b8605Smrg unsigned array = 0; 2007848b8605Smrg for (i = 0; i < ureg->nr_temps;) { 2008848b8605Smrg boolean local = util_bitmask_get(ureg->local_temps, i); 2009848b8605Smrg unsigned first = i; 2010848b8605Smrg i = util_bitmask_get_next_index(ureg->decl_temps, i + 1); 2011848b8605Smrg if (i == UTIL_BITMASK_INVALID_INDEX) 2012848b8605Smrg i = ureg->nr_temps; 2013848b8605Smrg 2014848b8605Smrg if (array < ureg->nr_array_temps && ureg->array_temps[array] == first) 2015848b8605Smrg emit_decl_temps( ureg, first, i - 1, local, ++array ); 2016848b8605Smrg else 2017848b8605Smrg emit_decl_temps( ureg, first, i - 1, local, 0 ); 2018848b8605Smrg } 2019848b8605Smrg } 2020848b8605Smrg 2021848b8605Smrg if (ureg->nr_addrs) { 2022848b8605Smrg emit_decl_range( ureg, 2023848b8605Smrg TGSI_FILE_ADDRESS, 2024848b8605Smrg 0, ureg->nr_addrs ); 2025848b8605Smrg } 2026848b8605Smrg 2027848b8605Smrg for (i = 0; i < ureg->nr_immediates; i++) { 2028848b8605Smrg emit_immediate( ureg, 2029848b8605Smrg ureg->immediate[i].value.u, 2030848b8605Smrg ureg->immediate[i].type ); 2031848b8605Smrg } 2032848b8605Smrg} 2033848b8605Smrg 2034848b8605Smrg/* Append the instruction tokens onto the declarations to build a 2035848b8605Smrg * contiguous stream suitable to send to the driver. 2036848b8605Smrg */ 2037848b8605Smrgstatic void copy_instructions( struct ureg_program *ureg ) 2038848b8605Smrg{ 2039848b8605Smrg unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count; 2040b8e80941Smrg union tgsi_any_token *out = get_tokens( ureg, 2041b8e80941Smrg DOMAIN_DECL, 2042848b8605Smrg nr_tokens ); 2043848b8605Smrg 2044b8e80941Smrg memcpy(out, 2045b8e80941Smrg ureg->domain[DOMAIN_INSN].tokens, 2046848b8605Smrg nr_tokens * sizeof out[0] ); 2047848b8605Smrg} 2048848b8605Smrg 2049848b8605Smrg 2050848b8605Smrgstatic void 2051848b8605Smrgfixup_header_size(struct ureg_program *ureg) 2052848b8605Smrg{ 2053848b8605Smrg union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 ); 2054848b8605Smrg 2055848b8605Smrg out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2; 2056848b8605Smrg} 2057848b8605Smrg 2058848b8605Smrg 2059848b8605Smrgstatic void 2060848b8605Smrgemit_header( struct ureg_program *ureg ) 2061848b8605Smrg{ 2062848b8605Smrg union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); 2063848b8605Smrg 2064848b8605Smrg out[0].header.HeaderSize = 2; 2065848b8605Smrg out[0].header.BodySize = 0; 2066848b8605Smrg 2067848b8605Smrg out[1].processor.Processor = ureg->processor; 2068848b8605Smrg out[1].processor.Padding = 0; 2069848b8605Smrg} 2070848b8605Smrg 2071848b8605Smrg 2072848b8605Smrgconst struct tgsi_token *ureg_finalize( struct ureg_program *ureg ) 2073848b8605Smrg{ 2074848b8605Smrg const struct tgsi_token *tokens; 2075848b8605Smrg 2076b8e80941Smrg switch (ureg->processor) { 2077b8e80941Smrg case PIPE_SHADER_VERTEX: 2078b8e80941Smrg case PIPE_SHADER_TESS_EVAL: 2079b8e80941Smrg ureg_property(ureg, TGSI_PROPERTY_NEXT_SHADER, 2080b8e80941Smrg ureg->next_shader_processor == -1 ? 2081b8e80941Smrg PIPE_SHADER_FRAGMENT : 2082b8e80941Smrg ureg->next_shader_processor); 2083b8e80941Smrg break; 2084b8e80941Smrg default: 2085b8e80941Smrg ; /* nothing */ 2086b8e80941Smrg } 2087b8e80941Smrg 2088848b8605Smrg emit_header( ureg ); 2089848b8605Smrg emit_decls( ureg ); 2090848b8605Smrg copy_instructions( ureg ); 2091848b8605Smrg fixup_header_size( ureg ); 2092b8e80941Smrg 2093848b8605Smrg if (ureg->domain[0].tokens == error_tokens || 2094848b8605Smrg ureg->domain[1].tokens == error_tokens) { 2095848b8605Smrg debug_printf("%s: error in generated shader\n", __FUNCTION__); 2096848b8605Smrg assert(0); 2097848b8605Smrg return NULL; 2098848b8605Smrg } 2099848b8605Smrg 2100848b8605Smrg tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; 2101848b8605Smrg 2102848b8605Smrg if (0) { 2103b8e80941Smrg debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__, 2104848b8605Smrg ureg->domain[DOMAIN_DECL].count); 2105848b8605Smrg tgsi_dump( tokens, 0 ); 2106848b8605Smrg } 2107848b8605Smrg 2108848b8605Smrg#if DEBUG 2109b8e80941Smrg /* tgsi_sanity doesn't seem to return if there are too many constants. */ 2110b8e80941Smrg bool too_many_constants = false; 2111b8e80941Smrg for (unsigned i = 0; i < ARRAY_SIZE(ureg->const_decls); i++) { 2112b8e80941Smrg for (unsigned j = 0; j < ureg->const_decls[i].nr_constant_ranges; j++) { 2113b8e80941Smrg if (ureg->const_decls[i].constant_range[j].last > 4096) { 2114b8e80941Smrg too_many_constants = true; 2115b8e80941Smrg break; 2116b8e80941Smrg } 2117b8e80941Smrg } 2118b8e80941Smrg } 2119b8e80941Smrg 2120b8e80941Smrg if (tokens && !too_many_constants && !tgsi_sanity_check(tokens)) { 2121848b8605Smrg debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n"); 2122848b8605Smrg tgsi_dump(tokens, 0); 2123848b8605Smrg assert(0); 2124848b8605Smrg } 2125848b8605Smrg#endif 2126848b8605Smrg 2127b8e80941Smrg 2128848b8605Smrg return tokens; 2129848b8605Smrg} 2130848b8605Smrg 2131848b8605Smrg 2132848b8605Smrgvoid *ureg_create_shader( struct ureg_program *ureg, 2133848b8605Smrg struct pipe_context *pipe, 2134848b8605Smrg const struct pipe_stream_output_info *so ) 2135848b8605Smrg{ 2136848b8605Smrg struct pipe_shader_state state; 2137848b8605Smrg 2138b8e80941Smrg pipe_shader_state_from_tgsi(&state, ureg_finalize(ureg)); 2139848b8605Smrg if(!state.tokens) 2140848b8605Smrg return NULL; 2141848b8605Smrg 2142848b8605Smrg if (so) 2143848b8605Smrg state.stream_output = *so; 2144848b8605Smrg 2145b8e80941Smrg switch (ureg->processor) { 2146b8e80941Smrg case PIPE_SHADER_VERTEX: 2147b8e80941Smrg return pipe->create_vs_state(pipe, &state); 2148b8e80941Smrg case PIPE_SHADER_TESS_CTRL: 2149b8e80941Smrg return pipe->create_tcs_state(pipe, &state); 2150b8e80941Smrg case PIPE_SHADER_TESS_EVAL: 2151b8e80941Smrg return pipe->create_tes_state(pipe, &state); 2152b8e80941Smrg case PIPE_SHADER_GEOMETRY: 2153b8e80941Smrg return pipe->create_gs_state(pipe, &state); 2154b8e80941Smrg case PIPE_SHADER_FRAGMENT: 2155b8e80941Smrg return pipe->create_fs_state(pipe, &state); 2156b8e80941Smrg default: 2157b8e80941Smrg return NULL; 2158b8e80941Smrg } 2159848b8605Smrg} 2160848b8605Smrg 2161848b8605Smrg 2162848b8605Smrgconst struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg, 2163848b8605Smrg unsigned *nr_tokens ) 2164848b8605Smrg{ 2165848b8605Smrg const struct tgsi_token *tokens; 2166848b8605Smrg 2167848b8605Smrg ureg_finalize(ureg); 2168848b8605Smrg 2169848b8605Smrg tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; 2170848b8605Smrg 2171b8e80941Smrg if (nr_tokens) 2172b8e80941Smrg *nr_tokens = ureg->domain[DOMAIN_DECL].count; 2173848b8605Smrg 2174848b8605Smrg ureg->domain[DOMAIN_DECL].tokens = 0; 2175848b8605Smrg ureg->domain[DOMAIN_DECL].size = 0; 2176848b8605Smrg ureg->domain[DOMAIN_DECL].order = 0; 2177848b8605Smrg ureg->domain[DOMAIN_DECL].count = 0; 2178848b8605Smrg 2179848b8605Smrg return tokens; 2180848b8605Smrg} 2181848b8605Smrg 2182848b8605Smrg 2183848b8605Smrgvoid ureg_free_tokens( const struct tgsi_token *tokens ) 2184848b8605Smrg{ 2185848b8605Smrg FREE((struct tgsi_token *)tokens); 2186848b8605Smrg} 2187848b8605Smrg 2188848b8605Smrg 2189b8e80941Smrgstruct ureg_program * 2190b8e80941Smrgureg_create(enum pipe_shader_type processor) 2191848b8605Smrg{ 2192b8e80941Smrg return ureg_create_with_screen(processor, NULL); 2193b8e80941Smrg} 2194b8e80941Smrg 2195b8e80941Smrg 2196b8e80941Smrgstruct ureg_program * 2197b8e80941Smrgureg_create_with_screen(enum pipe_shader_type processor, 2198b8e80941Smrg struct pipe_screen *screen) 2199b8e80941Smrg{ 2200b8e80941Smrg uint i; 2201848b8605Smrg struct ureg_program *ureg = CALLOC_STRUCT( ureg_program ); 2202b8e80941Smrg if (!ureg) 2203848b8605Smrg goto no_ureg; 2204848b8605Smrg 2205848b8605Smrg ureg->processor = processor; 2206b8e80941Smrg ureg->supports_any_inout_decl_range = 2207b8e80941Smrg screen && 2208b8e80941Smrg screen->get_shader_param(screen, processor, 2209b8e80941Smrg PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE) != 0; 2210b8e80941Smrg ureg->next_shader_processor = -1; 2211b8e80941Smrg 2212b8e80941Smrg for (i = 0; i < ARRAY_SIZE(ureg->properties); i++) 2213b8e80941Smrg ureg->properties[i] = ~0; 2214848b8605Smrg 2215848b8605Smrg ureg->free_temps = util_bitmask_create(); 2216848b8605Smrg if (ureg->free_temps == NULL) 2217848b8605Smrg goto no_free_temps; 2218848b8605Smrg 2219848b8605Smrg ureg->local_temps = util_bitmask_create(); 2220848b8605Smrg if (ureg->local_temps == NULL) 2221848b8605Smrg goto no_local_temps; 2222848b8605Smrg 2223848b8605Smrg ureg->decl_temps = util_bitmask_create(); 2224848b8605Smrg if (ureg->decl_temps == NULL) 2225848b8605Smrg goto no_decl_temps; 2226848b8605Smrg 2227848b8605Smrg return ureg; 2228848b8605Smrg 2229848b8605Smrgno_decl_temps: 2230848b8605Smrg util_bitmask_destroy(ureg->local_temps); 2231848b8605Smrgno_local_temps: 2232848b8605Smrg util_bitmask_destroy(ureg->free_temps); 2233848b8605Smrgno_free_temps: 2234848b8605Smrg FREE(ureg); 2235848b8605Smrgno_ureg: 2236848b8605Smrg return NULL; 2237848b8605Smrg} 2238848b8605Smrg 2239848b8605Smrg 2240b8e80941Smrgvoid 2241b8e80941Smrgureg_set_next_shader_processor(struct ureg_program *ureg, unsigned processor) 2242b8e80941Smrg{ 2243b8e80941Smrg ureg->next_shader_processor = processor; 2244b8e80941Smrg} 2245b8e80941Smrg 2246b8e80941Smrg 2247848b8605Smrgunsigned 2248848b8605Smrgureg_get_nr_outputs( const struct ureg_program *ureg ) 2249848b8605Smrg{ 2250848b8605Smrg if (!ureg) 2251848b8605Smrg return 0; 2252848b8605Smrg return ureg->nr_outputs; 2253848b8605Smrg} 2254848b8605Smrg 2255848b8605Smrg 2256848b8605Smrgvoid ureg_destroy( struct ureg_program *ureg ) 2257848b8605Smrg{ 2258848b8605Smrg unsigned i; 2259848b8605Smrg 2260b8e80941Smrg for (i = 0; i < ARRAY_SIZE(ureg->domain); i++) { 2261b8e80941Smrg if (ureg->domain[i].tokens && 2262848b8605Smrg ureg->domain[i].tokens != error_tokens) 2263848b8605Smrg FREE(ureg->domain[i].tokens); 2264848b8605Smrg } 2265848b8605Smrg 2266848b8605Smrg util_bitmask_destroy(ureg->free_temps); 2267848b8605Smrg util_bitmask_destroy(ureg->local_temps); 2268848b8605Smrg util_bitmask_destroy(ureg->decl_temps); 2269848b8605Smrg 2270848b8605Smrg FREE(ureg); 2271848b8605Smrg} 2272