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