static int emit_hw_vs( struct svga_context *svga, unsigned dirty ) { struct svga_shader_result *result = NULL; unsigned id = SVGA3D_INVALID_ID; int ret = 0; /* SVGA_NEW_NEED_SWTNL */ if (!svga->state.sw.need_swtnl) { struct svga_vertex_shader *vs = svga->curr.vs; struct svga_vs_compile_key key; ret = make_vs_key( svga, &key ); if (ret) return ret; result = search_vs_key( vs, &key ); if (!result) { ret = compile_vs( svga, vs, &key, &result ); if (ret) return ret; } assert (result); id = result->id; } if (result != svga->state.hw_draw.vs) { ret = SVGA3D_SetShader(svga->swc, SVGA3D_SHADERTYPE_VS, id ); if (ret) return ret; svga->dirty |= SVGA_NEW_VS_RESULT; svga->state.hw_draw.vs = result; } return 0; }
static enum pipe_error emit_hw_vs(struct svga_context *svga, unsigned dirty) { struct svga_shader_variant *variant; struct svga_vertex_shader *vs = svga->curr.vs; struct svga_fragment_shader *fs = svga->curr.fs; enum pipe_error ret = PIPE_OK; struct svga_compile_key key; /* If there is an active geometry shader, and it has stream output * defined, then we will skip the stream output from the vertex shader */ if (!svga_have_gs_streamout(svga)) { /* No GS stream out */ if (svga_have_vs_streamout(svga)) { /* Set VS stream out */ svga_set_stream_output(svga, vs->base.stream_output); } else { /* turn off stream out */ svga_set_stream_output(svga, NULL); } } /* SVGA_NEW_NEED_SWTNL */ if (svga->state.sw.need_swtnl && !svga_have_vgpu10(svga)) { /* No vertex shader is needed */ variant = NULL; } else { make_vs_key(svga, &key); /* See if we already have a VS variant that matches the key */ variant = svga_search_shader_key(&vs->base, &key); if (!variant) { /* Create VS variant now */ if (key.vs.passthrough) { ret = compile_passthrough_vs(svga, vs, fs, &variant); } else { ret = compile_vs(svga, vs, &key, &variant); } if (ret != PIPE_OK) return ret; /* insert the new variant at head of linked list */ assert(variant); variant->next = vs->base.variants; vs->base.variants = variant; } } if (variant != svga->state.hw_draw.vs) { /* Bind the new variant */ if (variant) { ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_VS, variant); if (ret != PIPE_OK) return ret; svga->rebind.flags.vs = FALSE; } svga->dirty |= SVGA_NEW_VS_VARIANT; svga->state.hw_draw.vs = variant; } return PIPE_OK; }
/** * The current vertex shader is already executed by the 'draw' * module, so we just need to generate a simple vertex shader * to pass through all those VS outputs that will * be consumed by the fragment shader. * Used when we employ the 'draw' module. */ static enum pipe_error compile_passthrough_vs(struct svga_context *svga, struct svga_vertex_shader *vs, struct svga_fragment_shader *fs, struct svga_shader_variant **out_variant) { struct svga_shader_variant *variant = NULL; unsigned num_inputs; unsigned i; unsigned num_elements; struct svga_vertex_shader new_vs; struct ureg_src src[PIPE_MAX_SHADER_INPUTS]; struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS]; struct ureg_program *ureg; unsigned num_tokens; struct svga_compile_key key; enum pipe_error ret; assert(svga_have_vgpu10(svga)); assert(fs); num_inputs = fs->base.info.num_inputs; ureg = ureg_create(TGSI_PROCESSOR_VERTEX); if (!ureg) return PIPE_ERROR_OUT_OF_MEMORY; /* draw will always add position */ dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); src[0] = ureg_DECL_vs_input(ureg, 0); num_elements = 1; /** * swtnl backend redefines the input layout based on the * fragment shader's inputs. So we only need to passthrough * those inputs that will be consumed by the fragment shader. * Note: DX10 requires the number of vertex elements * specified in the input layout to be no less than the * number of inputs to the vertex shader. */ for (i = 0; i < num_inputs; i++) { switch (fs->base.info.input_semantic_name[i]) { case TGSI_SEMANTIC_COLOR: case TGSI_SEMANTIC_GENERIC: case TGSI_SEMANTIC_FOG: dst[num_elements] = ureg_DECL_output(ureg, fs->base.info.input_semantic_name[i], fs->base.info.input_semantic_index[i]); src[num_elements] = ureg_DECL_vs_input(ureg, num_elements); num_elements++; break; default: break; } } for (i = 0; i < num_elements; i++) { ureg_MOV(ureg, dst[i], src[i]); } ureg_END(ureg); memset(&new_vs, 0, sizeof(new_vs)); new_vs.base.tokens = ureg_get_tokens(ureg, &num_tokens); tgsi_scan_shader(new_vs.base.tokens, &new_vs.base.info); memset(&key, 0, sizeof(key)); key.vs.undo_viewport = 1; ret = compile_vs(svga, &new_vs, &key, &variant); if (ret != PIPE_OK) return ret; ureg_free_tokens(new_vs.base.tokens); ureg_destroy(ureg); /* Overwrite the variant key to indicate it's a pass-through VS */ memset(&variant->key, 0, sizeof(variant->key)); variant->key.vs.passthrough = 1; variant->key.vs.undo_viewport = 1; *out_variant = variant; return PIPE_OK; }