mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-03 15:10:37 +01:00
r300g: fixup arb occulsion query support.
1: add rv530 support - num z pipes cap - add proper start/finish query options for rv530 2: convert to use linked list properly. 3: add flushing required check. 4: initial Z top disabling support. TODO: make it actually work on my rv530.
This commit is contained in:
parent
210481ae16
commit
c1bee7bdea
11 changed files with 134 additions and 43 deletions
|
|
@ -36,6 +36,8 @@ struct r300_capabilities {
|
|||
int num_vert_fpus;
|
||||
/* The number of fragment pipes */
|
||||
int num_frag_pipes;
|
||||
/* The number of z pipes */
|
||||
int num_z_pipes;
|
||||
/* Whether or not TCL is physically present */
|
||||
boolean has_tcl;
|
||||
/* Whether or not this is an RV515 or newer; R500s have many differences
|
||||
|
|
|
|||
|
|
@ -99,11 +99,9 @@ static void r300_destroy_context(struct pipe_context* context) {
|
|||
context->screen->buffer_destroy(r300->oqbo);
|
||||
|
||||
/* If there are any queries pending or not destroyed, remove them now. */
|
||||
if (r300->query_list) {
|
||||
foreach_s(query, temp, r300->query_list) {
|
||||
remove_from_list(query);
|
||||
FREE(query);
|
||||
}
|
||||
foreach_s(query, temp, &r300->query_list) {
|
||||
remove_from_list(query);
|
||||
FREE(query);
|
||||
}
|
||||
|
||||
FREE(r300->blend_color_state);
|
||||
|
|
@ -201,6 +199,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
|
|||
r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300);
|
||||
r300->dirty_state = R300_NEW_KITCHEN_SINK;
|
||||
r300->dirty_hw++;
|
||||
|
||||
make_empty_list(&r300->query_list);
|
||||
return &r300->context;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,6 +172,8 @@ struct r300_query {
|
|||
unsigned int count;
|
||||
/* The offset of this query into the query buffer, in bytes. */
|
||||
unsigned offset;
|
||||
/* if we've flushed the query */
|
||||
boolean flushed;
|
||||
/* Linked list members. */
|
||||
struct r300_query* prev;
|
||||
struct r300_query* next;
|
||||
|
|
@ -237,7 +239,7 @@ struct r300_context {
|
|||
/* Occlusion query buffer. */
|
||||
struct pipe_buffer* oqbo;
|
||||
/* Query list. */
|
||||
struct r300_query* query_list;
|
||||
struct r300_query query_list;
|
||||
|
||||
/* Various CSO state objects. */
|
||||
/* Blend state. */
|
||||
|
|
|
|||
|
|
@ -323,28 +323,30 @@ void r300_emit_fb_state(struct r300_context* r300,
|
|||
void r300_emit_query_begin(struct r300_context* r300,
|
||||
struct r300_query* query)
|
||||
{
|
||||
struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
|
||||
CS_LOCALS(r300);
|
||||
|
||||
/* XXX This will almost certainly not return good results
|
||||
* for overlapping queries. */
|
||||
BEGIN_CS(2);
|
||||
BEGIN_CS(4);
|
||||
if (caps->family == CHIP_FAMILY_RV530) {
|
||||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
|
||||
} else {
|
||||
OUT_CS_REG(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
|
||||
}
|
||||
OUT_CS_REG(R300_ZB_ZPASS_DATA, 0);
|
||||
END_CS;
|
||||
}
|
||||
|
||||
void r300_emit_query_end(struct r300_context* r300,
|
||||
struct r300_query* query)
|
||||
|
||||
static void r300_emit_query_finish(struct r300_context *r300,
|
||||
struct r300_query *query)
|
||||
{
|
||||
struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps;
|
||||
CS_LOCALS(r300);
|
||||
|
||||
if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
|
||||
0, RADEON_GEM_DOMAIN_GTT)) {
|
||||
debug_printf("r300: There wasn't room for the OQ buffer!?"
|
||||
" Oh noes!\n");
|
||||
}
|
||||
|
||||
assert(caps->num_frag_pipes);
|
||||
|
||||
BEGIN_CS(6 * caps->num_frag_pipes + 2);
|
||||
/* I'm not so sure I like this switch, but it's hard to be elegant
|
||||
* when there's so many special cases...
|
||||
|
|
@ -394,6 +396,55 @@ void r300_emit_query_end(struct r300_context* r300,
|
|||
|
||||
}
|
||||
|
||||
static void rv530_emit_query_single(struct r300_context *r300,
|
||||
struct r300_query *query)
|
||||
{
|
||||
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_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
|
||||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
|
||||
END_CS;
|
||||
}
|
||||
|
||||
static void rv530_emit_query_double(struct r300_context *r300,
|
||||
struct r300_query *query)
|
||||
{
|
||||
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_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 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_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
|
||||
OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
|
||||
END_CS;
|
||||
}
|
||||
|
||||
void r300_emit_query_end(struct r300_context* r300,
|
||||
struct r300_query* query)
|
||||
{
|
||||
struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps;
|
||||
|
||||
if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
|
||||
0, RADEON_GEM_DOMAIN_GTT)) {
|
||||
debug_printf("r300: There wasn't room for the OQ buffer!?"
|
||||
" Oh noes!\n");
|
||||
}
|
||||
|
||||
if (caps->family == CHIP_FAMILY_RV530) {
|
||||
if (caps->num_z_pipes == 2)
|
||||
rv530_emit_query_double(r300, query);
|
||||
else
|
||||
rv530_emit_query_single(r300, query);
|
||||
} else
|
||||
r300_emit_query_finish(r300, query);
|
||||
}
|
||||
|
||||
void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs)
|
||||
{
|
||||
CS_LOCALS(r300);
|
||||
|
|
|
|||
|
|
@ -26,9 +26,10 @@ static void r300_flush(struct pipe_context* pipe,
|
|||
unsigned flags,
|
||||
struct pipe_fence_handle** fence)
|
||||
{
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
CS_LOCALS(r300);
|
||||
struct r300_context *r300 = r300_context(pipe);
|
||||
struct r300_query *query;
|
||||
|
||||
CS_LOCALS(r300);
|
||||
/* We probably need to flush Draw, but we may have been called from
|
||||
* within Draw. This feels kludgy, but it might be the best thing. */
|
||||
if (!r300->draw->flushing) {
|
||||
|
|
@ -41,8 +42,13 @@ static void r300_flush(struct pipe_context* pipe,
|
|||
r300->dirty_state = R300_NEW_KITCHEN_SINK;
|
||||
r300->dirty_hw = 0;
|
||||
}
|
||||
/* reset flushed query */
|
||||
foreach(query, &r300->query_list) {
|
||||
query->flushed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void r300_init_flush_functions(struct r300_context* r300)
|
||||
{
|
||||
r300->context.flush = r300_flush;
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@
|
|||
|
||||
#include "r300_emit.h"
|
||||
|
||||
static struct pipe_query* r300_create_query(struct pipe_context* pipe,
|
||||
static struct pipe_query *r300_create_query(struct pipe_context *pipe,
|
||||
unsigned query_type)
|
||||
{
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
struct r300_screen* r300screen = r300_screen(r300->context.screen);
|
||||
unsigned query_size = r300screen->caps->num_frag_pipes * 4;
|
||||
struct r300_query* q, * qptr;
|
||||
struct r300_context *r300 = r300_context(pipe);
|
||||
struct r300_screen *r300screen = r300_screen(r300->context.screen);
|
||||
unsigned query_size;
|
||||
struct r300_query *q, *qptr;
|
||||
|
||||
q = CALLOC_STRUCT(r300_query);
|
||||
|
||||
|
|
@ -39,13 +39,16 @@ static struct pipe_query* r300_create_query(struct pipe_context* pipe,
|
|||
|
||||
q->active = FALSE;
|
||||
|
||||
if (!r300->query_list) {
|
||||
r300->query_list = q;
|
||||
} else if (!is_empty_list(r300->query_list)) {
|
||||
qptr = last_elem(r300->query_list);
|
||||
if (r300screen->caps->family == CHIP_FAMILY_RV530)
|
||||
query_size = r300screen->caps->num_z_pipes * sizeof(uint32_t);
|
||||
else
|
||||
query_size = r300screen->caps->num_frag_pipes * sizeof(uint32_t);
|
||||
|
||||
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);
|
||||
}
|
||||
insert_at_tail(&r300->query_list, q);
|
||||
|
||||
/* XXX */
|
||||
if (q->offset >= 4096) {
|
||||
|
|
@ -74,9 +77,10 @@ static void r300_begin_query(struct pipe_context* pipe,
|
|||
map = pipe->screen->buffer_map(pipe->screen, r300->oqbo,
|
||||
PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
map += q->offset / 4;
|
||||
*map = ~0;
|
||||
*map = ~0U;
|
||||
pipe->screen->buffer_unmap(pipe->screen, r300->oqbo);
|
||||
|
||||
q->flushed = FALSE;
|
||||
r300_emit_dirty_state(r300);
|
||||
r300_emit_query_begin(r300, q);
|
||||
}
|
||||
|
|
@ -98,28 +102,30 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
|
|||
{
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
struct r300_screen* r300screen = r300_screen(r300->context.screen);
|
||||
struct r300_query* q = (struct r300_query*)query;
|
||||
struct r300_query *q = (struct r300_query*)query;
|
||||
unsigned flags = PIPE_BUFFER_USAGE_CPU_READ;
|
||||
uint32_t* map;
|
||||
uint32_t temp;
|
||||
uint32_t temp = 0;
|
||||
unsigned i;
|
||||
|
||||
if (wait) {
|
||||
if (q->flushed == FALSE)
|
||||
pipe->flush(pipe, 0, NULL);
|
||||
} else {
|
||||
if (!wait) {
|
||||
flags |= PIPE_BUFFER_USAGE_DONTBLOCK;
|
||||
}
|
||||
|
||||
map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, flags);
|
||||
if (!map)
|
||||
return FALSE;
|
||||
map += q->offset / 4;
|
||||
for (i = 0; i < r300screen->caps->num_frag_pipes; i++) {
|
||||
if (*map == ~0) {
|
||||
if (*map == ~0U) {
|
||||
/* Looks like our results aren't ready yet. */
|
||||
if (wait) {
|
||||
debug_printf("r300: Despite waiting, OQ results haven't"
|
||||
" come in yet.\n");
|
||||
}
|
||||
temp = ~0;
|
||||
temp = ~0U;
|
||||
break;
|
||||
}
|
||||
temp += *map;
|
||||
|
|
@ -127,7 +133,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe,
|
|||
}
|
||||
pipe->screen->buffer_unmap(pipe->screen, r300->oqbo);
|
||||
|
||||
if (temp == ~0) {
|
||||
if (temp == ~0U) {
|
||||
/* Our results haven't been written yet... */
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1172,6 +1172,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
/* SU Depth Offset value */
|
||||
#define R300_SU_DEPTH_OFFSET 0x42c4
|
||||
|
||||
#define R300_SU_REG_DEST 0x42c8
|
||||
# define R300_RASTER_PIPE_SELECT_0 (1 << 0)
|
||||
# define R300_RASTER_PIPE_SELECT_1 (1 << 1)
|
||||
# define R300_RASTER_PIPE_SELECT_2 (1 << 2)
|
||||
# define R300_RASTER_PIPE_SELECT_3 (1 << 3)
|
||||
# define R300_RASTER_PIPE_SELECT_ALL 0xf
|
||||
|
||||
|
||||
/* BEGIN: Rasterization / Interpolators - many guesses */
|
||||
|
||||
|
|
@ -2095,6 +2102,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define R500_FG_ALPHA_VALUE 0x4be0
|
||||
# define R500_FG_ALPHA_VALUE_MASK 0x0000ffff
|
||||
|
||||
#define RV530_FG_ZBREG_DEST 0x4be8
|
||||
# define RV530_FG_ZBREG_DEST_PIPE_SELECT_0 (1 << 0)
|
||||
# define RV530_FG_ZBREG_DEST_PIPE_SELECT_1 (1 << 1)
|
||||
# define RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL (3 << 0)
|
||||
/* gap */
|
||||
|
||||
/* Fragment program parameters in 7.16 floating point */
|
||||
|
|
@ -3313,10 +3324,6 @@ enum {
|
|||
|
||||
#define R200_3D_DRAW_IMMD_2 0xC0003500
|
||||
|
||||
/* XXX Oh look, stuff not brought over from docs yet */
|
||||
|
||||
#define R300_SU_REG_DEST 0x42C8
|
||||
|
||||
#endif /* _R300_REG_H */
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
|
|
|||
|
|
@ -395,6 +395,7 @@ struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys)
|
|||
|
||||
caps->pci_id = r300_winsys->pci_id;
|
||||
caps->num_frag_pipes = r300_winsys->gb_pipes;
|
||||
caps->num_z_pipes = r300_winsys->z_pipes;
|
||||
|
||||
r300_parse_chipset(caps);
|
||||
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ static void*
|
|||
r300_create_dsa_state(struct pipe_context* pipe,
|
||||
const struct pipe_depth_stencil_alpha_state* state)
|
||||
{
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state);
|
||||
|
||||
/* Depth test setup. */
|
||||
|
|
@ -247,11 +248,15 @@ static void*
|
|||
R300_FG_ALPHA_FUNC_ENABLE;
|
||||
dsa->alpha_reference = CLAMP(state->alpha.ref_value * 1023.0f,
|
||||
0, 1023);
|
||||
} else {
|
||||
/* XXX need to fix this to be dynamically set
|
||||
dsa->z_buffer_top = R300_ZTOP_ENABLE; */
|
||||
}
|
||||
|
||||
dsa->z_buffer_top = R300_ZTOP_ENABLE;
|
||||
/* XXX TODO: add frag prog rules for ztop disable */
|
||||
if (state->alpha.enabled && state->alpha.func != PIPE_FUNC_ALWAYS)
|
||||
dsa->z_buffer_top = R300_ZTOP_DISABLE;
|
||||
if (!is_empty_list(&r300->query_list))
|
||||
dsa->z_buffer_top = R300_ZTOP_DISABLE;
|
||||
|
||||
return (void*)dsa;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@ struct r300_winsys {
|
|||
/* GB pipe count */
|
||||
uint32_t gb_pipes;
|
||||
|
||||
/* Z pipe count (rv530 only) */
|
||||
uint32_t z_pipes;
|
||||
|
||||
/* GART size. */
|
||||
uint32_t gart_size;
|
||||
|
||||
|
|
|
|||
|
|
@ -164,6 +164,16 @@ static void do_ioctls(struct r300_winsys* winsys, int fd)
|
|||
}
|
||||
winsys->gb_pipes = target;
|
||||
|
||||
/* get Z pipes */
|
||||
info.request = RADEON_INFO_NUM_Z_PIPES;
|
||||
retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
|
||||
if (retval) {
|
||||
fprintf(stderr, "%s: Failed to get GB pipe count, "
|
||||
"error number %d\n", __FUNCTION__, retval);
|
||||
exit(1);
|
||||
}
|
||||
winsys->z_pipes = target;
|
||||
|
||||
/* Then, get PCI ID */
|
||||
info.request = RADEON_INFO_DEVICE_ID;
|
||||
retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue