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;
|
HRESULT hr;
|
||||||
unsigned int pow2Width;
|
unsigned int pow2Width;
|
||||||
unsigned int pow2Height;
|
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);
|
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);
|
tmpW = max(1, tmpW >> 1);
|
||||||
tmpH = max(1, tmpH >> 1);
|
tmpH = max(1, tmpH >> 1);
|
||||||
}
|
}
|
||||||
|
object->baseTexture.shader_conversion_group = glDesc->conversion_group;
|
||||||
|
|
||||||
TRACE("(%p) : Created texture %p\n", This, object);
|
TRACE("(%p) : Created texture %p\n", This, object);
|
||||||
return WINED3D_OK;
|
return WINED3D_OK;
|
||||||
|
@ -947,6 +950,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
|
||||||
UINT tmpW;
|
UINT tmpW;
|
||||||
UINT tmpH;
|
UINT tmpH;
|
||||||
UINT tmpD;
|
UINT tmpD;
|
||||||
|
const GlPixelFormatDesc *glDesc;
|
||||||
|
getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
|
||||||
|
|
||||||
/* TODO: It should only be possible to create textures for formats
|
/* TODO: It should only be possible to create textures for formats
|
||||||
that are reported as supported */
|
that are reported as supported */
|
||||||
|
@ -1017,6 +1022,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa
|
||||||
tmpH = max(1, tmpH >> 1);
|
tmpH = max(1, tmpH >> 1);
|
||||||
tmpD = max(1, tmpD >> 1);
|
tmpD = max(1, tmpD >> 1);
|
||||||
}
|
}
|
||||||
|
object->baseTexture.shader_conversion_group = glDesc->conversion_group;
|
||||||
|
|
||||||
*ppVolumeTexture = (IWineD3DVolumeTexture *) object;
|
*ppVolumeTexture = (IWineD3DVolumeTexture *) object;
|
||||||
TRACE("(%p) : Created volume texture %p\n", This, object);
|
TRACE("(%p) : Created volume texture %p\n", This, object);
|
||||||
|
@ -1066,6 +1072,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
|
||||||
UINT tmpW;
|
UINT tmpW;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
unsigned int pow2EdgeLength = EdgeLength;
|
unsigned int pow2EdgeLength = EdgeLength;
|
||||||
|
const GlPixelFormatDesc *glDesc;
|
||||||
|
getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);
|
||||||
|
|
||||||
/* TODO: It should only be possible to create textures for formats
|
/* TODO: It should only be possible to create textures for formats
|
||||||
that are reported as supported */
|
that are reported as supported */
|
||||||
|
@ -1149,6 +1157,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface
|
||||||
}
|
}
|
||||||
tmpW = max(1, tmpW >> 1);
|
tmpW = max(1, tmpW >> 1);
|
||||||
}
|
}
|
||||||
|
object->baseTexture.shader_conversion_group = glDesc->conversion_group;
|
||||||
|
|
||||||
TRACE("(%p) : Created Cube Texture %p\n", This, object);
|
TRACE("(%p) : Created Cube Texture %p\n", This, object);
|
||||||
*ppCubeTexture = (IWineD3DCubeTexture *) 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_param;
|
||||||
glsl_dst_param_t dst_param2;
|
glsl_dst_param_t dst_param2;
|
||||||
WINED3DFORMAT fmt;
|
WINED3DFORMAT fmt;
|
||||||
|
WINED3DFORMAT conversion_group;
|
||||||
IWineD3DBaseTextureImpl *texture;
|
IWineD3DBaseTextureImpl *texture;
|
||||||
DWORD mask, mask_size;
|
DWORD mask, mask_size;
|
||||||
|
UINT i;
|
||||||
|
BOOL recorded = FALSE;
|
||||||
|
|
||||||
texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx];
|
texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx];
|
||||||
if(texture) {
|
if(texture) {
|
||||||
fmt = texture->resource.format;
|
fmt = texture->resource.format;
|
||||||
|
conversion_group = texture->baseTexture.shader_conversion_group;
|
||||||
} else {
|
} else {
|
||||||
fmt = WINED3DFMT_UNKNOWN;
|
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) {
|
switch(fmt) {
|
||||||
|
|
|
@ -67,6 +67,22 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_AddRef(IWineD3DPixelShader *iface)
|
||||||
return InterlockedIncrement(&This->ref);
|
return InterlockedIncrement(&This->ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void destroy_glsl_pshader(IWineD3DPixelShaderImpl *This) {
|
||||||
|
struct list *linked_programs = &This->baseShader.linked_programs;
|
||||||
|
|
||||||
|
TRACE("Deleting linked programs\n");
|
||||||
|
if (linked_programs->next) {
|
||||||
|
struct glsl_shader_prog_link *entry, *entry2;
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) {
|
||||||
|
delete_glsl_program_entry(This->baseShader.device, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Deleting shader object %u\n", This->baseShader.prgId);
|
||||||
|
GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
|
||||||
|
checkGLcall("glDeleteObjectARB");
|
||||||
|
}
|
||||||
|
|
||||||
static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) {
|
static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) {
|
||||||
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
|
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
|
||||||
ULONG ref;
|
ULONG ref;
|
||||||
|
@ -74,19 +90,7 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface)
|
||||||
ref = InterlockedDecrement(&This->ref);
|
ref = InterlockedDecrement(&This->ref);
|
||||||
if (ref == 0) {
|
if (ref == 0) {
|
||||||
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
|
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
|
||||||
struct list *linked_programs = &This->baseShader.linked_programs;
|
destroy_glsl_pshader(This);
|
||||||
|
|
||||||
TRACE("Deleting linked programs\n");
|
|
||||||
if (linked_programs->next) {
|
|
||||||
struct glsl_shader_prog_link *entry, *entry2;
|
|
||||||
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) {
|
|
||||||
delete_glsl_program_entry(This->baseShader.device, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("Deleting shader object %u\n", This->baseShader.prgId);
|
|
||||||
GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
|
|
||||||
checkGLcall("glDeleteObjectARB");
|
|
||||||
}
|
}
|
||||||
shader_delete_constant_list(&This->baseShader.constantsF);
|
shader_delete_constant_list(&This->baseShader.constantsF);
|
||||||
shader_delete_constant_list(&This->baseShader.constantsB);
|
shader_delete_constant_list(&This->baseShader.constantsB);
|
||||||
|
@ -523,11 +527,43 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader
|
||||||
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
|
IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface;
|
||||||
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
|
IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
|
||||||
CONST DWORD *function = This->baseShader.function;
|
CONST DWORD *function = This->baseShader.function;
|
||||||
|
UINT i, sampler;
|
||||||
|
IWineD3DBaseTextureImpl *texture;
|
||||||
|
|
||||||
TRACE("(%p) : function %p\n", iface, function);
|
TRACE("(%p) : function %p\n", iface, function);
|
||||||
|
|
||||||
/* We're already compiled. */
|
/* We're already compiled, but check if any of the hardcoded stateblock assumptions
|
||||||
if (This->baseShader.is_compiled) return WINED3D_OK;
|
* 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 */
|
/* We don't need to compile */
|
||||||
if (!function) {
|
if (!function) {
|
||||||
|
@ -547,6 +583,9 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader
|
||||||
/* FIXME: validate reg_maps against OpenGL */
|
/* 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 */
|
/* Generate the HW shader */
|
||||||
TRACE("(%p) : Generating hardware program\n", This);
|
TRACE("(%p) : Generating hardware program\n", This);
|
||||||
IWineD3DPixelShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function);
|
IWineD3DPixelShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function);
|
||||||
|
|
|
@ -27,8 +27,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
|
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
|
||||||
|
|
||||||
#define GLINFO_LOCATION This->adapter->gl_info
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Pixel format array
|
* Pixel format array
|
||||||
*/
|
*/
|
||||||
|
@ -210,9 +208,11 @@ static inline int getFmtIdx(WINED3DFORMAT fmt) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GLINFO_LOCATION (*gl_info)
|
||||||
BOOL initPixelFormats(WineD3D_GL_Info *gl_info)
|
BOOL initPixelFormats(WineD3D_GL_Info *gl_info)
|
||||||
{
|
{
|
||||||
unsigned int src;
|
unsigned int src;
|
||||||
|
int dst;
|
||||||
|
|
||||||
gl_info->gl_formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
gl_info->gl_formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||||
sizeof(formats) / sizeof(formats[0]) * sizeof(gl_info->gl_formats[0]));
|
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
|
* after this loop
|
||||||
*/
|
*/
|
||||||
for(src = 0; src < sizeof(gl_formats_template) / sizeof(gl_formats_template[0]); src++) {
|
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].glInternal = gl_formats_template[src].glInternal;
|
||||||
gl_info->gl_formats[dst].glGammaInternal = gl_formats_template[src].glGammaInternal;
|
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].glFormat = gl_formats_template[src].glFormat;
|
||||||
gl_info->gl_formats[dst].glType = gl_formats_template[src].glType;
|
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;
|
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)
|
const StaticPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, WineD3D_GL_Info *gl_info, const GlPixelFormatDesc **glDesc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -932,6 +932,7 @@ typedef struct IWineD3DBaseTextureClass
|
||||||
DWORD sampler;
|
DWORD sampler;
|
||||||
BOOL is_srgb;
|
BOOL is_srgb;
|
||||||
UINT srgb_mode_change_count;
|
UINT srgb_mode_change_count;
|
||||||
|
WINED3DFORMAT shader_conversion_group;
|
||||||
} IWineD3DBaseTextureClass;
|
} IWineD3DBaseTextureClass;
|
||||||
|
|
||||||
typedef struct IWineD3DBaseTextureImpl
|
typedef struct IWineD3DBaseTextureImpl
|
||||||
|
@ -1898,6 +1899,17 @@ typedef struct IWineD3DBaseShaderClass
|
||||||
struct list constantsI;
|
struct list constantsI;
|
||||||
shader_reg_maps reg_maps;
|
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 */
|
/* Pointer to the parent device */
|
||||||
IWineD3DDevice *device;
|
IWineD3DDevice *device;
|
||||||
|
|
||||||
|
|
|
@ -3691,6 +3691,7 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer,
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLint glInternal, glGammaInternal, glFormat, glType;
|
GLint glInternal, glGammaInternal, glFormat, glType;
|
||||||
|
WINED3DFORMAT conversion_group;
|
||||||
} GlPixelFormatDesc;
|
} GlPixelFormatDesc;
|
||||||
|
|
||||||
#define USE_GL_FUNC(type, pfn) type pfn;
|
#define USE_GL_FUNC(type, pfn) type pfn;
|
||||||
|
|
Loading…
Reference in New Issue