[WINED3D 3/3] Merge register counting pass for vertex/pixel shaders
Ivan Gyurdiev
ivg2 at cornell.edu
Fri Apr 28 04:23:52 CDT 2006
This patch merges the vertex first pass and the pixel first pass.
The pixel shader code was used, the vertex shader code was removed.
A check for NULL opcode (unhandled) was borrowed from the vertex
code,since this was bugzilla'd yesterday as causing crashes.
-------------- next part --------------
---
dlls/wined3d/baseshader.c | 81 +++++++++++++++++++++++++++
dlls/wined3d/pixelshader.c | 59 --------------------
dlls/wined3d/vertexshader.c | 120 ++++++----------------------------------
dlls/wined3d/wined3d_private.h | 6 ++
4 files changed, 105 insertions(+), 161 deletions(-)
28aba193fea01ffebacb377d64f3396223258cd4
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 7f34bfd..1691151 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -27,6 +27,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+inline static BOOL shader_is_version_token(DWORD token) {
+ return 0xFFFF0000 == (token & 0xFFFF0000) ||
+ 0xFFFE0000 == (token & 0xFFFF0000);
+}
+
+inline static BOOL shader_is_comment_token(DWORD token) {
+ return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
+}
+
int shader_addline(
SHADER_BUFFER* buffer,
const char *format, ...) {
@@ -78,4 +87,76 @@ const SHADER_OPCODE* shader_get_opcode(
return NULL;
}
+/* Note: For vertex shaders,
+ * texUsed = addrUsed, and
+ * D3DSPR_TEXTURE = D3DSPR_ADDR.
+ *
+ * Also note that this does not count the loop register
+ * as an address register. */
+
+void shader_get_registers_used(
+ IWineD3DBaseShader *iface,
+ CONST DWORD* pToken,
+ DWORD* tempsUsed,
+ DWORD* texUsed) {
+
+ if (pToken == NULL)
+ return;
+
+ *tempsUsed = 0;
+ *texUsed = 0;
+
+ while (D3DVS_END() != *pToken) {
+ CONST SHADER_OPCODE* curOpcode;
+
+ /* Skip version */
+ if (shader_is_version_token(*pToken)) {
+ ++pToken;
+ continue;
+
+ /* Skip comments */
+ } else if (shader_is_comment_token(*pToken)) {
+ DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
+ ++pToken;
+ pToken += comment_len;
+ continue;
+ }
+
+ /* Fetch opcode */
+ curOpcode = shader_get_opcode(iface, *pToken);
+ ++pToken;
+
+ /* Unhandled opcode, and its parameters */
+ if (NULL == curOpcode) {
+ while (*pToken & 0x80000000)
+ ++pToken;
+ continue;
+
+ /* Skip declarations (for now) */
+ } else if (D3DSIO_DCL == curOpcode->opcode) {
+ pToken += curOpcode->num_params;
+ continue;
+
+ /* Skip definitions (for now) */
+ } else if (D3DSIO_DEF == curOpcode->opcode) {
+ pToken += curOpcode->num_params;
+ continue;
+
+ /* Set texture registers, and temporary registers */
+ } else {
+ int i;
+
+ for (i = 0; i < curOpcode->num_params; ++i) {
+ DWORD regtype = (((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+ DWORD reg = (*pToken) & D3DSP_REGNUM_MASK;
+ if (D3DSPR_TEXTURE == regtype)
+ *texUsed |= (1 << reg);
+ if (D3DSPR_TEMP == regtype)
+ *tempsUsed |= (1 << reg);
+ ++pToken;
+ }
+ }
+ }
+}
+
/* TODO: Move other shared code here */
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index d097242..fe69949 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -899,63 +899,6 @@ inline static int gen_input_modifier_lin
return insert_line;
}
-inline static void pshader_program_get_registers_used(
- IWineD3DPixelShaderImpl *This,
- CONST DWORD* pToken, DWORD* tempsUsed, DWORD* texUsed) {
-
- if (pToken == NULL)
- return;
-
- *tempsUsed = 0;
- *texUsed = 0;
-
- while (D3DVS_END() != *pToken) {
- CONST SHADER_OPCODE* curOpcode;
-
- /* Skip version */
- if (pshader_is_version_token(*pToken)) {
- ++pToken;
- continue;
-
- /* Skip comments */
- } else if (pshader_is_comment_token(*pToken)) {
- DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
- ++pToken;
- pToken += comment_len;
- continue;
- }
-
- /* Fetch opcode */
- curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
- ++pToken;
-
- /* Skip declarations (for now) */
- if (D3DSIO_DCL == curOpcode->opcode) {
- pToken += curOpcode->num_params;
- continue;
-
- /* Skip definitions (for now) */
- } else if (D3DSIO_DEF == curOpcode->opcode) {
- pToken += curOpcode->num_params;
- continue;
-
- /* Set texture registers, and temporary registers */
- } else {
- int i;
-
- for (i = 0; i < curOpcode->num_params; ++i) {
- DWORD regtype = shader_get_regtype(*pToken);
- DWORD reg = (*pToken) & D3DSP_REGNUM_MASK;
- if (D3DSPR_TEXTURE == regtype)
- *texUsed |= (1 << reg);
- if (D3DSPR_TEMP == regtype)
- *tempsUsed |= (1 << reg);
- ++pToken;
- }
- }
- }
-}
-
void pshader_set_version(
IWineD3DPixelShaderImpl *This,
DWORD version) {
@@ -1055,7 +998,7 @@ inline static VOID IWineD3DPixelShaderIm
This->constants[i] = 0;
/* First pass: figure out which temporary and texture registers are used */
- pshader_program_get_registers_used(This, pToken, &tempsUsed, &texUsed);
+ shader_get_registers_used((IWineD3DBaseShader*) This, pToken, &tempsUsed, &texUsed);
TRACE("Texture registers used: %#lx, Temp registers used %#lx\n", texUsed, tempsUsed);
/* TODO: check register usage against GL/Directx limits, and fail if they're exceeded */
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 10fd07a..bdad583 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -1150,14 +1150,7 @@ inline static VOID IWineD3DVertexShaderI
DWORD i;
SHADER_BUFFER buffer;
char tmpLine[255];
- DWORD nUseAddressRegister = 0;
- DWORD nUseTempRegister = 0;
- DWORD regtype;
- DWORD reg;
- BOOL tmpsUsed[32];
-#if 0 /* TODO: loope register (just another address register ) */
- BOOL hasLoops = FALSE;
-#endif
+ DWORD addressUsed, tempsUsed;
#if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
@@ -1173,87 +1166,11 @@ inline static VOID IWineD3DVertexShaderI
buffer.bsize = 0;
buffer.lineNo = 0;
- /* set all the tmpsUsed to not used */
- memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
-
- /* TODO: renumbering of attributes if the values are higher than the highest supported attribute but the total number of attributes is less than the highest supported attribute */
- This->highestConstant = -1;
-
- /**
- * First pass to determine what we need to declare:
- * - Temporary variables
- * - Address variables
- */
- if (NULL != pToken) {
- while (D3DVS_END() != *pToken) {
- if (vshader_is_version_token(*pToken)) {
- /** skip version */
- ++pToken;
- continue;
- }
- if (vshader_is_comment_token(*pToken)) { /** comment */
- DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
- ++pToken;
- pToken += comment_len;
- continue;
- }
- curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
- ++pToken;
- /* TODO: dcl's */
- /* TODO: Consts */
-
- if (NULL == curOpcode) {
- while (*pToken & 0x80000000) {
- FIXME("unrecognized opcode: %08lx\n", *pToken);
- /* skip unrecognized opcode */
- ++pToken;
- }
- } else {
-
- /* Skip declarations, handled earlier */
- if (curOpcode->opcode == D3DSIO_DCL){
- pToken += 2;
-
- /* Skip definition of immediate constants, handled later */
- } else if(curOpcode->opcode == D3DSIO_DEF) {
- pToken += 5;
-
- } else {
- /* Check to see if and tmp or addressing redisters are used */
- if (curOpcode->num_params > 0) {
- regtype = shader_get_regtype(*pToken);
- reg = ((*pToken) & D3DSP_REGNUM_MASK);
- if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
- if (D3DSPR_TEMP == regtype){
- tmpsUsed[reg] = TRUE;
- if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
- }
- ++pToken;
- for (i = 1; i < curOpcode->num_params; ++i) {
- regtype = shader_get_regtype(*pToken);
- reg = ((*pToken) & D3DSP_REGNUM_MASK);
- if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
- if (D3DSPR_TEMP == regtype){
- tmpsUsed[reg] = TRUE;
- if(nUseTempRegister <= reg) nUseTempRegister = reg + 1;
- }
- ++pToken;
- }
- }
- }
-#if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
- if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
- FIXME("This shader requires gl shader language support\n");
-#if 0
- This->shaderLanguage = GLSHADER_GLSL;
-#endif
- }
-#endif
- }
- }
- }
+ /* First pass: figure out which temporary and texture registers are used */
+ shader_get_registers_used((IWineD3DBaseShader*) This, pToken, &tempsUsed, &addressUsed);
+ TRACE("Address registers used: %#lx, Temp registers used %#lx\n", addressUsed, tempsUsed);
- /* TODO: validate
+ /* TODO: check register usage against GL/Directx limits, and fail if they're exceeded
nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
nUseTempRegister <= GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
*/
@@ -1266,17 +1183,18 @@ inline static VOID IWineD3DVertexShaderI
/* FIXME: if jumps are used, use GLSL, else use ARB_vertex_program */
shader_addline(&buffer, "!!ARBvp1.0\n");
- /* Declare necessary things.
- * FIXME: replace with a bitmap
- * FIXME: loop counts as an address register */
-
- for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
- if (tmpsUsed[i])
- shader_addline(&buffer, "TEMP T%ld;\n", i);
+ /* Pre-declare registers */
+ for (i = 0; i < This->baseShader.limits.temporary; i++) {
+ if (tempsUsed & (1 << i))
+ shader_addline(&buffer, "TEMP T%lu;\n", i);
+ }
+
+ for (i = 0; i < This->baseShader.limits.address; i++) {
+ if (addressUsed & (1 << i))
+ shader_addline(&buffer, "ADDRESS A%ld;\n", i);
}
- for (i = 0; i < nUseAddressRegister; i++)
- shader_addline(&buffer, "ADDRESS A%ld;\n", i);
+ /* Why do we need to alias those? */
shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
This->baseShader.limits.constant_float,
This->baseShader.limits.constant_float - 1);
@@ -1426,12 +1344,8 @@ inline static VOID IWineD3DVertexShaderI
case D3DSIO_MOV:
/* Address registers must be loaded with the ARL instruction */
if (shader_get_regtype(*pToken) == D3DSPR_ADDR) {
- if (((*pToken) & D3DSP_REGNUM_MASK) < nUseAddressRegister) {
- strcpy(tmpLine, "ARL");
- break;
- } else
- FIXME("(%p) Try to load A%ld an undeclared address register!\n",
- This, ((*pToken) & D3DSP_REGNUM_MASK));
+ strcpy(tmpLine, "ARL");
+ break;
}
/* fall through */
case D3DSIO_ADD:
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0be6398..c5a1e80 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1216,6 +1216,12 @@ extern const SHADER_OPCODE* shader_get_o
IWineD3DBaseShader *iface,
const DWORD code);
+extern void shader_get_registers_used(
+ IWineD3DBaseShader *iface,
+ CONST DWORD* pToken,
+ DWORD* tempsUsed,
+ DWORD* texUsed);
+
inline static int shader_get_regtype(const DWORD param) {
return (((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) |
((param & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2));
--
1.2.6
More information about the wine-patches
mailing list