示例#1
0
static void
ilo_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
   struct ilo_context *ilo = ilo_context(pipe);
   int vs_scratch_size, gs_scratch_size, fs_scratch_size;

   if (ilo_debug & ILO_DEBUG_DRAW) {
      if (info->indexed) {
         ilo_printf("indexed draw %s: "
               "index start %d, count %d, vertex range [%d, %d]\n",
               u_prim_name(info->mode), info->start, info->count,
               info->min_index, info->max_index);
      }
      else {
         ilo_printf("draw %s: vertex start %d, count %d\n",
               u_prim_name(info->mode), info->start, info->count);
      }

      ilo_state_vector_dump_dirty(&ilo->state_vector);
   }

   if (ilo_skip_rendering(ilo))
      return;

   if (info->primitive_restart && info->indexed &&
       draw_vbo_need_sw_restart(ilo, info)) {
      draw_vbo_with_sw_restart(ilo, info);
      return;
   }

   ilo_finalize_3d_states(ilo, info);

   /* upload kernels */
   ilo_shader_cache_upload(ilo->shader_cache, &ilo->cp->builder);

   /* prepare scratch spaces */
   ilo_shader_cache_get_max_scratch_sizes(ilo->shader_cache,
         &vs_scratch_size, &gs_scratch_size, &fs_scratch_size);
   ilo_render_prepare_scratch_spaces(ilo->render,
         vs_scratch_size, gs_scratch_size, fs_scratch_size);

   ilo_blit_resolve_framebuffer(ilo);

   /* If draw_vbo ever fails, return immediately. */
   if (!draw_vbo(ilo, &ilo->state_vector))
      return;

   /* clear dirty status */
   ilo->state_vector.dirty = 0x0;

   /* avoid dangling pointer reference */
   ilo->state_vector.draw = NULL;

   if (ilo_debug & ILO_DEBUG_NOCACHE)
      ilo_render_emit_flush(ilo->render);
}
示例#2
0
文件: vc4_cl_dump.c 项目: xranby/mesa
static void
dump_VC4_PACKET_GL_ARRAY_PRIMITIVE(void *cl, uint32_t offset, uint32_t hw_offset)
{
    uint8_t *b = cl + offset;
    uint32_t *count = cl + offset + 1;
    uint32_t *start = cl + offset + 5;

    fprintf(stderr, "0x%08x 0x%08x:      0x%02x %s\n",
            offset, hw_offset, b[0], u_prim_name(b[0] & 0x7));
    fprintf(stderr, "0x%08x 0x%08x:      %d verts\n",
            offset + 1, hw_offset + 1, *count);
    fprintf(stderr, "0x%08x 0x%08x:      0x%08x start\n",
            offset + 5, hw_offset + 5, *start);
}
示例#3
0
static enum pc_di_primtype
mode2primtype(unsigned mode)
{
	switch (mode) {
	case PIPE_PRIM_POINTS:         return DI_PT_POINTLIST;
	case PIPE_PRIM_LINES:          return DI_PT_LINELIST;
	case PIPE_PRIM_LINE_STRIP:     return DI_PT_LINESTRIP;
	case PIPE_PRIM_TRIANGLES:      return DI_PT_TRILIST;
	case PIPE_PRIM_TRIANGLE_STRIP: return DI_PT_TRISTRIP;
	case PIPE_PRIM_TRIANGLE_FAN:   return DI_PT_TRIFAN;
	case PIPE_PRIM_QUADS:          return DI_PT_QUADLIST;
	case PIPE_PRIM_QUAD_STRIP:     return DI_PT_QUADSTRIP;
	case PIPE_PRIM_POLYGON:        return DI_PT_POLYGON;
	}
	DBG("unsupported mode: (%s) %d", u_prim_name(mode), mode);
	assert(0);
	return DI_PT_NONE;
}
示例#4
0
文件: vc4_cl_dump.c 项目: xranby/mesa
static void
dump_VC4_PACKET_GL_INDEXED_PRIMITIVE(void *cl, uint32_t offset, uint32_t hw_offset)
{
    uint8_t *b = cl + offset;
    uint32_t *count = cl + offset + 1;
    uint32_t *ib_offset = cl + offset + 5;
    uint32_t *max_index = cl + offset + 9;

    fprintf(stderr, "0x%08x 0x%08x:      0x%02x %s %s\n",
            offset, hw_offset,
            b[0], (b[0] & VC4_INDEX_BUFFER_U16) ? "16-bit" : "8-bit",
            u_prim_name(b[0] & 0x7));
    fprintf(stderr, "0x%08x 0x%08x:           %d verts\n",
            offset + 1, hw_offset + 1, *count);
    fprintf(stderr, "0x%08x 0x%08x:      0x%08x IB offset\n",
            offset + 5, hw_offset + 5, *ib_offset);
    fprintf(stderr, "0x%08x 0x%08x:      0x%08x max index\n",
            offset + 9, hw_offset + 9, *max_index);
}
示例#5
0
文件: draw_gs.c 项目: DirectFB/mesa
/**
 * Execute geometry shader.
 */
int draw_geometry_shader_run(struct draw_geometry_shader *shader,
                             const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
                             const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
                             const struct draw_vertex_info *input_verts,
                             const struct draw_prim_info *input_prim,
                             const struct tgsi_shader_info *input_info,
                             struct draw_vertex_info *output_verts,
                             struct draw_prim_info *output_prims )
{
   const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
   unsigned input_stride = input_verts->vertex_size;
   unsigned num_outputs = draw_total_gs_outputs(shader->draw);
   unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
   unsigned num_input_verts = input_prim->linear ?
      input_verts->count :
      input_prim->count;
   unsigned num_in_primitives =
      align(
         MAX2(u_decomposed_prims_for_vertices(input_prim->prim,
                                              num_input_verts),
              u_decomposed_prims_for_vertices(shader->input_primitive,
                                              num_input_verts)),
         shader->vector_length);
   unsigned max_out_prims =
      u_decomposed_prims_for_vertices(shader->output_primitive,
                                      shader->max_output_vertices)
      * num_in_primitives;

   //Assume at least one primitive
   max_out_prims = MAX2(max_out_prims, 1);


   output_verts->vertex_size = vertex_size;
   output_verts->stride = output_verts->vertex_size;
   /* we allocate exactly one extra vertex per primitive to allow the GS to emit
    * overflown vertices into some area where they won't harm anyone */
   output_verts->verts =
      (struct vertex_header *)MALLOC(output_verts->vertex_size *
                                     max_out_prims *
                                     shader->primitive_boundary);

#if 0
   debug_printf("%s count = %d (in prims # = %d)\n",
                __FUNCTION__, num_input_verts, num_in_primitives);
   debug_printf("\tlinear = %d, prim_info->count = %d\n",
                input_prim->linear, input_prim->count);
   debug_printf("\tprim pipe = %s, shader in = %s, shader out = %s, max out = %d\n",
                u_prim_name(input_prim->prim),
                u_prim_name(shader->input_primitive),
                u_prim_name(shader->output_primitive),
                shader->max_output_vertices);
#endif

   shader->emitted_vertices = 0;
   shader->emitted_primitives = 0;
   shader->vertex_size = vertex_size;
   shader->tmp_output = (float (*)[4])output_verts->verts->data;
   shader->fetched_prim_count = 0;
   shader->input_vertex_stride = input_stride;
   shader->input = input;
   shader->input_info = input_info;
   FREE(shader->primitive_lengths);
   shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));


#ifdef HAVE_LLVM
   if (draw_get_option_use_llvm()) {
      shader->gs_output = output_verts->verts;
      if (max_out_prims > shader->max_out_prims) {
         unsigned i;
         if (shader->llvm_prim_lengths) {
            for (i = 0; i < shader->max_out_prims; ++i) {
               align_free(shader->llvm_prim_lengths[i]);
            }
            FREE(shader->llvm_prim_lengths);
         }

         shader->llvm_prim_lengths = MALLOC(max_out_prims * sizeof(unsigned*));
         for (i = 0; i < max_out_prims; ++i) {
            int vector_size = shader->vector_length * sizeof(unsigned);
            shader->llvm_prim_lengths[i] =
               align_malloc(vector_size, vector_size);
         }

         shader->max_out_prims = max_out_prims;
      }
      shader->jit_context->prim_lengths = shader->llvm_prim_lengths;
      shader->jit_context->emitted_vertices = shader->llvm_emitted_vertices;
      shader->jit_context->emitted_prims = shader->llvm_emitted_primitives;
   }
#endif

   shader->prepare(shader, constants, constants_size);

   if (input_prim->linear)
      gs_run(shader, input_prim, input_verts,
             output_prims, output_verts);
   else
      gs_run_elts(shader, input_prim, input_verts,
                  output_prims, output_verts);

   /* Flush the remaining primitives. Will happen if
    * num_input_primitives % 4 != 0
    */
   if (shader->fetched_prim_count > 0) {
      gs_flush(shader);
   }

   debug_assert(shader->fetched_prim_count == 0);

   /* Update prim_info:
    */
   output_prims->linear = TRUE;
   output_prims->elts = NULL;
   output_prims->start = 0;
   output_prims->count = shader->emitted_vertices;
   output_prims->prim = shader->output_primitive;
   output_prims->flags = 0x0;
   output_prims->primitive_lengths = shader->primitive_lengths;
   output_prims->primitive_count = shader->emitted_primitives;
   output_verts->count = shader->emitted_vertices;

   if (shader->draw->collect_statistics) {
      unsigned i;
      for (i = 0; i < shader->emitted_primitives; ++i) {
         shader->draw->statistics.gs_primitives +=
            u_decomposed_prims_for_vertices(shader->output_primitive,
                                            shader->primitive_lengths[i]);
      }
   }

#if 0
   debug_printf("GS finished, prims = %d, verts = %d\n",
                output_prims->primitive_count,
                output_verts->count);
#endif

   return shader->emitted_vertices;
}
示例#6
0
文件: vc4_draw.c 项目: gqmelo/mesa
static void
vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
{
        struct vc4_context *vc4 = vc4_context(pctx);

        if (info->mode >= PIPE_PRIM_QUADS) {
                util_primconvert_save_index_buffer(vc4->primconvert, &vc4->indexbuf);
                util_primconvert_save_rasterizer_state(vc4->primconvert, &vc4->rasterizer->base);
                util_primconvert_draw_vbo(vc4->primconvert, info);
                perf_debug("Fallback conversion for %d %s vertices\n",
                           info->count, u_prim_name(info->mode));
                return;
        }

        /* Before setting up the draw, do any fixup blits necessary. */
        vc4_update_shadow_textures(pctx, &vc4->verttex);
        vc4_update_shadow_textures(pctx, &vc4->fragtex);

        vc4_hw_2116_workaround(pctx);

        vc4_get_draw_cl_space(vc4);

        if (vc4->prim_mode != info->mode) {
                vc4->prim_mode = info->mode;
                vc4->dirty |= VC4_DIRTY_PRIM_MODE;
        }

        vc4_start_draw(vc4);
        vc4_update_compiled_shaders(vc4, info->mode);

        vc4_emit_state(pctx);

        if ((vc4->dirty & (VC4_DIRTY_VTXBUF |
                           VC4_DIRTY_VTXSTATE |
                           VC4_DIRTY_PRIM_MODE |
                           VC4_DIRTY_RASTERIZER |
                           VC4_DIRTY_COMPILED_CS |
                           VC4_DIRTY_COMPILED_VS |
                           VC4_DIRTY_COMPILED_FS |
                           vc4->prog.cs->uniform_dirty_bits |
                           vc4->prog.vs->uniform_dirty_bits |
                           vc4->prog.fs->uniform_dirty_bits)) ||
            vc4->last_index_bias != info->index_bias) {
                vc4_emit_gl_shader_state(vc4, info);
        }

        vc4->dirty = 0;

        /* Note that the primitive type fields match with OpenGL/gallium
         * definitions, up to but not including QUADS.
         */
        struct vc4_cl_out *bcl = cl_start(&vc4->bcl);
        if (info->indexed) {
                uint32_t offset = vc4->indexbuf.offset;
                uint32_t index_size = vc4->indexbuf.index_size;
                struct pipe_resource *prsc;
                if (vc4->indexbuf.index_size == 4) {
                        prsc = vc4_get_shadow_index_buffer(pctx, &vc4->indexbuf,
                                                           info->count, &offset);
                        index_size = 2;
                } else {
                        if (vc4->indexbuf.user_buffer) {
                                prsc = NULL;
                                u_upload_data(vc4->uploader, 0,
                                              info->count * index_size, 4,
                                              vc4->indexbuf.user_buffer,
                                              &offset, &prsc);
                        } else {
                                prsc = vc4->indexbuf.buffer;
                        }
                }
                struct vc4_resource *rsc = vc4_resource(prsc);

                cl_start_reloc(&vc4->bcl, &bcl, 1);
                cl_u8(&bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE);
                cl_u8(&bcl,
                      info->mode |
                      (index_size == 2 ?
                       VC4_INDEX_BUFFER_U16:
                       VC4_INDEX_BUFFER_U8));
                cl_u32(&bcl, info->count);
                cl_reloc(vc4, &vc4->bcl, &bcl, rsc->bo, offset);
                cl_u32(&bcl, vc4->max_index);

                if (vc4->indexbuf.index_size == 4 || vc4->indexbuf.user_buffer)
                        pipe_resource_reference(&prsc, NULL);
        } else {
                cl_u8(&bcl, VC4_PACKET_GL_ARRAY_PRIMITIVE);
                cl_u8(&bcl, info->mode);
                cl_u32(&bcl, info->count);
                cl_u32(&bcl, info->start);
        }
        cl_end(&vc4->bcl, bcl);

        if (vc4->zsa && vc4->zsa->base.depth.enabled) {
                vc4->resolve |= PIPE_CLEAR_DEPTH;
        }
        if (vc4->zsa && vc4->zsa->base.stencil[0].enabled)
                vc4->resolve |= PIPE_CLEAR_STENCIL;
        vc4->resolve |= PIPE_CLEAR_COLOR0;

        vc4->shader_rec_count++;

        if (vc4_debug & VC4_DEBUG_ALWAYS_FLUSH)
                vc4_flush(pctx);
}
示例#7
0
/**
 * This function gets plugged into the VBO module and is called when
 * we have something to render.
 * Basically, translate the information into the format expected by gallium.
 */
void
st_draw_vbo(struct gl_context *ctx,
            const struct _mesa_prim *prims,
            GLuint nr_prims,
            const struct _mesa_index_buffer *ib,
	    GLboolean index_bounds_valid,
            GLuint min_index,
            GLuint max_index,
            struct gl_transform_feedback_object *tfb_vertcount,
            struct gl_buffer_object *indirect)
{
   struct st_context *st = st_context(ctx);
   struct pipe_index_buffer ibuffer = {0};
   struct pipe_draw_info info;
   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
   unsigned i;

   /* Mesa core state should have been validated already */
   assert(ctx->NewState == 0x0);

   /* Validate state. */
   if (st->dirty.st || ctx->NewDriverState) {
      st_validate_state(st);

#if 0
      if (MESA_VERBOSE & VERBOSE_GLSL) {
         check_uniforms(ctx);
      }
#else
      (void) check_uniforms;
#endif
   }

   if (st->vertex_array_out_of_memory) {
      return;
   }

   util_draw_init_info(&info);

   if (ib) {
      /* Get index bounds for user buffers. */
      if (!index_bounds_valid)
         if (!all_varyings_in_vbos(arrays))
            vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
                                   nr_prims);

      if (!setup_index_buffer(st, ib, &ibuffer)) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBegin/DrawElements/DrawArray");
         return;
      }

      info.indexed = TRUE;
      if (min_index != ~0 && max_index != ~0) {
         info.min_index = min_index;
         info.max_index = max_index;
      }

      /* The VBO module handles restart for the non-indexed GLDrawArrays
       * so we only set these fields for indexed drawing:
       */
      info.primitive_restart = ctx->Array._PrimitiveRestart;
      info.restart_index = ctx->Array.RestartIndex;
   }
   else {
      /* Transform feedback drawing is always non-indexed. */
      /* Set info.count_from_stream_output. */
      if (tfb_vertcount) {
         st_transform_feedback_draw_init(tfb_vertcount, &info);
      }
   }

   /* do actual drawing */
   for (i = 0; i < nr_prims; i++) {
      info.mode = translate_prim(ctx, prims[i].mode);
      info.start = prims[i].start;
      info.count = prims[i].count;
      info.start_instance = prims[i].base_instance;
      info.instance_count = prims[i].num_instances;
      info.index_bias = prims[i].basevertex;
      if (!ib) {
         info.min_index = info.start;
         info.max_index = info.start + info.count - 1;
      }

      if (ST_DEBUG & DEBUG_DRAW) {
         debug_printf("st/draw: mode %s  start %u  count %u  indexed %d\n",
                      u_prim_name(info.mode),
                      info.start,
                      info.count,
                      info.indexed);
      }

      if (info.count_from_stream_output) {
         cso_draw_vbo(st->cso_context, &info);
      }
      else if (info.primitive_restart) {
         /* don't trim, restarts might be inside index list */
         cso_draw_vbo(st->cso_context, &info);
      }
      else if (u_trim_pipe_prim(prims[i].mode, &info.count)) {
         cso_draw_vbo(st->cso_context, &info);
      }
   }

   if (ib && st->indexbuf_uploader && !_mesa_is_bufferobj(ib->obj)) {
      pipe_resource_reference(&ibuffer.buffer, NULL);
   }
}
示例#8
0
文件: draw_gs.c 项目: ilyesgouta/mesa
/**
 * Execute geometry shader using TGSI interpreter.
 */
int draw_geometry_shader_run(struct draw_geometry_shader *shader,
                             const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 
                             const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS], 
                             const struct draw_vertex_info *input_verts,
                             const struct draw_prim_info *input_prim,
                             const struct tgsi_shader_info *input_info,
                             struct draw_vertex_info *output_verts,
                             struct draw_prim_info *output_prims )
{
   const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
   unsigned input_stride = input_verts->vertex_size;
   unsigned num_outputs = shader->info.num_outputs;
   unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
   struct tgsi_exec_machine *machine = shader->machine;
   unsigned num_input_verts = input_prim->linear ?
                              input_verts->count :
                              input_prim->count;
   unsigned num_in_primitives =
      MAX2(u_gs_prims_for_vertices(input_prim->prim, num_input_verts),
           u_gs_prims_for_vertices(shader->input_primitive, num_input_verts));
   unsigned max_out_prims = u_gs_prims_for_vertices(shader->output_primitive,
                                                    shader->max_output_vertices)
                            * num_in_primitives;

   output_verts->vertex_size = vertex_size;
   output_verts->stride = output_verts->vertex_size;
   output_verts->verts =
      (struct vertex_header *)MALLOC(output_verts->vertex_size *
                                     num_in_primitives *
                                     shader->max_output_vertices);


#if 0
   debug_printf("%s count = %d (in prims # = %d)\n",
                __FUNCTION__, num_input_verts, num_in_primitives);
   debug_printf("\tlinear = %d, prim_info->count = %d\n",
                input_prim->linear, input_prim->count);
   debug_printf("\tprim pipe = %s, shader in = %s, shader out = %s, max out = %d\n",
                u_prim_name(input_prim->prim),
                u_prim_name(shader->input_primitive),
                u_prim_name(shader->output_primitive),
                shader->max_output_vertices);
#endif

   shader->emitted_vertices = 0;
   shader->emitted_primitives = 0;
   shader->vertex_size = vertex_size;
   shader->tmp_output = (float (*)[4])output_verts->verts->data;
   shader->in_prim_idx = 0;
   shader->input_vertex_stride = input_stride;
   shader->input = input;
   shader->input_info = input_info;
   FREE(shader->primitive_lengths);
   shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));

   tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
                                  constants, constants_size);

   if (input_prim->linear)
      gs_run(shader, input_prim, input_verts,
             output_prims, output_verts);
   else
      gs_run_elts(shader, input_prim, input_verts,
                  output_prims, output_verts);

   /* Update prim_info:
    */
   output_prims->linear = TRUE;
   output_prims->elts = NULL;
   output_prims->start = 0;
   output_prims->count = shader->emitted_vertices;
   output_prims->prim = shader->output_primitive;
   output_prims->flags = 0x0;
   output_prims->primitive_lengths = shader->primitive_lengths;
   output_prims->primitive_count = shader->emitted_primitives;
   output_verts->count = shader->emitted_vertices;

#if 0
   debug_printf("GS finished, prims = %d, verts = %d\n",
                output_prims->primitive_count,
                output_verts->count);
#endif

   return shader->emitted_vertices;
}
示例#9
0
文件: st_draw.c 项目: Echelon9/mesa
static void
st_indirect_draw_vbo(struct gl_context *ctx,
                     GLuint mode,
                     struct gl_buffer_object *indirect_data,
                     GLsizeiptr indirect_offset,
                     unsigned draw_count,
                     unsigned stride,
                     struct gl_buffer_object *indirect_params,
                     GLsizeiptr indirect_params_offset,
                     const struct _mesa_index_buffer *ib)
{
   struct st_context *st = st_context(ctx);
   struct pipe_index_buffer ibuffer = {0};
   struct pipe_draw_info info;

   /* Mesa core state should have been validated already */
   assert(ctx->NewState == 0x0);
   assert(stride);

   /* Validate state. */
   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK ||
       st->gfx_shaders_may_be_dirty) {
      st_validate_state(st, ST_PIPELINE_RENDER);
   }

   if (st->vertex_array_out_of_memory) {
      return;
   }

   util_draw_init_info(&info);

   if (ib) {
      if (!setup_index_buffer(st, ib, &ibuffer)) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDrawElementsIndirect%s",
                     (draw_count > 1) ? "Multi" : "",
                     indirect_params ? "CountARB" : "");
         return;
      }

      info.indexed = TRUE;

      /* Primitive restart is not handled by the VBO module in this case. */
      setup_primitive_restart(ctx, ib, &info);
   }

   info.mode = translate_prim(ctx, mode);
   info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
   info.indirect = st_buffer_object(indirect_data)->buffer;
   info.indirect_offset = indirect_offset;

   if (ST_DEBUG & DEBUG_DRAW) {
      debug_printf("st/draw indirect: mode %s drawcount %d indexed %d\n",
                   u_prim_name(info.mode),
                   draw_count,
                   info.indexed);
   }

   if (!st->has_multi_draw_indirect) {
      int i;

      assert(!indirect_params);
      info.indirect_count = 1;
      for (i = 0; i < draw_count; i++) {
         info.drawid = i;
         cso_draw_vbo(st->cso_context, &info);
         info.indirect_offset += stride;
      }
   } else {
      info.indirect_count = draw_count;
      info.indirect_stride = stride;
      if (indirect_params) {
         info.indirect_params = st_buffer_object(indirect_params)->buffer;
         info.indirect_params_offset = indirect_params_offset;
      }
      cso_draw_vbo(st->cso_context, &info);
   }
}
示例#10
0
文件: vc4_draw.c 项目: Echelon9/mesa
static void
vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
{
        struct vc4_context *vc4 = vc4_context(pctx);

        if (info->mode >= PIPE_PRIM_QUADS) {
                util_primconvert_save_index_buffer(vc4->primconvert, &vc4->indexbuf);
                util_primconvert_save_rasterizer_state(vc4->primconvert, &vc4->rasterizer->base);
                util_primconvert_draw_vbo(vc4->primconvert, info);
                perf_debug("Fallback conversion for %d %s vertices\n",
                           info->count, u_prim_name(info->mode));
                return;
        }

        /* Before setting up the draw, do any fixup blits necessary. */
        vc4_predraw_check_textures(pctx, &vc4->verttex);
        vc4_predraw_check_textures(pctx, &vc4->fragtex);

        vc4_hw_2116_workaround(pctx, info->count);

        struct vc4_job *job = vc4_get_job_for_fbo(vc4);

        vc4_get_draw_cl_space(job, info->count);

        if (vc4->prim_mode != info->mode) {
                vc4->prim_mode = info->mode;
                vc4->dirty |= VC4_DIRTY_PRIM_MODE;
        }

        vc4_start_draw(vc4);
        if (!vc4_update_compiled_shaders(vc4, info->mode)) {
                debug_warn_once("shader compile failed, skipping draw call.\n");
                return;
        }

        vc4_emit_state(pctx);

        if ((vc4->dirty & (VC4_DIRTY_VTXBUF |
                           VC4_DIRTY_VTXSTATE |
                           VC4_DIRTY_PRIM_MODE |
                           VC4_DIRTY_RASTERIZER |
                           VC4_DIRTY_COMPILED_CS |
                           VC4_DIRTY_COMPILED_VS |
                           VC4_DIRTY_COMPILED_FS |
                           vc4->prog.cs->uniform_dirty_bits |
                           vc4->prog.vs->uniform_dirty_bits |
                           vc4->prog.fs->uniform_dirty_bits)) ||
            vc4->last_index_bias != info->index_bias) {
                vc4_emit_gl_shader_state(vc4, info, 0);
        }

        vc4->dirty = 0;

        /* Note that the primitive type fields match with OpenGL/gallium
         * definitions, up to but not including QUADS.
         */
        struct vc4_cl_out *bcl = cl_start(&job->bcl);
        if (info->indexed) {
                uint32_t offset = vc4->indexbuf.offset;
                uint32_t index_size = vc4->indexbuf.index_size;
                struct pipe_resource *prsc;
                if (vc4->indexbuf.index_size == 4) {
                        prsc = vc4_get_shadow_index_buffer(pctx, &vc4->indexbuf,
                                                           info->count, &offset);
                        index_size = 2;
                } else {
                        if (vc4->indexbuf.user_buffer) {
                                prsc = NULL;
                                u_upload_data(vc4->uploader, 0,
                                              info->count * index_size, 4,
                                              vc4->indexbuf.user_buffer,
                                              &offset, &prsc);
                        } else {
                                prsc = vc4->indexbuf.buffer;
                        }
                }
                struct vc4_resource *rsc = vc4_resource(prsc);

                cl_start_reloc(&job->bcl, &bcl, 1);
                cl_u8(&bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE);
                cl_u8(&bcl,
                      info->mode |
                      (index_size == 2 ?
                       VC4_INDEX_BUFFER_U16:
                       VC4_INDEX_BUFFER_U8));
                cl_u32(&bcl, info->count);
                cl_reloc(job, &job->bcl, &bcl, rsc->bo, offset);
                cl_u32(&bcl, vc4->max_index);
                job->draw_calls_queued++;

                if (vc4->indexbuf.index_size == 4 || vc4->indexbuf.user_buffer)
                        pipe_resource_reference(&prsc, NULL);
        } else {
                uint32_t count = info->count;
                uint32_t start = info->start;
                uint32_t extra_index_bias = 0;

                while (count) {
                        uint32_t this_count = count;
                        uint32_t step = count;
                        static const uint32_t max_verts = 65535;

                        /* GFXH-515 / SW-5891: The binner emits 16 bit indices
                         * for drawarrays, which means that if start + count >
                         * 64k it would truncate the top bits.  Work around
                         * this by emitting a limited number of primitives at
                         * a time and reemitting the shader state pointing
                         * farther down the vertex attribute arrays.
                         *
                         * To do this properly for line loops or trifans, we'd
                         * need to make a new VB containing the first vertex
                         * plus whatever remainder.
                         */
                        if (extra_index_bias) {
                                cl_end(&job->bcl, bcl);
                                vc4_emit_gl_shader_state(vc4, info,
                                                         extra_index_bias);
                                bcl = cl_start(&job->bcl);
                        }

                        if (start + count > max_verts) {
                                switch (info->mode) {
                                case PIPE_PRIM_POINTS:
                                        this_count = step = max_verts;
                                        break;
                                case PIPE_PRIM_LINES:
                                        this_count = step = max_verts - (max_verts % 2);
                                        break;
                                case PIPE_PRIM_LINE_STRIP:
                                        this_count = max_verts;
                                        step = max_verts - 1;
                                        break;
                                case PIPE_PRIM_LINE_LOOP:
                                        this_count = max_verts;
                                        step = max_verts - 1;
                                        debug_warn_once("unhandled line loop "
                                                        "looping behavior with "
                                                        ">65535 verts\n");
                                        break;
                                case PIPE_PRIM_TRIANGLES:
                                        this_count = step = max_verts - (max_verts % 3);
                                        break;
                                case PIPE_PRIM_TRIANGLE_STRIP:
                                        this_count = max_verts;
                                        step = max_verts - 2;
                                        break;
                                default:
                                        debug_warn_once("unhandled primitive "
                                                        "max vert count, truncating\n");
                                        this_count = step = max_verts;
                                }
                        }

                        cl_u8(&bcl, VC4_PACKET_GL_ARRAY_PRIMITIVE);
                        cl_u8(&bcl, info->mode);
                        cl_u32(&bcl, this_count);
                        cl_u32(&bcl, start);
                        job->draw_calls_queued++;

                        count -= step;
                        extra_index_bias += start + step;
                        start = 0;
                }
        }
        cl_end(&job->bcl, bcl);

        /* We shouldn't have tripped the HW_2116 bug with the GFXH-515
         * workaround.
         */
        assert(job->draw_calls_queued <= VC4_HW_2116_COUNT);

        if (vc4->zsa && vc4->framebuffer.zsbuf) {
                struct vc4_resource *rsc =
                        vc4_resource(vc4->framebuffer.zsbuf->texture);

                if (vc4->zsa->base.depth.enabled) {
                        job->resolve |= PIPE_CLEAR_DEPTH;
                        rsc->initialized_buffers = PIPE_CLEAR_DEPTH;
                }

                if (vc4->zsa->base.stencil[0].enabled) {
                        job->resolve |= PIPE_CLEAR_STENCIL;
                        rsc->initialized_buffers |= PIPE_CLEAR_STENCIL;
                }
        }

        job->resolve |= PIPE_CLEAR_COLOR0;

        if (vc4_debug & VC4_DEBUG_ALWAYS_FLUSH)
                vc4_flush(pctx);
}
示例#11
0
enum pipe_error
svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
                       enum pipe_prim_type prim, unsigned start, unsigned count,
                       unsigned start_instance, unsigned instance_count)
{
   enum pipe_prim_type gen_prim;
   unsigned gen_size, gen_nr;
   enum indices_mode gen_type;
   u_generate_func gen_func;
   enum pipe_error ret = PIPE_OK;
   unsigned api_pv = hwtnl->api_pv;
   struct svga_context *svga = hwtnl->svga;

   if (svga->curr.rast->templ.fill_front !=
       svga->curr.rast->templ.fill_back) {
      assert(hwtnl->api_fillmode == PIPE_POLYGON_MODE_FILL);
   }

   if (svga->curr.rast->templ.flatshade &&
       svga->state.hw_draw.fs->constant_color_output) {
      /* The fragment color is a constant, not per-vertex so the whole
       * primitive will be the same color (except for possible blending).
       * We can ignore the current provoking vertex state and use whatever
       * the hardware wants.
       */
      api_pv = hwtnl->hw_pv;

      if (hwtnl->api_fillmode == PIPE_POLYGON_MODE_FILL) {
         /* Do some simple primitive conversions to avoid index buffer
          * generation below.  Note that polygons and quads are not directly
          * supported by the svga device.  Also note, we can only do this
          * for flat/constant-colored rendering because of provoking vertex.
          */
         if (prim == PIPE_PRIM_POLYGON) {
            prim = PIPE_PRIM_TRIANGLE_FAN;
         }
         else if (prim == PIPE_PRIM_QUADS && count == 4) {
            prim = PIPE_PRIM_TRIANGLE_FAN;
         }
      }
   }

   if (svga_need_unfilled_fallback(hwtnl, prim)) {
      /* Convert unfilled polygons into points, lines, triangles */
      gen_type = u_unfilled_generator(prim,
                                      start,
                                      count,
                                      hwtnl->api_fillmode,
                                      &gen_prim,
                                      &gen_size, &gen_nr, &gen_func);
   }
   else {
      /* Convert PIPE_PRIM_LINE_LOOP to PIPE_PRIM_LINESTRIP,
       * convert PIPE_PRIM_POLYGON to PIPE_PRIM_TRIANGLE_FAN,
       * etc, if needed (as determined by svga_hw_prims mask).
       */
      gen_type = u_index_generator(svga_hw_prims,
                                   prim,
                                   start,
                                   count,
                                   api_pv,
                                   hwtnl->hw_pv,
                                   &gen_prim, &gen_size, &gen_nr, &gen_func);
   }

   if (gen_type == U_GENERATE_LINEAR) {
      return simple_draw_arrays(hwtnl, gen_prim, start, count,
                                start_instance, instance_count);
   }
   else {
      struct pipe_resource *gen_buf = NULL;

      /* Need to draw as indexed primitive.
       * Potentially need to run the gen func to build an index buffer.
       */
      ret = retrieve_or_generate_indices(hwtnl,
                                         prim,
                                         gen_type,
                                         gen_nr,
                                         gen_size, gen_func, &gen_buf);
      if (ret != PIPE_OK)
         goto done;

      pipe_debug_message(&svga->debug.callback, PERF_INFO,
                         "generating temporary index buffer for drawing %s",
                         u_prim_name(prim));

      ret = svga_hwtnl_simple_draw_range_elements(hwtnl,
                                                  gen_buf,
                                                  gen_size,
                                                  start,
                                                  0,
                                                  count - 1,
                                                  gen_prim, 0, gen_nr,
                                                  start_instance,
                                                  instance_count);
      if (ret != PIPE_OK)
         goto done;

done:
      if (gen_buf)
         pipe_resource_reference(&gen_buf, NULL);

      return ret;
   }
}