forked from Mirrors/wine-wine
wined3d: Use new GenerateShader function for vertex shaders.
parent
36b0b9cc1c
commit
604579ed62
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue