mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-03 06:20:34 +02:00
r300g: rewrite occlusion queries
The previous implementation had issues with queries spanning over several command streams as well as using a very large number of queries. This fixes flickering in Enemy Territory: Quake Wars. The driver now renders everything correctly in this game and the graphics is awesome.
This commit is contained in:
parent
824c1f6a4a
commit
cf3778bae0
7 changed files with 168 additions and 159 deletions
|
|
@ -25,8 +25,23 @@
|
|||
|
||||
#include "util/u_format.h"
|
||||
|
||||
static void r300_blitter_save_states(struct r300_context* r300)
|
||||
enum r300_blitter_op
|
||||
{
|
||||
R300_CLEAR,
|
||||
R300_CLEAR_SURFACE,
|
||||
R300_COPY
|
||||
};
|
||||
|
||||
static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op op)
|
||||
{
|
||||
if (r300->query_current) {
|
||||
r300->blitter_saved_query = r300->query_current;
|
||||
r300_stop_query(r300);
|
||||
}
|
||||
|
||||
/* Yeah we have to save all those states to ensure the blitter operation
|
||||
* is really transparent. The states will be restored by the blitter once
|
||||
* copying is done. */
|
||||
util_blitter_save_blend(r300->blitter, r300->blend_state.state);
|
||||
util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state);
|
||||
util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref));
|
||||
|
|
@ -38,6 +53,30 @@ static void r300_blitter_save_states(struct r300_context* r300)
|
|||
util_blitter_save_vertex_elements(r300->blitter, r300->velems);
|
||||
util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count,
|
||||
r300->vertex_buffer);
|
||||
|
||||
if (op & (R300_CLEAR_SURFACE | R300_COPY))
|
||||
util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
|
||||
|
||||
if (op & R300_COPY) {
|
||||
struct r300_textures_state* state =
|
||||
(struct r300_textures_state*)r300->textures_state.state;
|
||||
|
||||
util_blitter_save_fragment_sampler_states(
|
||||
r300->blitter, state->sampler_state_count,
|
||||
(void**)state->sampler_states);
|
||||
|
||||
util_blitter_save_fragment_sampler_views(
|
||||
r300->blitter, state->sampler_view_count,
|
||||
(struct pipe_sampler_view**)state->sampler_views);
|
||||
}
|
||||
}
|
||||
|
||||
static void r300_blitter_end(struct r300_context *r300)
|
||||
{
|
||||
if (r300->blitter_saved_query) {
|
||||
r300_resume_query(r300, r300->blitter_saved_query);
|
||||
r300->blitter_saved_query = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear currently bound buffers. */
|
||||
|
|
@ -73,13 +112,45 @@ static void r300_clear(struct pipe_context* pipe,
|
|||
struct pipe_framebuffer_state* fb =
|
||||
(struct pipe_framebuffer_state*)r300->fb_state.state;
|
||||
|
||||
r300_blitter_save_states(r300);
|
||||
|
||||
r300_blitter_begin(r300, R300_CLEAR);
|
||||
util_blitter_clear(r300->blitter,
|
||||
fb->width,
|
||||
fb->height,
|
||||
fb->nr_cbufs,
|
||||
buffers, rgba, depth, stencil);
|
||||
r300_blitter_end(r300);
|
||||
}
|
||||
|
||||
/* Clear a region of a color surface to a constant value. */
|
||||
static void r300_clear_render_target(struct pipe_context *pipe,
|
||||
struct pipe_surface *dst,
|
||||
const float *rgba,
|
||||
unsigned dstx, unsigned dsty,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
struct r300_context *r300 = r300_context(pipe);
|
||||
|
||||
r300_blitter_begin(r300, R300_CLEAR_SURFACE);
|
||||
util_blitter_clear_render_target(r300->blitter, dst, rgba,
|
||||
dstx, dsty, width, height);
|
||||
r300_blitter_end(r300);
|
||||
}
|
||||
|
||||
/* Clear a region of a depth stencil surface. */
|
||||
static void r300_clear_depth_stencil(struct pipe_context *pipe,
|
||||
struct pipe_surface *dst,
|
||||
unsigned clear_flags,
|
||||
double depth,
|
||||
unsigned stencil,
|
||||
unsigned dstx, unsigned dsty,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
struct r300_context *r300 = r300_context(pipe);
|
||||
|
||||
r300_blitter_begin(r300, R300_CLEAR_SURFACE);
|
||||
util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil,
|
||||
dstx, dsty, width, height);
|
||||
r300_blitter_end(r300);
|
||||
}
|
||||
|
||||
/* Copy a block of pixels from one surface to another using HW. */
|
||||
|
|
@ -93,27 +164,12 @@ static void r300_hw_copy_region(struct pipe_context* pipe,
|
|||
unsigned width, unsigned height)
|
||||
{
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
struct r300_textures_state* state =
|
||||
(struct r300_textures_state*)r300->textures_state.state;
|
||||
|
||||
/* Yeah we have to save all those states to ensure this blitter operation
|
||||
* is really transparent. The states will be restored by the blitter once
|
||||
* copying is done. */
|
||||
r300_blitter_save_states(r300);
|
||||
util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
|
||||
|
||||
util_blitter_save_fragment_sampler_states(
|
||||
r300->blitter, state->sampler_state_count,
|
||||
(void**)state->sampler_states);
|
||||
|
||||
util_blitter_save_fragment_sampler_views(
|
||||
r300->blitter, state->sampler_view_count,
|
||||
(struct pipe_sampler_view**)state->sampler_views);
|
||||
|
||||
/* Do a copy */
|
||||
r300_blitter_begin(r300, R300_COPY);
|
||||
util_blitter_copy_region(r300->blitter, dst, subdst, dstx, dsty, dstz,
|
||||
src, subsrc, srcx, srcy, srcz, width, height,
|
||||
TRUE);
|
||||
r300_blitter_end(r300);
|
||||
}
|
||||
|
||||
/* Copy a block of pixels from one surface to another. */
|
||||
|
|
@ -187,40 +243,6 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
|
|||
}
|
||||
}
|
||||
|
||||
/* Clear a region of a color surface to a constant value. */
|
||||
static void r300_clear_render_target(struct pipe_context *pipe,
|
||||
struct pipe_surface *dst,
|
||||
const float *rgba,
|
||||
unsigned dstx, unsigned dsty,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
struct r300_context *r300 = r300_context(pipe);
|
||||
|
||||
r300_blitter_save_states(r300);
|
||||
util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
|
||||
|
||||
util_blitter_clear_render_target(r300->blitter, dst, rgba,
|
||||
dstx, dsty, width, height);
|
||||
}
|
||||
|
||||
/* Clear a region of a depth stencil surface. */
|
||||
static void r300_clear_depth_stencil(struct pipe_context *pipe,
|
||||
struct pipe_surface *dst,
|
||||
unsigned clear_flags,
|
||||
double depth,
|
||||
unsigned stencil,
|
||||
unsigned dstx, unsigned dsty,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
struct r300_context *r300 = r300_context(pipe);
|
||||
|
||||
r300_blitter_save_states(r300);
|
||||
util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
|
||||
|
||||
util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil,
|
||||
dstx, dsty, width, height);
|
||||
}
|
||||
|
||||
void r300_init_blit_functions(struct r300_context *r300)
|
||||
{
|
||||
r300->context.clear = r300_clear;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
static void r300_destroy_context(struct pipe_context* context)
|
||||
{
|
||||
struct r300_context* r300 = r300_context(context);
|
||||
struct r300_query* query, * temp;
|
||||
struct r300_query *query, *temp;
|
||||
struct r300_atom *atom;
|
||||
|
||||
util_blitter_destroy(r300->blitter);
|
||||
|
|
@ -55,9 +55,6 @@ static void r300_destroy_context(struct pipe_context* context)
|
|||
}
|
||||
}
|
||||
|
||||
/* Free the OQ BO. */
|
||||
context->screen->resource_destroy(context->screen, r300->oqbo);
|
||||
|
||||
/* If there are any queries pending or not destroyed, remove them now. */
|
||||
foreach_s(query, temp, &r300->query_list) {
|
||||
remove_from_list(query);
|
||||
|
|
@ -221,9 +218,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
|
|||
|
||||
r300_setup_atoms(r300);
|
||||
|
||||
/* Open up the OQ BO. */
|
||||
r300->oqbo = pipe_buffer_create(screen,
|
||||
R300_BIND_OQBO, 4096);
|
||||
make_empty_list(&r300->query_list);
|
||||
|
||||
r300_init_blit_functions(r300);
|
||||
|
|
|
|||
|
|
@ -241,14 +241,23 @@ struct r300_constant_buffer {
|
|||
struct r300_query {
|
||||
/* The kind of query. Currently only OQ is supported. */
|
||||
unsigned type;
|
||||
/* The current count of this query. Required to be at least 32 bits. */
|
||||
unsigned int count;
|
||||
/* The offset of this query into the query buffer, in bytes. */
|
||||
unsigned offset;
|
||||
/* The number of pipes where query results are stored. */
|
||||
unsigned num_pipes;
|
||||
/* How many results have been written, in dwords. It's incremented
|
||||
* after end_query and flush. */
|
||||
unsigned num_results;
|
||||
/* if we've flushed the query */
|
||||
boolean flushed;
|
||||
/* if begin has been emitted */
|
||||
boolean begin_emitted;
|
||||
|
||||
/* The buffer where query results are stored. */
|
||||
struct r300_winsys_buffer *buffer;
|
||||
/* The size of the buffer. */
|
||||
unsigned buffer_size;
|
||||
/* The domain of the buffer. */
|
||||
enum r300_buffer_domain domain;
|
||||
|
||||
/* Linked list members. */
|
||||
struct r300_query* prev;
|
||||
struct r300_query* next;
|
||||
|
|
@ -388,10 +397,11 @@ struct r300_context {
|
|||
/* Offset into the VBO. */
|
||||
size_t vbo_offset;
|
||||
|
||||
/* Occlusion query buffer. */
|
||||
struct pipe_resource* oqbo;
|
||||
/* Query list. */
|
||||
/* The currently active query. */
|
||||
struct r300_query *query_current;
|
||||
/* The saved query for blitter operations. */
|
||||
struct r300_query *blitter_saved_query;
|
||||
/* Query list. */
|
||||
struct r300_query query_list;
|
||||
|
||||
/* Various CSO state objects. */
|
||||
|
|
@ -522,6 +532,11 @@ void r300_init_render_functions(struct r300_context *r300);
|
|||
void r300_init_state_functions(struct r300_context* r300);
|
||||
void r300_init_resource_functions(struct r300_context* r300);
|
||||
|
||||
/* r300_query.c */
|
||||
void r300_resume_query(struct r300_context *r300,
|
||||
struct r300_query *query);
|
||||
void r300_stop_query(struct r300_context *r300);
|
||||
|
||||
/* r300_render_translate.c */
|
||||
void r300_begin_vertex_translate(struct r300_context *r300);
|
||||
void r300_end_vertex_translate(struct r300_context *r300);
|
||||
|
|
|
|||
|
|
@ -32,12 +32,6 @@
|
|||
|
||||
#define R300_INVALID_FORMAT 0xffff
|
||||
|
||||
/* XXX: this is just a bandaid on larger problems in
|
||||
* r300_screen_buffer.h which doesn't seem to be fully ported to
|
||||
* gallium-resources.
|
||||
*/
|
||||
#define R300_BIND_OQBO (1<<21)
|
||||
|
||||
/* Tiling flags. */
|
||||
enum r300_buffer_tiling {
|
||||
R300_BUFFER_LINEAR = 0,
|
||||
|
|
|
|||
|
|
@ -353,13 +353,14 @@ void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state)
|
|||
OUT_CS_REG(R300_ZB_ZPASS_DATA, 0);
|
||||
END_CS;
|
||||
query->begin_emitted = TRUE;
|
||||
query->flushed = FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
|
||||
struct r300_query *query)
|
||||
{
|
||||
struct r300_capabilities* caps = &r300->screen->caps;
|
||||
struct r300_winsys_buffer *buf = r300->query_current->buffer;
|
||||
CS_LOCALS(r300);
|
||||
|
||||
assert(caps->num_frag_pipes);
|
||||
|
|
@ -378,28 +379,28 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
|
|||
/* pipe 3 only */
|
||||
OUT_CS_REG(R300_SU_REG_DEST, 1 << 3);
|
||||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
|
||||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3),
|
||||
0, r300_buffer(r300->oqbo)->domain, 0);
|
||||
OUT_CS_RELOC(buf, (query->num_results + 3) * 4,
|
||||
0, query->domain, 0);
|
||||
case 3:
|
||||
/* pipe 2 only */
|
||||
OUT_CS_REG(R300_SU_REG_DEST, 1 << 2);
|
||||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
|
||||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2),
|
||||
0, r300_buffer(r300->oqbo)->domain, 0);
|
||||
OUT_CS_RELOC(buf, (query->num_results + 2) * 4,
|
||||
0, query->domain, 0);
|
||||
case 2:
|
||||
/* pipe 1 only */
|
||||
/* As mentioned above, accomodate RV380 and older. */
|
||||
OUT_CS_REG(R300_SU_REG_DEST,
|
||||
1 << (caps->high_second_pipe ? 3 : 1));
|
||||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
|
||||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1),
|
||||
0, r300_buffer(r300->oqbo)->domain, 0);
|
||||
OUT_CS_RELOC(buf, (query->num_results + 1) * 4,
|
||||
0, query->domain, 0);
|
||||
case 1:
|
||||
/* pipe 0 only */
|
||||
OUT_CS_REG(R300_SU_REG_DEST, 1 << 0);
|
||||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
|
||||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0),
|
||||
0, r300_buffer(r300->oqbo)->domain, 0);
|
||||
OUT_CS_RELOC(buf, (query->num_results + 0) * 4,
|
||||
0, query->domain, 0);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "r300: Implementation error: Chipset reports %d"
|
||||
|
|
@ -415,12 +416,13 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300,
|
|||
static void rv530_emit_query_end_single_z(struct r300_context *r300,
|
||||
struct r300_query *query)
|
||||
{
|
||||
struct r300_winsys_buffer *buf = r300->query_current->buffer;
|
||||
CS_LOCALS(r300);
|
||||
|
||||
BEGIN_CS(8);
|
||||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
|
||||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
|
||||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, r300_buffer(r300->oqbo)->domain, 0);
|
||||
OUT_CS_RELOC(buf, query->num_results * 4, 0, query->domain, 0);
|
||||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
|
||||
END_CS;
|
||||
}
|
||||
|
|
@ -428,15 +430,16 @@ static void rv530_emit_query_end_single_z(struct r300_context *r300,
|
|||
static void rv530_emit_query_end_double_z(struct r300_context *r300,
|
||||
struct r300_query *query)
|
||||
{
|
||||
struct r300_winsys_buffer *buf = r300->query_current->buffer;
|
||||
CS_LOCALS(r300);
|
||||
|
||||
BEGIN_CS(14);
|
||||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
|
||||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
|
||||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, r300_buffer(r300->oqbo)->domain, 0);
|
||||
OUT_CS_RELOC(buf, (query->num_results + 0) * 4, 0, query->domain, 0);
|
||||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
|
||||
OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
|
||||
OUT_CS_BUF_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, r300_buffer(r300->oqbo)->domain, 0);
|
||||
OUT_CS_RELOC(buf, (query->num_results + 1) * 4, 0, query->domain, 0);
|
||||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
|
||||
END_CS;
|
||||
}
|
||||
|
|
@ -461,6 +464,13 @@ void r300_emit_query_end(struct r300_context* r300)
|
|||
r300_emit_query_end_frag_pipes(r300, query);
|
||||
|
||||
query->begin_emitted = FALSE;
|
||||
query->num_results += query->num_pipes;
|
||||
|
||||
/* XXX grab all the results and reset the counter. */
|
||||
if (query->num_results >= query->buffer_size / 4 - 4) {
|
||||
query->num_results = (query->buffer_size / 4) / 2;
|
||||
fprintf(stderr, "r300: Rewinding OQBO...\n");
|
||||
}
|
||||
}
|
||||
|
||||
void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state)
|
||||
|
|
@ -895,10 +905,9 @@ validate:
|
|||
}
|
||||
}
|
||||
/* ...occlusion query buffer... */
|
||||
if (r300->query_start.dirty ||
|
||||
(r300->query_current && r300->query_current->begin_emitted)) {
|
||||
if (!r300_add_buffer(r300->rws, r300->oqbo,
|
||||
0, r300_buffer(r300->oqbo)->domain)) {
|
||||
if (r300->query_current) {
|
||||
if (!r300->rws->add_buffer(r300->rws, r300->query_current->buffer,
|
||||
0, r300->query_current->domain)) {
|
||||
r300->context.flush(&r300->context, 0, NULL);
|
||||
goto validate;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "r300_context.h"
|
||||
#include "r300_screen.h"
|
||||
#include "r300_emit.h"
|
||||
#include "r300_winsys.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
@ -34,30 +35,27 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
|
|||
{
|
||||
struct r300_context *r300 = r300_context(pipe);
|
||||
struct r300_screen *r300screen = r300->screen;
|
||||
unsigned query_size;
|
||||
struct r300_query *q, *qptr;
|
||||
struct r300_query *q;
|
||||
|
||||
assert(query_type == PIPE_QUERY_OCCLUSION_COUNTER);
|
||||
|
||||
q = CALLOC_STRUCT(r300_query);
|
||||
if (!q)
|
||||
return NULL;
|
||||
|
||||
q->type = query_type;
|
||||
assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER);
|
||||
q->domain = R300_DOMAIN_GTT;
|
||||
q->buffer_size = 4096;
|
||||
|
||||
if (r300screen->caps.family == CHIP_FAMILY_RV530)
|
||||
query_size = r300screen->caps.num_z_pipes * sizeof(uint32_t);
|
||||
q->num_pipes = r300screen->caps.num_z_pipes;
|
||||
else
|
||||
query_size = r300screen->caps.num_frag_pipes * sizeof(uint32_t);
|
||||
q->num_pipes = r300screen->caps.num_frag_pipes;
|
||||
|
||||
if (!is_empty_list(&r300->query_list)) {
|
||||
qptr = last_elem(&r300->query_list);
|
||||
q->offset = qptr->offset + query_size;
|
||||
}
|
||||
insert_at_tail(&r300->query_list, q);
|
||||
|
||||
/* XXX */
|
||||
if (q->offset >= 4096) {
|
||||
q->offset = 0;
|
||||
fprintf(stderr, "r300: Rewinding OQBO...\n");
|
||||
}
|
||||
/* Open up the occlusion query buffer. */
|
||||
q->buffer = r300->rws->buffer_create(r300->rws, 4096, 0, q->domain, q->buffer_size);
|
||||
|
||||
return (struct pipe_query*)q;
|
||||
}
|
||||
|
|
@ -65,18 +63,26 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe,
|
|||
static void r300_destroy_query(struct pipe_context* pipe,
|
||||
struct pipe_query* query)
|
||||
{
|
||||
struct r300_query* q = (struct r300_query*)query;
|
||||
struct r300_context *r300 = r300_context(pipe);
|
||||
struct r300_query* q = r300_query(query);
|
||||
|
||||
r300->rws->buffer_reference(r300->rws, &q->buffer, NULL);
|
||||
remove_from_list(q);
|
||||
FREE(query);
|
||||
}
|
||||
|
||||
void r300_resume_query(struct r300_context *r300,
|
||||
struct r300_query *query)
|
||||
{
|
||||
r300->query_current = query;
|
||||
r300->query_start.dirty = TRUE;
|
||||
}
|
||||
|
||||
static void r300_begin_query(struct pipe_context* pipe,
|
||||
struct pipe_query* query)
|
||||
{
|
||||
uint32_t value = ~0U;
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
struct r300_query* q = (struct r300_query*)query;
|
||||
struct r300_query* q = r300_query(query);
|
||||
|
||||
if (r300->query_current != NULL) {
|
||||
fprintf(stderr, "r300: begin_query: "
|
||||
|
|
@ -85,30 +91,29 @@ static void r300_begin_query(struct pipe_context* pipe,
|
|||
return;
|
||||
}
|
||||
|
||||
pipe_buffer_write(pipe,
|
||||
r300->oqbo,
|
||||
q->offset,
|
||||
sizeof value,
|
||||
&value);
|
||||
q->num_results = 0;
|
||||
r300_resume_query(r300, q);
|
||||
}
|
||||
|
||||
q->flushed = FALSE;
|
||||
r300->query_current = q;
|
||||
r300->query_start.dirty = TRUE;
|
||||
void r300_stop_query(struct r300_context *r300)
|
||||
{
|
||||
r300_emit_query_end(r300);
|
||||
r300->query_current = NULL;
|
||||
}
|
||||
|
||||
static void r300_end_query(struct pipe_context* pipe,
|
||||
struct pipe_query* query)
|
||||
{
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
struct r300_query *q = r300_query(query);
|
||||
|
||||
if ((struct r300_query*)query != r300->query_current) {
|
||||
if (q != r300->query_current) {
|
||||
fprintf(stderr, "r300: end_query: Got invalid query.\n");
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
r300_emit_query_end(r300);
|
||||
r300->query_current = NULL;
|
||||
r300_stop_query(r300);
|
||||
}
|
||||
|
||||
static boolean r300_get_query_result(struct pipe_context* pipe,
|
||||
|
|
@ -117,54 +122,28 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
|
|||
void* vresult)
|
||||
{
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
struct r300_screen* r300screen = r300->screen;
|
||||
struct r300_query *q = (struct r300_query*)query;
|
||||
struct pipe_transfer *transfer;
|
||||
unsigned flags = PIPE_TRANSFER_READ;
|
||||
uint32_t* map;
|
||||
uint32_t temp = 0;
|
||||
unsigned i, num_results;
|
||||
struct r300_query *q = r300_query(query);
|
||||
unsigned flags, i;
|
||||
uint32_t temp, *map;
|
||||
uint64_t *result = (uint64_t*)vresult;
|
||||
|
||||
if (q->flushed == FALSE)
|
||||
if (!q->flushed)
|
||||
pipe->flush(pipe, 0, NULL);
|
||||
if (!wait) {
|
||||
flags |= PIPE_TRANSFER_DONTBLOCK;
|
||||
}
|
||||
|
||||
map = pipe_buffer_map(pipe, r300->oqbo, flags, &transfer);
|
||||
flags = PIPE_TRANSFER_READ | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0);
|
||||
|
||||
map = r300->rws->buffer_map(r300->rws, q->buffer, flags);
|
||||
if (!map)
|
||||
return FALSE;
|
||||
map += q->offset / 4;
|
||||
|
||||
if (r300screen->caps.family == CHIP_FAMILY_RV530)
|
||||
num_results = r300screen->caps.num_z_pipes;
|
||||
else
|
||||
num_results = r300screen->caps.num_frag_pipes;
|
||||
|
||||
for (i = 0; i < num_results; i++) {
|
||||
if (*map == ~0U) {
|
||||
/* Looks like our results aren't ready yet. */
|
||||
if (wait) {
|
||||
fprintf(stderr, "r300: Despite waiting, OQ results haven't "
|
||||
"come in yet. This is a driver bug.\n"
|
||||
"r300: Returning bogus results to avoid "
|
||||
"a possible infinite loop...\n");
|
||||
temp = 987654321;
|
||||
} else {
|
||||
temp = ~0U;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Sum up the results. */
|
||||
temp = 0;
|
||||
for (i = 0; i < q->num_results; i++) {
|
||||
temp += *map;
|
||||
map++;
|
||||
}
|
||||
pipe_buffer_unmap(pipe, r300->oqbo, transfer);
|
||||
|
||||
if (temp == ~0U) {
|
||||
/* Our results haven't been written yet... */
|
||||
return FALSE;
|
||||
}
|
||||
r300->rws->buffer_unmap(r300->rws, q->buffer);
|
||||
|
||||
*result = temp;
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -264,10 +264,6 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
|
|||
rbuf->b.vtbl = &r300_buffer_vtbl;
|
||||
pipe_reference_init(&rbuf->b.b.reference, 1);
|
||||
rbuf->b.b.screen = screen;
|
||||
|
||||
if (rbuf->b.b.bind & R300_BIND_OQBO)
|
||||
alignment = 4096;
|
||||
|
||||
rbuf->domain = R300_DOMAIN_GTT;
|
||||
|
||||
rbuf->buf = r300screen->rws->buffer_create(r300screen->rws,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue