示例#1
0
/**
 * Parse TGSI shader and translate to SVGA/DX9 serialized
 * representation.
 *
 * In this function SVGA shader is emitted to an in-memory buffer that
 * can be dynamically grown.  Once we've finished and know how large
 * it is, it will be copied to a hardware buffer for upload.
 */
struct svga_shader_variant *
svga_tgsi_vgpu9_translate(struct svga_context *svga,
                          const struct svga_shader *shader,
                          const struct svga_compile_key *key,
                          enum pipe_shader_type unit)
{
   struct svga_shader_variant *variant = NULL;
   struct svga_shader_emitter emit;

   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_TGSIVGPU9TRANSLATE);

   memset(&emit, 0, sizeof(emit));

   emit.size = 1024;
   emit.buf = MALLOC(emit.size);
   if (emit.buf == NULL) {
      goto fail;
   }

   emit.ptr = emit.buf;
   emit.unit = unit;
   emit.key = *key;

   tgsi_scan_shader(shader->tokens, &emit.info);

   emit.imm_start = emit.info.file_max[TGSI_FILE_CONSTANT] + 1;

   if (unit == PIPE_SHADER_FRAGMENT)
      emit.imm_start += key->num_unnormalized_coords;

   if (unit == PIPE_SHADER_VERTEX) {
      emit.imm_start += key->vs.need_prescale ? 2 : 0;
   }

   emit.nr_hw_float_const =
      (emit.imm_start + emit.info.file_max[TGSI_FILE_IMMEDIATE] + 1);

   emit.nr_hw_temp = emit.info.file_max[TGSI_FILE_TEMPORARY] + 1;

   if (emit.nr_hw_temp >= SVGA3D_TEMPREG_MAX) {
      debug_printf("svga: too many temporary registers (%u)\n",
                   emit.nr_hw_temp);
      goto fail;
   }

   if (emit.info.indirect_files & (1 << TGSI_FILE_TEMPORARY)) {
      debug_printf(
         "svga: indirect indexing of temporary registers is not supported.\n");
      goto fail;
   }

   emit.in_main_func = TRUE;

   if (!svga_shader_emit_header(&emit)) {
      debug_printf("svga: emit header failed\n");
      goto fail;
   }

   if (!svga_shader_emit_instructions(&emit, shader->tokens)) {
      debug_printf("svga: emit instructions failed\n");
      goto fail;
   }

   variant = svga_new_shader_variant(svga);
   if (!variant)
      goto fail;

   variant->shader = shader;
   variant->tokens = (const unsigned *) emit.buf;
   variant->nr_tokens = (emit.ptr - emit.buf) / sizeof(unsigned);
   memcpy(&variant->key, key, sizeof(*key));
   variant->id = UTIL_BITMASK_INVALID_INDEX;

   variant->pstipple_sampler_unit = emit.pstipple_sampler_unit;

   /* If there was exactly one write to a fragment shader output register
    * and it came from a constant buffer, we know all fragments will have
    * the same color (except for blending).
    */
   variant->constant_color_output =
      emit.constant_color_output && emit.num_output_writes == 1;

#if 0
   if (!svga_shader_verify(variant->tokens, variant->nr_tokens) ||
       SVGA_DEBUG & DEBUG_TGSI) {
      debug_printf("#####################################\n");
      debug_printf("Shader %u below\n", shader->id);
      tgsi_dump(shader->tokens, 0);
      if (SVGA_DEBUG & DEBUG_TGSI) {
         debug_printf("Shader %u compiled below\n", shader->id);
         svga_shader_dump(variant->tokens, variant->nr_tokens, FALSE);
      }
      debug_printf("#####################################\n");
   }
#endif

   goto done;

fail:
   FREE(variant);
   if (emit.buf != err_buf)
      FREE(emit.buf);
   variant = NULL;

done:
   SVGA_STATS_TIME_POP(svga_sws(svga));
   return variant;
}
示例#2
0
/* Parse TGSI shader and translate to SVGA/DX9 serialized
 * representation.  
 *
 * In this function SVGA shader is emitted to an in-memory buffer that
 * can be dynamically grown.  Once we've finished and know how large
 * it is, it will be copied to a hardware buffer for upload.
 */
static struct svga_shader_result *
svga_tgsi_translate( const struct svga_shader *shader,
                     union svga_compile_key key,
                     unsigned unit )
{
   struct svga_shader_result *result = NULL;
   struct svga_shader_emitter emit;
   int ret = 0;

   memset(&emit, 0, sizeof(emit));

   emit.use_sm30 = shader->use_sm30;
   emit.size = 1024;
   emit.buf = MALLOC(emit.size);
   if (emit.buf == NULL) {
      ret = PIPE_ERROR_OUT_OF_MEMORY;
      goto fail;
   }

   emit.ptr = emit.buf;
   emit.unit = unit;
   emit.key = key;

   tgsi_scan_shader( shader->tokens, &emit.info);

   emit.imm_start = emit.info.file_max[TGSI_FILE_CONSTANT] + 1;
   
   if (unit == PIPE_SHADER_FRAGMENT)
      emit.imm_start += key.fkey.num_unnormalized_coords;

   if (unit == PIPE_SHADER_VERTEX) {
      emit.imm_start += key.vkey.need_prescale ? 2 : 0;
      emit.imm_start += key.vkey.num_zero_stride_vertex_elements;
   }

   emit.nr_hw_const = (emit.imm_start + emit.info.file_max[TGSI_FILE_IMMEDIATE] + 1);

   emit.nr_hw_temp = emit.info.file_max[TGSI_FILE_TEMPORARY] + 1;
   emit.in_main_func = TRUE;

   if (!svga_shader_emit_header( &emit ))
      goto fail;

   if (!svga_shader_emit_instructions( &emit, shader->tokens ))
      goto fail;
   
   result = CALLOC_STRUCT(svga_shader_result);
   if (result == NULL)
      goto fail;

   result->shader = shader;
   result->tokens = (const unsigned *)emit.buf;
   result->nr_tokens = (emit.ptr - emit.buf) / sizeof(unsigned);
   memcpy(&result->key, &key, sizeof key);

   if (SVGA_DEBUG & DEBUG_TGSI) 
   {
      debug_printf( "#####################################\n" );
      debug_printf( "Shader %u below\n", shader->id );
      tgsi_dump( shader->tokens, 0 );
      if (SVGA_DEBUG & DEBUG_TGSI) {
         debug_printf( "Shader %u compiled below\n", shader->id );
         svga_shader_dump( result->tokens,
                           result->nr_tokens ,
                           FALSE );
      }
      debug_printf( "#####################################\n" );
   }

   return result;

fail:
   FREE(result);
   FREE(emit.buf);
   return NULL;
}