[1/2] wined3d: Fix glDrawBuffers() optimization.
Matteo Bruni
matteo.mystral at gmail.com
Tue Jun 7 08:36:55 CDT 2011
This patch fixes an optimization which wasn't really designed to work
with multiple render targets. It helps for
http://bugs.winehq.org/show_bug.cgi?id=26869 and it is also the patch
Stefan was waiting for to go ahead with his performance patches. ;)
-------------- next part --------------
From b22c5ad8a0fed8f405d4727e7480ebe1fcdce6a2 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <mbruni at codeweavers.com>
Date: Mon, 6 Jun 2011 17:44:43 +0200
Subject: wined3d: Fix glDrawBuffers() optimization.
---
dlls/wined3d/context.c | 60 ++++++++++++++++++++++++++++------------
dlls/wined3d/wined3d_private.h | 3 +-
2 files changed, 44 insertions(+), 19 deletions(-)
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 8ada3d1..5cd0517 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1321,6 +1321,17 @@ static int WineD3D_ChoosePixelFormat(struct wined3d_device *device, HDC hdc,
return iPixelFormat;
}
+static inline DWORD generate_rt_mask(GLenum buffer)
+{
+ /* Should take care of all the GL_FRONT/GL_BACK/GL_AUXi/GL_NONE... cases */
+ return buffer ? (1 << 31) | buffer : 0;
+}
+
+static inline DWORD generate_rt_mask_from_surface(struct wined3d_surface *target)
+{
+ return (1 << 31) | surface_get_gl_buffer(target);
+}
+
/* Do not call while under the GL lock. */
struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
struct wined3d_surface *target, const struct wined3d_format *ds_format)
@@ -1457,7 +1468,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
ret->tid = GetCurrentThreadId();
ret->render_offscreen = surface_is_offscreen(target);
- ret->draw_buffer_dirty = TRUE;
+ ret->draw_buffers_mask = generate_rt_mask(GL_BACK);
ret->valid = 1;
ret->glCtx = ctx;
@@ -2017,7 +2028,7 @@ void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer)
{
glDrawBuffer(buffer);
checkGLcall("glDrawBuffer()");
- context->draw_buffer_dirty = TRUE;
+ context->draw_buffers_mask = generate_rt_mask(buffer);
}
static inline void context_set_render_offscreen(struct wined3d_context *context, const struct StateEntry *StateTable,
@@ -2075,6 +2086,8 @@ static void context_validate_onscreen_formats(struct wined3d_device *device,
/* Context activation is done by the caller. */
void context_apply_blit_state(struct wined3d_context *context, struct wined3d_device *device)
{
+ DWORD rt_mask;
+
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
{
context_validate_onscreen_formats(device, context, NULL);
@@ -2086,23 +2099,26 @@ void context_apply_blit_state(struct wined3d_context *context, struct wined3d_de
ENTER_GL();
context_apply_fbo_state_blit(context, GL_FRAMEBUFFER, context->current_rt, NULL, SFLAG_INTEXTURE);
LEAVE_GL();
+ rt_mask = 1;
}
else
{
ENTER_GL();
context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
LEAVE_GL();
+ rt_mask = generate_rt_mask_from_surface(context->current_rt);
}
-
- context->draw_buffer_dirty = TRUE;
+ }
+ else
+ {
+ rt_mask = generate_rt_mask_from_surface(context->current_rt);
}
ENTER_GL();
- if (context->draw_buffer_dirty)
+ if (rt_mask != context->draw_buffers_mask)
{
context_apply_draw_buffers(context, 1, &context->current_rt);
- if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
- context->draw_buffer_dirty = FALSE;
+ context->draw_buffers_mask = rt_mask;
}
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
@@ -2168,19 +2184,22 @@ BOOL context_apply_clear_state(struct wined3d_context *context, struct wined3d_d
else
{
context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
- rt_mask = 1;
+ rt_mask = generate_rt_mask_from_surface(rts[0]);
}
LEAVE_GL();
}
else
{
- rt_mask = 1;
+ rt_mask = generate_rt_mask_from_surface(rts[0]);
}
ENTER_GL();
- context_apply_draw_buffers(context, rt_mask, rts);
- context->draw_buffer_dirty = TRUE;
+ if (rt_mask != context->draw_buffers_mask)
+ {
+ context_apply_draw_buffers(context, rt_mask, rts);
+ context->draw_buffers_mask = rt_mask;
+ }
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
{
@@ -2214,6 +2233,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
const struct StateEntry *state_table = device->StateTable;
const struct wined3d_fb_state *fb = &device->fb;
unsigned int i;
+ DWORD rt_mask;
if (!context_validate_rt_config(context->gl_info->limits.buffers,
fb->render_targets, fb->depth_stencil))
@@ -2236,26 +2256,31 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
ENTER_GL();
context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
LEAVE_GL();
+ rt_mask = generate_rt_mask_from_surface(fb->render_targets[0]);
}
else
{
+ const struct wined3d_shader *ps = device->stateBlock->state.pixel_shader;
+
ENTER_GL();
context_apply_fbo_state(context, GL_FRAMEBUFFER, fb->render_targets, fb->depth_stencil, SFLAG_INTEXTURE);
glReadBuffer(GL_NONE);
checkGLcall("glReadBuffer");
LEAVE_GL();
+ rt_mask = ps ? ps->reg_maps.rt_mask : 1;
+ rt_mask &= device->valid_rt_mask;
}
}
+ else
+ {
+ rt_mask = generate_rt_mask_from_surface(fb->render_targets[0]);
+ }
ENTER_GL();
- if (context->draw_buffer_dirty)
+ if (context->draw_buffers_mask != rt_mask)
{
- const struct wined3d_shader *ps = device->stateBlock->state.pixel_shader;
- DWORD rt_mask = ps ? ps->reg_maps.rt_mask : 1;
-
- rt_mask &= device->valid_rt_mask;
context_apply_draw_buffers(context, rt_mask, fb->render_targets);
- context->draw_buffer_dirty = FALSE;
+ context->draw_buffers_mask = rt_mask;
}
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
@@ -2334,7 +2359,6 @@ static void context_setup_target(struct wined3d_device *device,
}
}
- context->draw_buffer_dirty = TRUE;
context->current_rt = target;
context_set_render_offscreen(context, StateTable, render_offscreen);
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 8530a86..d898654 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1053,7 +1053,6 @@ struct wined3d_context
/* Stores some information about the context state for optimization */
WORD render_offscreen : 1;
- WORD draw_buffer_dirty : 1;
WORD last_was_rhw : 1; /* true iff last draw_primitive was in xyzrhw mode */
WORD last_was_pshader : 1;
WORD last_was_vshader : 1;
@@ -1067,6 +1066,7 @@ struct wined3d_context
WORD current : 1;
WORD destroyed : 1;
WORD valid : 1;
+ WORD padding : 1;
BYTE texShaderBumpMap; /* MAX_TEXTURES, 8 */
BYTE lastWasPow2Texture; /* MAX_TEXTURES, 8 */
DWORD numbered_array_mask;
@@ -1098,6 +1098,7 @@ struct wined3d_context
BOOL rebind_fbo;
struct wined3d_surface **blit_targets;
GLenum *draw_buffers;
+ DWORD draw_buffers_mask; /* Enabled draw buffers, 31 max. */
/* Queries */
GLuint *free_occlusion_queries;
--
1.7.3.4
More information about the wine-patches
mailing list