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_inlines.h" 27bf215546Sopenharmony_ci#include "pipe/p_defines.h" 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_math.h" 30bf215546Sopenharmony_ci#include "util/u_memory.h" 31bf215546Sopenharmony_ci#include "util/u_bitmask.h" 32bf215546Sopenharmony_ci#include "tgsi/tgsi_ureg.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "svga_context.h" 35bf215546Sopenharmony_ci#include "svga_state.h" 36bf215546Sopenharmony_ci#include "svga_cmd.h" 37bf215546Sopenharmony_ci#include "svga_shader.h" 38bf215546Sopenharmony_ci#include "svga_resource_texture.h" 39bf215546Sopenharmony_ci#include "svga_tgsi.h" 40bf215546Sopenharmony_ci#include "svga_format.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include "svga_hw_reg.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci/** 47bf215546Sopenharmony_ci * If we fail to compile a fragment shader (because it uses too many 48bf215546Sopenharmony_ci * registers, for example) we'll use a dummy/fallback shader that 49bf215546Sopenharmony_ci * simply emits a constant color (red for debug, black for release). 50bf215546Sopenharmony_ci * We hit this with the Unigine/Heaven demo when Shaders = High. 51bf215546Sopenharmony_ci * With black, the demo still looks good. 52bf215546Sopenharmony_ci */ 53bf215546Sopenharmony_cistatic const struct tgsi_token * 54bf215546Sopenharmony_ciget_dummy_fragment_shader(void) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci#ifdef DEBUG 57bf215546Sopenharmony_ci static const float color[4] = { 1.0, 0.0, 0.0, 0.0 }; /* red */ 58bf215546Sopenharmony_ci#else 59bf215546Sopenharmony_ci static const float color[4] = { 0.0, 0.0, 0.0, 0.0 }; /* black */ 60bf215546Sopenharmony_ci#endif 61bf215546Sopenharmony_ci struct ureg_program *ureg; 62bf215546Sopenharmony_ci const struct tgsi_token *tokens; 63bf215546Sopenharmony_ci struct ureg_src src; 64bf215546Sopenharmony_ci struct ureg_dst dst; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci ureg = ureg_create(PIPE_SHADER_FRAGMENT); 67bf215546Sopenharmony_ci if (!ureg) 68bf215546Sopenharmony_ci return NULL; 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 71bf215546Sopenharmony_ci src = ureg_DECL_immediate(ureg, color, 4); 72bf215546Sopenharmony_ci ureg_MOV(ureg, dst, src); 73bf215546Sopenharmony_ci ureg_END(ureg); 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci tokens = ureg_get_tokens(ureg, NULL); 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci ureg_destroy(ureg); 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci return tokens; 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci/** 84bf215546Sopenharmony_ci * Replace the given shader's instruction with a simple constant-color 85bf215546Sopenharmony_ci * shader. We use this when normal shader translation fails. 86bf215546Sopenharmony_ci */ 87bf215546Sopenharmony_cistruct svga_shader_variant * 88bf215546Sopenharmony_cisvga_get_compiled_dummy_fragment_shader(struct svga_context *svga, 89bf215546Sopenharmony_ci struct svga_shader *shader, 90bf215546Sopenharmony_ci const struct svga_compile_key *key) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci struct svga_fragment_shader *fs = (struct svga_fragment_shader *)shader; 93bf215546Sopenharmony_ci const struct tgsi_token *dummy = get_dummy_fragment_shader(); 94bf215546Sopenharmony_ci struct svga_shader_variant *variant; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci if (!dummy) { 97bf215546Sopenharmony_ci return NULL; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci FREE((void *) fs->base.tokens); 101bf215546Sopenharmony_ci fs->base.tokens = dummy; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci svga_tgsi_scan_shader(&fs->base); 104bf215546Sopenharmony_ci svga_remap_generics(fs->base.info.generic_inputs_mask, 105bf215546Sopenharmony_ci fs->generic_remap_table); 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci variant = svga_tgsi_compile_shader(svga, shader, key); 108bf215546Sopenharmony_ci return variant; 109bf215546Sopenharmony_ci} 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci/* SVGA_NEW_TEXTURE_BINDING 113bf215546Sopenharmony_ci * SVGA_NEW_RAST 114bf215546Sopenharmony_ci * SVGA_NEW_NEED_SWTNL 115bf215546Sopenharmony_ci * SVGA_NEW_SAMPLER 116bf215546Sopenharmony_ci */ 117bf215546Sopenharmony_cistatic enum pipe_error 118bf215546Sopenharmony_cimake_fs_key(const struct svga_context *svga, 119bf215546Sopenharmony_ci struct svga_fragment_shader *fs, 120bf215546Sopenharmony_ci struct svga_compile_key *key) 121bf215546Sopenharmony_ci{ 122bf215546Sopenharmony_ci const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT; 123bf215546Sopenharmony_ci unsigned i; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci memset(key, 0, sizeof *key); 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci memcpy(key->generic_remap_table, fs->generic_remap_table, 128bf215546Sopenharmony_ci sizeof(fs->generic_remap_table)); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci /* SVGA_NEW_GS, SVGA_NEW_VS 131bf215546Sopenharmony_ci */ 132bf215546Sopenharmony_ci struct svga_geometry_shader *gs = svga->curr.gs; 133bf215546Sopenharmony_ci struct svga_vertex_shader *vs = svga->curr.vs; 134bf215546Sopenharmony_ci if (gs) { 135bf215546Sopenharmony_ci key->fs.gs_generic_outputs = gs->base.info.generic_outputs_mask; 136bf215546Sopenharmony_ci key->fs.layer_to_zero = !gs->base.info.writes_layer; 137bf215546Sopenharmony_ci } else { 138bf215546Sopenharmony_ci key->fs.vs_generic_outputs = vs->base.info.generic_outputs_mask; 139bf215546Sopenharmony_ci key->fs.layer_to_zero = 1; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci /* Only need fragment shader fixup for twoside lighting if doing 143bf215546Sopenharmony_ci * hwtnl. Otherwise the draw module does the whole job for us. 144bf215546Sopenharmony_ci * 145bf215546Sopenharmony_ci * SVGA_NEW_SWTNL 146bf215546Sopenharmony_ci */ 147bf215546Sopenharmony_ci if (!svga->state.sw.need_swtnl) { 148bf215546Sopenharmony_ci /* SVGA_NEW_RAST, SVGA_NEW_REDUCED_PRIMITIVE 149bf215546Sopenharmony_ci */ 150bf215546Sopenharmony_ci enum pipe_prim_type prim_mode; 151bf215546Sopenharmony_ci struct svga_shader *shader; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci /* Find the last shader in the vertex pipeline and the output primitive mode 154bf215546Sopenharmony_ci * from that shader. 155bf215546Sopenharmony_ci */ 156bf215546Sopenharmony_ci if (svga->curr.tes) { 157bf215546Sopenharmony_ci shader = &svga->curr.tes->base; 158bf215546Sopenharmony_ci prim_mode = shader->info.tes.prim_mode; 159bf215546Sopenharmony_ci } else if (svga->curr.gs) { 160bf215546Sopenharmony_ci shader = &svga->curr.gs->base; 161bf215546Sopenharmony_ci prim_mode = shader->info.gs.out_prim; 162bf215546Sopenharmony_ci } else { 163bf215546Sopenharmony_ci shader = &svga->curr.vs->base; 164bf215546Sopenharmony_ci prim_mode = svga->curr.reduced_prim; 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci key->fs.light_twoside = svga->curr.rast->templ.light_twoside; 168bf215546Sopenharmony_ci key->fs.front_ccw = svga->curr.rast->templ.front_ccw; 169bf215546Sopenharmony_ci key->fs.pstipple = (svga->curr.rast->templ.poly_stipple_enable && 170bf215546Sopenharmony_ci prim_mode == PIPE_PRIM_TRIANGLES); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci if (svga->curr.gs) { 173bf215546Sopenharmony_ci key->fs.aa_point = (svga->curr.rast->templ.point_smooth && 174bf215546Sopenharmony_ci shader->info.gs.in_prim == PIPE_PRIM_POINTS && 175bf215546Sopenharmony_ci (svga->curr.rast->pointsize > 1.0 || 176bf215546Sopenharmony_ci shader->info.writes_psize)); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci if (key->fs.aa_point) { 179bf215546Sopenharmony_ci assert(svga->curr.gs->aa_point_coord_index != -1); 180bf215546Sopenharmony_ci key->fs.aa_point_coord_index = svga->curr.gs->aa_point_coord_index; 181bf215546Sopenharmony_ci } 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci } 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci /* The blend workaround for simulating logicop xor behaviour 186bf215546Sopenharmony_ci * requires that the incoming fragment color be white. This change 187bf215546Sopenharmony_ci * achieves that by creating a variant of the current fragment 188bf215546Sopenharmony_ci * shader that overrides all output colors with 1,1,1,1 189bf215546Sopenharmony_ci * 190bf215546Sopenharmony_ci * This will work for most shaders, including those containing 191bf215546Sopenharmony_ci * TEXKIL and/or depth-write. However, it will break on the 192bf215546Sopenharmony_ci * combination of xor-logicop plus alphatest. 193bf215546Sopenharmony_ci * 194bf215546Sopenharmony_ci * Ultimately, we could implement alphatest in the shader using 195bf215546Sopenharmony_ci * texkil prior to overriding the outgoing fragment color. 196bf215546Sopenharmony_ci * 197bf215546Sopenharmony_ci * SVGA_NEW_BLEND 198bf215546Sopenharmony_ci */ 199bf215546Sopenharmony_ci key->fs.white_fragments = svga->curr.blend->need_white_fragments; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci key->fs.alpha_to_one = svga->curr.blend->alpha_to_one; 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci#ifdef DEBUG 204bf215546Sopenharmony_ci /* 205bf215546Sopenharmony_ci * We expect a consistent set of samplers and sampler views. 206bf215546Sopenharmony_ci * Do some debug checks/warnings here. 207bf215546Sopenharmony_ci */ 208bf215546Sopenharmony_ci { 209bf215546Sopenharmony_ci static boolean warned = FALSE; 210bf215546Sopenharmony_ci unsigned i, n = MAX2(svga->curr.num_sampler_views[shader], 211bf215546Sopenharmony_ci svga->curr.num_samplers[shader]); 212bf215546Sopenharmony_ci /* Only warn once to prevent too much debug output */ 213bf215546Sopenharmony_ci if (!warned) { 214bf215546Sopenharmony_ci if (svga->curr.num_sampler_views[shader] != 215bf215546Sopenharmony_ci svga->curr.num_samplers[shader]) { 216bf215546Sopenharmony_ci debug_printf("svga: mismatched number of sampler views (%u) " 217bf215546Sopenharmony_ci "vs. samplers (%u)\n", 218bf215546Sopenharmony_ci svga->curr.num_sampler_views[shader], 219bf215546Sopenharmony_ci svga->curr.num_samplers[shader]); 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci for (i = 0; i < n; i++) { 222bf215546Sopenharmony_ci if ((svga->curr.sampler_views[shader][i] == NULL) != 223bf215546Sopenharmony_ci (svga->curr.sampler[shader][i] == NULL)) 224bf215546Sopenharmony_ci debug_printf("sampler_view[%u] = %p but sampler[%u] = %p\n", 225bf215546Sopenharmony_ci i, svga->curr.sampler_views[shader][i], 226bf215546Sopenharmony_ci i, svga->curr.sampler[shader][i]); 227bf215546Sopenharmony_ci } 228bf215546Sopenharmony_ci warned = TRUE; 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci#endif 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci /* XXX: want to limit this to the textures that the shader actually 234bf215546Sopenharmony_ci * refers to. 235bf215546Sopenharmony_ci * 236bf215546Sopenharmony_ci * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER 237bf215546Sopenharmony_ci */ 238bf215546Sopenharmony_ci svga_init_shader_key_common(svga, shader, &fs->base, key); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci for (i = 0; i < svga->curr.num_samplers[shader]; ++i) { 241bf215546Sopenharmony_ci struct pipe_sampler_view *view = svga->curr.sampler_views[shader][i]; 242bf215546Sopenharmony_ci const struct svga_sampler_state *sampler = svga->curr.sampler[shader][i]; 243bf215546Sopenharmony_ci if (view) { 244bf215546Sopenharmony_ci struct pipe_resource *tex = view->texture; 245bf215546Sopenharmony_ci if (tex->target != PIPE_BUFFER) { 246bf215546Sopenharmony_ci struct svga_texture *stex = svga_texture(tex); 247bf215546Sopenharmony_ci SVGA3dSurfaceFormat format = stex->key.format; 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci if (!svga_have_vgpu10(svga) && 250bf215546Sopenharmony_ci (format == SVGA3D_Z_D16 || 251bf215546Sopenharmony_ci format == SVGA3D_Z_D24X8 || 252bf215546Sopenharmony_ci format == SVGA3D_Z_D24S8)) { 253bf215546Sopenharmony_ci /* If we're sampling from a SVGA3D_Z_D16, SVGA3D_Z_D24X8, 254bf215546Sopenharmony_ci * or SVGA3D_Z_D24S8 surface, we'll automatically get 255bf215546Sopenharmony_ci * shadow comparison. But we only get LEQUAL mode. 256bf215546Sopenharmony_ci * Set TEX_COMPARE_NONE here so we don't emit the extra FS 257bf215546Sopenharmony_ci * code for shadow comparison. 258bf215546Sopenharmony_ci */ 259bf215546Sopenharmony_ci key->tex[i].compare_mode = PIPE_TEX_COMPARE_NONE; 260bf215546Sopenharmony_ci key->tex[i].compare_func = PIPE_FUNC_NEVER; 261bf215546Sopenharmony_ci /* These depth formats _only_ support comparison mode and 262bf215546Sopenharmony_ci * not ordinary sampling so warn if the later is expected. 263bf215546Sopenharmony_ci */ 264bf215546Sopenharmony_ci if (sampler->compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) { 265bf215546Sopenharmony_ci debug_warn_once("Unsupported shadow compare mode"); 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci /* The shader translation code can emit code to 268bf215546Sopenharmony_ci * handle ALWAYS and NEVER compare functions 269bf215546Sopenharmony_ci */ 270bf215546Sopenharmony_ci else if (sampler->compare_func == PIPE_FUNC_ALWAYS || 271bf215546Sopenharmony_ci sampler->compare_func == PIPE_FUNC_NEVER) { 272bf215546Sopenharmony_ci key->tex[i].compare_mode = sampler->compare_mode; 273bf215546Sopenharmony_ci key->tex[i].compare_func = sampler->compare_func; 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci else if (sampler->compare_func != PIPE_FUNC_LEQUAL) { 276bf215546Sopenharmony_ci debug_warn_once("Unsupported shadow compare function"); 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci } 280bf215546Sopenharmony_ci } 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci /* sprite coord gen state */ 284bf215546Sopenharmony_ci key->sprite_coord_enable = svga->curr.rast->templ.sprite_coord_enable; 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode 287bf215546Sopenharmony_ci == PIPE_SPRITE_COORD_LOWER_LEFT); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci key->fs.flatshade = svga->curr.rast->templ.flatshade; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci /* SVGA_NEW_DEPTH_STENCIL_ALPHA */ 292bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) { 293bf215546Sopenharmony_ci /* Alpha testing is not supported in integer-valued render targets. */ 294bf215546Sopenharmony_ci if (svga_has_any_integer_cbufs(svga)) { 295bf215546Sopenharmony_ci key->fs.alpha_func = SVGA3D_CMP_ALWAYS; 296bf215546Sopenharmony_ci key->fs.alpha_ref = 0; 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci else { 299bf215546Sopenharmony_ci key->fs.alpha_func = svga->curr.depth->alphafunc; 300bf215546Sopenharmony_ci key->fs.alpha_ref = svga->curr.depth->alpharef; 301bf215546Sopenharmony_ci } 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci /* SVGA_NEW_FRAME_BUFFER | SVGA_NEW_BLEND */ 305bf215546Sopenharmony_ci if (fs->base.info.fs.color0_writes_all_cbufs || 306bf215546Sopenharmony_ci svga->curr.blend->need_white_fragments) { 307bf215546Sopenharmony_ci /* Replicate color0 output (or white) to N colorbuffers */ 308bf215546Sopenharmony_ci key->fs.write_color0_to_n_cbufs = svga->curr.framebuffer.nr_cbufs; 309bf215546Sopenharmony_ci } 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci return PIPE_OK; 312bf215546Sopenharmony_ci} 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci/** 316bf215546Sopenharmony_ci * svga_reemit_fs_bindings - Reemit the fragment shader bindings 317bf215546Sopenharmony_ci */ 318bf215546Sopenharmony_cienum pipe_error 319bf215546Sopenharmony_cisvga_reemit_fs_bindings(struct svga_context *svga) 320bf215546Sopenharmony_ci{ 321bf215546Sopenharmony_ci enum pipe_error ret; 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci assert(svga->rebind.flags.fs); 324bf215546Sopenharmony_ci assert(svga_have_gb_objects(svga)); 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci if (!svga->state.hw_draw.fs) 327bf215546Sopenharmony_ci return PIPE_OK; 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci if (!svga_need_to_rebind_resources(svga)) { 330bf215546Sopenharmony_ci ret = svga->swc->resource_rebind(svga->swc, NULL, 331bf215546Sopenharmony_ci svga->state.hw_draw.fs->gb_shader, 332bf215546Sopenharmony_ci SVGA_RELOC_READ); 333bf215546Sopenharmony_ci } 334bf215546Sopenharmony_ci else { 335bf215546Sopenharmony_ci if (svga_have_vgpu10(svga)) 336bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetShader(svga->swc, SVGA3D_SHADERTYPE_PS, 337bf215546Sopenharmony_ci svga->state.hw_draw.fs->gb_shader, 338bf215546Sopenharmony_ci svga->state.hw_draw.fs->id); 339bf215546Sopenharmony_ci else 340bf215546Sopenharmony_ci ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_PS, 341bf215546Sopenharmony_ci svga->state.hw_draw.fs->gb_shader); 342bf215546Sopenharmony_ci } 343bf215546Sopenharmony_ci 344bf215546Sopenharmony_ci if (ret != PIPE_OK) 345bf215546Sopenharmony_ci return ret; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci svga->rebind.flags.fs = FALSE; 348bf215546Sopenharmony_ci return PIPE_OK; 349bf215546Sopenharmony_ci} 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_cistatic enum pipe_error 354bf215546Sopenharmony_ciemit_hw_fs(struct svga_context *svga, uint64_t dirty) 355bf215546Sopenharmony_ci{ 356bf215546Sopenharmony_ci struct svga_shader_variant *variant = NULL; 357bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 358bf215546Sopenharmony_ci struct svga_fragment_shader *fs = svga->curr.fs; 359bf215546Sopenharmony_ci struct svga_compile_key key; 360bf215546Sopenharmony_ci struct svga_shader *prevShader = NULL; /* shader in the previous stage */ 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITFS); 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci prevShader = svga->curr.gs ? 365bf215546Sopenharmony_ci &svga->curr.gs->base : (svga->curr.tes ? 366bf215546Sopenharmony_ci &svga->curr.tes->base : &svga->curr.vs->base); 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci /* Disable rasterization if rasterizer_discard flag is set or 369bf215546Sopenharmony_ci * vs/gs does not output position. 370bf215546Sopenharmony_ci */ 371bf215546Sopenharmony_ci svga->disable_rasterizer = 372bf215546Sopenharmony_ci svga->curr.rast->templ.rasterizer_discard || 373bf215546Sopenharmony_ci !prevShader->info.writes_position; 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci /* Set FS to NULL when rasterization is to be disabled */ 376bf215546Sopenharmony_ci if (svga->disable_rasterizer) { 377bf215546Sopenharmony_ci /* Set FS to NULL if it has not been done */ 378bf215546Sopenharmony_ci if (svga->state.hw_draw.fs) { 379bf215546Sopenharmony_ci ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_PS, NULL); 380bf215546Sopenharmony_ci if (ret != PIPE_OK) 381bf215546Sopenharmony_ci goto done; 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci svga->rebind.flags.fs = FALSE; 384bf215546Sopenharmony_ci svga->state.hw_draw.fs = NULL; 385bf215546Sopenharmony_ci goto done; 386bf215546Sopenharmony_ci } 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci /* SVGA_NEW_BLEND 389bf215546Sopenharmony_ci * SVGA_NEW_TEXTURE_BINDING 390bf215546Sopenharmony_ci * SVGA_NEW_RAST 391bf215546Sopenharmony_ci * SVGA_NEW_NEED_SWTNL 392bf215546Sopenharmony_ci * SVGA_NEW_SAMPLER 393bf215546Sopenharmony_ci * SVGA_NEW_FRAME_BUFFER 394bf215546Sopenharmony_ci * SVGA_NEW_DEPTH_STENCIL_ALPHA 395bf215546Sopenharmony_ci * SVGA_NEW_VS 396bf215546Sopenharmony_ci */ 397bf215546Sopenharmony_ci ret = make_fs_key(svga, fs, &key); 398bf215546Sopenharmony_ci if (ret != PIPE_OK) 399bf215546Sopenharmony_ci goto done; 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci variant = svga_search_shader_key(&fs->base, &key); 402bf215546Sopenharmony_ci if (!variant) { 403bf215546Sopenharmony_ci ret = svga_compile_shader(svga, &fs->base, &key, &variant); 404bf215546Sopenharmony_ci if (ret != PIPE_OK) 405bf215546Sopenharmony_ci goto done; 406bf215546Sopenharmony_ci } 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci assert(variant); 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci if (variant != svga->state.hw_draw.fs) { 411bf215546Sopenharmony_ci ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_PS, variant); 412bf215546Sopenharmony_ci if (ret != PIPE_OK) 413bf215546Sopenharmony_ci goto done; 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ci svga->rebind.flags.fs = FALSE; 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_FS_VARIANT; 418bf215546Sopenharmony_ci svga->state.hw_draw.fs = variant; 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_cidone: 422bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svga_sws(svga)); 423bf215546Sopenharmony_ci return ret; 424bf215546Sopenharmony_ci} 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_fs = 427bf215546Sopenharmony_ci{ 428bf215546Sopenharmony_ci "fragment shader (hwtnl)", 429bf215546Sopenharmony_ci (SVGA_NEW_FS | 430bf215546Sopenharmony_ci SVGA_NEW_GS | 431bf215546Sopenharmony_ci SVGA_NEW_VS | 432bf215546Sopenharmony_ci SVGA_NEW_TEXTURE_BINDING | 433bf215546Sopenharmony_ci SVGA_NEW_NEED_SWTNL | 434bf215546Sopenharmony_ci SVGA_NEW_RAST | 435bf215546Sopenharmony_ci SVGA_NEW_STIPPLE | 436bf215546Sopenharmony_ci SVGA_NEW_REDUCED_PRIMITIVE | 437bf215546Sopenharmony_ci SVGA_NEW_SAMPLER | 438bf215546Sopenharmony_ci SVGA_NEW_FRAME_BUFFER | 439bf215546Sopenharmony_ci SVGA_NEW_DEPTH_STENCIL_ALPHA | 440bf215546Sopenharmony_ci SVGA_NEW_BLEND | 441bf215546Sopenharmony_ci SVGA_NEW_FS_RAW_BUFFER), 442bf215546Sopenharmony_ci emit_hw_fs 443bf215546Sopenharmony_ci}; 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci 447