r300: Predict emit size for next rendering operation.

We do flush for cmd buffer in case there isn't enough space left for whole
rendering operation. This protects dma regions from getting released in middle
of state emit.

Signed-off-by: Pauli Nieminen <suokkos@gmail.com>
This commit is contained in:
Pauli Nieminen
2009-08-21 18:55:34 +03:00
parent 12fe319c53
commit d6b5464aaa
4 changed files with 43 additions and 4 deletions

View File

@@ -38,6 +38,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_context.h"
#define CACHE_FLUSH_BUFSZ (4*2)
#define PRE_EMIT_STATE_BUFSZ (2+2)
#define AOS_BUFSZ(nr) (3+(nr >>1)*3 + (nr&1)*2 + (nr*2))
#define FIREAOS_BUFSZ (3)
#define SCISSORS_BUFSZ (3)
extern void r300InitCmdBuf(r300ContextPtr r300);
void r300_emit_scissor(GLcontext *ctx);

View File

@@ -39,6 +39,7 @@
#include "r300_render.h"
#include "r300_state.h"
#include "r300_tex.h"
#include "r300_cmdbuf.h"
#include "radeon_buffer_objects.h"
@@ -567,6 +568,34 @@ static void r300FreeData(GLcontext *ctx)
}
}
static GLuint r300PredictTryDrawPrimsSize(GLcontext *ctx, GLuint nr_prims)
{
struct r300_context *r300 = R300_CONTEXT(ctx);
struct r300_vertex_buffer *vbuf = &r300->vbuf;
int flushed;
GLuint dwords;
GLuint state_size;
dwords = 2*CACHE_FLUSH_BUFSZ;
dwords += PRE_EMIT_STATE_BUFSZ;
dwords += (AOS_BUFSZ(vbuf->num_attribs)
+ SCISSORS_BUFSZ
+ FIREAOS_BUFSZ )*nr_prims;
state_size= radeonCountEmitSize(&r300->radeon);
flushed = rcommonEnsureCmdBufSpace(&r300->radeon,
dwords + state_size,
__FUNCTION__);
if (flushed)
dwords += radeonCountEmitSize(&r300->radeon);
else
dwords += state_size;
if (RADEON_DEBUG & DEBUG_PRIMS)
fprintf(stderr, "%s: total prediction size is %d.\n", __FUNCTION__, dwords);
return dwords;
}
static GLboolean r300TryDrawPrims(GLcontext *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
@@ -592,8 +621,6 @@ static GLboolean r300TryDrawPrims(GLcontext *ctx,
r300SwitchFallback(ctx, R300_FALLBACK_INVALID_BUFFERS, !r300ValidateBuffers(ctx));
/* ensure we have the cmd buf space in advance to cover
* the state + DMA AOS pointers */
rcommonEnsureCmdBufSpace(&r300->radeon,
r300->radeon.hw.max_state_size + (60*sizeof(int)),
__FUNCTION__);
@@ -607,6 +634,10 @@ static GLboolean r300TryDrawPrims(GLcontext *ctx,
r300UpdateShaderStates(r300);
/* ensure we have the cmd buf space in advance to cover
* the state + DMA AOS pointers */
r300PredictTryDrawPrimsSize(ctx, nr_prims);
r300SetupIndexBuffer(ctx, ib);
r300AllocDmaRegions(ctx, arrays, max_index + 1);

View File

@@ -3,7 +3,7 @@
#include "radeon_bocs_wrapper.h"
void rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller);
int rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller);
int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller);
int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller);
void rcommonInitCmdBuf(radeonContextPtr rmesa);

View File

@@ -1189,14 +1189,16 @@ int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller)
*
* \param dwords The number of dwords we need to be free on the command buffer
*/
void rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller)
int rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller)
{
if ((rmesa->cmdbuf.cs->cdw + dwords + 128) > rmesa->cmdbuf.size
|| radeon_cs_need_flush(rmesa->cmdbuf.cs)) {
/* If we try to flush empty buffer there is too big rendering operation. */
assert(rmesa->cmdbuf.cs->cdw);
rcommonFlushCmdBuf(rmesa, caller);
return GL_TRUE;
}
return GL_FALSE;
}
void rcommonInitCmdBuf(radeonContextPtr rmesa)