radeon/r200/r300: fix up the whole buffer space checking.

This fixes up the buffer validation scheme, so that we keep a list
of buffers to validate so cmdbuf flushes during a pipeline get
all the buffers revalidated on the next emit.

This also fixes radeonFlush to not flush unless we have something
useful to send to the GPU, like a DMA buffer or something not state
This commit is contained in:
Dave Airlie 2009-04-02 18:58:49 +10:00
parent 4170216009
commit 05304d41f2
10 changed files with 148 additions and 91 deletions

View file

@ -2273,33 +2273,24 @@ static void update_texturematrix( GLcontext *ctx )
static GLboolean r200ValidateBuffers(GLcontext *ctx)
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
struct radeon_cs_space_check bos[8];
struct radeon_renderbuffer *rrb;
int num_bo = 0;
int i;
int flushed = 0, ret;
again:
num_bo = 0;
radeon_validate_reset_bos(&rmesa->radeon);
rrb = radeon_get_colorbuffer(&rmesa->radeon);
/* color buffer */
if (rrb && rrb->bo) {
bos[num_bo].bo = rrb->bo;
bos[num_bo].read_domains = 0;
bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
bos[num_bo].new_accounted = 0;
num_bo++;
radeon_validate_bo(&rmesa->radeon, rrb->bo,
0, RADEON_GEM_DOMAIN_VRAM);
}
/* depth buffer */
rrb = radeon_get_depthbuffer(&rmesa->radeon);
/* color buffer */
if (rrb && rrb->bo) {
bos[num_bo].bo = rrb->bo;
bos[num_bo].read_domains = 0;
bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
bos[num_bo].new_accounted = 0;
num_bo++;
radeon_validate_bo(&rmesa->radeon, rrb->bo,
0, RADEON_GEM_DOMAIN_VRAM);
}
for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
@ -2307,26 +2298,17 @@ again:
if (!ctx->Texture.Unit[i]._ReallyEnabled)
continue;
t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
bos[num_bo].bo = t->mt->bo;
bos[num_bo].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
bos[num_bo].write_domain = 0;
bos[num_bo].new_accounted = 0;
num_bo++;
if (t->image_override && t->bo)
radeon_validate_bo(&rmesa->radeon, t->bo,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
else if (t->mt->bo)
radeon_validate_bo(&rmesa->radeon, t->mt->bo,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
}
ret = radeon_cs_space_check(rmesa->radeon.cmdbuf.cs, bos, num_bo);
if (ret == RADEON_CS_SPACE_OP_TO_BIG)
return GL_FALSE;
if (ret == RADEON_CS_SPACE_FLUSH) {
radeonFlush(ctx);
if (flushed)
return GL_FALSE;
flushed = 1;
goto again;
}
return GL_TRUE;
return radeon_revalidate_bos(ctx);
}
GLboolean r200ValidateState( GLcontext *ctx )

View file

@ -352,7 +352,7 @@ void r300EmitCacheFlush(r300ContextPtr rmesa)
{
BATCH_LOCALS(&rmesa->radeon);
BEGIN_BATCH(4);
BEGIN_BATCH_NO_AUTOSTATE(4);
OUT_BATCH_REGVAL(R300_RB3D_DSTCACHE_CTLSTAT,
R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);

View file

@ -268,40 +268,29 @@ static GLboolean r300_validate_texture(GLcontext * ctx, struct gl_texture_object
return GL_TRUE;
}
/**
* Ensure all enabled and complete textures are uploaded along with any buffers being used.
*/
GLboolean r300ValidateBuffers(GLcontext * ctx)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct radeon_cs_space_check bos[16];
struct radeon_renderbuffer *rrb;
int num_bo = 0;
int i;
int flushed = 0, ret;
again:
num_bo = 0;
radeon_validate_reset_bos(&rmesa->radeon);
rrb = radeon_get_colorbuffer(&rmesa->radeon);
/* color buffer */
if (rrb && rrb->bo) {
bos[num_bo].bo = rrb->bo;
bos[num_bo].read_domains = 0;
bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
bos[num_bo].new_accounted = 0;
num_bo++;
radeon_validate_bo(&rmesa->radeon, rrb->bo,
0, RADEON_GEM_DOMAIN_VRAM);
}
/* depth buffer */
rrb = radeon_get_depthbuffer(&rmesa->radeon);
/* color buffer */
if (rrb && rrb->bo) {
bos[num_bo].bo = rrb->bo;
bos[num_bo].read_domains = 0;
bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM;
bos[num_bo].new_accounted = 0;
num_bo++;
radeon_validate_bo(&rmesa->radeon, rrb->bo,
0, RADEON_GEM_DOMAIN_VRAM);
}
for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
@ -317,26 +306,15 @@ again:
}
t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
if (t->image_override && t->bo)
bos[num_bo].bo = t->bo;
radeon_validate_bo(&rmesa->radeon, t->bo,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
else if (t->mt->bo)
bos[num_bo].bo = t->mt->bo;
bos[num_bo].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM;
bos[num_bo].write_domain = 0;
bos[num_bo].new_accounted = 0;
num_bo++;
radeon_validate_bo(&rmesa->radeon, t->mt->bo,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
}
ret = radeon_cs_space_check(rmesa->radeon.cmdbuf.cs, bos, num_bo);
if (ret == RADEON_CS_SPACE_OP_TO_BIG)
return GL_FALSE;
if (ret == RADEON_CS_SPACE_FLUSH) {
radeonFlush(ctx);
if (flushed)
return GL_FALSE;
flushed = 1;
goto again;
}
return GL_TRUE;
return radeon_revalidate_bos(ctx);
}
void r300SetTexOffset(__DRIcontext * pDRICtx, GLint texname,

View file

@ -906,6 +906,49 @@ static INLINE void radeonEmitAtoms(radeonContextPtr radeon, GLboolean dirty)
COMMIT_BATCH();
}
GLboolean radeon_revalidate_bos(GLcontext *ctx)
{
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
int flushed = 0;
int ret;
again:
ret = radeon_cs_space_check(radeon->cmdbuf.cs, radeon->state.bos, radeon->state.validated_bo_count);
if (ret == RADEON_CS_SPACE_OP_TO_BIG)
return GL_FALSE;
if (ret == RADEON_CS_SPACE_FLUSH) {
radeonFlush(ctx);
if (flushed)
return GL_FALSE;
flushed = 1;
goto again;
}
return GL_TRUE;
}
void radeon_validate_reset_bos(radeonContextPtr radeon)
{
int i;
for (i = 0; i < radeon->state.validated_bo_count; i++) {
radeon->state.bos[i].bo = NULL;
radeon->state.bos[i].read_domains = 0;
radeon->state.bos[i].write_domain = 0;
radeon->state.bos[i].new_accounted = 0;
}
radeon->state.validated_bo_count = 0;
}
void radeon_validate_bo(radeonContextPtr radeon, struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain)
{
radeon->state.bos[radeon->state.validated_bo_count].bo = bo;
radeon->state.bos[radeon->state.validated_bo_count].read_domains = read_domains;
radeon->state.bos[radeon->state.validated_bo_count].write_domain = write_domain;
radeon->state.bos[radeon->state.validated_bo_count].new_accounted = 0;
radeon->state.validated_bo_count++;
assert(radeon->state.validated_bo_count < RADEON_MAX_BOS);
}
void radeonEmitState(radeonContextPtr radeon)
{
if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
@ -947,6 +990,14 @@ void radeonFlush(GLcontext *ctx)
if (RADEON_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s %d\n", __FUNCTION__, radeon->cmdbuf.cs->cdw);
/* okay if we have no cmds in the buffer &&
we have no DMA flush &&
we have no DMA buffer allocated.
then no point flushing anything at all.
*/
if (!radeon->dma.flush && !radeon->cmdbuf.cs->cdw && !radeon->dma.current)
return;
if (radeon->dma.flush)
radeon->dma.flush( ctx );
@ -1015,6 +1066,11 @@ int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller)
}
radeon_cs_erase(rmesa->cmdbuf.cs);
rmesa->cmdbuf.flushing = 0;
if (radeon_revalidate_bos(rmesa->glCtx) == GL_FALSE) {
fprintf(stderr,"failed to revalidate buffers\n");
}
return ret;
}

View file

@ -47,6 +47,9 @@ void radeon_get_cliprects(radeonContextPtr radeon,
struct drm_clip_rect **cliprects,
unsigned int *num_cliprects,
int *x_off, int *y_off);
GLboolean radeon_revalidate_bos(GLcontext *ctx);
void radeon_validate_bo(radeonContextPtr radeon, struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain);
void radeon_validate_reset_bos(radeonContextPtr radeon);
void radeon_fbo_init(struct radeon_context *radeon);
void

View file

@ -219,7 +219,6 @@ void radeonDestroyContext(__DRIcontextPrivate *driContextPriv )
if (radeon) {
if (radeon->dma.current) {
radeonReleaseDmaRegion( radeon );
rcommonFlushCmdBuf( radeon, __FUNCTION__ );
}

View file

@ -13,6 +13,10 @@
#include "dri_util.h"
#include "tnl/t_vertex.h"
struct radeon_context;
#include "radeon_bocs_wrapper.h"
/* This union is used to avoid warnings/miscompilation
with float to uint32_t casts due to strict-aliasing */
typedef union { GLfloat f; uint32_t ui32; } float_ui32_type;
@ -384,11 +388,15 @@ typedef void (*radeon_line_func) (radeonContextPtr,
typedef void (*radeon_point_func) (radeonContextPtr, radeonVertex *);
#define RADEON_MAX_BOS 24
struct radeon_state {
struct radeon_colorbuffer_state color;
struct radeon_depthbuffer_state depth;
struct radeon_scissor_state scissor;
struct radeon_stencilbuffer_state stencil;
struct radeon_cs_space_check bos[RADEON_MAX_BOS];
int validated_bo_count;
};
/**

View file

@ -163,8 +163,6 @@ void rcommon_emit_vector(GLcontext * ctx, struct radeon_aos *aos,
void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size)
{
struct radeon_cs_space_check bos[1];
int flushed = 0, ret;
size = MAX2(size, MAX_DMA_BUF_SZ * 16);
@ -200,24 +198,11 @@ again_alloc:
rmesa->dma.current_used = 0;
rmesa->dma.current_vertexptr = 0;
bos[0].bo = rmesa->dma.current;
bos[0].read_domains = RADEON_GEM_DOMAIN_GTT;
bos[0].write_domain =0 ;
bos[0].new_accounted = 0;
radeon_validate_bo(rmesa, rmesa->dma.current, RADEON_GEM_DOMAIN_GTT, 0);
ret = radeon_cs_space_check(rmesa->cmdbuf.cs, bos, 1);
if (ret == RADEON_CS_SPACE_OP_TO_BIG) {
fprintf(stderr,"Got OPEARTION TO BIG ILLEGAL - this cannot happen");
assert(0);
} else if (ret == RADEON_CS_SPACE_FLUSH) {
rcommonFlushCmdBuf(rmesa, __FUNCTION__);
if (flushed) {
fprintf(stderr,"flushed but still no space\n");
assert(0);
}
flushed = 1;
goto again_alloc;
}
if (radeon_revalidate_bos(rmesa->glCtx) == GL_FALSE)
fprintf(stderr,"failure to revalidate BOs - badness\n");
radeon_bo_map(rmesa->dma.current, 1);
}

View file

@ -47,6 +47,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "swrast_setup/swrast_setup.h"
#include "radeon_context.h"
#include "radeon_mipmap_tree.h"
#include "radeon_ioctl.h"
#include "radeon_state.h"
#include "radeon_tcl.h"
@ -2043,8 +2044,48 @@ static void update_texturematrix( GLcontext *ctx )
}
}
static GLboolean r100ValidateBuffers(GLcontext *ctx)
{
r100ContextPtr rmesa = R100_CONTEXT(ctx);
struct radeon_renderbuffer *rrb;
int i;
void radeonValidateState( GLcontext *ctx )
radeon_validate_reset_bos(&rmesa->radeon);
rrb = radeon_get_colorbuffer(&rmesa->radeon);
/* color buffer */
if (rrb && rrb->bo) {
radeon_validate_bo(&rmesa->radeon, rrb->bo,
0, RADEON_GEM_DOMAIN_VRAM);
}
/* depth buffer */
rrb = radeon_get_depthbuffer(&rmesa->radeon);
/* color buffer */
if (rrb && rrb->bo) {
radeon_validate_bo(&rmesa->radeon, rrb->bo,
0, RADEON_GEM_DOMAIN_VRAM);
}
for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
radeonTexObj *t;
if (!ctx->Texture.Unit[i]._ReallyEnabled)
continue;
t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
if (t->image_override && t->bo)
radeon_validate_bo(&rmesa->radeon, t->bo,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
else if (t->mt->bo)
radeon_validate_bo(&rmesa->radeon, t->mt->bo,
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
}
return radeon_revalidate_bos(ctx);
}
GLboolean radeonValidateState( GLcontext *ctx )
{
r100ContextPtr rmesa = R100_CONTEXT(ctx);
GLuint new_state = rmesa->radeon.NewGLState;
@ -2061,6 +2102,10 @@ void radeonValidateState( GLcontext *ctx )
new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
}
/* we need to do a space check here */
if (!r100ValidateBuffers(ctx))
return GL_FALSE;
/* Need an event driven matrix update?
*/
if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
@ -2136,7 +2181,8 @@ static void radeonWrapRunPipeline( GLcontext *ctx )
/* Validate state:
*/
if (rmesa->radeon.NewGLState)
radeonValidateState( ctx );
if (!radeonValidateState( ctx ))
FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
has_material = (ctx->Light.Enabled && check_material( ctx ));

View file

@ -50,7 +50,7 @@ extern void radeonUpdateDrawBuffer( GLcontext *ctx );
extern void radeonUploadTexMatrix( r100ContextPtr rmesa,
int unit, GLboolean swapcols );
extern void radeonValidateState( GLcontext *ctx );
extern GLboolean radeonValidateState( GLcontext *ctx );
extern void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode );