wined3d: Reuse the shader buffer between shaders.

This commit is contained in:
Henri Verbeet 2009-07-09 09:56:07 +02:00 committed by Alexandre Julliard
parent def8d4f401
commit bddc4d3f0d
3 changed files with 65 additions and 62 deletions

View File

@ -138,15 +138,20 @@ const struct wined3d_shader_frontend *shader_select_frontend(DWORD version_token
}
}
void shader_buffer_init(struct SHADER_BUFFER *buffer)
void shader_buffer_clear(struct SHADER_BUFFER *buffer)
{
buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
buffer->buffer[0] = '\0';
buffer->bsize = 0;
buffer->lineNo = 0;
buffer->newline = TRUE;
}
void shader_buffer_init(struct SHADER_BUFFER *buffer)
{
buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
shader_buffer_clear(buffer);
}
void shader_buffer_free(struct SHADER_BUFFER *buffer)
{
HeapFree(GetProcessHeap(), 0, buffer->buffer);

View File

@ -83,6 +83,7 @@ struct constant_heap
/* GLSL shader private data */
struct shader_glsl_priv {
struct SHADER_BUFFER shader_buffer;
struct wine_rb_tree program_lookup;
struct glsl_shader_prog_link *glsl_program;
struct constant_heap vconst_heap;
@ -3504,8 +3505,8 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, const WineD3D_GL_Info *gl_in
}
/* GL locking is done by the caller */
static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexshader,
IWineD3DPixelShader *pixelshader, const WineD3D_GL_Info *gl_info)
static GLhandleARB generate_param_reorder_function(struct SHADER_BUFFER *buffer,
IWineD3DVertexShader *vertexshader, IWineD3DPixelShader *pixelshader, const WineD3D_GL_Info *gl_info)
{
GLhandleARB ret = 0;
IWineD3DVertexShaderImpl *vs = (IWineD3DVertexShaderImpl *) vertexshader;
@ -3514,15 +3515,14 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
DWORD vs_major = vs->baseShader.reg_maps.shader_version.major;
DWORD ps_major = ps ? ps->baseShader.reg_maps.shader_version.major : 0;
unsigned int i;
SHADER_BUFFER buffer;
const char *semantic_name;
UINT semantic_idx;
char reg_mask[6];
const struct wined3d_shader_signature_element *output_signature;
shader_buffer_init(&buffer);
shader_buffer_clear(buffer);
shader_addline(&buffer, "#version 120\n");
shader_addline(buffer, "#version 120\n");
if(vs_major < 3 && ps_major < 3) {
/* That one is easy: The vertex shader writes to the builtin varyings, the pixel shader reads from them.
@ -3532,16 +3532,16 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
if (((GLINFO_LOCATION).quirks & WINED3D_QUIRK_SET_TEXCOORD_W)
&& ps_major == 0 && vs_major > 0 && !device->frag_pipe->ffp_proj_control)
{
shader_addline(&buffer, "void order_ps_input() {\n");
shader_addline(buffer, "void order_ps_input() {\n");
for(i = 0; i < min(8, MAX_REG_TEXCRD); i++) {
if(vs->baseShader.reg_maps.texcoord_mask[i] != 0 &&
vs->baseShader.reg_maps.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL) {
shader_addline(&buffer, "gl_TexCoord[%u].w = 1.0;\n", i);
shader_addline(buffer, "gl_TexCoord[%u].w = 1.0;\n", i);
}
}
shader_addline(&buffer, "}\n");
shader_addline(buffer, "}\n");
} else {
shader_addline(&buffer, "void order_ps_input() { /* do nothing */ }\n");
shader_addline(buffer, "void order_ps_input() { /* do nothing */ }\n");
}
} else if(ps_major < 3 && vs_major >= 3) {
WORD map = vs->baseShader.reg_maps.output_registers;
@ -3549,7 +3549,7 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
/* The vertex shader writes to its own varyings, the pixel shader needs them in the builtin ones */
output_signature = vs->output_signature;
shader_addline(&buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT);
shader_addline(buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT);
for (i = 0; map; map >>= 1, ++i)
{
DWORD write_mask;
@ -3564,13 +3564,13 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR))
{
if (semantic_idx == 0)
shader_addline(&buffer, "gl_FrontColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask);
shader_addline(buffer, "gl_FrontColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask);
else if (semantic_idx == 1)
shader_addline(&buffer, "gl_FrontSecondaryColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask);
shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT[%u]%s;\n", reg_mask, i, reg_mask);
}
else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION))
{
shader_addline(&buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask);
shader_addline(buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask);
}
else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD))
{
@ -3579,22 +3579,22 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
if (!((GLINFO_LOCATION).quirks & WINED3D_QUIRK_SET_TEXCOORD_W) || ps_major > 0)
write_mask |= WINED3DSP_WRITEMASK_3;
shader_addline(&buffer, "gl_TexCoord[%u]%s = OUT[%u]%s;\n",
shader_addline(buffer, "gl_TexCoord[%u]%s = OUT[%u]%s;\n",
semantic_idx, reg_mask, i, reg_mask);
if (!(write_mask & WINED3DSP_WRITEMASK_3))
shader_addline(&buffer, "gl_TexCoord[%u].w = 1.0;\n", semantic_idx);
shader_addline(buffer, "gl_TexCoord[%u].w = 1.0;\n", semantic_idx);
}
}
else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE))
{
shader_addline(&buffer, "gl_PointSize = OUT[%u].x;\n", i);
shader_addline(buffer, "gl_PointSize = OUT[%u].x;\n", i);
}
else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG))
{
shader_addline(&buffer, "gl_FogFragCoord = OUT[%u].%c;\n", i, reg_mask[1]);
shader_addline(buffer, "gl_FogFragCoord = OUT[%u].%c;\n", i, reg_mask[1]);
}
}
shader_addline(&buffer, "}\n");
shader_addline(buffer, "}\n");
} else if(ps_major >= 3 && vs_major >= 3) {
WORD map = vs->baseShader.reg_maps.output_registers;
@ -3602,8 +3602,8 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
output_signature = vs->output_signature;
/* This one is tricky: a 3.0 pixel shader reads from a 3.0 vertex shader */
shader_addline(&buffer, "varying vec4 IN[%u];\n", vec4_varyings(3, gl_info));
shader_addline(&buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT);
shader_addline(buffer, "varying vec4 IN[%u];\n", vec4_varyings(3, gl_info));
shader_addline(buffer, "void order_ps_input(in vec4 OUT[%u]) {\n", MAX_REG_OUTPUT);
/* First, sort out position and point size. Those are not passed to the pixel shader */
for (i = 0; map; map >>= 1, ++i)
@ -3615,41 +3615,40 @@ static GLhandleARB generate_param_reorder_function(IWineD3DVertexShader *vertexs
if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION))
{
shader_addline(&buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask);
shader_addline(buffer, "gl_Position%s = OUT[%u]%s;\n", reg_mask, i, reg_mask);
}
else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE))
{
shader_addline(&buffer, "gl_PointSize = OUT[%u].x;\n", i);
shader_addline(buffer, "gl_PointSize = OUT[%u].x;\n", i);
}
}
/* Then, fix the pixel shader input */
handle_ps3_input(&buffer, gl_info, ps->input_reg_map, ps->input_signature,
handle_ps3_input(buffer, gl_info, ps->input_reg_map, ps->input_signature,
&ps->baseShader.reg_maps, output_signature, &vs->baseShader.reg_maps);
shader_addline(&buffer, "}\n");
shader_addline(buffer, "}\n");
} else if(ps_major >= 3 && vs_major < 3) {
shader_addline(&buffer, "varying vec4 IN[%u];\n", vec4_varyings(3, gl_info));
shader_addline(&buffer, "void order_ps_input() {\n");
shader_addline(buffer, "varying vec4 IN[%u];\n", vec4_varyings(3, gl_info));
shader_addline(buffer, "void order_ps_input() {\n");
/* The vertex shader wrote to the builtin varyings. There is no need to figure out position and
* point size, but we depend on the optimizers kindness to find out that the pixel shader doesn't
* read gl_TexCoord and gl_ColorX, otherwise we'll run out of varyings
*/
handle_ps3_input(&buffer, gl_info, ps->input_reg_map, ps->input_signature,
handle_ps3_input(buffer, gl_info, ps->input_reg_map, ps->input_signature,
&ps->baseShader.reg_maps, NULL, NULL);
shader_addline(&buffer, "}\n");
shader_addline(buffer, "}\n");
} else {
ERR("Unexpected vertex and pixel shader version condition: vs: %d, ps: %d\n", vs_major, ps_major);
}
ret = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
checkGLcall("glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB)");
GL_EXTCALL(glShaderSourceARB(ret, 1, (const char**)&buffer.buffer, NULL));
checkGLcall("glShaderSourceARB(ret, 1, &buffer.buffer, NULL)");
GL_EXTCALL(glShaderSourceARB(ret, 1, (const char**)&buffer->buffer, NULL));
checkGLcall("glShaderSourceARB(ret, 1, &buffer->buffer, NULL)");
GL_EXTCALL(glCompileShaderARB(ret));
checkGLcall("glCompileShaderARB(ret)");
shader_buffer_free(&buffer);
return ret;
}
@ -3839,15 +3838,14 @@ static GLuint shader_glsl_generate_vshader(IWineD3DVertexShaderImpl *This,
return shader_obj;
}
static GLhandleARB find_glsl_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args,
const struct ps_np2fixup_info **np2fixup_info)
static GLhandleARB find_glsl_pshader(struct SHADER_BUFFER *buffer, IWineD3DPixelShaderImpl *shader,
const struct ps_compile_args *args, const struct ps_np2fixup_info **np2fixup_info)
{
UINT i;
DWORD new_size;
struct glsl_ps_compiled_shader *new_array;
struct glsl_pshader_private *shader_data;
struct ps_np2fixup_info *np2fixup = NULL;
SHADER_BUFFER buffer;
GLhandleARB ret;
if(!shader->backend_priv) {
@ -3894,9 +3892,8 @@ static GLhandleARB find_glsl_pshader(IWineD3DPixelShaderImpl *shader, const stru
pixelshader_update_samplers(&shader->baseShader.reg_maps,
((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
shader_buffer_init(&buffer);
ret = shader_glsl_generate_pshader(shader, &buffer, args, np2fixup);
shader_buffer_free(&buffer);
shader_buffer_clear(buffer);
ret = shader_glsl_generate_pshader(shader, buffer, args, np2fixup);
shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
*np2fixup_info = np2fixup;
@ -3909,13 +3906,13 @@ static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const str
return stored->fog_src == new->fog_src;
}
static GLhandleARB find_glsl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args)
static GLhandleARB find_glsl_vshader(struct SHADER_BUFFER *buffer, IWineD3DVertexShaderImpl *shader,
const struct vs_compile_args *args)
{
UINT i;
DWORD new_size;
struct glsl_vs_compiled_shader *new_array;
DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map;
SHADER_BUFFER buffer;
struct glsl_vshader_private *shader_data;
GLhandleARB ret;
@ -3957,9 +3954,8 @@ static GLhandleARB find_glsl_vshader(IWineD3DVertexShaderImpl *shader, const str
shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
shader_buffer_init(&buffer);
ret = shader_glsl_generate_vshader(shader, &buffer, args);
shader_buffer_free(&buffer);
shader_buffer_clear(buffer);
ret = shader_glsl_generate_vshader(shader, buffer, args);
shader_data->gl_shaders[shader_data->num_gl_shaders++].prgId = ret;
return ret;
@ -4020,11 +4016,12 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
/* Attach GLSL vshader */
if (vshader)
{
GLhandleARB vshader_id = find_glsl_vshader((IWineD3DVertexShaderImpl *)vshader, &vs_compile_args);
GLhandleARB vshader_id = find_glsl_vshader(&priv->shader_buffer, (IWineD3DVertexShaderImpl *)vshader,
&vs_compile_args);
WORD map = ((IWineD3DBaseShaderImpl *)vshader)->baseShader.reg_maps.input_registers;
char tmp_name[10];
reorder_shader_id = generate_param_reorder_function(vshader, pshader, gl_info);
reorder_shader_id = generate_param_reorder_function(&priv->shader_buffer, vshader, pshader, gl_info);
TRACE("Attaching GLSL shader object %u to program %u\n", reorder_shader_id, programId);
GL_EXTCALL(glAttachObjectARB(programId, reorder_shader_id));
checkGLcall("glAttachObjectARB");
@ -4061,8 +4058,8 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
/* Attach GLSL pshader */
if (pshader)
{
GLhandleARB pshader_id = find_glsl_pshader((IWineD3DPixelShaderImpl *)pshader, &ps_compile_args,
&entry->np2Fixup_info);
GLhandleARB pshader_id = find_glsl_pshader(&priv->shader_buffer, (IWineD3DPixelShaderImpl *)pshader,
&ps_compile_args, &entry->np2Fixup_info);
TRACE("Attaching GLSL shader object %u to program %u\n", pshader_id, programId);
GL_EXTCALL(glAttachObjectARB(programId, pshader_id));
checkGLcall("glAttachObjectARB");
@ -4459,45 +4456,45 @@ static HRESULT shader_glsl_alloc(IWineD3DDevice *iface) {
struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv));
SIZE_T stack_size = wined3d_log2i(max(GL_LIMITS(vshader_constantsF), GL_LIMITS(pshader_constantsF))) + 1;
shader_buffer_init(&priv->shader_buffer);
priv->stack = HeapAlloc(GetProcessHeap(), 0, stack_size * sizeof(*priv->stack));
if (!priv->stack)
{
ERR("Failed to allocate memory.\n");
HeapFree(GetProcessHeap(), 0, priv);
return E_OUTOFMEMORY;
goto fail;
}
if (!constant_heap_init(&priv->vconst_heap, GL_LIMITS(vshader_constantsF)))
{
ERR("Failed to initialize vertex shader constant heap\n");
HeapFree(GetProcessHeap(), 0, priv->stack);
HeapFree(GetProcessHeap(), 0, priv);
return E_OUTOFMEMORY;
goto fail;
}
if (!constant_heap_init(&priv->pconst_heap, GL_LIMITS(pshader_constantsF)))
{
ERR("Failed to initialize pixel shader constant heap\n");
constant_heap_free(&priv->vconst_heap);
HeapFree(GetProcessHeap(), 0, priv->stack);
HeapFree(GetProcessHeap(), 0, priv);
return E_OUTOFMEMORY;
goto fail;
}
if (wine_rb_init(&priv->program_lookup, &wined3d_glsl_program_rb_functions) == -1)
{
ERR("Failed to initialize rbtree.\n");
constant_heap_free(&priv->pconst_heap);
constant_heap_free(&priv->vconst_heap);
HeapFree(GetProcessHeap(), 0, priv->stack);
HeapFree(GetProcessHeap(), 0, priv);
return E_OUTOFMEMORY;
goto fail;
}
priv->next_constant_version = 1;
This->shader_priv = priv;
return WINED3D_OK;
fail:
constant_heap_free(&priv->pconst_heap);
constant_heap_free(&priv->vconst_heap);
HeapFree(GetProcessHeap(), 0, priv->stack);
shader_buffer_free(&priv->shader_buffer);
HeapFree(GetProcessHeap(), 0, priv);
return E_OUTOFMEMORY;
}
/* Context activation is done by the caller. */

View File

@ -2601,6 +2601,7 @@ typedef struct IWineD3DBaseShaderImpl {
IWineD3DBaseShaderClass baseShader;
} IWineD3DBaseShaderImpl;
void shader_buffer_clear(struct SHADER_BUFFER *buffer);
void shader_buffer_init(struct SHADER_BUFFER *buffer);
void shader_buffer_free(struct SHADER_BUFFER *buffer);
void shader_cleanup(IWineD3DBaseShader *iface);