xref: /aosp_15_r20/external/mesa3d/src/mesa/state_tracker/st_draw_feedback.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 
29 #include "main/arrayobj.h"
30 #include "main/image.h"
31 #include "main/macros.h"
32 #include "main/varray.h"
33 
34 #include "vbo/vbo.h"
35 
36 #include "st_context.h"
37 #include "st_atom.h"
38 #include "st_cb_bitmap.h"
39 #include "st_draw.h"
40 #include "st_program.h"
41 #include "st_util.h"
42 
43 #include "pipe/p_context.h"
44 #include "pipe/p_defines.h"
45 #include "util/u_inlines.h"
46 #include "util/u_draw.h"
47 #include "util/format/u_format.h"
48 
49 #include "draw/draw_private.h"
50 #include "draw/draw_context.h"
51 
52 
53 /**
54  * Set the (private) draw module's post-transformed vertex format when in
55  * GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
56  */
57 static void
set_feedback_vertex_format(struct gl_context * ctx)58 set_feedback_vertex_format(struct gl_context *ctx)
59 {
60 #if 0
61    struct st_context *st = st_context(ctx);
62    struct vertex_info vinfo;
63    GLuint i;
64 
65    memset(&vinfo, 0, sizeof(vinfo));
66 
67    if (ctx->RenderMode == GL_SELECT) {
68       assert(ctx->RenderMode == GL_SELECT);
69       vinfo.num_attribs = 1;
70       vinfo.format[0] = FORMAT_4F;
71       vinfo.interp_mode[0] = INTERP_LINEAR;
72    }
73    else {
74       /* GL_FEEDBACK, or glRasterPos */
75       /* emit all attribs (pos, color, texcoord) as GLfloat[4] */
76       vinfo.num_attribs = st->state.vs->cso->state.num_outputs;
77       for (i = 0; i < vinfo.num_attribs; i++) {
78          vinfo.format[i] = FORMAT_4F;
79          vinfo.interp_mode[i] = INTERP_LINEAR;
80       }
81    }
82 
83    draw_set_vertex_info(st->draw, &vinfo);
84 #endif
85 }
86 
87 
88 /**
89  * Called by VBO to draw arrays when in selection or feedback mode and
90  * to implement glRasterPos.
91  * This function mirrors the normal st_draw_vbo().
92  * Look at code refactoring some day.
93  */
94 void
st_feedback_draw_vbo(struct gl_context * ctx,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)95 st_feedback_draw_vbo(struct gl_context *ctx,
96                      const struct pipe_draw_info *info,
97                      unsigned drawid_offset,
98                      const struct pipe_draw_indirect_info *indirect,
99                      const struct pipe_draw_start_count_bias *draws,
100                      unsigned num_draws)
101 {
102    struct st_context *st = st_context(ctx);
103    struct pipe_context *pipe = st->pipe;
104    struct draw_context *draw = st_get_draw_context(st);
105    struct gl_vertex_program *vp;
106    struct st_common_variant *vp_variant;
107    struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
108    unsigned num_vbuffers = 0;
109    struct cso_velems_state velements;
110    struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {NULL};
111    struct pipe_transfer *ib_transfer = NULL;
112    GLuint i;
113    const void *mapped_indices = NULL;
114 
115    if (!draw)
116       return;
117 
118    /* must get these after state validation! */
119    struct st_common_variant_key key = {
120       .st = st,
121       .passthrough_edgeflags = st->ctx->Array._PerVertexEdgeFlagsEnabled,
122       .is_draw_shader = true
123    };
124    vp = (struct gl_vertex_program *)ctx->VertexProgram._Current;
125    vp_variant = st_get_common_variant(st, &vp->Base, &key);
126 
127    /*
128     * Set up the draw module's state.
129     *
130     * We'd like to do this less frequently, but the normal state-update
131     * code sends state updates to the pipe, not to our private draw module.
132     */
133    assert(draw);
134    draw_set_viewport_states(draw, 0, 1, &st->state.viewport[0]);
135    draw_set_clip_state(draw, &st->state.clip);
136    draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL);
137    draw_bind_vertex_shader(draw, vp_variant->base.driver_shader);
138    set_feedback_vertex_format(ctx);
139 
140    /* Must setup these after state validation! */
141    /* Setup arrays */
142    st_setup_arrays(st, vp, vp_variant, &velements, vbuffers, &num_vbuffers);
143    /* Setup current values as userspace arrays */
144    st_setup_current_user(st, vp, vp_variant, &velements, vbuffers, &num_vbuffers);
145 
146    /* Map all buffers and tell draw about their mapping */
147    for (unsigned buf = 0; buf < num_vbuffers; ++buf) {
148       struct pipe_vertex_buffer *vbuffer = &vbuffers[buf];
149 
150       if (vbuffer->is_user_buffer) {
151          draw_set_mapped_vertex_buffer(draw, buf, vbuffer->buffer.user, ~0);
152       } else {
153          void *map = pipe_buffer_map(pipe, vbuffer->buffer.resource,
154                                      PIPE_MAP_READ, &vb_transfer[buf]);
155          draw_set_mapped_vertex_buffer(draw, buf, map,
156                                        vbuffer->buffer.resource->width0);
157       }
158    }
159 
160    draw_set_vertex_elements(draw, vp->num_inputs, velements.velems);
161    draw_set_vertex_buffers(draw, num_vbuffers, vbuffers);
162 
163    if (info->index_size) {
164       if (info->has_user_indices) {
165          mapped_indices = info->index.user;
166       } else {
167          mapped_indices = pipe_buffer_map(pipe, info->index.resource,
168                                           PIPE_MAP_READ, &ib_transfer);
169       }
170 
171       draw_set_indexes(draw, (uint8_t *)mapped_indices, info->index_size, ~0);
172    }
173 
174    /* set constant buffer 0 */
175    struct gl_program_parameter_list *params = vp->Base.Parameters;
176 
177    /* Update the constants which come from fixed-function state, such as
178     * transformation matrices, fog factors, etc.
179     *
180     * It must be done here if the state tracker doesn't update state vars
181     * in gl_program_parameter_list because allow_constbuf0_as_real_buffer
182     * is set.
183     */
184    if ((st->prefer_real_buffer_in_constbuf0 || st->allow_st_finalize_nir_twice) && params->StateFlags)
185       _mesa_load_state_parameters(st->ctx, params);
186 
187    draw_set_constant_buffer_stride(draw, sizeof(float));
188    draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0,
189                                    params->ParameterValues,
190                                    params->NumParameterValues * 4);
191 
192    /* set uniform buffers */
193    const struct gl_program *prog = &vp->Base;
194    struct pipe_transfer *ubo_transfer[PIPE_MAX_CONSTANT_BUFFERS] = {0};
195    assert(prog->info.num_ubos <= ARRAY_SIZE(ubo_transfer));
196 
197    for (unsigned i = 0; i < prog->sh.NumUniformBlocks; i++) {
198       struct gl_buffer_binding *binding =
199          &st->ctx->UniformBufferBindings[prog->sh.UniformBlocks[i]->Binding];
200       struct gl_buffer_object *st_obj = binding->BufferObject;
201       struct pipe_resource *buf = st_obj->buffer;
202 
203       if (!buf)
204          continue;
205 
206       unsigned offset = binding->Offset;
207       unsigned size = buf->width0 - offset;
208 
209       /* AutomaticSize is FALSE if the buffer was set with BindBufferRange.
210        * Take the minimum just to be sure.
211        */
212       if (!binding->AutomaticSize)
213          size = MIN2(size, (unsigned) binding->Size);
214 
215       void *ptr = pipe_buffer_map_range(pipe, buf, offset, size,
216                                         PIPE_MAP_READ, &ubo_transfer[i]);
217 
218       draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 1 + i, ptr,
219                                       size);
220    }
221 
222    /* shader buffers */
223    /* TODO: atomic counter buffers */
224    struct pipe_transfer *ssbo_transfer[PIPE_MAX_SHADER_BUFFERS] = {0};
225 
226    for (unsigned i = 0; i < prog->info.num_ssbos; i++) {
227       struct gl_buffer_binding *binding =
228          &st->ctx->ShaderStorageBufferBindings[
229             prog->sh.ShaderStorageBlocks[i]->Binding];
230       struct gl_buffer_object *st_obj = binding->BufferObject;
231       struct pipe_resource *buf = st_obj->buffer;
232 
233       if (!buf)
234          continue;
235 
236       unsigned offset = binding->Offset;
237       unsigned size = buf->width0 - binding->Offset;
238 
239       /* AutomaticSize is FALSE if the buffer was set with BindBufferRange.
240        * Take the minimum just to be sure.
241        */
242       if (!binding->AutomaticSize)
243          size = MIN2(size, (unsigned) binding->Size);
244 
245       void *ptr = pipe_buffer_map_range(pipe, buf, offset, size,
246                                         PIPE_MAP_READ, &ssbo_transfer[i]);
247 
248       draw_set_mapped_shader_buffer(draw, PIPE_SHADER_VERTEX,
249                                     i, ptr, size);
250    }
251 
252    /* samplers */
253    struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
254    for (unsigned i = 0; i < st->state.num_vert_samplers; i++)
255       samplers[i] = &st->state.vert_samplers[i];
256 
257    draw_set_samplers(draw, PIPE_SHADER_VERTEX, samplers,
258                      st->state.num_vert_samplers);
259 
260    /* sampler views */
261    struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS];
262    unsigned num_views =
263       st_get_sampler_views(st, PIPE_SHADER_VERTEX, prog, views);
264 
265    draw_set_sampler_views(draw, PIPE_SHADER_VERTEX, views, num_views);
266 
267    struct pipe_transfer *sv_transfer[PIPE_MAX_SAMPLERS][PIPE_MAX_TEXTURE_LEVELS];
268 
269    for (unsigned i = 0; i < num_views; i++) {
270       struct pipe_sampler_view *view = views[i];
271       if (!view)
272          continue;
273 
274       struct pipe_resource *res = view->texture;
275       unsigned width0 = res->width0;
276       unsigned num_layers = res->depth0;
277       unsigned first_level = 0;
278       unsigned last_level = 0;
279       uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
280       uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
281       uint32_t mip_offset[PIPE_MAX_TEXTURE_LEVELS];
282       uintptr_t mip_addr[PIPE_MAX_TEXTURE_LEVELS];
283       uintptr_t base_addr;
284 
285       if (res->target != PIPE_BUFFER) {
286          first_level = view->u.tex.first_level;
287          last_level = view->u.tex.last_level;
288          num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1;
289          base_addr = UINTPTR_MAX;
290 
291          for (unsigned j = first_level; j <= last_level; j++) {
292             unsigned map_layers = res->target == PIPE_TEXTURE_3D ?
293                                      util_num_layers(res, j) : num_layers;
294 
295             sv_transfer[i][j] = NULL;
296             mip_addr[j] = (uintptr_t)
297                           pipe_texture_map_3d(pipe, res, j,
298                                                PIPE_MAP_READ, 0, 0,
299                                                view->u.tex.first_layer,
300                                                u_minify(res->width0, j),
301                                                u_minify(res->height0, j),
302                                                map_layers, &sv_transfer[i][j]);
303             row_stride[j] = sv_transfer[i][j]->stride;
304             img_stride[j] = sv_transfer[i][j]->layer_stride;
305 
306             /* Get the minimum address, because the draw module takes only
307              * 1 address for the whole texture + uint32 offsets for mip levels,
308              * so we need to convert mapped resource pointers into that scheme.
309              */
310             base_addr = MIN2(base_addr, mip_addr[j]);
311          }
312          for (unsigned j = first_level; j <= last_level; j++) {
313             /* TODO: The draw module should accept pointers for mipmap levels
314              * instead of offsets. This is unlikely to work on 64-bit archs.
315              */
316             assert(mip_addr[j] - base_addr <= UINT32_MAX);
317             mip_offset[j] = mip_addr[j] - base_addr;
318          }
319       } else {
320          width0 = view->u.buf.size / util_format_get_blocksize(view->format);
321 
322          /* probably don't really need to fill that out */
323          mip_offset[0] = 0;
324          row_stride[0] = 0;
325          img_stride[0] = 0;
326 
327          sv_transfer[i][0] = NULL;
328          base_addr = (uintptr_t)
329                      pipe_buffer_map_range(pipe, res, view->u.buf.offset,
330                                            view->u.buf.size,
331                                            PIPE_MAP_READ,
332                                            &sv_transfer[i][0]);
333       }
334 
335       draw_set_mapped_texture(draw, PIPE_SHADER_VERTEX, i, width0,
336                               res->height0, num_layers, first_level,
337                               last_level, 0, 0, (void*)base_addr, row_stride,
338                               img_stride, mip_offset);
339    }
340 
341    /* shader images */
342    struct pipe_image_view images[PIPE_MAX_SHADER_IMAGES];
343    struct pipe_transfer *img_transfer[PIPE_MAX_SHADER_IMAGES] = {0};
344 
345    for (unsigned i = 0; i < prog->info.num_images; i++) {
346       struct pipe_image_view *img = &images[i];
347 
348       st_convert_image_from_unit(st, img, prog->sh.ImageUnits[i],
349                                  prog->sh.image_access[i]);
350 
351       struct pipe_resource *res = img->resource;
352       if (!res)
353          continue;
354 
355       unsigned width, height, num_layers, row_stride, img_stride;
356       void *addr;
357 
358       if (res->target != PIPE_BUFFER) {
359          width = u_minify(res->width0, img->u.tex.level);
360          height = u_minify(res->height0, img->u.tex.level);
361          num_layers = img->u.tex.last_layer - img->u.tex.first_layer + 1;
362 
363          addr = pipe_texture_map_3d(pipe, res, img->u.tex.level,
364                                      PIPE_MAP_READ, 0, 0,
365                                      img->u.tex.first_layer,
366                                      width, height, num_layers,
367                                      &img_transfer[i]);
368          row_stride = img_transfer[i]->stride;
369          img_stride = img_transfer[i]->layer_stride;
370       } else {
371          width = img->u.buf.size / util_format_get_blocksize(img->format);
372 
373          /* probably don't really need to fill that out */
374          row_stride = 0;
375          img_stride = 0;
376          height = num_layers = 1;
377 
378          addr = pipe_buffer_map_range(pipe, res, img->u.buf.offset,
379                                       img->u.buf.size, PIPE_MAP_READ,
380                                       &img_transfer[i]);
381       }
382 
383       draw_set_mapped_image(draw, PIPE_SHADER_VERTEX, i, width, height,
384                             num_layers, addr, row_stride, img_stride, 0, 0);
385    }
386    draw_set_images(draw, PIPE_SHADER_VERTEX, images, prog->info.num_images);
387 
388    /* draw here */
389    for (i = 0; i < num_draws; i++) {
390       draw_vbo(draw, info, info->increment_draw_id ? i : 0, indirect,
391                &draws[i], 1, ctx->TessCtrlProgram.patch_vertices);
392    }
393 
394    /* unmap images */
395    for (unsigned i = 0; i < prog->info.num_images; i++) {
396       if (img_transfer[i]) {
397          draw_set_mapped_image(draw, PIPE_SHADER_VERTEX, i, 0, 0, 0, NULL, 0, 0, 0, 0);
398          if (img_transfer[i]->resource->target == PIPE_BUFFER)
399             pipe_buffer_unmap(pipe, img_transfer[i]);
400          else
401             pipe_texture_unmap(pipe, img_transfer[i]);
402       }
403    }
404 
405    /* unmap sampler views */
406    for (unsigned i = 0; i < num_views; i++) {
407       struct pipe_sampler_view *view = views[i];
408 
409       if (view) {
410          if (view->texture->target != PIPE_BUFFER) {
411             for (unsigned j = view->u.tex.first_level;
412                  j <= view->u.tex.last_level; j++) {
413                pipe_texture_unmap(pipe, sv_transfer[i][j]);
414             }
415          } else {
416             pipe_buffer_unmap(pipe, sv_transfer[i][0]);
417          }
418 
419          pipe_sampler_view_reference(&views[i], NULL);
420       }
421    }
422 
423    draw_set_samplers(draw, PIPE_SHADER_VERTEX, NULL, 0);
424    draw_set_sampler_views(draw, PIPE_SHADER_VERTEX, NULL, 0);
425 
426    for (unsigned i = 0; i < prog->info.num_ssbos; i++) {
427       if (ssbo_transfer[i]) {
428          draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 1 + i,
429                                          NULL, 0);
430          pipe_buffer_unmap(pipe, ssbo_transfer[i]);
431       }
432    }
433 
434    for (unsigned i = 0; i < prog->info.num_ubos; i++) {
435       if (ubo_transfer[i]) {
436          draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 1 + i,
437                                          NULL, 0);
438          pipe_buffer_unmap(pipe, ubo_transfer[i]);
439       }
440    }
441 
442    /*
443     * unmap vertex/index buffers
444     */
445    if (info->index_size) {
446       draw_set_indexes(draw, NULL, 0, 0);
447       if (ib_transfer)
448          pipe_buffer_unmap(pipe, ib_transfer);
449    }
450 
451    for (unsigned buf = 0; buf < num_vbuffers; ++buf) {
452       if (vb_transfer[buf])
453          pipe_buffer_unmap(pipe, vb_transfer[buf]);
454       draw_set_mapped_vertex_buffer(draw, buf, NULL, 0);
455       if (!vbuffers[buf].is_user_buffer)
456          pipe_resource_reference(&vbuffers[buf].buffer.resource, NULL);
457    }
458    draw_set_vertex_buffers(draw, 0, NULL);
459 
460    draw_bind_vertex_shader(draw, NULL);
461 }
462 
463 void
st_feedback_draw_vbo_multi_mode(struct gl_context * ctx,struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draws,const unsigned char * mode,unsigned num_draws)464 st_feedback_draw_vbo_multi_mode(struct gl_context *ctx,
465                                 struct pipe_draw_info *info,
466                                 const struct pipe_draw_start_count_bias *draws,
467                                 const unsigned char *mode,
468                                 unsigned num_draws)
469 {
470    for (unsigned i = 0; i < num_draws; i++) {
471       info->mode = mode[i];
472       st_feedback_draw_vbo(ctx, info, 0, NULL, &draws[i], 1);
473    }
474 }
475