Commit 8763f6ea authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Make find_gl_vshader backend specific.

parent 732a9a15
......@@ -1943,10 +1943,10 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol
shader_addline(buffer, "CMP result.color.xyz, %s, %s, %s;\n", tmp3, tmp2, tmp1);
}
static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
/* GL locking is done by the caller */
static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This,
SHADER_BUFFER *buffer, const struct ps_compile_args *args)
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
const shader_reg_maps* reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
......@@ -2057,10 +2057,9 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
}
/* GL locking is done by the caller */
static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This,
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;
......@@ -2086,7 +2085,7 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
if(need_helper_const(gl_info)) {
shader_addline(buffer, "PARAM helper_const = { 2.0, -1.0, %d.0, 0.0 };\n", This->rel_offset);
}
if(need_mova_const((IWineD3DBaseShader *) iface, gl_info)) {
if(need_mova_const((IWineD3DBaseShader *) This, gl_info)) {
shader_addline(buffer, "PARAM mova_const = { 0.5, 0.0, 2.0, 1.0 };\n");
shader_addline(buffer, "TEMP A0_SHADOW;\n");
}
......@@ -2245,12 +2244,68 @@ static GLuint find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_
shader_buffer_init(&buffer);
shader->gl_shaders[shader->num_gl_shaders].prgId =
shader_arb_generate_pshader((IWineD3DPixelShader *)shader, &buffer, args);
shader_arb_generate_pshader(shader, &buffer, args);
shader_buffer_free(&buffer);
return shader->gl_shaders[shader->num_gl_shaders++].prgId;
}
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;
}
static GLuint find_arb_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;
SHADER_BUFFER buffer;
GLuint ret;
/* 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->num_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_buffer_init(&buffer);
ret = shader_arb_generate_vshader(shader, &buffer, args);
shader_buffer_free(&buffer);
shader->gl_shaders[shader->num_gl_shaders++].prgId = ret;
return ret;
}
/* GL locking is done by the caller */
static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
......@@ -2262,7 +2317,7 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
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);
priv->current_vprogram_id = find_arb_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args);
/* Bind the vertex program */
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
......@@ -2589,7 +2644,6 @@ const shader_backend_t arb_program_shader_backend = {
shader_arb_alloc,
shader_arb_free,
shader_arb_dirty_const,
shader_arb_generate_vshader,
shader_arb_get_caps,
shader_arb_color_fixup_supported,
shader_arb_add_instruction_modifiers,
......
......@@ -1283,12 +1283,6 @@ static void shader_none_destroy(IWineD3DBaseShader *iface) {}
static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
static void shader_none_free(IWineD3DDevice *iface) {}
static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;}
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;
}
static void shader_none_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) {}
#define GLINFO_LOCATION (*gl_info)
......@@ -1332,7 +1326,6 @@ const shader_backend_t none_shader_backend = {
shader_none_alloc,
shader_none_free,
shader_none_dirty_const,
shader_none_generate_vshader,
shader_none_get_caps,
shader_none_color_fixup_supported,
shader_none_add_instruction_modifiers,
......
......@@ -3609,10 +3609,9 @@ static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const WineD
}
/* GL locking is done by the caller */
static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
static GLuint shader_glsl_generate_pshader(IWineD3DPixelShaderImpl *This,
SHADER_BUFFER *buffer, const struct ps_compile_args *args)
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
CONST DWORD *function = This->baseShader.function;
const char *fragcolor;
......@@ -3646,7 +3645,7 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
/* Pack 3.0 inputs */
if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader)
{
pshader_glsl_input_pack(iface, buffer, This->input_signature, reg_maps, args->vp_mode);
pshader_glsl_input_pack((IWineD3DPixelShader *) This, buffer, This->input_signature, reg_maps, args->vp_mode);
}
/* Base Shader Body */
......@@ -3720,11 +3719,9 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
}
/* GL locking is done by the caller */
/* GL locking is done by the caller */
static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface,
static GLuint shader_glsl_generate_vshader(IWineD3DVertexShaderImpl *This,
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;
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
......@@ -3831,12 +3828,68 @@ static GLhandleARB find_glsl_pshader(IWineD3DPixelShaderImpl *shader, const stru
((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
shader_buffer_init(&buffer);
shader->gl_shaders[shader->num_gl_shaders].prgId =
shader_glsl_generate_pshader((IWineD3DPixelShader*) shader, &buffer, args);
shader_glsl_generate_pshader(shader, &buffer, args);
shader_buffer_free(&buffer);
return shader->gl_shaders[shader->num_gl_shaders++].prgId;
}
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;
}
static GLhandleARB find_glsl_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;
SHADER_BUFFER buffer;
GLhandleARB ret;
/* 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->num_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_buffer_init(&buffer);
ret = shader_glsl_generate_vshader(shader, &buffer, args);
shader_buffer_free(&buffer);
shader->gl_shaders[shader->num_gl_shaders++].prgId = ret;
return ret;
}
/** Sets the GLSL program ID for the given pixel and vertex shader combination.
* It sets the programId on the current StateBlock (because it should be called
* inside of the DrawPrimitive() part of the render loop).
......@@ -3899,7 +3952,7 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
priv->glsl_program = entry;
if(use_vs) {
vshader_id = find_gl_vshader((IWineD3DVertexShaderImpl *) vshader, &vs_compile_args);
vshader_id = find_glsl_vshader((IWineD3DVertexShaderImpl *) vshader, &vs_compile_args);
} else {
vshader_id = 0;
}
......@@ -4562,7 +4615,6 @@ const shader_backend_t glsl_shader_backend = {
shader_glsl_alloc,
shader_glsl_free,
shader_glsl_dirty_const,
shader_glsl_generate_vshader,
shader_glsl_get_caps,
shader_glsl_color_fixup_supported,
shader_glsl_add_instruction_modifiers,
......
......@@ -332,21 +332,6 @@ static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertex
return WINED3D_OK;
}
/* GL locking is done by the caller */
static GLuint vertexshader_compile(IWineD3DVertexShaderImpl *This, const struct vs_compile_args *args) {
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
SHADER_BUFFER buffer;
GLuint ret;
/* Generate the HW shader */
TRACE("(%p) : Generating hardware program\n", This);
shader_buffer_init(&buffer);
ret = deviceImpl->shader_backend->shader_generate_vshader((IWineD3DVertexShader *)This, &buffer, args);
shader_buffer_free(&buffer);
return ret;
}
const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
{
/*** IUnknown methods ***/
......@@ -367,53 +352,3 @@ void find_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockIm
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;
}
/* GL locking is done by the caller */
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->num_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;
}
......@@ -809,8 +809,6 @@ typedef struct {
HRESULT (*shader_alloc_private)(IWineD3DDevice *iface);
void (*shader_free_private)(IWineD3DDevice *iface);
BOOL (*shader_dirtifyable_constants)(IWineD3DDevice *iface);
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);
void (*shader_add_instruction_modifiers)(const struct wined3d_shader_instruction *ins);
......@@ -2689,7 +2687,6 @@ typedef struct IWineD3DVertexShaderImpl {
extern const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl;
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