r300g: fix crash when flushing ZMASK

https://bugs.freedesktop.org/show_bug.cgi?id=32912

The fix is to call update_derived_state before user buffer uploads.
I've also moved some code around.

Unfortunately, there are still some ZMASK-related bugs which cause
misrendering, i.e. flushing doesn't always work and glean/fbo fails.
This commit is contained in:
Marek Olšák
2011-01-09 05:34:36 +01:00
parent 69191d4123
commit 3332229b3b
5 changed files with 81 additions and 92 deletions
+58 -4
View File
@@ -179,6 +179,12 @@ static void r300_clear(struct pipe_context* pipe,
boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
uint32_t hyperz_dcv = hyperz->zb_depthclearvalue;
/* Decompress zbuffers that are bound as textures. If we didn't flush here,
* it would happen inside the blitter when updating derived state,
* causing a blitter operation to be called from inside the blitter,
* which would overwrite saved states and they would never get restored. */
r300_flush_depth_textures(r300);
/* Enable fast Z clear.
* The zbuffer must be in micro-tiled mode, otherwise it locks up. */
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && can_hyperz) {
@@ -274,6 +280,12 @@ static void r300_clear_render_target(struct pipe_context *pipe,
{
struct r300_context *r300 = r300_context(pipe);
/* Decompress zbuffers that are bound as textures. If we didn't flush here,
* it would happen inside the blitter when updating derived state,
* causing a blitter operation to be called from inside the blitter,
* which would overwrite saved states and they would never get restored. */
r300_flush_depth_textures(r300);
r300_blitter_begin(r300, R300_CLEAR_SURFACE);
util_blitter_clear_render_target(r300->blitter, dst, rgba,
dstx, dsty, width, height);
@@ -291,6 +303,12 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe,
{
struct r300_context *r300 = r300_context(pipe);
/* Decompress zbuffers that are bound as textures. If we didn't flush here,
* it would happen inside the blitter when updating derived state,
* causing a blitter operation to be called from inside the blitter,
* which would overwrite saved states and they would never get restored. */
r300_flush_depth_textures(r300);
r300_blitter_begin(r300, R300_CLEAR_SURFACE);
util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil,
dstx, dsty, width, height);
@@ -298,10 +316,10 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe,
}
/* Flush a depth stencil buffer. */
void r300_flush_depth_stencil(struct pipe_context *pipe,
struct pipe_resource *dst,
unsigned level,
unsigned layer)
static void r300_flush_depth_stencil(struct pipe_context *pipe,
struct pipe_resource *dst,
unsigned level,
unsigned layer)
{
struct r300_context *r300 = r300_context(pipe);
struct pipe_surface *dstsurf, surf_tmpl;
@@ -320,6 +338,7 @@ void r300_flush_depth_stencil(struct pipe_context *pipe,
dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);
r300->z_decomp_rd = TRUE;
r300_blitter_begin(r300, R300_CLEAR_SURFACE);
util_blitter_flush_depth_stencil(r300->blitter, dstsurf);
r300_blitter_end(r300);
@@ -329,6 +348,39 @@ void r300_flush_depth_stencil(struct pipe_context *pipe,
pipe_surface_reference(&dstsurf, NULL);
}
/* We can't use compressed zbuffers as samplers. */
void r300_flush_depth_textures(struct r300_context *r300)
{
struct r300_textures_state *state =
(struct r300_textures_state*)r300->textures_state.state;
unsigned i, level;
unsigned count = MIN2(state->sampler_view_count,
state->sampler_state_count);
if (r300->z_decomp_rd)
return;
for (i = 0; i < count; i++)
if (state->sampler_views[i] && state->sampler_states[i]) {
struct pipe_resource *tex = state->sampler_views[i]->base.texture;
if (tex->target == PIPE_TEXTURE_3D ||
tex->target == PIPE_TEXTURE_CUBE)
continue;
/* Ignore non-depth textures.
* Also ignore reinterpreted depth textures, e.g. resource_copy. */
if (!util_format_is_depth_or_stencil(tex->format))
continue;
for (level = 0; level <= tex->last_level; level++)
if (r300_texture(tex)->zmask_in_use[level]) {
/* We don't handle 3D textures and cubemaps yet. */
r300_flush_depth_stencil(&r300->context, tex, level, 0);
}
}
}
/* Copy a block of pixels from one surface to another using HW. */
static void r300_hw_copy_region(struct pipe_context* pipe,
struct pipe_resource *dst,
@@ -360,6 +412,7 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
enum pipe_format old_format = dst->format;
enum pipe_format new_format = old_format;
boolean is_depth;
if (!pipe->screen->is_format_supported(pipe->screen,
old_format, src->target,
src->nr_samples,
@@ -390,6 +443,7 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
if (is_depth) {
r300_flush_depth_stencil(pipe, src, src_level, src_box->z);
}
if (old_format != new_format) {
r300_texture_reinterpret_format(pipe->screen,
dst, new_format);
+19 -19
View File
@@ -656,6 +656,22 @@ static INLINE struct r300_fragment_shader *r300_fs(struct r300_context *r300)
return (struct r300_fragment_shader*)r300->fs.state;
}
static INLINE void r300_mark_atom_dirty(struct r300_context *r300,
struct r300_atom *atom)
{
atom->dirty = TRUE;
if (!r300->first_dirty) {
r300->first_dirty = atom;
r300->last_dirty = atom+1;
} else {
if (atom < r300->first_dirty)
r300->first_dirty = atom;
else if (atom+1 > r300->last_dirty)
r300->last_dirty = atom+1;
}
}
struct pipe_context* r300_create_context(struct pipe_screen* screen,
void *priv);
@@ -672,10 +688,7 @@ void r300_init_state_functions(struct r300_context* r300);
void r300_init_resource_functions(struct r300_context* r300);
/* r300_blit.c */
void r300_flush_depth_stencil(struct pipe_context *pipe,
struct pipe_resource *dst,
unsigned level,
unsigned layer);
void r300_flush_depth_textures(struct r300_context *r300);
/* r300_query.c */
void r300_resume_query(struct r300_context *r300,
@@ -710,21 +723,8 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
enum r300_fb_state_change change);
void r300_mark_fs_code_dirty(struct r300_context *r300);
static INLINE void r300_mark_atom_dirty(struct r300_context *r300,
struct r300_atom *atom)
{
atom->dirty = TRUE;
if (!r300->first_dirty) {
r300->first_dirty = atom;
r300->last_dirty = atom+1;
} else {
if (atom < r300->first_dirty)
r300->first_dirty = atom;
if (atom+1 > r300->last_dirty)
r300->last_dirty = atom+1;
}
}
/* r300_state_derived.c */
void r300_update_derived_state(struct r300_context* r300);
/* r300_debug.c */
void r500_dump_rs_block(struct r300_rs_block *rs);
+4 -5
View File
@@ -39,7 +39,6 @@
#include "r300_screen_buffer.h"
#include "r300_emit.h"
#include "r300_reg.h"
#include "r300_state_derived.h"
#include <limits.h>
@@ -569,8 +568,6 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
r300_translate_index_buffer(r300, &indexBuffer, &indexSize, index_offset,
&start, count);
r300_update_derived_state(r300);
/* Fallback for misaligned ushort indices. */
if (indexSize == 2 && (start & 1) &&
!r300_is_user_buffer(indexBuffer)) {
@@ -643,8 +640,6 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
unsigned short_count;
r300_update_derived_state(r300);
if (immd_is_good_idea(r300, count)) {
r300_emit_draw_arrays_immediate(r300, mode, start, count);
} else {
@@ -720,6 +715,8 @@ static void r300_draw_vbo(struct pipe_context* pipe,
return;
}
r300_update_derived_state(r300);
/* Set up the fallback for an incompatible vertex layout if needed. */
if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) {
r300_begin_vertex_translate(r300, real_min_index, real_max_index);
@@ -737,6 +734,8 @@ static void r300_draw_vbo(struct pipe_context* pipe,
min_index = MAX2(min_index, info->start);
max_index = MIN2(max_index, info->start + count - 1);
r300_update_derived_state(r300);
/* Set up the fallback for an incompatible vertex layout if needed. */
if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) {
r300_begin_vertex_translate(r300, min_index, max_index);
@@ -32,7 +32,6 @@
#include "r300_hyperz.h"
#include "r300_screen.h"
#include "r300_shader_semantics.h"
#include "r300_state_derived.h"
#include "r300_state_inlines.h"
#include "r300_texture.h"
#include "r300_vs.h"
@@ -863,39 +862,6 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
}
}
/* We can't use compressed zbuffers as samplers. */
static void r300_flush_depth_textures(struct r300_context *r300)
{
struct r300_textures_state *state =
(struct r300_textures_state*)r300->textures_state.state;
unsigned i, level;
unsigned count = MIN2(state->sampler_view_count,
state->sampler_state_count);
if (r300->z_decomp_rd)
return;
for (i = 0; i < count; i++)
if (state->sampler_views[i] && state->sampler_states[i]) {
struct pipe_resource *tex = state->sampler_views[i]->base.texture;
if (tex->target == PIPE_TEXTURE_3D ||
tex->target == PIPE_TEXTURE_CUBE)
continue;
/* Ignore non-depth textures.
* Also ignore reinterpreted depth textures, e.g. resource_copy. */
if (!util_format_is_depth_or_stencil(tex->format))
continue;
for (level = 0; level <= tex->last_level; level++)
if (r300_texture(tex)->zmask_in_use[level]) {
/* We don't handle 3D textures and cubemaps yet. */
r300_flush_depth_stencil(&r300->context, tex, level, 0);
}
}
}
void r300_update_derived_state(struct r300_context* r300)
{
r300_flush_depth_textures(r300);
@@ -1,30 +0,0 @@
/*
* Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
#ifndef R300_STATE_DERIVED_H
#define R300_STATE_DERIVED_H
struct r300_context;
void r300_update_derived_state(struct r300_context* r300);
#endif /* R300_STATE_DERIVED_H */