Ivan Gyurdiev : wined3d: Support more than 4/6 tex/temp registers.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Apr 19 13:15:14 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 70fc78b64e6f06cbdd8e271517a6693c641fa51e
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=70fc78b64e6f06cbdd8e271517a6693c641fa51e
Author: Ivan Gyurdiev <ivg2 at cornell.edu>
Date: Wed Apr 19 10:17:24 2006 -0400
wined3d: Support more than 4/6 tex/temp registers.
---
dlls/wined3d/pixelshader.c | 104 +++++++++++++++++++++++++++++++++++++++-----
1 files changed, 92 insertions(+), 12 deletions(-)
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index c7c9884..c2b37e2 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -955,6 +955,64 @@ 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 = pshader_program_get_opcode(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 = (((*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;
+ }
+ }
+ }
+}
+
/* NOTE: A description of how to parse tokens can be found at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/graphics/hh/graphics/usermodedisplaydriver_shader_cc8e4e05-f5c3-4ec0-8853-8ce07c1551b2.xml.asp */
inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelShader *iface, CONST DWORD *pFunction) {
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
@@ -977,6 +1035,9 @@ #endif
/* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
unsigned int pgmLength = 0;
+ /* Keep bitmaps of used temporary and texture registers */
+ DWORD tempsUsed, texUsed;
+
#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... */
if (This->device->fixupVertexBufferSize < PGMSIZE) {
@@ -990,11 +1051,17 @@ #else
pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PGMSIZE); /* 64kb should be enough */
#endif
-
/* TODO: Think about using a first pass to work out what's required for the second pass. */
for(i = 0; i < WINED3D_PSHADER_MAX_CONSTANTS; i++)
This->constants[i] = 0;
+ /* First pass: figure out which temporary and texture registers are used */
+ pshader_program_get_registers_used(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 */
+
+ /* Second pass, process opcodes */
if (NULL != pToken) {
while (D3DPS_END() != *pToken) {
#if 0 /* For pixel and vertex shader versions 2_0 and later, bits 24 through 27 specify the size in DWORDs of the instruction */
@@ -1005,6 +1072,7 @@ #endif
if (pshader_is_version_token(*pToken)) { /** version */
int numTemps;
int numConstants;
+ int numTex;
/* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */
version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F);
@@ -1016,21 +1084,28 @@ #endif
case 10:
case 11:
case 12:
- case 13:
+ case 13:numTemps=12;
+ numConstants=8;
+ numTex=4;
+ break;
case 14: numTemps=12;
numConstants=8;
+ numTex=6;
break;
case 20: numTemps=12;
numConstants=8;
+ numTex=8;
FIXME("No work done yet to support ps2.0 in hw\n");
break;
case 30: numTemps=32;
numConstants=8;
+ numTex=0;
FIXME("No work done yet to support ps3.0 in hw\n");
break;
default:
numTemps=12;
numConstants=8;
+ numTex=8;
FIXME("Unrecognized pixel shader version!\n");
}
@@ -1038,15 +1113,18 @@ #endif
strcpy(tmpLine, "!!ARBfp1.0\n");
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
- /* TODO: find out how many registers are really needed */
- for(i = 0; i < 6; i++) {
- sprintf(tmpLine, "TEMP T%lu;\n", i);
- addline(&lineNum, pgmStr, &pgmLength, tmpLine);
+ for(i = 0; i < numTex; i++) {
+ if (texUsed & (1 << i)) {
+ sprintf(tmpLine, "TEMP T%lu;\n", i);
+ addline(&lineNum, pgmStr, &pgmLength, tmpLine);
+ }
}
- for(i = 0; i < 6; i++) {
- sprintf(tmpLine, "TEMP R%lu;\n", i);
- addline(&lineNum, pgmStr, &pgmLength, tmpLine);
+ for(i = 0; i < numTemps; i++) {
+ if (tempsUsed & (1 << i)) {
+ sprintf(tmpLine, "TEMP R%lu;\n", i);
+ addline(&lineNum, pgmStr, &pgmLength, tmpLine);
+ }
}
sprintf(tmpLine, "TEMP TMP;\n");
@@ -1067,9 +1145,11 @@ #endif
strcpy(tmpLine, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
- for(i = 0; i < 4; i++) {
- sprintf(tmpLine, "MOV T%lu, fragment.texcoord[%lu];\n", i, i);
- addline(&lineNum, pgmStr, &pgmLength, tmpLine);
+ for(i = 0; i < numTex; i++) {
+ if (texUsed & (1 << i)) {
+ sprintf(tmpLine, "MOV T%lu, fragment.texcoord[%lu];\n", i, i);
+ addline(&lineNum, pgmStr, &pgmLength, tmpLine);
+ }
}
++pToken;
More information about the wine-cvs
mailing list