summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2011-02-23 18:45:04 +0000
committerBrian Paul <[email protected]>2011-09-23 07:58:44 -0600
commitfd69fc87444af8ead30b4af64598a98df7969397 (patch)
tree0458afbb167bcf780613e6da134fc5ecdb341117
parent157309348e3d9cc5c6bb81e68f13500e702d3a1e (diff)
svga: Coalesce multiple shader constants in a single command.
HWv8 feature. Tested with GoogleEarth, Mesa demos.
-rw-r--r--src/gallium/drivers/svga/svga_cmd.c53
-rw-r--r--src/gallium/drivers/svga/svga_cmd.h8
-rw-r--r--src/gallium/drivers/svga/svga_state_constants.c121
3 files changed, 178 insertions, 4 deletions
diff --git a/src/gallium/drivers/svga/svga_cmd.c b/src/gallium/drivers/svga/svga_cmd.c
index ebcd4bcaf10..d7611d4d042 100644
--- a/src/gallium/drivers/svga/svga_cmd.c
+++ b/src/gallium/drivers/svga/svga_cmd.c
@@ -758,6 +758,59 @@ SVGA3D_SetShaderConst(struct svga_winsys_context *swc,
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * SVGA3D_SetShaderConsts --
+ *
+ * Set the value of successive shader constants.
+ *
+ * Shader constants are analogous to uniform variables in GLSL,
+ * except that they belong to the render context rather than to
+ * an individual shader.
+ *
+ * Constants may have one of three types: A 4-vector of floats,
+ * a 4-vector of integers, or a single boolean flag.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+enum pipe_error
+SVGA3D_SetShaderConsts(struct svga_winsys_context *swc,
+ uint32 reg, // IN
+ uint32 numRegs, // IN
+ SVGA3dShaderType type, // IN
+ SVGA3dShaderConstType ctype, // IN
+ const void *values) // IN
+{
+ SVGA3dCmdSetShaderConst *cmd;
+
+ cmd = SVGA3D_FIFOReserve(swc,
+ SVGA_3D_CMD_SET_SHADER_CONST,
+ sizeof *cmd + (numRegs - 1) * sizeof cmd->values,
+ 0);
+ if(!cmd)
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ cmd->cid = swc->cid;
+ cmd->reg = reg;
+ cmd->type = type;
+ cmd->ctype = ctype;
+
+ memcpy(&cmd->values, values, numRegs * sizeof cmd->values);
+
+ swc->commit(swc);
+
+ return PIPE_OK;
+}
+
+
diff --git a/src/gallium/drivers/svga/svga_cmd.h b/src/gallium/drivers/svga/svga_cmd.h
index 223ab17df81..9bbe95f18b8 100644
--- a/src/gallium/drivers/svga/svga_cmd.h
+++ b/src/gallium/drivers/svga/svga_cmd.h
@@ -211,6 +211,14 @@ SVGA3D_SetShaderConst(struct svga_winsys_context *swc,
SVGA3dShaderConstType ctype, const void *value);
enum pipe_error
+SVGA3D_SetShaderConsts(struct svga_winsys_context *swc,
+ uint32 reg,
+ uint32 numRegs,
+ SVGA3dShaderType type,
+ SVGA3dShaderConstType ctype,
+ const void *values);
+
+enum pipe_error
SVGA3D_SetShader(struct svga_winsys_context *swc,
SVGA3dShaderType type, uint32 shid);
diff --git a/src/gallium/drivers/svga/svga_state_constants.c b/src/gallium/drivers/svga/svga_state_constants.c
index 6c3275e74c0..a28fcf91225 100644
--- a/src/gallium/drivers/svga/svga_state_constants.c
+++ b/src/gallium/drivers/svga/svga_state_constants.c
@@ -26,6 +26,7 @@
#include "util/u_inlines.h"
#include "pipe/p_defines.h"
+#include "svga_screen.h"
#include "svga_context.h"
#include "svga_state.h"
#include "svga_cmd.h"
@@ -34,6 +35,13 @@
#include "svga_hw_reg.h"
+
+/*
+ * Don't try to send more than 4k of successive constants.
+ */
+#define MAX_CONST_REG_COUNT 256 /* 4k */
+
+
/***********************************************************************
* Hardware update
*/
@@ -48,7 +56,9 @@ static int svga_shader_type( int shader )
return shader + 1;
}
-
+/*
+ * Check and emit one shader constant register.
+ */
static int emit_const( struct svga_context *svga,
int unit,
int i,
@@ -56,6 +66,8 @@ static int emit_const( struct svga_context *svga,
{
int ret = PIPE_OK;
+ assert(i < CB_MAX);
+
if (memcmp(svga->state.hw_draw.cb[unit][i], value, 4 * sizeof(float)) != 0) {
if (SVGA_DEBUG & DEBUG_CONSTS)
debug_printf("%s %s %d: %f %f %f %f\n",
@@ -81,10 +93,103 @@ static int emit_const( struct svga_context *svga,
return ret;
}
+/*
+ * Check and emit a range of shader constant registers, trying to coalesce
+ * successive shader constant updates in a single command in order to save
+ * space on the command buffer. This is a HWv8 feature.
+ */
+static enum pipe_error emit_const_range( struct svga_context *svga,
+ unsigned unit,
+ unsigned offset,
+ unsigned count,
+ const float (*values)[4] )
+{
+ unsigned i, j;
+ enum pipe_error ret;
+
+ assert(offset + count < CB_MAX);
+
+ i = 0;
+ while (i < count) {
+ if (memcmp(svga->state.hw_draw.cb[unit][offset + i],
+ values[i],
+ 4 * sizeof(float)) != 0) {
+
+ /*
+ * Found one dirty constant
+ */
+
+ if (SVGA_DEBUG & DEBUG_CONSTS)
+ debug_printf("%s %s %d: %f %f %f %f\n",
+ __FUNCTION__,
+ unit == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
+ offset + i,
+ values[i][0],
+ values[i][1],
+ values[i][2],
+ values[i][3]);
+
+ /*
+ * Look for more consecutive dirty constants.
+ */
+
+ j = i + 1;
+ while (j < count &&
+ j < i + MAX_CONST_REG_COUNT &&
+ memcmp(svga->state.hw_draw.cb[unit][offset + j],
+ values[j],
+ 4 * sizeof(float)) != 0) {
+
+ if (SVGA_DEBUG & DEBUG_CONSTS)
+ debug_printf("%s %s %d: %f %f %f %f\n",
+ __FUNCTION__,
+ unit == PIPE_SHADER_VERTEX ? "VERT" : "FRAG",
+ offset + j,
+ values[j][0],
+ values[j][1],
+ values[j][2],
+ values[j][3]);
+
+ ++j;
+ }
+
+ assert(j >= i + 1);
+
+ /*
+ * Send them all together.
+ */
+
+ ret = SVGA3D_SetShaderConsts(svga->swc,
+ offset + i, j - i,
+ svga_shader_type(unit),
+ SVGA3D_CONST_TYPE_FLOAT,
+ values + i);
+ if (ret != PIPE_OK) {
+ return ret;
+ }
+
+ /*
+ * Local copy of the hardware state.
+ */
+
+ memcpy(svga->state.hw_draw.cb[unit][offset + i],
+ values[i],
+ (j - i) * 4 * sizeof(float));
+
+ i = j + 1;
+ } else {
+ ++i;
+ }
+ }
+
+ return PIPE_OK;
+}
+
static int emit_consts( struct svga_context *svga,
int offset,
int unit )
{
+ struct svga_screen *ss = svga_screen(svga->pipe.screen);
struct pipe_transfer *transfer = NULL;
unsigned count;
const float (*data)[4] = NULL;
@@ -105,10 +210,18 @@ static int emit_consts( struct svga_context *svga,
goto done;
}
- for (i = 0; i < count; i++) {
- ret = emit_const( svga, unit, offset + i, data[i] );
- if (ret)
+ if (ss->hw_version >= SVGA3D_HWVERSION_WS8_B1) {
+ ret = emit_const_range( svga, unit, offset, count, data );
+ if (ret != PIPE_OK) {
goto done;
+ }
+ } else {
+ for (i = 0; i < count; i++) {
+ ret = emit_const( svga, unit, offset + i, data[i] );
+ if (ret != PIPE_OK) {
+ goto done;
+ }
+ }
}
done: