void
vec4_gs_visitor::visit(ir_emit_vertex *ir)
{
   this->current_annotation = "emit vertex: safety check";

   /* To ensure that we don't output more vertices than the shader specified
    * using max_vertices, do the logic inside a conditional of the form "if
    * (vertex_count < MAX)"
    */
   unsigned num_output_vertices = c->gp->program.VerticesOut;
   emit(CMP(dst_null_d(), this->vertex_count,
            src_reg(num_output_vertices), BRW_CONDITIONAL_L));
   emit(IF(BRW_PREDICATE_NORMAL));
   {
      /* If we're outputting 32 control data bits or less, then we can wait
       * until the shader is over to output them all.  Otherwise we need to
       * output them as we go.  Now is the time to do it, since we're about to
       * output the vertex_count'th vertex, so it's guaranteed that the
       * control data bits associated with the (vertex_count - 1)th vertex are
       * correct.
       */
      if (c->control_data_header_size_bits > 32) {
         this->current_annotation = "emit vertex: emit control data bits";
         /* Only emit control data bits if we've finished accumulating a batch
          * of 32 bits.  This is the case when:
          *
          *     (vertex_count * bits_per_vertex) % 32 == 0
          *
          * (in other words, when the last 5 bits of vertex_count *
          * bits_per_vertex are 0).  Assuming bits_per_vertex == 2^n for some
          * integer n (which is always the case, since bits_per_vertex is
          * always 1 or 2), this is equivalent to requiring that the last 5-n
          * bits of vertex_count are 0:
          *
          *     vertex_count & (2^(5-n) - 1) == 0
          *
          * 2^(5-n) == 2^5 / 2^n == 32 / bits_per_vertex, so this is
          * equivalent to:
          *
          *     vertex_count & (32 / bits_per_vertex - 1) == 0
          */
         vec4_instruction *inst =
            emit(AND(dst_null_d(), this->vertex_count,
                     (uint32_t) (32 / c->control_data_bits_per_vertex - 1)));
         inst->conditional_mod = BRW_CONDITIONAL_Z;
         emit(IF(BRW_PREDICATE_NORMAL));
         {
            emit_control_data_bits();

            /* Reset control_data_bits to 0 so we can start accumulating a new
             * batch.
             *
             * Note: in the case where vertex_count == 0, this neutralizes the
             * effect of any call to EndPrimitive() that the shader may have
             * made before outputting its first vertex.
             */
            inst = emit(MOV(dst_reg(this->control_data_bits), 0u));
            inst->force_writemask_all = true;
         }
         emit(BRW_OPCODE_ENDIF);
      }

      this->current_annotation = "emit vertex: vertex data";
      emit_vertex();

      /* In stream mode we have to set control data bits for all vertices
       * unless we have disabled control data bits completely (which we do
       * do for GL_POINTS outputs that don't use streams).
       */
      if (c->control_data_header_size_bits > 0 &&
          c->prog_data.control_data_format ==
             GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_SID) {
          this->current_annotation = "emit vertex: Stream control data bits";
          set_stream_control_data_bits(ir->stream_id());
      }

      this->current_annotation = "emit vertex: increment vertex count";
      emit(ADD(dst_reg(this->vertex_count), this->vertex_count,
               src_reg(1u)));
   }
   emit(BRW_OPCODE_ENDIF);

   this->current_annotation = NULL;
}
Example #2
0
void
vec4_gs_visitor::gs_emit_vertex(int stream_id)
{
    this->current_annotation = "emit vertex: safety check";

    /* Haswell and later hardware ignores the "Render Stream Select" bits
     * from the 3DSTATE_STREAMOUT packet when the SOL stage is disabled,
     * and instead sends all primitives down the pipeline for rasterization.
     * If the SOL stage is enabled, "Render Stream Select" is honored and
     * primitives bound to non-zero streams are discarded after stream output.
     *
     * Since the only purpose of primives sent to non-zero streams is to
     * be recorded by transform feedback, we can simply discard all geometry
     * bound to these streams when transform feedback is disabled.
     */
    if (stream_id > 0 && !nir->info->has_transform_feedback_varyings)
        return;

    /* If we're outputting 32 control data bits or less, then we can wait
     * until the shader is over to output them all.  Otherwise we need to
     * output them as we go.  Now is the time to do it, since we're about to
     * output the vertex_count'th vertex, so it's guaranteed that the
     * control data bits associated with the (vertex_count - 1)th vertex are
     * correct.
     */
    if (c->control_data_header_size_bits > 32) {
        this->current_annotation = "emit vertex: emit control data bits";
        /* Only emit control data bits if we've finished accumulating a batch
         * of 32 bits.  This is the case when:
         *
         *     (vertex_count * bits_per_vertex) % 32 == 0
         *
         * (in other words, when the last 5 bits of vertex_count *
         * bits_per_vertex are 0).  Assuming bits_per_vertex == 2^n for some
         * integer n (which is always the case, since bits_per_vertex is
         * always 1 or 2), this is equivalent to requiring that the last 5-n
         * bits of vertex_count are 0:
         *
         *     vertex_count & (2^(5-n) - 1) == 0
         *
         * 2^(5-n) == 2^5 / 2^n == 32 / bits_per_vertex, so this is
         * equivalent to:
         *
         *     vertex_count & (32 / bits_per_vertex - 1) == 0
         */
        vec4_instruction *inst =
            emit(AND(dst_null_ud(), this->vertex_count,
                     brw_imm_ud(32 / c->control_data_bits_per_vertex - 1)));
        inst->conditional_mod = BRW_CONDITIONAL_Z;

        emit(IF(BRW_PREDICATE_NORMAL));
        {
            /* If vertex_count is 0, then no control data bits have been
             * accumulated yet, so we skip emitting them.
             */
            emit(CMP(dst_null_ud(), this->vertex_count, brw_imm_ud(0u),
                     BRW_CONDITIONAL_NEQ));
            emit(IF(BRW_PREDICATE_NORMAL));
            emit_control_data_bits();
            emit(BRW_OPCODE_ENDIF);

            /* Reset control_data_bits to 0 so we can start accumulating a new
             * batch.
             *
             * Note: in the case where vertex_count == 0, this neutralizes the
             * effect of any call to EndPrimitive() that the shader may have
             * made before outputting its first vertex.
             */
            inst = emit(MOV(dst_reg(this->control_data_bits), brw_imm_ud(0u)));
            inst->force_writemask_all = true;
        }
        emit(BRW_OPCODE_ENDIF);
    }

    this->current_annotation = "emit vertex: vertex data";
    emit_vertex();

    /* In stream mode we have to set control data bits for all vertices
     * unless we have disabled control data bits completely (which we do
     * do for GL_POINTS outputs that don't use streams).
     */
    if (c->control_data_header_size_bits > 0 &&
            gs_prog_data->control_data_format ==
            GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_SID) {
        this->current_annotation = "emit vertex: Stream control data bits";
        set_stream_control_data_bits(stream_id);
    }

    this->current_annotation = NULL;
}