wined3d: Addline cleanup.
This commit is contained in:
parent
da1d724c40
commit
5f10560762
|
@ -9,6 +9,7 @@ EXTRAINCL = @X_CFLAGS@
|
|||
EXTRALIBS = -luuid @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@ @OPENGL_LIBS@
|
||||
|
||||
C_SRCS = \
|
||||
baseshader.c \
|
||||
basetexture.c \
|
||||
cubetexture.c \
|
||||
device.c \
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* shaders implementation
|
||||
*
|
||||
* Copyright 2002-2003 Jason Edmeades
|
||||
* Copyright 2002-2003 Raphael Junqueira
|
||||
* Copyright 2005 Oliver Stieber
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "wined3d_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
|
||||
|
||||
int shader_addline(
|
||||
SHADER_BUFFER* buffer,
|
||||
const char *format, ...) {
|
||||
|
||||
char* base = buffer->buffer + buffer->bsize;
|
||||
int rc;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
rc = vsnprintf(base, SHADER_PGMSIZE - 1 - buffer->bsize, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (rc < 0 || /* C89 */
|
||||
rc > SHADER_PGMSIZE - 1 - buffer->bsize) { /* C99 */
|
||||
|
||||
ERR("The buffer allocated for the shader program string "
|
||||
"is too small at %d bytes.\n", SHADER_PGMSIZE);
|
||||
buffer->bsize = SHADER_PGMSIZE - 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer->bsize += rc;
|
||||
buffer->lineNo++;
|
||||
TRACE("GL HW (%u, %u) : %s", buffer->lineNo, buffer->bsize, base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Move other shared code here */
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* shaders implementation
|
||||
*
|
||||
* Copyright 2005 Oliver Stieber
|
||||
* Copyright 2002-2003 Jason Edmeades
|
||||
* Copyright 2002-2003 Raphael Junqueira
|
||||
* Copyright 2005 Oliver Stieber
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -37,9 +39,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
|
|||
# define TRACE_VSVECTOR(name)
|
||||
#endif
|
||||
|
||||
/* The maximum size of the program */
|
||||
#define PGMSIZE 65535
|
||||
|
||||
#define GLNAME_REQUIRE_GLSL ((const char *)1)
|
||||
/* *******************************************
|
||||
IWineD3DPixelShader IUnknown parts follow
|
||||
|
@ -827,20 +826,6 @@ inline static void get_input_register_swizzle(const DWORD instr, char *swzstring
|
|||
}
|
||||
}
|
||||
|
||||
inline static void addline(unsigned int *lineNum, char *pgm, unsigned int *pgmLength, char *line) {
|
||||
int lineLen = strlen(line);
|
||||
if(lineLen + *pgmLength > PGMSIZE - 1 /* - 1 to allow a NULL at the end */) {
|
||||
ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, lineLen + *pgmLength);
|
||||
return;
|
||||
} else {
|
||||
memcpy(pgm + *pgmLength, line, lineLen);
|
||||
}
|
||||
|
||||
*pgmLength += lineLen;
|
||||
++(*lineNum);
|
||||
TRACE("GL HW (%u, %u) : %s", *lineNum, *pgmLength, line);
|
||||
}
|
||||
|
||||
static const char* shift_tab[] = {
|
||||
"dummy", /* 0 (none) */
|
||||
"coefmul.x", /* 1 (x2) */
|
||||
|
@ -997,36 +982,34 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
const SHADER_OPCODE *curOpcode = NULL;
|
||||
const DWORD *pInstr;
|
||||
DWORD i;
|
||||
unsigned lineNum = 0; /* The line number of the generated program (for loging)*/
|
||||
char *pgmStr = NULL; /* A pointer to the program data generated by this function */
|
||||
char tmpLine[255];
|
||||
#if 0 /* TODO: loop register (just another address register ) */
|
||||
BOOL hasLoops = FALSE;
|
||||
#endif
|
||||
SHADER_BUFFER buffer;
|
||||
|
||||
BOOL saturate; /* clamp to 0.0 -> 1.0*/
|
||||
int row = 0; /* not sure, something to do with macros? */
|
||||
DWORD tcw[2];
|
||||
int version = 0; /* The version of the shader */
|
||||
|
||||
/* 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) {
|
||||
if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
|
||||
HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
|
||||
This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
|
||||
This->fixupVertexBufferSize = PGMSIZE;
|
||||
This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
|
||||
This->fixupVertexBufferSize = SHADER_PGMSIZE;
|
||||
This->fixupVertexBuffer[0] = 0;
|
||||
}
|
||||
pgmStr = This->device->fixupVertexBuffer;
|
||||
buffer.buffer = This->device->fixupVertexBuffer;
|
||||
#else
|
||||
pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, PGMSIZE); /* 64kb should be enough */
|
||||
buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
|
||||
#endif
|
||||
buffer.bsize = 0;
|
||||
buffer.lineNo = 0;
|
||||
|
||||
/* 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++)
|
||||
|
@ -1087,46 +1070,31 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
}
|
||||
|
||||
/* FIXME: if jumps are used, use GLSL, else use ARB_fragment_program */
|
||||
strcpy(tmpLine, "!!ARBfp1.0\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "!!ARBfp1.0\n");
|
||||
|
||||
for(i = 0; i < numTex; i++) {
|
||||
if (texUsed & (1 << i)) {
|
||||
sprintf(tmpLine, "TEMP T%lu;\n", i);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
}
|
||||
if (texUsed & (1 << i))
|
||||
shader_addline(&buffer,"TEMP T%lu;\n", i);
|
||||
}
|
||||
|
||||
for(i = 0; i < numTemps; i++) {
|
||||
if (tempsUsed & (1 << i)) {
|
||||
sprintf(tmpLine, "TEMP R%lu;\n", i);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
}
|
||||
if (tempsUsed & (1 << i))
|
||||
shader_addline(&buffer, "TEMP R%lu;\n", i);
|
||||
}
|
||||
|
||||
sprintf(tmpLine, "TEMP TMP;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "TEMP TMP2;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "TEMP TA;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "TEMP TB;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "TEMP TC;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "TEMP TMP;\n");
|
||||
shader_addline(&buffer, "TEMP TMP2;\n");
|
||||
shader_addline(&buffer, "TEMP TA;\n");
|
||||
shader_addline(&buffer, "TEMP TB;\n");
|
||||
shader_addline(&buffer, "TEMP TC;\n");
|
||||
|
||||
strcpy(tmpLine, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
strcpy(tmpLine, "PARAM coefmul = { 2, 4, 8, 16 };\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
strcpy(tmpLine, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
|
||||
shader_addline(&buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
|
||||
shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
|
||||
|
||||
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);
|
||||
}
|
||||
if (texUsed & (1 << i))
|
||||
shader_addline(&buffer, "MOV T%lu, fragment.texcoord[%lu];\n", i, i);
|
||||
}
|
||||
|
||||
++pToken;
|
||||
|
@ -1168,14 +1136,13 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
TRACE("Found opcode D3D:%s GL:%s, PARAMS:%d, \n",
|
||||
curOpcode->name, curOpcode->glname, curOpcode->num_params);
|
||||
|
||||
sprintf(tmpLine, "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
|
||||
shader_addline(&buffer,
|
||||
"PARAM C%lu = { %f, %f, %f, %f };\n", reg,
|
||||
*((const float *)(pToken + 1)),
|
||||
*((const float *)(pToken + 2)),
|
||||
*((const float *)(pToken + 3)),
|
||||
*((const float *)(pToken + 4)) );
|
||||
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
|
||||
This->constants[reg] = 1;
|
||||
pToken += 5;
|
||||
continue;
|
||||
|
@ -1244,7 +1211,7 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
|
||||
else if (version == 14) {
|
||||
if (gen_input_modifier_line(*pToken, 0, reg_coord, tmpLine, This->constants))
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, tmpLine);
|
||||
get_input_register_swizzle(*pToken, reg_coord_swz);
|
||||
pToken++;
|
||||
}
|
||||
|
@ -1268,9 +1235,8 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
pToken++;
|
||||
}
|
||||
|
||||
sprintf(tmpLine, "TEX %s, %s%s, texture[%lu], 2D;\n",
|
||||
shader_addline(&buffer, "TEX %s, %s%s, texture[%lu], 2D;\n",
|
||||
reg_dest, reg_coord, reg_coord_swz, reg_sampler_code);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
@ -1280,14 +1246,12 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
get_write_mask(*pToken, tmp);
|
||||
if (version != 14) {
|
||||
DWORD reg = *pToken & D3DSP_REGNUM_MASK;
|
||||
sprintf(tmpLine, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "MOV T%lu%s, fragment.texcoord[%lu];\n", reg, tmp, reg);
|
||||
++pToken;
|
||||
} else {
|
||||
DWORD reg1 = *pToken & D3DSP_REGNUM_MASK;
|
||||
DWORD reg2 = *++pToken & D3DSP_REGNUM_MASK;
|
||||
sprintf(tmpLine, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "MOV R%lu%s, fragment.texcoord[%lu];\n", reg1, tmp, reg2);
|
||||
++pToken;
|
||||
}
|
||||
continue;
|
||||
|
@ -1297,11 +1261,9 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
{
|
||||
DWORD reg = *pToken & D3DSP_REGNUM_MASK;
|
||||
char buf[50];
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
}
|
||||
sprintf(tmpLine, "DP3 TMP.x, T%lu, %s;\n", reg, buf);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants))
|
||||
shader_addline(&buffer, tmpLine);
|
||||
shader_addline(&buffer, "DP3 TMP.x, T%lu, %s;\n", reg, buf);
|
||||
++pToken;
|
||||
continue;
|
||||
}
|
||||
|
@ -1310,13 +1272,10 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
{
|
||||
DWORD reg = *pToken & D3DSP_REGNUM_MASK;
|
||||
char buf[50];
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
}
|
||||
sprintf(tmpLine, "DP3 TMP.y, T%lu, %s;\n", reg, buf);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants))
|
||||
shader_addline(&buffer, tmpLine);
|
||||
shader_addline(&buffer, "DP3 TMP.y, T%lu, %s;\n", reg, buf);
|
||||
shader_addline(&buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg, reg);
|
||||
++pToken;
|
||||
continue;
|
||||
}
|
||||
|
@ -1325,12 +1284,9 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
{
|
||||
DWORD reg1 = *pToken & D3DSP_REGNUM_MASK;
|
||||
DWORD reg2 = *++pToken & D3DSP_REGNUM_MASK;
|
||||
sprintf(tmpLine, "MOV TMP.r, T%lu.a;\n", reg2);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "MOV TMP.g, T%lu.r;\n", reg2);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "MOV TMP.r, T%lu.a;\n", reg2);
|
||||
shader_addline(&buffer, "MOV TMP.g, T%lu.r;\n", reg2);
|
||||
shader_addline(&buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
|
||||
++pToken;
|
||||
continue;
|
||||
}
|
||||
|
@ -1339,12 +1295,9 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
{
|
||||
DWORD reg1 = *pToken & D3DSP_REGNUM_MASK;
|
||||
DWORD reg2 = *++pToken & D3DSP_REGNUM_MASK;
|
||||
sprintf(tmpLine, "MOV TMP.r, T%lu.g;\n", reg2);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "MOV TMP.g, T%lu.b;\n", reg2);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "MOV TMP.r, T%lu.g;\n", reg2);
|
||||
shader_addline(&buffer, "MOV TMP.g, T%lu.b;\n", reg2);
|
||||
shader_addline(&buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
|
||||
++pToken;
|
||||
continue;
|
||||
}
|
||||
|
@ -1355,10 +1308,8 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
DWORD reg2 = *++pToken & D3DSP_REGNUM_MASK;
|
||||
|
||||
/* FIXME: Should apply the BUMPMAPENV matrix */
|
||||
sprintf(tmpLine, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "ADD TMP.rg, fragment.texcoord[%lu], T%lu;\n", reg1, reg2);
|
||||
shader_addline(&buffer, "TEX T%lu, TMP, texture[%lu], 2D;\n", reg1, reg1);
|
||||
++pToken;
|
||||
continue;
|
||||
}
|
||||
|
@ -1367,11 +1318,9 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
{
|
||||
DWORD reg = *pToken & D3DSP_REGNUM_MASK;
|
||||
char buf[50];
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
}
|
||||
sprintf(tmpLine, "DP3 TMP.%c, T%lu, %s;\n", 'x'+row, reg, buf);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants))
|
||||
shader_addline(&buffer, tmpLine);
|
||||
shader_addline(&buffer, "DP3 TMP.%c, T%lu, %s;\n", 'x'+row, reg, buf);
|
||||
tcw[row++] = reg;
|
||||
++pToken;
|
||||
continue;
|
||||
|
@ -1381,16 +1330,12 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
{
|
||||
DWORD reg = *pToken & D3DSP_REGNUM_MASK;
|
||||
char buf[50];
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
}
|
||||
|
||||
sprintf(tmpLine, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants))
|
||||
shader_addline(&buffer, tmpLine);
|
||||
shader_addline(&buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
|
||||
|
||||
/* Cubemap textures will be more used than 3D ones. */
|
||||
sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
|
||||
row = 0;
|
||||
++pToken;
|
||||
continue;
|
||||
|
@ -1399,31 +1344,22 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
{
|
||||
DWORD reg = *pToken & D3DSP_REGNUM_MASK;
|
||||
char buf[50];
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants)) {
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
}
|
||||
sprintf(tmpLine, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
if (gen_input_modifier_line(*++pToken, 0, buf, tmpLine, This->constants))
|
||||
shader_addline(&buffer, tmpLine);
|
||||
shader_addline(&buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
|
||||
|
||||
/* Construct the eye-ray vector from w coordinates */
|
||||
sprintf(tmpLine, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", tcw[0]);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", tcw[1]);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "MOV TMP2.x, fragment.texcoord[%lu].w;\n", tcw[0]);
|
||||
shader_addline(&buffer, "MOV TMP2.y, fragment.texcoord[%lu].w;\n", tcw[1]);
|
||||
shader_addline(&buffer, "MOV TMP2.z, fragment.texcoord[%lu].w;\n", reg);
|
||||
|
||||
/* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
|
||||
sprintf(tmpLine, "DP3 TMP.w, TMP, TMP2;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "MUL TMP, TMP.w, TMP;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "DP3 TMP.w, TMP, TMP2;\n");
|
||||
shader_addline(&buffer, "MUL TMP, TMP.w, TMP;\n");
|
||||
shader_addline(&buffer, "MAD TMP, coefmul.x, TMP, -TMP2;\n");
|
||||
|
||||
/* Cubemap textures will be more used than 3D ones. */
|
||||
sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
|
||||
row = 0;
|
||||
++pToken;
|
||||
continue;
|
||||
|
@ -1434,24 +1370,17 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
DWORD reg = *pToken & D3DSP_REGNUM_MASK;
|
||||
DWORD reg3 = *(pToken + 2) & D3DSP_REGNUM_MASK;
|
||||
char buf[50];
|
||||
if (gen_input_modifier_line(*(pToken + 1), 0, buf, tmpLine, This->constants)) {
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
}
|
||||
sprintf(tmpLine, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
if (gen_input_modifier_line(*(pToken + 1), 0, buf, tmpLine, This->constants))
|
||||
shader_addline(&buffer, tmpLine);
|
||||
shader_addline(&buffer, "DP3 TMP.z, T%lu, %s;\n", reg, buf);
|
||||
|
||||
/* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
|
||||
sprintf(tmpLine, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
|
||||
sprintf(tmpLine, "MUL TMP, TMP.w, TMP;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "DP3 TMP.w, TMP, C[%lu];\n", reg3);
|
||||
shader_addline(&buffer, "MUL TMP, TMP.w, TMP;\n");
|
||||
shader_addline(&buffer, "MAD TMP, coefmul.x, TMP, -C[%lu];\n", reg3);
|
||||
|
||||
/* Cubemap textures will be more used than 3D ones. */
|
||||
sprintf(tmpLine, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "TEX T%lu, TMP, texture[%lu], CUBE;\n", reg, reg);
|
||||
row = 0;
|
||||
pToken += 3;
|
||||
continue;
|
||||
|
@ -1494,7 +1423,7 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
for (i = 1; i < curOpcode->num_params; ++i) {
|
||||
TRACE("(%p) : Param %ld token %lx\n", This, i, *(pToken + i));
|
||||
if (gen_input_modifier_line(*(pToken + i), i - 1, regs[i - 1], tmpOp, This->constants)) {
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpOp);
|
||||
shader_addline(&buffer, tmpOp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1515,12 +1444,13 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
|
||||
switch(curOpcode->opcode) {
|
||||
case D3DSIO_CMP:
|
||||
sprintf(tmpLine, "CMP%s %s, %s, %s, %s;\n", (saturate ? "_SAT" : ""), operands[0], operands[1], operands[3], operands[2]);
|
||||
sprintf(tmpLine, "CMP%s %s, %s, %s, %s;\n", (saturate ? "_SAT" : ""),
|
||||
operands[0], operands[1], operands[3], operands[2]);
|
||||
break;
|
||||
case D3DSIO_CND:
|
||||
sprintf(tmpLine, "ADD TMP, -%s, coefdiv.x;", operands[1]);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
sprintf(tmpLine, "CMP%s %s, TMP, %s, %s;\n", (saturate ? "_SAT" : ""), operands[0], operands[2], operands[3]);
|
||||
shader_addline(&buffer, "ADD TMP, -%s, coefdiv.x;\n", operands[1]);
|
||||
sprintf(tmpLine, "CMP%s %s, TMP, %s, %s;\n", (saturate ? "_SAT" : ""),
|
||||
operands[0], operands[2], operands[3]);
|
||||
break;
|
||||
default:
|
||||
if (saturate && (shift == 0))
|
||||
|
@ -1533,34 +1463,31 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
}
|
||||
strcat(tmpLine,";\n");
|
||||
}
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, tmpLine);
|
||||
|
||||
/* A shift requires another line. */
|
||||
if (shift != 0) {
|
||||
gen_output_modifier_line(saturate, output_wmask, shift, output_rname, tmpLine);
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, tmpLine);
|
||||
}
|
||||
pToken += curOpcode->num_params;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* TODO: What about result.depth? */
|
||||
strcpy(tmpLine, "MOV result.color, R0;\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
|
||||
strcpy(tmpLine, "END\n");
|
||||
addline(&lineNum, pgmStr, &pgmLength, tmpLine);
|
||||
shader_addline(&buffer, "MOV result.color, R0;\n");
|
||||
shader_addline(&buffer, "END\n");
|
||||
}
|
||||
|
||||
/* finally null terminate the pgmStr*/
|
||||
pgmStr[pgmLength] = 0;
|
||||
/* finally null terminate the buffer */
|
||||
buffer.buffer[buffer.bsize] = 0;
|
||||
if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
|
||||
/* Create the hw shader */
|
||||
|
||||
/* pgmStr sometimes gets too long for a normal TRACE */
|
||||
/* The program string sometimes gets too long for a normal TRACE */
|
||||
TRACE("Generated program:\n");
|
||||
if (TRACE_ON(d3d_shader)) {
|
||||
fprintf(stderr, "%s\n", pgmStr);
|
||||
fprintf(stderr, "%s\n", buffer.buffer);
|
||||
}
|
||||
|
||||
/* TODO: change to resource.glObjectHandel or something like that */
|
||||
|
@ -1571,7 +1498,9 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
|
||||
TRACE("Created hw pixel shader, prg=%d\n", This->baseShader.prgId);
|
||||
/* Create the program and check for errors */
|
||||
GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr), pgmStr));
|
||||
GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
buffer.bsize, buffer.buffer));
|
||||
|
||||
if (glGetError() == GL_INVALID_OPERATION) {
|
||||
GLint errPos;
|
||||
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
|
||||
|
@ -1581,7 +1510,7 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateProgramArbHW(IWineD3DPixelSha
|
|||
}
|
||||
}
|
||||
#if 1 /* if were using the data buffer of device then we don't need to free it */
|
||||
HeapFree(GetProcessHeap(), 0, pgmStr);
|
||||
HeapFree(GetProcessHeap(), 0, buffer.buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1047,8 +1047,7 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexS
|
|||
const SHADER_OPCODE* curOpcode = NULL;
|
||||
int nRemInstr = -1;
|
||||
DWORD i;
|
||||
unsigned lineNum = 0;
|
||||
char *pgmStr = NULL;
|
||||
SHADER_BUFFER buffer;
|
||||
char tmpLine[255];
|
||||
DWORD nUseAddressRegister = 0;
|
||||
DWORD nUseTempRegister = 0;
|
||||
|
@ -1059,31 +1058,20 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexS
|
|||
BOOL hasLoops = FALSE;
|
||||
#endif
|
||||
|
||||
#define PGMSIZE 65535
|
||||
/* Keep a running length for pgmStr so that we don't have to caculate strlen every time we concatanate */
|
||||
int pgmLength = 0;
|
||||
|
||||
#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) {
|
||||
if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
|
||||
HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
|
||||
This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, PGMSIZE);
|
||||
This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
|
||||
This->fixupVertexBufferSize = PGMSIZE;
|
||||
This->fixupVertexBuffer[0] = 0;
|
||||
}
|
||||
pgmStr = This->device->fixupVertexBuffer;
|
||||
buffer.buffer = This->device->fixupVertexBuffer;
|
||||
#endif
|
||||
#define PNSTRCAT(_pgmStr, _tmpLine) { \
|
||||
int _tmpLineLen = strlen(_tmpLine); \
|
||||
if(_tmpLineLen + pgmLength > PGMSIZE) { \
|
||||
ERR("The buffer allocated for the vertex program string pgmStr is too small at %d bytes, at least %d bytes in total are required.\n", PGMSIZE, _tmpLineLen + pgmLength); \
|
||||
} else { \
|
||||
memcpy(_pgmStr + pgmLength, _tmpLine, _tmpLineLen); \
|
||||
} \
|
||||
pgmLength += _tmpLineLen; \
|
||||
}
|
||||
buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
|
||||
buffer.bsize = 0;
|
||||
buffer.lineNo = 0;
|
||||
|
||||
pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */
|
||||
/* Initialise the shader */
|
||||
This->namedArrays = FALSE;
|
||||
This->declaredArrays = FALSE;
|
||||
|
@ -1240,43 +1228,31 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexS
|
|||
|
||||
|
||||
/* FIXME: if jumps are used, use GLSL, else use ARB_vertex_program */
|
||||
strcpy(tmpLine, "!!ARBvp1.0\n");
|
||||
TRACE("GL HW (%u) : %s", pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
|
||||
PNSTRCAT(pgmStr, tmpLine);
|
||||
++lineNum;
|
||||
shader_addline(&buffer, "!!ARBvp1.0\n");
|
||||
|
||||
/* This should be a bitmap so that only temp registers that are used are declared. */
|
||||
for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
|
||||
if (tmpsUsed[i]) { /* only write out the temps if they are actually in use */
|
||||
sprintf(tmpLine, "TEMP T%ld;\n", i);
|
||||
++lineNum;
|
||||
TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
|
||||
PNSTRCAT(pgmStr, tmpLine);
|
||||
|
||||
}
|
||||
if (tmpsUsed[i])
|
||||
shader_addline(&buffer, "TEMP T%ld;\n", i);
|
||||
}
|
||||
/* TODO: loop register counts as an address register */
|
||||
for (i = 0; i < nUseAddressRegister; i++) {
|
||||
sprintf(tmpLine, "ADDRESS A%ld;\n", i);
|
||||
++lineNum;
|
||||
TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
|
||||
PNSTRCAT(pgmStr, tmpLine);
|
||||
|
||||
shader_addline(&buffer, "ADDRESS A%ld;\n", i);
|
||||
}
|
||||
|
||||
/* Due to the dynamic constants binding mechanism, we need to declare
|
||||
* all the constants for relative addressing. */
|
||||
/* Mesa supports only 95 constants for VS1.X although we should have at least 96. */
|
||||
if (GL_VEND(MESA) || GL_VEND(WINE)) {
|
||||
numConstants = 95;
|
||||
}
|
||||
/* FIXME: We should be counting the number of constants in the first pass and then validating that many are supported
|
||||
Looking at some of the shaders in use by applications we'd need to create a list of all used env variables
|
||||
*/
|
||||
sprintf(tmpLine, "PARAM C[%d] = { program.env[0..%d] };\n", numConstants, numConstants - 1);
|
||||
TRACE("GL HW (%u,%u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
|
||||
PNSTRCAT(pgmStr, tmpLine);
|
||||
|
||||
++lineNum;
|
||||
/* FIXME: We should be counting the number of constants in the first pass
|
||||
* and then validating that many are supported. Looking at some of the shaders in use
|
||||
* by applications we'd need to create a list of all used env variables
|
||||
*/
|
||||
shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
|
||||
numConstants, numConstants - 1);
|
||||
|
||||
++pToken;
|
||||
continue;
|
||||
|
@ -1308,21 +1284,12 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexS
|
|||
/* Handle definitions here, they don't fit well with the
|
||||
* other instructions below [for now ] */
|
||||
|
||||
char tmpChar[80];
|
||||
sprintf(tmpLine, "PARAM const%lu = {", *pToken & 0xFF);
|
||||
sprintf(tmpChar,"%f ,", *(float *) (pToken + 1));
|
||||
strcat(tmpLine, tmpChar);
|
||||
sprintf(tmpChar,"%f ,", *(float *) (pToken + 2));
|
||||
strcat(tmpLine, tmpChar);
|
||||
sprintf(tmpChar,"%f ,", *(float *) (pToken + 3));
|
||||
strcat(tmpLine, tmpChar);
|
||||
sprintf(tmpChar,"%f}", *(float *) (pToken + 4));
|
||||
strcat(tmpLine, tmpChar);
|
||||
|
||||
strcat(tmpLine,";\n");
|
||||
++lineNum;
|
||||
TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
|
||||
PNSTRCAT(pgmStr, tmpLine);
|
||||
shader_addline(&buffer,
|
||||
"PARAM const%lu = { %f, %f, %f, %f };\n", *pToken & 0xFF,
|
||||
*(float *) (pToken + 1),
|
||||
*(float *) (pToken + 2),
|
||||
*(float *) (pToken + 3),
|
||||
*(float *) (pToken + 4));
|
||||
|
||||
pToken += 5;
|
||||
continue;
|
||||
|
@ -1392,22 +1359,11 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexS
|
|||
FIXME("Unrecognised dcl %08lx", *pToken & 0xFFFF);
|
||||
}
|
||||
{
|
||||
char tmpChar[80];
|
||||
++pToken;
|
||||
sprintf(tmpLine, "ATTRIB ");
|
||||
vshader_program_add_param(This, *pToken, FALSE, tmpLine);
|
||||
|
||||
sprintf(tmpChar," = %s", attribName);
|
||||
strcat(tmpLine, tmpChar);
|
||||
strcat(tmpLine,";\n");
|
||||
++lineNum;
|
||||
if (This->namedArrays) {
|
||||
TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
|
||||
PNSTRCAT(pgmStr, tmpLine);
|
||||
|
||||
} else {
|
||||
TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine);
|
||||
}
|
||||
if (This->namedArrays)
|
||||
shader_addline(&buffer, "%s = %s;\n", tmpLine, attribName);
|
||||
}
|
||||
} else {
|
||||
/* eat the token so it doesn't generate a warning */
|
||||
|
@ -1489,21 +1445,14 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexS
|
|||
++pToken;
|
||||
}
|
||||
}
|
||||
strcat(tmpLine,";\n");
|
||||
++lineNum;
|
||||
TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
|
||||
PNSTRCAT(pgmStr, tmpLine);
|
||||
|
||||
shader_addline(&buffer, "%s;\n", tmpLine);
|
||||
}
|
||||
}
|
||||
strcpy(tmpLine, "END\n");
|
||||
++lineNum;
|
||||
TRACE("GL HW (%u, %u) : %s", lineNum, pgmLength, tmpLine); /* Don't add \n to this line as already in tmpLine */
|
||||
PNSTRCAT(pgmStr, tmpLine);
|
||||
|
||||
shader_addline(&buffer, "END\n");
|
||||
}
|
||||
/* finally null terminate the pgmStr*/
|
||||
pgmStr[pgmLength] = 0;
|
||||
|
||||
/* finally null terminate the buffer */
|
||||
buffer.buffer[buffer.bsize] = 0;
|
||||
|
||||
/* Check that Vertex Shaders are supported */
|
||||
if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
|
||||
|
@ -1514,7 +1463,9 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexS
|
|||
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->baseShader.prgId));
|
||||
|
||||
/* Create the program and check for errors */
|
||||
GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr)/*pgmLength*/, pgmStr));
|
||||
GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
buffer.bsize, buffer.buffer));
|
||||
|
||||
if (glGetError() == GL_INVALID_OPERATION) {
|
||||
GLint errPos;
|
||||
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
|
||||
|
@ -1524,9 +1475,8 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexS
|
|||
}
|
||||
}
|
||||
#if 1 /* if were using the data buffer of device then we don't need to free it */
|
||||
HeapFree(GetProcessHeap(), 0, pgmStr);
|
||||
HeapFree(GetProcessHeap(), 0, buffer.buffer);
|
||||
#endif
|
||||
#undef PNSTRCAT
|
||||
}
|
||||
|
||||
BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
|
||||
|
|
|
@ -1198,6 +1198,19 @@ typedef struct SHADER_OPCODE {
|
|||
DWORD max_version;
|
||||
} SHADER_OPCODE;
|
||||
|
||||
#define SHADER_PGMSIZE 65535
|
||||
typedef struct SHADER_BUFFER {
|
||||
char* buffer;
|
||||
size_t bsize;
|
||||
unsigned int lineNo;
|
||||
} SHADER_BUFFER;
|
||||
|
||||
/* Base Shader utility functions.
|
||||
* (may move callers into the same file in the future) */
|
||||
extern int shader_addline(
|
||||
SHADER_BUFFER* buffer,
|
||||
const char* fmt, ...);
|
||||
|
||||
/*****************************************************************************
|
||||
* IDirect3DBaseShader implementation structure
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue