Commit 8dcd5128 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

WineD3D: Put vertex shader duplication infrastructure in place.

parent ad880ba0
......@@ -510,7 +510,7 @@ static void vshader_program_add_param(const SHADER_OPCODE_ARG *arg, const DWORD
break;
case WINED3DSPR_INPUT:
if (This->swizzle_map & (1 << reg)) is_color = TRUE;
if (This->cur_args->swizzle_map & (1 << reg)) is_color = TRUE;
sprintf(tmpReg, "vertex.attrib[%u]", reg);
strcat(hwLine, tmpReg);
......@@ -1745,14 +1745,15 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (useVS) {
TRACE("Using vertex shader\n");
IWineD3DVertexShaderImpl_CompileShader(This->stateBlock->vertexShader);
struct vs_compile_args compile_args;
priv->current_vprogram_id = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId;
TRACE("Using vertex shader\n");
find_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args);
priv->current_vprogram_id = find_gl_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args);
/* Bind the vertex program */
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);");
/* Enable OpenGL vertex programs */
glEnable(GL_VERTEX_PROGRAM_ARB);
......@@ -1773,7 +1774,7 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
/* Bind the fragment program */
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);");
if(!priv->use_arbfp_fixed_func) {
/* Enable OpenGL fragment programs */
......@@ -1860,14 +1861,19 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) {
This->shader_array_size = 0;
} else {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
UINT i;
ENTER_GL();
GL_EXTCALL(glDeleteProgramsARB(1, &This->prgId));
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->prgId))");
((IWineD3DVertexShaderImpl *) This)->prgId = 0;
for(i = 0; i < This->num_gl_shaders; i++) {
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
}
LEAVE_GL();
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
This->gl_shaders = NULL;
This->num_gl_shaders = 0;
This->shader_array_size = 0;
}
baseShader->baseShader.is_compiled = FALSE;
}
static HRESULT shader_arb_alloc(IWineD3DDevice *iface) {
......@@ -2008,13 +2014,14 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUF
return retval;
}
static void shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer) {
static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer, const struct vs_compile_args *args) {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
const shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device;
const WineD3D_GL_Info *gl_info = &device->adapter->gl_info;
const local_constant *lconst;
GLuint ret;
/* Create the hw ARB shader */
shader_addline(buffer, "!!ARBvp1.0\n");
......@@ -2086,12 +2093,12 @@ static void shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFF
shader_addline(buffer, "END\n");
/* TODO: change to resource.glObjectHandle or something like that */
GL_EXTCALL(glGenProgramsARB(1, &This->prgId));
GL_EXTCALL(glGenProgramsARB(1, &ret));
TRACE("Creating a hw vertex shader, prg=%d\n", This->prgId);
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->prgId));
TRACE("Creating a hw vertex shader, prg=%d\n", ret);
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ret));
TRACE("Created hw vertex shader, prg=%d\n", This->prgId);
TRACE("Created hw vertex shader, prg=%d\n", ret);
/* Create the program and check for errors */
GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
buffer->bsize, buffer->buffer));
......@@ -2101,16 +2108,17 @@ static void shader_arb_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFF
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->prgId = -1;
}
/* Load immediate constants */
if(!This->baseShader.load_local_constsF) {
LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
const float *value = (const float *)lconst->value;
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, lconst->idx, value));
ret = -1;
} else {
/* Load immediate constants */
if(!This->baseShader.load_local_constsF) {
LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
const float *value = (const float *)lconst->value;
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, lconst->idx, value));
}
}
}
return ret;
}
static void shader_arb_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)
......
......@@ -1133,8 +1133,9 @@ static GLuint shader_none_generate_pshader(IWineD3DPixelShader *iface, SHADER_BU
FIXME("NONE shader backend asked to generate a pixel shader\n");
return 0;
}
static void shader_none_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer) {
static GLuint shader_none_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer, const struct vs_compile_args *args) {
FIXME("NONE shader backend asked to generate a vertex shader\n");
return 0;
}
#define GLINFO_LOCATION (*gl_info)
......
......@@ -101,16 +101,18 @@ struct glsl_shader_prog_link {
GLhandleARB luminanceoffset_location[MAX_TEXTURES];
GLhandleARB ycorrection_location;
GLenum vertex_color_clamp;
GLhandleARB vshader;
IWineD3DVertexShader *vshader;
IWineD3DPixelShader *pshader;
struct vs_compile_args vs_args;
struct ps_compile_args ps_args;
UINT constant_version;
};
typedef struct {
GLhandleARB vshader;
IWineD3DVertexShader *vshader;
IWineD3DPixelShader *pshader;
struct ps_compile_args ps_args;
struct vs_compile_args vs_args;
} glsl_program_key_t;
......@@ -1030,7 +1032,7 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to
strcpy(tmpStr, "gl_SecondaryColor");
}
} else {
if (((IWineD3DVertexShaderImpl *)This)->swizzle_map & (1 << reg)) *is_color = TRUE;
if (((IWineD3DVertexShaderImpl *)This)->cur_args->swizzle_map & (1 << reg)) *is_color = TRUE;
sprintf(tmpStr, "attrib%u", reg);
}
break;
......@@ -2918,17 +2920,20 @@ static void add_glsl_program_entry(struct shader_glsl_priv *priv, struct glsl_sh
key = HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t));
key->vshader = entry->vshader;
key->pshader = entry->pshader;
key->vs_args = entry->vs_args;
key->ps_args = entry->ps_args;
hash_table_put(priv->glsl_program_lookup, key, entry);
}
static struct glsl_shader_prog_link *get_glsl_program_entry(struct shader_glsl_priv *priv,
GLhandleARB vshader, IWineD3DPixelShader *pshader, struct ps_compile_args *ps_args) {
IWineD3DVertexShader *vshader, IWineD3DPixelShader *pshader, struct vs_compile_args *vs_args,
struct ps_compile_args *ps_args) {
glsl_program_key_t key;
key.vshader = vshader;
key.pshader = pshader;
key.vs_args = *vs_args;
key.ps_args = *ps_args;
return hash_table_get(priv->glsl_program_lookup, &key);
......@@ -2942,6 +2947,7 @@ static void delete_glsl_program_entry(struct shader_glsl_priv *priv, const WineD
key = HeapAlloc(GetProcessHeap(), 0, sizeof(glsl_program_key_t));
key->vshader = entry->vshader;
key->pshader = entry->pshader;
key->vs_args = entry->vs_args;
key->ps_args = entry->ps_args;
hash_table_remove(priv->glsl_program_lookup, key);
......@@ -3293,21 +3299,22 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
int i;
char glsl_name[8];
GLhandleARB vshader_id, pshader_id;
struct ps_compile_args compile_args;
struct ps_compile_args ps_compile_args;
struct vs_compile_args vs_compile_args;
if(use_vs) {
IWineD3DVertexShaderImpl_CompileShader(vshader);
vshader_id = ((IWineD3DVertexShaderImpl*)vshader)->prgId;
find_vs_compile_args((IWineD3DVertexShaderImpl*)This->stateBlock->vertexShader, This->stateBlock, &vs_compile_args);
} else {
vshader_id = 0;
/* FIXME: Do we really have to spend CPU cycles to generate a few zeroed bytes? */
memset(&vs_compile_args, 0, sizeof(vs_compile_args));
}
if(use_ps) {
find_ps_compile_args((IWineD3DPixelShaderImpl*)This->stateBlock->pixelShader, This->stateBlock, &compile_args);
find_ps_compile_args((IWineD3DPixelShaderImpl*)This->stateBlock->pixelShader, This->stateBlock, &ps_compile_args);
} else {
/* FIXME: Do we really have to spend CPU cycles to generate a few zeroed bytes? */
memset(&compile_args, 0, sizeof(compile_args));
memset(&ps_compile_args, 0, sizeof(ps_compile_args));
}
entry = get_glsl_program_entry(priv, vshader_id, pshader, &compile_args);
entry = get_glsl_program_entry(priv, vshader, pshader, &vs_compile_args, &ps_compile_args);
if (entry) {
priv->glsl_program = entry;
return;
......@@ -3320,9 +3327,10 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
/* Create the entry */
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
entry->programId = programId;
entry->vshader = vshader_id;
entry->vshader = vshader;
entry->pshader = pshader;
entry->ps_args = compile_args;
entry->vs_args = vs_compile_args;
entry->ps_args = ps_compile_args;
entry->constant_version = 0;
/* Add the hash table entry */
add_glsl_program_entry(priv, entry);
......@@ -3330,6 +3338,12 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
/* Set the current program */
priv->glsl_program = entry;
if(use_vs) {
vshader_id = find_gl_vshader((IWineD3DVertexShaderImpl *) vshader, &vs_compile_args);
} else {
vshader_id = 0;
}
/* Attach GLSL vshader */
if (vshader_id) {
int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */
......@@ -3369,7 +3383,7 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
}
if(use_ps) {
pshader_id = find_gl_pshader((IWineD3DPixelShaderImpl *) pshader, &compile_args);
pshader_id = find_gl_pshader((IWineD3DPixelShaderImpl *) pshader, &ps_compile_args);
} else {
pshader_id = 0;
}
......@@ -3619,7 +3633,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) {
if(ps->num_gl_shaders == 0) return;
} else {
vs = (IWineD3DVertexShaderImpl *) This;
if(vs->prgId == 0) return;
if(vs->num_gl_shaders == 0) return;
}
linked_programs = &This->baseShader.linked_programs;
......@@ -3654,13 +3668,19 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) {
ps->num_gl_shaders = 0;
ps->shader_array_size = 0;
} else {
TRACE("Deleting shader object %u\n", vs->prgId);
UINT i;
ENTER_GL();
GL_EXTCALL(glDeleteObjectARB(vs->prgId));
checkGLcall("glDeleteObjectARB");
for(i = 0; i < vs->num_gl_shaders; i++) {
TRACE("deleting vshader %u\n", vs->gl_shaders[i].prgId);
GL_EXTCALL(glDeleteObjectARB(vs->gl_shaders[i].prgId));
checkGLcall("glDeleteObjectARB");
}
LEAVE_GL();
vs->prgId = 0;
vs->baseShader.is_compiled = FALSE;
HeapFree(GetProcessHeap(), 0, vs->gl_shaders);
vs->gl_shaders = NULL;
vs->num_gl_shaders = 0;
vs->shader_array_size = 0;
}
}
......@@ -3668,7 +3688,7 @@ static unsigned int glsl_program_key_hash(const void *key)
{
const glsl_program_key_t *k = key;
unsigned int hash = k->vshader | ((DWORD_PTR) k->pshader) << 16;
unsigned int hash = ((DWORD_PTR) k->vshader) | ((DWORD_PTR) k->pshader) << 16;
hash += ~(hash << 15);
hash ^= (hash >> 10);
hash += (hash << 3);
......@@ -3685,7 +3705,8 @@ static BOOL glsl_program_key_compare(const void *keya, const void *keyb)
const glsl_program_key_t *kb = keyb;
return ka->vshader == kb->vshader && ka->pshader == kb->pshader &&
(memcmp(&ka->ps_args, &kb->ps_args, sizeof(kb->ps_args)) == 0);
(memcmp(&ka->ps_args, &kb->ps_args, sizeof(kb->ps_args)) == 0) &&
(memcmp(&ka->vs_args, &kb->vs_args, sizeof(kb->vs_args)) == 0);
}
static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count)
......@@ -3870,7 +3891,7 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BU
return shader_obj;
}
static void shader_glsl_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer) {
static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer, const struct vs_compile_args *args) {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
......@@ -3920,8 +3941,7 @@ static void shader_glsl_generate_vshader(IWineD3DVertexShader *iface, SHADER_BUF
GL_EXTCALL(glCompileShaderARB(shader_obj));
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
/* Store the shader object */
This->prgId = shader_obj;
return shader_obj;
}
static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)
......
......@@ -216,21 +216,6 @@ BOOL vshader_get_input(
return FALSE;
}
/** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
or GLSL and send it to the card */
static void IWineD3DVertexShaderImpl_GenerateShader(IWineD3DVertexShader *iface,
const struct shader_reg_maps* reg_maps, const DWORD *pFunction)
{
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
SHADER_BUFFER buffer;
This->swizzle_map = ((IWineD3DDeviceImpl *)This->baseShader.device)->strided_streams.swizzle_map;
shader_buffer_init(&buffer);
((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_generate_vshader(iface, &buffer);
shader_buffer_free(&buffer);
}
/* *******************************************
IWineD3DVertexShader IUnknown parts follow
******************************************* */
......@@ -416,40 +401,20 @@ static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertex
return WINED3D_OK;
}
HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
CONST DWORD *function = This->baseShader.function;
static GLuint vertexshader_compile(IWineD3DVertexShaderImpl *This, const struct vs_compile_args *args) {
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
TRACE("(%p) : function %p\n", iface, function);
/* We're already compiled. */
if (This->baseShader.is_compiled) {
if ((This->swizzle_map & deviceImpl->strided_streams.use_map) != deviceImpl->strided_streams.swizzle_map)
{
WARN("Recompiling vertex shader %p due to D3DCOLOR input changes\n", This);
goto recompile;
}
return WINED3D_OK;
recompile:
if(This->recompile_count < 50) {
This->recompile_count++;
} else {
FIXME("Vertexshader %p recompiled more than 50 times\n", This);
}
deviceImpl->shader_backend->shader_destroy((IWineD3DBaseShader *) iface);
}
SHADER_BUFFER buffer;
GLuint ret;
/* Generate the HW shader */
TRACE("(%p) : Generating hardware program\n", This);
IWineD3DVertexShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function);
This->baseShader.is_compiled = TRUE;
shader_buffer_init(&buffer);
This->cur_args = args;
ret = deviceImpl->shader_backend->shader_generate_vshader((IWineD3DVertexShader *)This, &buffer, args);
This->cur_args = NULL;
shader_buffer_free(&buffer);
return WINED3D_OK;
return ret;
}
const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
......@@ -468,3 +433,56 @@ const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
IWineD3DVertexShaderImpl_FakeSemantics,
IWIneD3DVertexShaderImpl_SetLocalConstantsF
};
void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args) {
args->fog_src = stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ? VS_FOG_COORD : VS_FOG_Z;
args->swizzle_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.swizzle_map;
}
static inline BOOL vs_args_equal(const struct vs_compile_args *stored, const struct vs_compile_args *new,
const DWORD use_map) {
if((stored->swizzle_map & use_map) != new->swizzle_map) return FALSE;
return stored->fog_src == new->fog_src;
}
GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args)
{
UINT i;
DWORD new_size = shader->shader_array_size;
struct vs_compiled_shader *new_array;
DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map;
/* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
* so a linear search is more performant than a hashmap or a binary search
* (cache coherency etc)
*/
for(i = 0; i < shader->num_gl_shaders; i++) {
if(vs_args_equal(&shader->gl_shaders[i].args, args, use_map)) {
return shader->gl_shaders[i].prgId;
}
}
TRACE("No matching GL shader found, compiling a new shader\n");
if(shader->shader_array_size == shader->num_gl_shaders) {
if(shader->gl_shaders) {
new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2);
new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders,
new_size * sizeof(*shader->gl_shaders));
} else {
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
new_size = 1;
}
if(!new_array) {
ERR("Out of memory\n");
return 0;
}
shader->gl_shaders = new_array;
shader->shader_array_size = new_size;
}
shader->gl_shaders[shader->num_gl_shaders].args = *args;
shader->gl_shaders[shader->num_gl_shaders].prgId = vertexshader_compile(shader, args);
return shader->gl_shaders[shader->num_gl_shaders++].prgId;
}
......@@ -459,6 +459,18 @@ struct ps_compile_args {
/* Texture types(2D, Cube, 3D) in ps 1.x */
};
#define MAX_ATTRIBS 16
enum fog_src_type {
VS_FOG_Z = 0,
VS_FOG_COORD = 1
};
struct vs_compile_args {
WORD fog_src;
WORD swizzle_map; /* MAX_ATTRIBS, 16 */
};
typedef struct {
const SHADER_HANDLER *shader_instruction_handler_table;
void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL useVS);
......@@ -473,7 +485,7 @@ typedef struct {
void (*shader_free_private)(IWineD3DDevice *iface);
BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface);
GLuint (*shader_generate_pshader)(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer, const struct ps_compile_args *args);
void (*shader_generate_vshader)(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer);
GLuint (*shader_generate_vshader)(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer, const struct vs_compile_args *args);
void (*shader_get_caps)(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *caps);
BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup);
} shader_backend_t;
......@@ -2207,7 +2219,6 @@ typedef struct IWineD3DBaseShaderClass
CONST SHADER_OPCODE *shader_ins;
DWORD *function;
UINT functionLength;
BOOL is_compiled;
UINT cur_loop_depth, cur_loop_regno;
BOOL load_local_constsF;
BOOL uses_bool_consts, uses_int_consts;
......@@ -2323,8 +2334,14 @@ static inline BOOL shader_constant_is_local(IWineD3DBaseShaderImpl* This, DWORD
}
/*****************************************************************************
* IDirect3DVertexShader implementation structure
* IDirect3DVertexShader implementation structures
*/
struct vs_compiled_shader {
struct vs_compile_args args;
GLuint prgId;
};
typedef struct IWineD3DVertexShaderImpl {
/* IUnknown parts*/
const IWineD3DVertexShaderVtbl *lpVtbl;
......@@ -2338,22 +2355,25 @@ typedef struct IWineD3DVertexShaderImpl {
DWORD usage;
/* The GL shader */
GLuint prgId;
struct vs_compiled_shader *gl_shaders;
UINT num_gl_shaders, shader_array_size;
/* Vertex shader input and output semantics */
semantic semantics_in [MAX_ATTRIBS];
semantic semantics_out [MAX_REG_OUTPUT];
WORD swizzle_map; /* MAX_ATTRIBS, 16 */
UINT min_rel_offset, max_rel_offset;
UINT rel_offset;
UINT recompile_count;
const struct vs_compile_args *cur_args;
} IWineD3DVertexShaderImpl;
extern const SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[];
extern const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl;
HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface);
void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args);
GLuint find_gl_vshader(IWineD3DVertexShaderImpl *shader, const struct vs_compile_args *args);
/*****************************************************************************
* IDirect3DPixelShader implementation structure
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment