[Mesa-dev] [PATCH 13/18] gallium/u_simple_shaders: generate POSITION from VERTEXID if not present
Marek Olšák
maraeo at gmail.com
Thu Aug 17 18:31:34 UTC 2017
From: Marek Olšák <marek.olsak at amd.com>
---
src/gallium/auxiliary/util/u_blitter.c | 3 +-
src/gallium/auxiliary/util/u_simple_shaders.c | 54 +++++++++++++++++++++++++--
src/gallium/auxiliary/util/u_simple_shaders.h | 3 +-
src/mesa/state_tracker/st_cb_clear.c | 2 +-
4 files changed, 55 insertions(+), 7 deletions(-)
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 7a3eb63..54d3009 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -358,21 +358,22 @@ static void bind_vs_passthrough(struct blitter_context_priv *ctx)
}
pipe->bind_vs_state(pipe, ctx->vs);
}
static void bind_vs_layered(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
if (!ctx->vs_layered) {
- ctx->vs_layered = util_make_layered_clear_vertex_shader(pipe);
+ ctx->vs_layered =
+ util_make_layered_clear_vertex_shader(pipe, true);
}
pipe->bind_vs_state(pipe, ctx->vs_layered);
}
static void bind_fs_empty(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
if (!ctx->fs_empty) {
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c
index 9679545..763c634 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.c
+++ b/src/gallium/auxiliary/util/u_simple_shaders.c
@@ -72,65 +72,111 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
void *
util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes,
bool window_space, bool layered,
const struct pipe_stream_output_info *so)
{
struct ureg_program *ureg;
uint i;
+ bool has_position = false;
ureg = ureg_create( PIPE_SHADER_VERTEX );
if (!ureg)
return NULL;
if (window_space)
ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
for (i = 0; i < num_attribs; i++) {
struct ureg_src src;
struct ureg_dst dst;
src = ureg_DECL_vs_input( ureg, i );
dst = ureg_DECL_output( ureg,
semantic_names[i],
semantic_indexes[i]);
ureg_MOV( ureg, dst, src );
+
+ if (semantic_names[i] == TGSI_SEMANTIC_POSITION)
+ has_position = true;
}
if (layered) {
struct ureg_src instance_id =
ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0);
struct ureg_dst layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0);
ureg_MOV(ureg, ureg_writemask(layer, TGSI_WRITEMASK_X),
ureg_scalar(instance_id, TGSI_SWIZZLE_X));
}
+ /* If there is no position to pass from inputs, generate it from VertexID.
+ */
+ if (!has_position) {
+ struct ureg_src vertex_id =
+ ureg_DECL_system_value(ureg, TGSI_SEMANTIC_VERTEXID, 0);
+ struct ureg_dst temp = ureg_DECL_temporary(ureg);
+ struct ureg_dst pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+
+ vertex_id = ureg_scalar(vertex_id, TGSI_SWIZZLE_X);
+
+ /* We want:
+ * VertexID posX posY
+ * 0 -1 -1
+ * 1 1 -1
+ * 2 1 1
+ * 3 -1 1
+ *
+ * posX = (VertexID >> 1) ^ (VertexID & 1) ? 1 : -1;
+ * posY = VertexID >> 1 ? 1 : -1;
+ * posZ = 0;
+ * posW = 1;
+ */
+ ureg_USHR(ureg, ureg_writemask(temp, TGSI_WRITEMASK_Y),
+ vertex_id, ureg_imm1u(ureg, 1));
+ ureg_AND(ureg, ureg_writemask(temp, TGSI_WRITEMASK_X),
+ vertex_id, ureg_imm1u(ureg, 1));
+ ureg_XOR(ureg, ureg_writemask(temp, TGSI_WRITEMASK_X),
+ ureg_scalar(ureg_src(temp), TGSI_SWIZZLE_X),
+ ureg_scalar(ureg_src(temp), TGSI_SWIZZLE_Y));
+
+ ureg_UCMP(ureg, ureg_writemask(pos, TGSI_WRITEMASK_XY),
+ ureg_swizzle(ureg_src(temp),
+ TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y,
+ TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y),
+ ureg_imm1f(ureg, 1), ureg_imm1f(ureg, -1));
+ ureg_MOV(ureg, ureg_writemask(pos, TGSI_WRITEMASK_ZW),
+ ureg_imm4f(ureg, 0, 0, 0, 1));
+ }
+
ureg_END( ureg );
return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
}
-void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe)
+void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe,
+ bool has_position_input)
{
const unsigned semantic_names[] = {TGSI_SEMANTIC_POSITION,
TGSI_SEMANTIC_GENERIC};
const unsigned semantic_indices[] = {0, 0};
+ unsigned offset = has_position_input ? 0 : 1;
- return util_make_vertex_passthrough_shader_with_so(pipe, 2, semantic_names,
- semantic_indices, false,
- true, NULL);
+ return util_make_vertex_passthrough_shader_with_so(pipe, 2 - offset,
+ semantic_names + offset,
+ semantic_indices + offset,
+ false, true, NULL);
}
/**
* Takes position and color, and outputs position, color, and instance id.
*/
void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe)
{
static const char text[] =
"VERT\n"
"DCL IN[0]\n"
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.h b/src/gallium/auxiliary/util/u_simple_shaders.h
index a281f57..bb2ad66 100644
--- a/src/gallium/auxiliary/util/u_simple_shaders.h
+++ b/src/gallium/auxiliary/util/u_simple_shaders.h
@@ -53,21 +53,22 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
extern void *
util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes,
bool window_space, bool layered,
const struct pipe_stream_output_info *so);
extern void *
-util_make_layered_clear_vertex_shader(struct pipe_context *pipe);
+util_make_layered_clear_vertex_shader(struct pipe_context *pipe,
+ bool has_position_input);
extern void *
util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe);
extern void *
util_make_layered_clear_geometry_shader(struct pipe_context *pipe);
extern void *
util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
unsigned tex_target,
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index cda9c71..5afc876 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -148,21 +148,21 @@ set_vertex_shader_layered(struct st_context *st)
if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_INSTANCEID)) {
assert(!"Got layered clear, but VS instancing is unsupported");
set_vertex_shader(st);
return;
}
if (!st->clear.vs_layered) {
bool vs_layer =
pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT);
if (vs_layer) {
- st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe);
+ st->clear.vs_layered = util_make_layered_clear_vertex_shader(pipe, true);
} else {
st->clear.vs_layered = util_make_layered_clear_helper_vertex_shader(pipe);
st->clear.gs_layered = util_make_layered_clear_geometry_shader(pipe);
}
}
cso_set_vertex_shader_handle(st->cso_context, st->clear.vs_layered);
cso_set_geometry_shader_handle(st->cso_context, st->clear.gs_layered);
}
--
2.7.4
More information about the mesa-dev
mailing list