WineD3D: Put vertex shader duplication infrastructure in place.
This commit is contained in:
parent
ad880ba057
commit
8dcd51286d
|
@ -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;
|
||||
} else {
|
||||
vshader_id = 0;
|
||||
}
|
||||
if(use_ps) {
|
||||
find_ps_compile_args((IWineD3DPixelShaderImpl*)This->stateBlock->pixelShader, This->stateBlock, &compile_args);
|
||||
find_vs_compile_args((IWineD3DVertexShaderImpl*)This->stateBlock->vertexShader, This->stateBlock, &vs_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(&vs_compile_args, 0, sizeof(vs_compile_args));
|
||||
}
|
||||
entry = get_glsl_program_entry(priv, vshader_id, pshader, &compile_args);
|
||||
if(use_ps) {
|
||||
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(&ps_compile_args, 0, sizeof(ps_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);
|
||||
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);
|
||||
|
||||
This->baseShader.is_compiled = TRUE;
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue