diff options
author | Brian Paul <[email protected]> | 2015-08-07 15:22:01 -0600 |
---|---|---|
committer | Brian Paul <[email protected]> | 2015-09-02 09:05:23 -0600 |
commit | a633948e7ea2445ff88c469edf47c44cfec8d962 (patch) | |
tree | 179ed6ee379846032d914f89745c4060df0e330f /src/gallium | |
parent | ff85bcdba21ccf88f1a359f2055847e2c820e85f (diff) |
svga: add new svga_state_gs.c file
Signed-off-by: Brian Paul <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/svga/svga_state_gs.c | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/src/gallium/drivers/svga/svga_state_gs.c b/src/gallium/drivers/svga/svga_state_gs.c new file mode 100644 index 00000000000..9f6885b95a2 --- /dev/null +++ b/src/gallium/drivers/svga/svga_state_gs.c @@ -0,0 +1,264 @@ +/********************************************************** + * Copyright 2014 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **********************************************************/ + +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_bitmask.h" +#include "translate/translate.h" +#include "tgsi/tgsi_ureg.h" + +#include "svga_context.h" +#include "svga_cmd.h" +#include "svga_shader.h" +#include "svga_tgsi.h" +#include "svga_streamout.h" +#include "svga_format.h" + +/** + * If we fail to compile a geometry shader we'll use a dummy/fallback shader + * that simply emits the incoming vertices. + */ +static const struct tgsi_token * +get_dummy_geometry_shader(void) +{ + //XXX + return NULL; +} + + +static struct svga_shader_variant * +translate_geometry_program(struct svga_context *svga, + const struct svga_geometry_shader *gs, + const struct svga_compile_key *key) +{ + if (svga_have_vgpu10(svga)) { + return svga_tgsi_vgpu10_translate(svga, &gs->base, key, + PIPE_SHADER_GEOMETRY); + } + else { + return svga_tgsi_vgpu9_translate(&gs->base, key, PIPE_SHADER_GEOMETRY); + } +} + + +/** + * Translate TGSI shader into an svga shader variant. + */ +static enum pipe_error +compile_gs(struct svga_context *svga, + struct svga_geometry_shader *gs, + const struct svga_compile_key *key, + struct svga_shader_variant **out_variant) +{ + struct svga_shader_variant *variant; + enum pipe_error ret = PIPE_ERROR; + + variant = translate_geometry_program(svga, gs, key); + if (variant == NULL) { + /* some problem during translation, try the dummy shader */ + const struct tgsi_token *dummy = get_dummy_geometry_shader(); + if (!dummy) { + ret = PIPE_ERROR_OUT_OF_MEMORY; + goto fail; + } + debug_printf("Failed to compile geometry shader, using dummy shader instead.\n"); + FREE((void *) gs->base.tokens); + gs->base.tokens = dummy; + variant = translate_geometry_program(svga, gs, key); + if (variant == NULL) { + ret = PIPE_ERROR; + goto fail; + } + } + + ret = svga_define_shader(svga, SVGA3D_SHADERTYPE_GS, variant); + if (ret != PIPE_OK) + goto fail; + + *out_variant = variant; + + return PIPE_OK; + +fail: + if (variant) { + svga_destroy_shader_variant(svga, SVGA3D_SHADERTYPE_GS, variant); + } + return ret; +} + +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_reemit_gs_bindings - Reemit the geometry shader bindings + */ +enum pipe_error +svga_reemit_gs_bindings(struct svga_context *svga) +{ + enum pipe_error ret; + struct svga_winsys_gb_shader *gbshader = NULL; + SVGA3dShaderId shaderId = SVGA3D_INVALID_ID; + + assert(svga->rebind.flags.gs); + assert(svga_have_gb_objects(svga)); + + /* Geometry Shader is only supported in vgpu10 */ + assert(svga_have_vgpu10(svga)); + + if (svga->state.hw_draw.gs) { + gbshader = svga->state.hw_draw.gs->gb_shader; + shaderId = svga->state.hw_draw.gs->id; + } + + if (!svga_need_to_rebind_resources(svga)) { + ret = svga->swc->resource_rebind(svga->swc, NULL, gbshader, + SVGA_RELOC_READ); + goto out; + } + + ret = SVGA3D_vgpu10_SetShader(svga->swc, SVGA3D_SHADERTYPE_GS, + gbshader, shaderId); + + out: + if (ret != PIPE_OK) + return ret; + + svga->rebind.flags.gs = FALSE; + return PIPE_OK; +} + +static enum pipe_error +emit_hw_gs(struct svga_context *svga, unsigned dirty) +{ + struct svga_shader_variant *variant; + struct svga_geometry_shader *gs = svga->curr.gs; + enum pipe_error ret = PIPE_OK; + struct svga_compile_key key; + + /* If there's a user-defined GS, we should have a pointer to a derived + * GS. This should have been resolved in update_tgsi_transform(). + */ + if (svga->curr.user_gs) + assert(svga->curr.gs); + + if (gs == NULL) { + if (svga->state.hw_draw.gs != NULL) { + + /** The previous geometry shader is made inactive. + * Needs to unbind the geometry shader. + */ + ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_GS, NULL); + svga->state.hw_draw.gs = NULL; + } + return ret; + } + + /* If there is stream output info for this geometry shader, then use + * it instead of the one from the vertex shader. + */ + if (svga_have_gs_streamout(svga)) { + svga_set_stream_output(svga, gs->base.stream_output); + } + else if (!svga_have_vs_streamout(svga)) { + /* 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 geometry shader is needed */ + variant = NULL; + } + else { + make_gs_key(svga, &key); + + /* See if we already have a GS variant that matches the key */ + variant = svga_search_shader_key(&gs->base, &key); + + if (!variant) { + ret = compile_gs(svga, gs, &key, &variant); + if (ret != PIPE_OK) + return ret; + + /* insert the new variant at head of linked list */ + assert(variant); + variant->next = gs->base.variants; + gs->base.variants = variant; + } + } + + if (variant != svga->state.hw_draw.gs) { + /* Bind the new variant */ + ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_GS, variant); + if (ret != PIPE_OK) + return ret; + + svga->rebind.flags.gs = FALSE; + svga->dirty |= SVGA_NEW_GS_VARIANT; + svga->state.hw_draw.gs = variant; + } + + return PIPE_OK; +} + +struct svga_tracked_state svga_hw_gs = +{ + "geometry shader (hwtnl)", + (SVGA_NEW_VS | + SVGA_NEW_FS | + SVGA_NEW_GS | + SVGA_NEW_TEXTURE_BINDING | + SVGA_NEW_SAMPLER | + SVGA_NEW_RAST | + SVGA_NEW_NEED_SWTNL), + emit_hw_gs +}; |