static void make_gs_key(struct svga_context *svga, struct svga_compile_key *key) { struct svga_geometry_shader *gs = svga->curr.gs; memset(key, 0, sizeof *key); /* * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER */ svga_init_shader_key_common(svga, PIPE_SHADER_GEOMETRY, key); memcpy(key->generic_remap_table, gs->generic_remap_table, sizeof(gs->generic_remap_table)); key->gs.vs_generic_outputs = svga->curr.vs->generic_outputs; key->gs.need_prescale = svga->state.hw_clear.prescale.enabled; key->gs.writes_psize = gs->base.info.writes_psize; key->gs.wide_point = gs->wide_point; key->sprite_coord_enable = svga->curr.rast->templ.sprite_coord_enable; key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT); /* SVGA_NEW_RAST */ key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable; }
/* SVGA_NEW_PRESCALE, SVGA_NEW_RAST, SVGA_NEW_FS */ static void make_vs_key(struct svga_context *svga, struct svga_compile_key *key) { const unsigned shader = PIPE_SHADER_VERTEX; memset(key, 0, sizeof *key); if (svga->state.sw.need_swtnl && svga_have_vgpu10(svga)) { /* Set both of these flags, to match compile_passthrough_vs() */ key->vs.passthrough = 1; key->vs.undo_viewport = 1; return; } /* SVGA_NEW_PRESCALE */ key->vs.need_prescale = svga->state.hw_clear.prescale.enabled && (svga->curr.gs == NULL); /* SVGA_NEW_RAST */ key->vs.allow_psiz = svga->curr.rast->templ.point_size_per_vertex; /* SVGA_NEW_FS */ key->vs.fs_generic_inputs = svga->curr.fs->generic_inputs; svga_remap_generics(key->vs.fs_generic_inputs, key->generic_remap_table); /* SVGA_NEW_VELEMENT */ key->vs.adjust_attrib_range = svga->curr.velems->adjust_attrib_range; key->vs.adjust_attrib_w_1 = svga->curr.velems->adjust_attrib_w_1; key->vs.attrib_is_pure_int = svga->curr.velems->attrib_is_pure_int; key->vs.adjust_attrib_itof = svga->curr.velems->adjust_attrib_itof; key->vs.adjust_attrib_utof = svga->curr.velems->adjust_attrib_utof; key->vs.attrib_is_bgra = svga->curr.velems->attrib_is_bgra; key->vs.attrib_puint_to_snorm = svga->curr.velems->attrib_puint_to_snorm; key->vs.attrib_puint_to_uscaled = svga->curr.velems->attrib_puint_to_uscaled; key->vs.attrib_puint_to_sscaled = svga->curr.velems->attrib_puint_to_sscaled; /* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER */ svga_init_shader_key_common(svga, shader, key); /* SVGA_NEW_RAST */ key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable; }
/* SVGA_NEW_TEXTURE_BINDING * SVGA_NEW_RAST * SVGA_NEW_NEED_SWTNL * SVGA_NEW_SAMPLER */ static enum pipe_error make_fs_key(const struct svga_context *svga, struct svga_fragment_shader *fs, struct svga_compile_key *key) { const unsigned shader = PIPE_SHADER_FRAGMENT; unsigned i; memset(key, 0, sizeof *key); memcpy(key->generic_remap_table, fs->generic_remap_table, sizeof(fs->generic_remap_table)); /* SVGA_NEW_GS, SVGA_NEW_VS */ if (svga->curr.gs) { key->fs.gs_generic_outputs = svga->curr.gs->generic_outputs; } else { key->fs.vs_generic_outputs = svga->curr.vs->generic_outputs; } /* Only need fragment shader fixup for twoside lighting if doing * hwtnl. Otherwise the draw module does the whole job for us. * * SVGA_NEW_SWTNL */ if (!svga->state.sw.need_swtnl) { /* SVGA_NEW_RAST, SVGA_NEW_REDUCED_PRIMITIVE */ key->fs.light_twoside = svga->curr.rast->templ.light_twoside; key->fs.front_ccw = svga->curr.rast->templ.front_ccw; key->fs.pstipple = (svga->curr.rast->templ.poly_stipple_enable && svga->curr.reduced_prim == PIPE_PRIM_TRIANGLES); key->fs.aa_point = (svga->curr.rast->templ.point_smooth && svga->curr.reduced_prim == PIPE_PRIM_POINTS && (svga->curr.rast->pointsize > 1.0 || svga->curr.vs->base.info.writes_psize)); if (key->fs.aa_point) { assert(svga->curr.gs != NULL); assert(svga->curr.gs->aa_point_coord_index != -1); key->fs.aa_point_coord_index = svga->curr.gs->aa_point_coord_index; } } /* The blend workaround for simulating logicop xor behaviour * requires that the incoming fragment color be white. This change * achieves that by creating a variant of the current fragment * shader that overrides all output colors with 1,1,1,1 * * This will work for most shaders, including those containing * TEXKIL and/or depth-write. However, it will break on the * combination of xor-logicop plus alphatest. * * Ultimately, we could implement alphatest in the shader using * texkil prior to overriding the outgoing fragment color. * * SVGA_NEW_BLEND */ if (svga->curr.blend->need_white_fragments) { key->fs.white_fragments = 1; } #ifdef DEBUG /* * We expect a consistent set of samplers and sampler views. * Do some debug checks/warnings here. */ { static boolean warned = FALSE; unsigned i, n = MAX2(svga->curr.num_sampler_views[shader], svga->curr.num_samplers[shader]); /* Only warn once to prevent too much debug output */ if (!warned) { if (svga->curr.num_sampler_views[shader] != svga->curr.num_samplers[shader]) { debug_printf("svga: mismatched number of sampler views (%u) " "vs. samplers (%u)\n", svga->curr.num_sampler_views[shader], svga->curr.num_samplers[shader]); } for (i = 0; i < n; i++) { if ((svga->curr.sampler_views[shader][i] == NULL) != (svga->curr.sampler[shader][i] == NULL)) debug_printf("sampler_view[%u] = %p but sampler[%u] = %p\n", i, svga->curr.sampler_views[shader][i], i, svga->curr.sampler[shader][i]); } warned = TRUE; } } #endif /* XXX: want to limit this to the textures that the shader actually * refers to. * * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER */ svga_init_shader_key_common(svga, shader, key); for (i = 0; i < svga->curr.num_samplers[shader]; ++i) { struct pipe_sampler_view *view = svga->curr.sampler_views[shader][i]; const struct svga_sampler_state *sampler = svga->curr.sampler[shader][i]; if (view) { struct pipe_resource *tex = view->texture; if (tex->target != PIPE_BUFFER) { struct svga_texture *stex = svga_texture(tex); SVGA3dSurfaceFormat format = stex->key.format; if (!svga_have_vgpu10(svga) && (format == SVGA3D_Z_D16 || format == SVGA3D_Z_D24X8 || format == SVGA3D_Z_D24S8)) { /* If we're sampling from a SVGA3D_Z_D16, SVGA3D_Z_D24X8, * or SVGA3D_Z_D24S8 surface, we'll automatically get * shadow comparison. But we only get LEQUAL mode. * Set TEX_COMPARE_NONE here so we don't emit the extra FS * code for shadow comparison. */ key->tex[i].compare_mode = PIPE_TEX_COMPARE_NONE; key->tex[i].compare_func = PIPE_FUNC_NEVER; /* These depth formats _only_ support comparison mode and * not ordinary sampling so warn if the later is expected. */ if (sampler->compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) { debug_warn_once("Unsupported shadow compare mode"); } /* The shader translation code can emit code to * handle ALWAYS and NEVER compare functions */ else if (sampler->compare_func == PIPE_FUNC_ALWAYS || sampler->compare_func == PIPE_FUNC_NEVER) { key->tex[i].compare_mode = sampler->compare_mode; key->tex[i].compare_func = sampler->compare_func; } else if (sampler->compare_func != PIPE_FUNC_LEQUAL) { debug_warn_once("Unsupported shadow compare function"); } } else { /* For other texture formats, just use the compare func/mode * as-is. Should be no-ops for color textures. For depth * textures, we do not get automatic depth compare. We have * to do it ourselves in the shader. And we don't get PCF. */ key->tex[i].compare_mode = sampler->compare_mode; key->tex[i].compare_func = sampler->compare_func; } } } } /* sprite coord gen state */ for (i = 0; i < svga->curr.num_samplers[shader]; ++i) { key->tex[i].sprite_texgen = svga->curr.rast->templ.sprite_coord_enable & (1 << i); } key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT); key->fs.flatshade = svga->curr.rast->templ.flatshade; /* SVGA_NEW_DEPTH_STENCIL_ALPHA */ if (svga_have_vgpu10(svga)) { /* Alpha testing is not supported in integer-valued render targets. */ if (svga_has_any_integer_cbufs(svga)) { key->fs.alpha_func = SVGA3D_CMP_ALWAYS; key->fs.alpha_ref = 0; } else { key->fs.alpha_func = svga->curr.depth->alphafunc; key->fs.alpha_ref = svga->curr.depth->alpharef; } } /* SVGA_NEW_FRAME_BUFFER */ if (fs->base.info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS]) { /* Replicate color0 output to N colorbuffers */ key->fs.write_color0_to_n_cbufs = svga->curr.framebuffer.nr_cbufs; } return PIPE_OK; }