wined3d: Implement draw calls with no attachments.

Supported when ARB_framebuffer_no_attachments is available.

It was reported that no attachments framebuffers trigger GPU hangs
in The Witcher 3 on some system configurations with radeonsi driver.
MESA_EXTENSION_OVERRIDE=-GL_ARB_framebuffer_no_attachments can be used
as a workaround until it's fixed.

Signed-off-by: Józef Kucia <jkucia@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Józef Kucia 2018-03-01 19:36:52 +01:00 committed by Alexandre Julliard
parent 4998cea070
commit 7096e1e02d
4 changed files with 48 additions and 16 deletions

View File

@ -700,8 +700,8 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
static void context_apply_fbo_entry(struct wined3d_context *context, GLenum target, struct fbo_entry *entry) static void context_apply_fbo_entry(struct wined3d_context *context, GLenum target, struct fbo_entry *entry)
{ {
const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_gl_info *gl_info = context->gl_info;
unsigned int i;
GLuint read_binding, draw_binding; GLuint read_binding, draw_binding;
unsigned int i;
if (entry->flags & WINED3D_FBO_ENTRY_FLAG_ATTACHED) if (entry->flags & WINED3D_FBO_ENTRY_FLAG_ATTACHED)
{ {
@ -713,6 +713,16 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
draw_binding = context->fbo_draw_binding; draw_binding = context->fbo_draw_binding;
context_bind_fbo(context, GL_FRAMEBUFFER, entry->id); context_bind_fbo(context, GL_FRAMEBUFFER, entry->id);
if (gl_info->supported[ARB_FRAMEBUFFER_NO_ATTACHMENTS])
{
GL_EXTCALL(glFramebufferParameteri(GL_FRAMEBUFFER,
GL_FRAMEBUFFER_DEFAULT_WIDTH, gl_info->limits.framebuffer_width));
GL_EXTCALL(glFramebufferParameteri(GL_FRAMEBUFFER,
GL_FRAMEBUFFER_DEFAULT_HEIGHT, gl_info->limits.framebuffer_height));
GL_EXTCALL(glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS, 1));
GL_EXTCALL(glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 1));
}
/* Apply render targets */ /* Apply render targets */
for (i = 0; i < gl_info->limits.buffers; ++i) for (i = 0; i < gl_info->limits.buffers; ++i)
{ {
@ -2996,12 +3006,13 @@ void context_apply_blit_state(struct wined3d_context *context, const struct wine
context_invalidate_state(context, STATE_FRAMEBUFFER); context_invalidate_state(context, STATE_FRAMEBUFFER);
} }
static BOOL context_validate_rt_config(UINT rt_count, struct wined3d_rendertarget_view * const *rts, static BOOL have_framebuffer_attachment(unsigned int rt_count, struct wined3d_rendertarget_view * const *rts,
const struct wined3d_rendertarget_view *ds) const struct wined3d_rendertarget_view *ds)
{ {
unsigned int i; unsigned int i;
if (ds) return TRUE; if (ds)
return TRUE;
for (i = 0; i < rt_count; ++i) for (i = 0; i < rt_count; ++i)
{ {
@ -3009,7 +3020,6 @@ static BOOL context_validate_rt_config(UINT rt_count, struct wined3d_rendertarge
return TRUE; return TRUE;
} }
WARN("Invalid render target config, need at least one attachment.\n");
return FALSE; return FALSE;
} }
@ -3026,8 +3036,11 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != state->fb if (isStateDirty(context, STATE_FRAMEBUFFER) || fb != state->fb
|| rt_count != gl_info->limits.buffers) || rt_count != gl_info->limits.buffers)
{ {
if (!context_validate_rt_config(rt_count, rts, dsv)) if (!have_framebuffer_attachment(rt_count, rts, dsv))
{
WARN("Invalid render target config, need at least one attachment.\n");
return FALSE; return FALSE;
}
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
{ {
@ -3908,8 +3921,16 @@ static BOOL context_apply_draw_state(struct wined3d_context *context,
unsigned int i; unsigned int i;
WORD map; WORD map;
if (!context_validate_rt_config(gl_info->limits.buffers, fb->render_targets, fb->depth_stencil)) if (!have_framebuffer_attachment(gl_info->limits.buffers, fb->render_targets, fb->depth_stencil))
return FALSE; {
if (!gl_info->supported[ARB_FRAMEBUFFER_NO_ATTACHMENTS])
{
FIXME("OpenGL implementation does not support framebuffers with no attachments.\n");
return FALSE;
}
context_set_render_offscreen(context, TRUE);
}
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && isStateDirty(context, STATE_FRAMEBUFFER)) if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && isStateDirty(context, STATE_FRAMEBUFFER))
{ {

View File

@ -3779,6 +3779,19 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
gl_info->limits.samples = gl_max; gl_info->limits.samples = gl_max;
} }
if (gl_info->supported[ARB_FRAMEBUFFER_NO_ATTACHMENTS])
{
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &gl_max);
gl_info->limits.framebuffer_width = gl_max;
gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &gl_max);
gl_info->limits.framebuffer_height = gl_max;
}
else
{
gl_info->limits.framebuffer_width = gl_info->limits.texture_size;
gl_info->limits.framebuffer_height = gl_info->limits.texture_size;
}
gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL] = gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL] =
min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_GL_FRAGMENT_SAMPLERS); min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], MAX_GL_FRAGMENT_SAMPLERS);
sampler_count = 0; sampler_count = 0;

View File

@ -4671,17 +4671,15 @@ static void viewport_miscpart(struct wined3d_context *context, const struct wine
} }
else if (depth_stencil) else if (depth_stencil)
{ {
width = depth_stencil->width;
height = depth_stencil->height; height = depth_stencil->height;
} }
else else
{ {
FIXME("No attachments draw calls not supported.\n"); height = gl_info->limits.framebuffer_height;
return;
} }
gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z); gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
checkGLcall("glDepthRange");
/* Note: GL requires lower left, DirectX supplies upper left. This is /* Note: GL requires lower left, DirectX supplies upper left. This is
* reversed when using offscreen rendering. */ * reversed when using offscreen rendering. */
y = context->render_offscreen ? vp.y : height - (vp.y + vp.height); y = context->render_offscreen ? vp.y : height - (vp.y + vp.height);
@ -4690,7 +4688,7 @@ static void viewport_miscpart(struct wined3d_context *context, const struct wine
GL_EXTCALL(glViewportIndexedf(0, vp.x, y, vp.width, vp.height)); GL_EXTCALL(glViewportIndexedf(0, vp.x, y, vp.width, vp.height));
else else
gl_info->gl_ops.gl.p_glViewport(vp.x, y, vp.width, vp.height); gl_info->gl_ops.gl.p_glViewport(vp.x, y, vp.width, vp.height);
checkGLcall("glViewport"); checkGLcall("setting clip space and viewport");
} }
static void viewport_miscpart_cc(struct wined3d_context *context, static void viewport_miscpart_cc(struct wined3d_context *context,
@ -4717,17 +4715,14 @@ static void viewport_miscpart_cc(struct wined3d_context *context,
} }
else if (depth_stencil) else if (depth_stencil)
{ {
width = depth_stencil->width;
height = depth_stencil->height; height = depth_stencil->height;
} }
else else
{ {
FIXME("No attachments draw calls not supported.\n"); height = gl_info->limits.framebuffer_height;
return;
} }
gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z); gl_info->gl_ops.gl.p_glDepthRange(vp.min_z, vp.max_z);
checkGLcall("glDepthRange");
if (context->render_offscreen) if (context->render_offscreen)
{ {

View File

@ -2533,6 +2533,9 @@ struct wined3d_gl_limits
unsigned int texture_buffer_offset_alignment; unsigned int texture_buffer_offset_alignment;
unsigned int framebuffer_width;
unsigned int framebuffer_height;
UINT glsl_varyings; UINT glsl_varyings;
UINT glsl_vs_float_constants; UINT glsl_vs_float_constants;
UINT glsl_ps_float_constants; UINT glsl_ps_float_constants;