wined3d: Recompile glsl pixelshaders if the sampler format changes.
This commit is contained in:
parent
10f25e0104
commit
1c4a15d2cd
|
@ -846,6 +846,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U
|
|||
HRESULT hr;
|
||||
unsigned int pow2Width;
|
||||
unsigned int pow2Height;
|
||||
const GlPixelFormatDesc *glDesc;
|
||||
getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
|
||||
|
||||
|
||||
TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
|
||||
|
@ -928,6 +930,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U
|
|||
tmpW = max(1, tmpW >> 1);
|
||||
tmpH = max(1, tmpH >> 1);
|
||||
}
|
||||
object->baseTexture.shader_conversion_group = glDesc->conversion_group;
|
||||
|
||||
TRACE("(%p) : Created texture %p\n", This, object);
|
||||
return WINED3D_OK;
|
||||
|
@ -947,6 +950,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
|
|||
UINT tmpW;
|
||||
UINT tmpH;
|
||||
UINT tmpD;
|
||||
const GlPixelFormatDesc *glDesc;
|
||||
getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
|
||||
|
||||
/* TODO: It should only be possible to create textures for formats
|
||||
that are reported as supported */
|
||||
|
@ -1017,6 +1022,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
|
|||
tmpH = max(1, tmpH >> 1);
|
||||
tmpD = max(1, tmpD >> 1);
|
||||
}
|
||||
object->baseTexture.shader_conversion_group = glDesc->conversion_group;
|
||||
|
||||
*ppVolumeTexture = (IWineD3DVolumeTexture *) object;
|
||||
TRACE("(%p) : Created volume texture %p\n", This, object);
|
||||
|
@ -1066,6 +1072,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
|
|||
UINT tmpW;
|
||||
HRESULT hr;
|
||||
unsigned int pow2EdgeLength = EdgeLength;
|
||||
const GlPixelFormatDesc *glDesc;
|
||||
getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
|
||||
|
||||
/* TODO: It should only be possible to create textures for formats
|
||||
that are reported as supported */
|
||||
|
@ -1149,6 +1157,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
|
|||
}
|
||||
tmpW = max(1, tmpW >> 1);
|
||||
}
|
||||
object->baseTexture.shader_conversion_group = glDesc->conversion_group;
|
||||
|
||||
TRACE("(%p) : Created Cube Texture %p\n", This, object);
|
||||
*ppCubeTexture = (IWineD3DCubeTexture *) object;
|
||||
|
|
|
@ -976,14 +976,34 @@ static void shader_glsl_add_color_correction(SHADER_OPCODE_ARG* arg, DWORD sampl
|
|||
glsl_dst_param_t dst_param;
|
||||
glsl_dst_param_t dst_param2;
|
||||
WINED3DFORMAT fmt;
|
||||
WINED3DFORMAT conversion_group;
|
||||
IWineD3DBaseTextureImpl *texture;
|
||||
DWORD mask, mask_size;
|
||||
UINT i;
|
||||
BOOL recorded = FALSE;
|
||||
|
||||
texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx];
|
||||
if(texture) {
|
||||
fmt = texture->resource.format;
|
||||
conversion_group = texture->baseTexture.shader_conversion_group;
|
||||
} else {
|
||||
fmt = WINED3DFMT_UNKNOWN;
|
||||
conversion_group = WINED3DFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
/* before doing anything, record the sampler with the format in the format conversion list,
|
||||
* but check if it's not there already
|
||||
*/
|
||||
for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) {
|
||||
if(shader->baseShader.sampled_samplers[i] == sampler_idx) {
|
||||
recorded = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!recorded) {
|
||||
shader->baseShader.sampled_samplers[shader->baseShader.num_sampled_samplers] = sampler_idx;
|
||||
shader->baseShader.num_sampled_samplers++;
|
||||
shader->baseShader.sampled_format[sampler_idx] = conversion_group;
|
||||
}
|
||||
|
||||
switch(fmt) {
|
||||
|
|
|
@ -67,13 +67,7 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_AddRef(IWineD3DPixelShader *iface)
|
|||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) {
|
||||
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
|
||||
ULONG ref;
|
||||
TRACE("(%p) : Releasing from %d\n", This, This->ref);
|
||||
ref = InterlockedDecrement(&This->ref);
|
||||
if (ref == 0) {
|
||||
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
|
||||
static void destroy_glsl_pshader(IWineD3DPixelShaderImpl *This) {
|
||||
struct list *linked_programs = &This->baseShader.linked_programs;
|
||||
|
||||
TRACE("Deleting linked programs\n");
|
||||
|
@ -88,6 +82,16 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface)
|
|||
GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
|
||||
checkGLcall("glDeleteObjectARB");
|
||||
}
|
||||
|
||||
static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) {
|
||||
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
|
||||
ULONG ref;
|
||||
TRACE("(%p) : Releasing from %d\n", This, This->ref);
|
||||
ref = InterlockedDecrement(&This->ref);
|
||||
if (ref == 0) {
|
||||
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
|
||||
destroy_glsl_pshader(This);
|
||||
}
|
||||
shader_delete_constant_list(&This->baseShader.constantsF);
|
||||
shader_delete_constant_list(&This->baseShader.constantsB);
|
||||
shader_delete_constant_list(&This->baseShader.constantsI);
|
||||
|
@ -523,11 +527,43 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader
|
|||
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
|
||||
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
|
||||
CONST DWORD *function = This->baseShader.function;
|
||||
UINT i, sampler;
|
||||
IWineD3DBaseTextureImpl *texture;
|
||||
|
||||
TRACE("(%p) : function %p\n", iface, function);
|
||||
|
||||
/* We're already compiled. */
|
||||
if (This->baseShader.is_compiled) return WINED3D_OK;
|
||||
/* We're already compiled, but check if any of the hardcoded stateblock assumptions
|
||||
* changed.
|
||||
*/
|
||||
if (This->baseShader.is_compiled) {
|
||||
for(i = 0; i < This->baseShader.num_sampled_samplers; i++) {
|
||||
sampler = This->baseShader.sampled_samplers[i];
|
||||
texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler];
|
||||
if(texture && texture->baseTexture.shader_conversion_group != This->baseShader.sampled_format[sampler]) {
|
||||
WARN("Recompiling shader %p due to format change on sampler %d\n", This, sampler);
|
||||
WARN("Old format group %s, new is %s\n",
|
||||
debug_d3dformat(This->baseShader.sampled_format[sampler]),
|
||||
debug_d3dformat(texture->baseTexture.shader_conversion_group));
|
||||
goto recompile;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Check projected textures */
|
||||
/* TODO: Check texture types(2D, Cube, 3D) */
|
||||
|
||||
return WINED3D_OK;
|
||||
|
||||
recompile:
|
||||
if(This->baseShader.recompile_count > 50) {
|
||||
FIXME("Shader %p recompiled more than 50 times\n", This);
|
||||
} else {
|
||||
This->baseShader.recompile_count++;
|
||||
}
|
||||
|
||||
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
|
||||
destroy_glsl_pshader(This);
|
||||
}
|
||||
}
|
||||
|
||||
/* We don't need to compile */
|
||||
if (!function) {
|
||||
|
@ -547,6 +583,9 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader
|
|||
/* FIXME: validate reg_maps against OpenGL */
|
||||
}
|
||||
|
||||
/* Reset fields tracking stateblock values beeing hardcoded in the shader */
|
||||
This->baseShader.num_sampled_samplers = 0;
|
||||
|
||||
/* Generate the HW shader */
|
||||
TRACE("(%p) : Generating hardware program\n", This);
|
||||
IWineD3DPixelShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function);
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
|
||||
|
||||
#define GLINFO_LOCATION This->adapter->gl_info
|
||||
|
||||
/*****************************************************************************
|
||||
* Pixel format array
|
||||
*/
|
||||
|
@ -210,9 +208,11 @@ static inline int getFmtIdx(WINED3DFORMAT fmt) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
#define GLINFO_LOCATION (*gl_info)
|
||||
BOOL initPixelFormats(WineD3D_GL_Info *gl_info)
|
||||
{
|
||||
unsigned int src;
|
||||
int dst;
|
||||
|
||||
gl_info->gl_formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
sizeof(formats) / sizeof(formats[0]) * sizeof(gl_info->gl_formats[0]));
|
||||
|
@ -222,15 +222,51 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info)
|
|||
* after this loop
|
||||
*/
|
||||
for(src = 0; src < sizeof(gl_formats_template) / sizeof(gl_formats_template[0]); src++) {
|
||||
int dst = getFmtIdx(gl_formats_template[src].fmt);
|
||||
dst = getFmtIdx(gl_formats_template[src].fmt);
|
||||
gl_info->gl_formats[dst].glInternal = gl_formats_template[src].glInternal;
|
||||
gl_info->gl_formats[dst].glGammaInternal = gl_formats_template[src].glGammaInternal;
|
||||
gl_info->gl_formats[dst].glFormat = gl_formats_template[src].glFormat;
|
||||
gl_info->gl_formats[dst].glType = gl_formats_template[src].glType;
|
||||
gl_info->gl_formats[dst].conversion_group= WINED3DFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
/* V8U8 and V16U16 are always tidied up in the pixel shader - blue is set to 1.0.
|
||||
* They can't be switched with other formats, but they can be switched with each other,
|
||||
* except if GL_ATI_envmap_bumpmap is supported. In this case, V8U8 uses the gl native format,
|
||||
* but V16U16 is converted.
|
||||
*/
|
||||
dst = getFmtIdx(WINED3DFMT_V8U8);
|
||||
gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8;
|
||||
dst = getFmtIdx(WINED3DFMT_V16U16);
|
||||
if(!GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
|
||||
gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8;
|
||||
} else {
|
||||
gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V16U16;
|
||||
}
|
||||
|
||||
if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
|
||||
/* If GL_NV_texture_shader is not supported, those formats are converted, incompatibly
|
||||
* with each other
|
||||
*/
|
||||
dst = getFmtIdx(WINED3DFMT_L6V5U5);
|
||||
gl_info->gl_formats[dst].conversion_group = WINED3DFMT_L6V5U5;
|
||||
dst = getFmtIdx(WINED3DFMT_X8L8V8U8);
|
||||
gl_info->gl_formats[dst].conversion_group = WINED3DFMT_X8L8V8U8;
|
||||
dst = getFmtIdx(WINED3DFMT_Q8W8V8U8);
|
||||
gl_info->gl_formats[dst].conversion_group = WINED3DFMT_Q8W8V8U8;
|
||||
} else {
|
||||
/* If GL_NV_texture_shader is supported, WINED3DFMT_L6V5U5 and WINED3DFMT_X8L8V8U8
|
||||
* are converted at surface loading time, but they do not need any modification in
|
||||
* the shader, thus they are compatible with all WINED3DFMT_UNKNOWN group formats.
|
||||
* WINED3DFMT_Q8W8V8U8 doesn't even need load-time conversion
|
||||
*/
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#undef GLINFO_LOCATION
|
||||
|
||||
#define GLINFO_LOCATION This->adapter->gl_info
|
||||
|
||||
const StaticPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, WineD3D_GL_Info *gl_info, const GlPixelFormatDesc **glDesc)
|
||||
{
|
||||
|
|
|
@ -932,6 +932,7 @@ typedef struct IWineD3DBaseTextureClass
|
|||
DWORD sampler;
|
||||
BOOL is_srgb;
|
||||
UINT srgb_mode_change_count;
|
||||
WINED3DFORMAT shader_conversion_group;
|
||||
} IWineD3DBaseTextureClass;
|
||||
|
||||
typedef struct IWineD3DBaseTextureImpl
|
||||
|
@ -1898,6 +1899,17 @@ typedef struct IWineD3DBaseShaderClass
|
|||
struct list constantsI;
|
||||
shader_reg_maps reg_maps;
|
||||
|
||||
/* Pixel formats of sampled textures, for format conversion. This
|
||||
* represents the formats found during compilation, it is not initialized
|
||||
* on the first parser pass. It is needed to check if the shader
|
||||
* needs recompilation to adjust the format conversion
|
||||
*/
|
||||
WINED3DFORMAT sampled_format[MAX_COMBINED_SAMPLERS];
|
||||
UINT sampled_samplers[MAX_COMBINED_SAMPLERS];
|
||||
UINT num_sampled_samplers;
|
||||
|
||||
UINT recompile_count;
|
||||
|
||||
/* Pointer to the parent device */
|
||||
IWineD3DDevice *device;
|
||||
|
||||
|
|
|
@ -3691,6 +3691,7 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer,
|
|||
|
||||
typedef struct {
|
||||
GLint glInternal, glGammaInternal, glFormat, glType;
|
||||
WINED3DFORMAT conversion_group;
|
||||
} GlPixelFormatDesc;
|
||||
|
||||
#define USE_GL_FUNC(type, pfn) type pfn;
|
||||
|
|
Loading…
Reference in New Issue