1 /*
2 * Copyright 2009 Corbin Simpson <[email protected]>
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "util/u_memory.h"
7
8 #include "r300_context.h"
9 #include "r300_screen.h"
10 #include "r300_emit.h"
11
12 #include <stdio.h>
13
r300_create_query(struct pipe_context * pipe,unsigned query_type,unsigned index)14 static struct pipe_query *r300_create_query(struct pipe_context *pipe,
15 unsigned query_type,
16 unsigned index)
17 {
18 struct r300_context *r300 = r300_context(pipe);
19 struct r300_screen *r300screen = r300->screen;
20 struct r300_query *q;
21
22 if (query_type != PIPE_QUERY_OCCLUSION_COUNTER &&
23 query_type != PIPE_QUERY_OCCLUSION_PREDICATE &&
24 query_type != PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE &&
25 query_type != PIPE_QUERY_GPU_FINISHED) {
26 return NULL;
27 }
28
29 q = CALLOC_STRUCT(r300_query);
30 if (!q)
31 return NULL;
32
33 q->type = query_type;
34
35 if (query_type == PIPE_QUERY_GPU_FINISHED) {
36 return (struct pipe_query*)q;
37 }
38
39 if (r300screen->caps.family == CHIP_RV530)
40 q->num_pipes = r300screen->info.r300_num_z_pipes;
41 else
42 q->num_pipes = r300screen->info.r300_num_gb_pipes;
43
44 q->buf = r300->rws->buffer_create(r300->rws,
45 r300screen->info.gart_page_size,
46 r300screen->info.gart_page_size,
47 RADEON_DOMAIN_GTT,
48 RADEON_FLAG_NO_INTERPROCESS_SHARING);
49 if (!q->buf) {
50 FREE(q);
51 return NULL;
52 }
53 return (struct pipe_query*)q;
54 }
55
r300_destroy_query(struct pipe_context * pipe,struct pipe_query * query)56 static void r300_destroy_query(struct pipe_context* pipe,
57 struct pipe_query* query)
58 {
59 struct r300_context *r300 = r300_context(pipe);
60 struct r300_query* q = r300_query(query);
61
62 radeon_bo_reference(r300->rws, &q->buf, NULL);
63 FREE(query);
64 }
65
r300_resume_query(struct r300_context * r300,struct r300_query * query)66 void r300_resume_query(struct r300_context *r300,
67 struct r300_query *query)
68 {
69 r300->query_current = query;
70 r300_mark_atom_dirty(r300, &r300->query_start);
71 }
72
r300_begin_query(struct pipe_context * pipe,struct pipe_query * query)73 static bool r300_begin_query(struct pipe_context* pipe,
74 struct pipe_query* query)
75 {
76 struct r300_context* r300 = r300_context(pipe);
77 struct r300_query* q = r300_query(query);
78
79 if (q->type == PIPE_QUERY_GPU_FINISHED)
80 return true;
81
82 if (r300->query_current != NULL) {
83 fprintf(stderr, "r300: begin_query: "
84 "Some other query has already been started.\n");
85 assert(0);
86 return false;
87 }
88
89 q->num_results = 0;
90 r300_resume_query(r300, q);
91 return true;
92 }
93
r300_stop_query(struct r300_context * r300)94 void r300_stop_query(struct r300_context *r300)
95 {
96 r300_emit_query_end(r300);
97 r300->query_current = NULL;
98 }
99
r300_end_query(struct pipe_context * pipe,struct pipe_query * query)100 static bool r300_end_query(struct pipe_context* pipe,
101 struct pipe_query* query)
102 {
103 struct r300_context* r300 = r300_context(pipe);
104 struct r300_query *q = r300_query(query);
105
106 if (q->type == PIPE_QUERY_GPU_FINISHED) {
107 radeon_bo_reference(r300->rws, &q->buf, NULL);
108 r300_flush(pipe, PIPE_FLUSH_ASYNC,
109 (struct pipe_fence_handle**)&q->buf);
110 return true;
111 }
112
113 if (q != r300->query_current) {
114 fprintf(stderr, "r300: end_query: Got invalid query.\n");
115 assert(0);
116 return false;
117 }
118
119 r300_stop_query(r300);
120
121 return true;
122 }
123
r300_get_query_result(struct pipe_context * pipe,struct pipe_query * query,bool wait,union pipe_query_result * vresult)124 static bool r300_get_query_result(struct pipe_context* pipe,
125 struct pipe_query* query,
126 bool wait,
127 union pipe_query_result *vresult)
128 {
129 struct r300_context* r300 = r300_context(pipe);
130 struct r300_query *q = r300_query(query);
131 unsigned i;
132 uint32_t temp, *map;
133
134 if (q->type == PIPE_QUERY_GPU_FINISHED) {
135 if (wait) {
136 r300->rws->buffer_wait(r300->rws, q->buf, OS_TIMEOUT_INFINITE,
137 RADEON_USAGE_READWRITE);
138 vresult->b = true;
139 } else {
140 vresult->b = r300->rws->buffer_wait(r300->rws, q->buf, 0, RADEON_USAGE_READWRITE);
141 }
142 return vresult->b;
143 }
144
145 map = r300->rws->buffer_map(r300->rws, q->buf, &r300->cs,
146 PIPE_MAP_READ |
147 (!wait ? PIPE_MAP_DONTBLOCK : 0));
148 if (!map)
149 return false;
150
151 /* Sum up the results. */
152 temp = 0;
153 for (i = 0; i < q->num_results; i++) {
154 /* Convert little endian values written by GPU to CPU byte order */
155 temp += util_le32_to_cpu(*map);
156 map++;
157 }
158
159 if (q->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
160 q->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
161 vresult->b = temp != 0;
162 } else {
163 vresult->u64 = temp;
164 }
165 return true;
166 }
167
r300_render_condition(struct pipe_context * pipe,struct pipe_query * query,bool condition,enum pipe_render_cond_flag mode)168 static void r300_render_condition(struct pipe_context *pipe,
169 struct pipe_query *query,
170 bool condition,
171 enum pipe_render_cond_flag mode)
172 {
173 struct r300_context *r300 = r300_context(pipe);
174 union pipe_query_result result;
175 bool wait;
176
177 r300->skip_rendering = false;
178
179 if (query) {
180 wait = mode == PIPE_RENDER_COND_WAIT ||
181 mode == PIPE_RENDER_COND_BY_REGION_WAIT;
182
183 if (r300_get_query_result(pipe, query, wait, &result)) {
184 if (r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE ||
185 r300_query(query)->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE) {
186 r300->skip_rendering = condition == result.b;
187 } else {
188 r300->skip_rendering = condition == !!result.u64;
189 }
190 }
191 }
192 }
193
194 static void
r300_set_active_query_state(struct pipe_context * pipe,bool enable)195 r300_set_active_query_state(struct pipe_context *pipe, bool enable)
196 {
197 }
198
r300_init_query_functions(struct r300_context * r300)199 void r300_init_query_functions(struct r300_context* r300)
200 {
201 r300->context.create_query = r300_create_query;
202 r300->context.destroy_query = r300_destroy_query;
203 r300->context.begin_query = r300_begin_query;
204 r300->context.end_query = r300_end_query;
205 r300->context.get_query_result = r300_get_query_result;
206 r300->context.set_active_query_state = r300_set_active_query_state;
207 r300->context.render_condition = r300_render_condition;
208 }
209