예제 #1
0
/* Asynchronous compute shader compilation. */
static void si_create_compute_state_async(void *job, int thread_index)
{
	struct si_compute *program = (struct si_compute *)job;
	struct si_shader *shader = &program->shader;
	struct si_shader_selector sel;
	LLVMTargetMachineRef tm;
	struct pipe_debug_callback *debug = &program->compiler_ctx_state.debug;

	assert(!debug->debug_message || debug->async);
	assert(thread_index >= 0);
	assert(thread_index < ARRAY_SIZE(program->screen->tm));
	tm = program->screen->tm[thread_index];

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

	sel.screen = program->screen;

	if (program->ir_type == PIPE_SHADER_IR_TGSI) {
		tgsi_scan_shader(program->ir.tgsi, &sel.info);
		sel.tokens = program->ir.tgsi;
	} else {
		assert(program->ir_type == PIPE_SHADER_IR_NIR);
		sel.nir = program->ir.nir;

		si_nir_scan_shader(sel.nir, &sel.info);
		si_lower_nir(&sel);
	}


	sel.type = PIPE_SHADER_COMPUTE;
	sel.local_size = program->local_size;
	si_get_active_slot_masks(&sel.info,
				 &program->active_const_and_shader_buffers,
				 &program->active_samplers_and_images);

	program->shader.selector = &sel;
	program->shader.is_monolithic = true;
	program->uses_grid_size = sel.info.uses_grid_size;
	program->uses_block_size = sel.info.uses_block_size;
	program->uses_bindless_samplers = sel.info.uses_bindless_samplers;
	program->uses_bindless_images = sel.info.uses_bindless_images;

	if (si_shader_create(program->screen, tm, &program->shader, debug)) {
		program->shader.compilation_failed = true;
	} else {
		bool scratch_enabled = shader->config.scratch_bytes_per_wave > 0;
		unsigned user_sgprs = SI_NUM_RESOURCE_SGPRS +
				      (sel.info.uses_grid_size ? 3 : 0) +
				      (sel.info.uses_block_size ? 3 : 0);

		shader->config.rsrc1 =
			S_00B848_VGPRS((shader->config.num_vgprs - 1) / 4) |
			S_00B848_SGPRS((shader->config.num_sgprs - 1) / 8) |
			S_00B848_DX10_CLAMP(1) |
			S_00B848_FLOAT_MODE(shader->config.float_mode);

		shader->config.rsrc2 =
			S_00B84C_USER_SGPR(user_sgprs) |
			S_00B84C_SCRATCH_EN(scratch_enabled) |
			S_00B84C_TGID_X_EN(sel.info.uses_block_id[0]) |
			S_00B84C_TGID_Y_EN(sel.info.uses_block_id[1]) |
			S_00B84C_TGID_Z_EN(sel.info.uses_block_id[2]) |
			S_00B84C_TIDIG_COMP_CNT(sel.info.uses_thread_id[2] ? 2 :
						sel.info.uses_thread_id[1] ? 1 : 0) |
			S_00B84C_LDS_SIZE(shader->config.lds_size);

		program->variable_group_size =
			sel.info.properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] == 0;
	}

	if (program->ir_type == PIPE_SHADER_IR_TGSI)
		FREE(program->ir.tgsi);

	program->shader.selector = NULL;
}
예제 #2
0
파일: si_compute.c 프로젝트: etnaviv/mesa
static void *si_create_compute_state(
	struct pipe_context *ctx,
	const struct pipe_compute_state *cso)
{
	struct si_context *sctx = (struct si_context *)ctx;
	struct si_screen *sscreen = (struct si_screen *)ctx->screen;
	struct si_compute *program = CALLOC_STRUCT(si_compute);
	struct si_shader *shader = &program->shader;


	program->ir_type = cso->ir_type;
	program->local_size = cso->req_local_mem;
	program->private_size = cso->req_private_mem;
	program->input_size = cso->req_input_mem;
	program->use_code_object_v2 = HAVE_LLVM >= 0x0400 &&
					cso->ir_type == PIPE_SHADER_IR_NATIVE;


	if (cso->ir_type == PIPE_SHADER_IR_TGSI) {
		struct si_shader_selector sel;
		bool scratch_enabled;

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

		sel.tokens = tgsi_dup_tokens(cso->prog);
		if (!sel.tokens) {
			FREE(program);
			return NULL;
		}

		tgsi_scan_shader(cso->prog, &sel.info);
		sel.type = PIPE_SHADER_COMPUTE;
		sel.local_size = cso->req_local_mem;

		p_atomic_inc(&sscreen->b.num_shaders_created);

		program->shader.selector = &sel;

		if (si_shader_create(sscreen, sctx->tm, &program->shader,
		                     &sctx->b.debug)) {
			FREE(sel.tokens);
			FREE(program);
			return NULL;
		}

		scratch_enabled = shader->config.scratch_bytes_per_wave > 0;

		shader->config.rsrc1 =
			   S_00B848_VGPRS((shader->config.num_vgprs - 1) / 4) |
			   S_00B848_SGPRS((shader->config.num_sgprs - 1) / 8) |
			   S_00B848_DX10_CLAMP(1) |
			   S_00B848_FLOAT_MODE(shader->config.float_mode);

		shader->config.rsrc2 = S_00B84C_USER_SGPR(SI_CS_NUM_USER_SGPR) |
			   S_00B84C_SCRATCH_EN(scratch_enabled) |
			   S_00B84C_TGID_X_EN(1) | S_00B84C_TGID_Y_EN(1) |
			   S_00B84C_TGID_Z_EN(1) | S_00B84C_TIDIG_COMP_CNT(2) |
			   S_00B84C_LDS_SIZE(shader->config.lds_size);

		FREE(sel.tokens);
	} else {
		const struct pipe_llvm_program_header *header;
		const char *code;
		header = cso->prog;
		code = cso->prog + sizeof(struct pipe_llvm_program_header);

		radeon_elf_read(code, header->num_bytes, &program->shader.binary);
		if (program->use_code_object_v2) {
			const amd_kernel_code_t *code_object =
				si_compute_get_code_object(program, 0);
			code_object_to_config(code_object, &program->shader.config);
		} else {
			si_shader_binary_read_config(&program->shader.binary,
				     &program->shader.config, 0);
		}
		si_shader_dump(sctx->screen, &program->shader, &sctx->b.debug,
			       PIPE_SHADER_COMPUTE, stderr);
		si_shader_binary_upload(sctx->screen, &program->shader);
	}

	return program;
}
예제 #3
0
/* Asynchronous compute shader compilation. */
static void si_create_compute_state_async(void *job, int thread_index)
{
	struct si_compute *program = (struct si_compute *)job;
	struct si_shader *shader = &program->shader;
	struct si_shader_selector sel;
	struct ac_llvm_compiler *compiler;
	struct pipe_debug_callback *debug = &program->compiler_ctx_state.debug;
	struct si_screen *sscreen = program->screen;

	assert(!debug->debug_message || debug->async);
	assert(thread_index >= 0);
	assert(thread_index < ARRAY_SIZE(sscreen->compiler));
	compiler = &sscreen->compiler[thread_index];

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

	sel.screen = sscreen;

	if (program->ir_type == PIPE_SHADER_IR_TGSI) {
		tgsi_scan_shader(program->ir.tgsi, &sel.info);
		sel.tokens = program->ir.tgsi;
	} else {
		assert(program->ir_type == PIPE_SHADER_IR_NIR);
		sel.nir = program->ir.nir;

		si_nir_scan_shader(sel.nir, &sel.info);
		si_lower_nir(&sel);
	}

	/* Store the declared LDS size into tgsi_shader_info for the shader
	 * cache to include it.
	 */
	sel.info.properties[TGSI_PROPERTY_CS_LOCAL_SIZE] = program->local_size;

	sel.type = PIPE_SHADER_COMPUTE;
	si_get_active_slot_masks(&sel.info,
				 &program->active_const_and_shader_buffers,
				 &program->active_samplers_and_images);

	program->shader.selector = &sel;
	program->shader.is_monolithic = true;
	program->uses_grid_size = sel.info.uses_grid_size;
	program->uses_bindless_samplers = sel.info.uses_bindless_samplers;
	program->uses_bindless_images = sel.info.uses_bindless_images;
	program->reads_variable_block_size =
		sel.info.uses_block_size &&
		sel.info.properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] == 0;
	program->num_cs_user_data_dwords =
		sel.info.properties[TGSI_PROPERTY_CS_USER_DATA_DWORDS];

	void *ir_binary = si_get_ir_binary(&sel);

	/* Try to load the shader from the shader cache. */
	mtx_lock(&sscreen->shader_cache_mutex);

	if (ir_binary &&
	    si_shader_cache_load_shader(sscreen, ir_binary, shader)) {
		mtx_unlock(&sscreen->shader_cache_mutex);

		si_shader_dump_stats_for_shader_db(shader, debug);
		si_shader_dump(sscreen, shader, debug, PIPE_SHADER_COMPUTE,
			       stderr, true);

		if (si_shader_binary_upload(sscreen, shader))
			program->shader.compilation_failed = true;
	} else {
		mtx_unlock(&sscreen->shader_cache_mutex);

		if (si_shader_create(sscreen, compiler, &program->shader, debug)) {
			program->shader.compilation_failed = true;

			if (program->ir_type == PIPE_SHADER_IR_TGSI)
				FREE(program->ir.tgsi);
			program->shader.selector = NULL;
			return;
		}

		bool scratch_enabled = shader->config.scratch_bytes_per_wave > 0;
		unsigned user_sgprs = SI_NUM_RESOURCE_SGPRS +
				      (sel.info.uses_grid_size ? 3 : 0) +
				      (program->reads_variable_block_size ? 3 : 0) +
				      program->num_cs_user_data_dwords;

		shader->config.rsrc1 =
			S_00B848_VGPRS((shader->config.num_vgprs - 1) / 4) |
			S_00B848_SGPRS((shader->config.num_sgprs - 1) / 8) |
			S_00B848_DX10_CLAMP(1) |
			S_00B848_FLOAT_MODE(shader->config.float_mode);

		shader->config.rsrc2 =
			S_00B84C_USER_SGPR(user_sgprs) |
			S_00B84C_SCRATCH_EN(scratch_enabled) |
			S_00B84C_TGID_X_EN(sel.info.uses_block_id[0]) |
			S_00B84C_TGID_Y_EN(sel.info.uses_block_id[1]) |
			S_00B84C_TGID_Z_EN(sel.info.uses_block_id[2]) |
			S_00B84C_TIDIG_COMP_CNT(sel.info.uses_thread_id[2] ? 2 :
						sel.info.uses_thread_id[1] ? 1 : 0) |
			S_00B84C_LDS_SIZE(shader->config.lds_size);

		if (ir_binary) {
			mtx_lock(&sscreen->shader_cache_mutex);
			if (!si_shader_cache_insert_shader(sscreen, ir_binary, shader, true))
				FREE(ir_binary);
			mtx_unlock(&sscreen->shader_cache_mutex);
		}
	}

	if (program->ir_type == PIPE_SHADER_IR_TGSI)
		FREE(program->ir.tgsi);

	program->shader.selector = NULL;
}