wined3d: Use new GenerateShader function for vertex shaders.

oldstable
Jason Green 2006-05-09 22:38:33 -04:00 committed by Alexandre Julliard
parent 36b0b9cc1c
commit 604579ed62
1 changed files with 1 additions and 167 deletions

View File

@ -1195,172 +1195,6 @@ inline static VOID IWineD3DVertexShaderImpl_GenerateShader(
#endif
}
/**
* Function parser ...
*/
inline static VOID IWineD3DVertexShaderImpl_GenerateProgramArbHW(IWineD3DVertexShader *iface, CONST DWORD* pFunction) {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
const DWORD* pToken = pFunction;
const SHADER_OPCODE* curOpcode = NULL;
DWORD i;
SHADER_BUFFER buffer;
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... */
if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
HeapFree(GetProcessHeap(), 0, This->fixupVertexBuffer);
This->fixupVertexBuffer = HeapAlloc(GetProcessHeap() , 0, SHADER_PGMSIZE);
This->fixupVertexBufferSize = PGMSIZE;
This->fixupVertexBuffer[0] = 0;
}
buffer.buffer = This->device->fixupVertexBuffer;
#endif
buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE);
buffer.bsize = 0;
buffer.lineNo = 0;
/* First pass: figure out which temporary and texture registers are used */
shader_get_registers_used((IWineD3DBaseShader*) This, pToken);
addressUsed = This->baseShader.textures_used;
tempsUsed = This->baseShader.temps_used;
TRACE("Address registers used: %#lx, Temp registers used %#lx\n", addressUsed, tempsUsed);
/* 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
*/
/* Mesa supports only 95 constants */
if (GL_VEND(MESA) || GL_VEND(WINE))
This->baseShader.limits.constant_float =
min(95, This->baseShader.limits.constant_float);
/* FIXME: if jumps are used, use GLSL, else use ARB_vertex_program */
shader_addline(&buffer, "!!ARBvp1.0\n");
/* Pre-declare registers */
for (i = 0; i < This->baseShader.limits.temporary; i++) {
if (tempsUsed & (1 << i))
shader_addline(&buffer, "TEMP R%lu;\n", i);
}
for (i = 0; i < This->baseShader.limits.address; i++) {
if (addressUsed & (1 << 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);
/** second pass, now generate */
pToken = pFunction;
if (NULL != pToken) {
while (1) {
if (D3DVS_END() == *pToken)
break;
/* Skip version */
if (vshader_is_version_token(*pToken)) {
++pToken;
continue;
}
/* Skip comments */
if (vshader_is_comment_token(*pToken)) {
DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
++pToken;
TRACE("#%s\n", (char*)pToken);
pToken += comment_len;
continue;
}
/* Read opcode */
curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
++pToken;
/* Unknown opcode and its parameters */
if (NULL == curOpcode) {
while (*pToken & 0x80000000) {
FIXME("unrecognized opcode: %08lx\n", *pToken);
++pToken;
}
/* Unhandled opcode */
} else if (GLNAME_REQUIRE_GLSL == curOpcode->glname) {
FIXME("Token %s requires greater functionality than "
"Vertex_Program_ARB supports\n", curOpcode->name);
pToken += curOpcode->num_params;
/* If a generator function is set, use it */
} else if (curOpcode->hw_fct != NULL) {
SHADER_OPCODE_ARG hw_arg;
hw_arg.shader = (IWineD3DBaseShader*) This;
hw_arg.opcode = curOpcode;
hw_arg.buffer = &buffer;
if (curOpcode->num_params > 0) {
hw_arg.dst = *pToken;
/* FIXME: this does not account for relative address tokens */
for (i = 1; i < curOpcode->num_params; i++)
hw_arg.src[i-1] = *(pToken + i);
}
curOpcode->hw_fct(&hw_arg);
pToken += curOpcode->num_params;
/* Unrecognized or No-Op code */
} else {
switch (curOpcode->opcode) {
case D3DSIO_NOP:
break;
default:
FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
pToken += curOpcode->num_params;
}
}
}
shader_addline(&buffer, "END\n");
}
/* finally null terminate the buffer */
buffer.buffer[buffer.bsize] = 0;
/* Check that Vertex Shaders are supported */
if (GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
/* Create the hw shader */
/* TODO: change to resource.glObjectHandel or something like that */
GL_EXTCALL(glGenProgramsARB(1, &This->baseShader.prgId));
TRACE("Creating a hw vertex shader, prg=%d\n", This->baseShader.prgId);
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,
buffer.bsize, buffer.buffer));
if (glGetError() == GL_INVALID_OPERATION) {
GLint errPos;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
FIXME("HW VertexShader Error at position %d: %s\n",
errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
This->baseShader.prgId = -1;
}
}
#if 1 /* if were using the data buffer of device then we don't need to free it */
HeapFree(GetProcessHeap(), 0, buffer.buffer);
#endif
}
BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) {
/**
* TODO: use the NV_vertex_program (or 1_1) extension
@ -1864,7 +1698,7 @@ HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface,
/* Generate HW shader in needed */
if (NULL != pFunction && wined3d_settings.vs_mode == VS_HW) {
#if 1
IWineD3DVertexShaderImpl_GenerateProgramArbHW(iface, pFunction);
IWineD3DVertexShaderImpl_GenerateShader(iface, pFunction);
#endif
}