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