Commit 019f6a85 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Mask out writes to unused render targets.

Outputs not written by the pixel shader are undefined in GL, but in D3D the render target is unmodified.
parent d5ee9a40
......@@ -1118,7 +1118,7 @@ static void shader_arb_get_register_name(const struct wined3d_shader_instruction
else
{
if(ctx->cur_ps_args->super.srgb_correction) FIXME("sRGB correction on higher render targets\n");
if (reg_maps->highest_render_target > 0)
if (reg_maps->rt_mask > 1)
{
sprintf(register_name, "result.color[%u]", reg->idx);
}
......@@ -3615,7 +3615,7 @@ static GLuint shader_arb_generate_pshader(struct wined3d_shader *shader,
priv_ctx.target_version = ARB;
}
if (reg_maps->highest_render_target > 0)
if (reg_maps->rt_mask > 1)
{
shader_addline(buffer, "OPTION ARB_draw_buffers;\n");
}
......
......@@ -1977,9 +1977,9 @@ static struct wined3d_context *FindContext(struct wined3d_device *device, struct
}
/* Context activation is done by the caller. */
static void context_apply_draw_buffers(struct wined3d_context *context, UINT rt_count, struct wined3d_surface **rts)
static void context_apply_draw_buffers(struct wined3d_context *context, DWORD rt_mask, struct wined3d_surface **rts)
{
if (!rt_count)
if (!rt_mask)
{
ENTER_GL();
glDrawBuffer(GL_NONE);
......@@ -1999,19 +1999,22 @@ static void context_apply_draw_buffers(struct wined3d_context *context, UINT rt_
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
{
const struct wined3d_gl_info *gl_info = context->gl_info;
unsigned int i;
unsigned int i = 0;
for (i = 0; i < rt_count; ++i)
while (rt_mask)
{
if (rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
if ((rt_mask & 1) && rts[i] && rts[i]->resource.format->id != WINED3DFMT_NULL)
context->draw_buffers[i] = GL_COLOR_ATTACHMENT0 + i;
else
context->draw_buffers[i] = GL_NONE;
rt_mask >>= 1;
++i;
}
if (gl_info->supported[ARB_DRAW_BUFFERS])
{
GL_EXTCALL(glDrawBuffersARB(rt_count, context->draw_buffers));
GL_EXTCALL(glDrawBuffersARB(i, context->draw_buffers));
checkGLcall("glDrawBuffers()");
}
else
......@@ -2153,6 +2156,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, struct wined3d_d
UINT rt_count, struct wined3d_surface **rts, struct wined3d_surface *depth_stencil)
{
const struct StateEntry *state_table = device->StateTable;
DWORD rt_mask = 0;
UINT i;
if (!context_validate_rt_config(rt_count, rts, depth_stencil))
......@@ -2170,6 +2174,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, struct wined3d_d
for (i = 0; i < rt_count; ++i)
{
context->blit_targets[i] = rts[i];
rt_mask |= (1 << i);
}
while (i < context->gl_info->limits.buffers)
{
......@@ -2183,12 +2188,17 @@ 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;
}
LEAVE_GL();
}
else
{
rt_mask = 1;
}
context_apply_draw_buffers(context, rt_count, rts);
context_apply_draw_buffers(context, rt_mask, rts);
context->draw_buffer_dirty = TRUE;
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
......@@ -2261,7 +2271,11 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
if (context->draw_buffer_dirty)
{
context_apply_draw_buffers(context, context->gl_info->limits.buffers, fb->render_targets);
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;
}
......
......@@ -1166,6 +1166,9 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
device->updateStateBlock = device->stateBlock;
wined3d_stateblock_incref(device->updateStateBlock);
device->valid_rt_mask = 0;
for (i = 0; i < gl_info->limits.buffers; ++i)
device->valid_rt_mask |= (1 << i);
device->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(*device->fb.render_targets) * gl_info->limits.buffers);
......
......@@ -418,7 +418,7 @@ static void shader_record_register_usage(struct wined3d_shader *shader, struct w
break;
case WINED3DSPR_COLOROUT:
reg_maps->highest_render_target = max(reg_maps->highest_render_target, reg->idx);
reg_maps->rt_mask |= (1 << reg->idx);
break;
default:
......@@ -821,6 +821,11 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
}
reg_maps->loop_depth = max_loop_depth;
/* PS before 2.0 don't have explicit color outputs. Instead the value of
* R0 is written to the render target. */
if (shader_version.major < 2 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
reg_maps->rt_mask |= (1 << 0);
shader->functionLength = ((const char *)ptr - (const char *)byte_code);
return WINED3D_OK;
......
......@@ -560,9 +560,10 @@ struct wined3d_shader_reg_maps
WORD usespow : 1;
WORD padding : 3;
DWORD rt_mask; /* Used render targets, 32 max. */
/* Whether or not loops are used in this shader, and nesting depth */
unsigned loop_depth;
unsigned highest_render_target;
UINT min_rel_offset, max_rel_offset;
};
......@@ -1716,6 +1717,7 @@ struct wined3d_device
unsigned int highest_dirty_ps_const, highest_dirty_vs_const;
/* Render Target Support */
DWORD valid_rt_mask;
struct wined3d_fb_state fb;
struct wined3d_surface *onscreen_depth_stencil;
struct wined3d_surface *auto_depth_stencil;
......
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