⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slang_assemble.c

📁 mesa-6.5-minigui源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	size = _slang_sizeof_aggregate (&agg);
	result = dereference_aggregate (A, &agg, &size, &ti.swz, ti.is_swizzled);

end:
	slang_storage_aggregate_destruct (&agg);
end1:
	slang_assembly_typeinfo_destruct (&ti);
	return result;
}

GLboolean _slang_assemble_function_call (slang_assemble_ctx *A, slang_function *fun,
	slang_operation *params, GLuint param_count, GLboolean assignment)
{
	GLuint i;
	slang_swizzle p_swz[64];
	slang_ref_type p_ref[64];

	/* TODO: fix this, allocate dynamically */
	if (param_count > 64)
		return GL_FALSE;

	/* make room for the return value, if any */
	if (fun->header.type.specifier.type != slang_spec_void)
	{
		GLuint ret_size = 0;

		if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, 0, &ret_size))
			return GL_FALSE;
		if (!PLAB (A->file, slang_asm_local_alloc, ret_size))
			return GL_FALSE;
	}

	/* push the actual parameters on the stack */
	for (i = 0; i < param_count; i++)
	{
		if (fun->parameters->variables[i].type.qualifier == slang_qual_inout ||
			fun->parameters->variables[i].type.qualifier == slang_qual_out)
		{
			if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
				return GL_FALSE;
			/* TODO: optimize the "out" parameter case */
			if (!_slang_assemble_operation (A, &params[i], slang_ref_force))
				return GL_FALSE;
			p_swz[i] = A->swz;
			p_ref[i] = A->ref;
			if (!PUSH (A->file, slang_asm_addr_copy))
				return GL_FALSE;
			if (!PUSH (A->file, slang_asm_addr_deref))
				return GL_FALSE;
			if (i == 0 && assignment)
			{
				/* duplicate the resulting address */
				if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
					return GL_FALSE;
				if (!PUSH (A->file, slang_asm_addr_deref))
					return GL_FALSE;
			}
			if (!_slang_dereference (A, &params[i]))
				return GL_FALSE;
		}
		else
		{
			if (!_slang_assemble_operation (A, &params[i], slang_ref_forbid))
				return GL_FALSE;
			p_swz[i] = A->swz;
			p_ref[i] = A->ref;
		}
	}

	/* call the function */
	if (!PLAB (A->file, slang_asm_call, fun->address))
		return GL_FALSE;

	/* pop the parameters from the stack */
	for (i = param_count; i > 0; i--)
	{
		GLuint j = i - 1;

		A->swz = p_swz[j];
		A->ref = p_ref[j];
		if (fun->parameters->variables[j].type.qualifier == slang_qual_inout ||
			fun->parameters->variables[j].type.qualifier == slang_qual_out)
		{
			/* for output parameter copy the contents of the formal parameter
			 * back to the original actual parameter */
			if (!_slang_assemble_assignment (A, &params[j]))
				return GL_FALSE;
			/* pop the actual parameter's address */
			if (!PLAB (A->file, slang_asm_local_free, 4))
				return GL_FALSE;
		}
		else
		{
			/* pop the value of the parameter */
			if (!_slang_cleanup_stack (A, &params[j]))
				return GL_FALSE;
		}
	}

	return GL_TRUE;
}

GLboolean _slang_assemble_function_call_name (slang_assemble_ctx *A, const char *name,
	slang_operation *params, GLuint param_count, GLboolean assignment)
{
	slang_atom atom;
	slang_function *fun;

	atom = slang_atom_pool_atom (A->atoms, name);
	if (atom == SLANG_ATOM_NULL)
		return GL_FALSE;
	fun = _slang_locate_function (A->space.funcs, atom, params, param_count, &A->space, A->atoms);
	if (fun == NULL)
		return GL_FALSE;
	return _slang_assemble_function_call (A, fun, params, param_count, assignment);
}

static GLboolean assemble_function_call_name_dummyint (slang_assemble_ctx *A, const char *name,
	slang_operation *params)
{
	slang_operation p[2];
	GLboolean result;

	p[0] = params[0];
	if (!slang_operation_construct (&p[1]))
		return GL_FALSE;
	p[1].type = slang_oper_literal_int;
	result = _slang_assemble_function_call_name (A, name, p, 2, GL_FALSE);
	slang_operation_destruct (&p[1]);
	return result;
}

static const struct
{
	const char *name;
	slang_assembly_type code1, code2;
} inst[] = {
	/* core */
	{ "float_add",      slang_asm_float_add,      slang_asm_float_copy },
	{ "float_multiply", slang_asm_float_multiply, slang_asm_float_copy },
	{ "float_divide",   slang_asm_float_divide,   slang_asm_float_copy },
	{ "float_negate",   slang_asm_float_negate,   slang_asm_float_copy },
	{ "float_less",     slang_asm_float_less,     slang_asm_bool_copy },
	{ "float_equal",    slang_asm_float_equal_exp,slang_asm_bool_copy },
	{ "float_to_int",   slang_asm_float_to_int,   slang_asm_int_copy },
	{ "float_sine",     slang_asm_float_sine,     slang_asm_float_copy },
	{ "float_arcsine",  slang_asm_float_arcsine,  slang_asm_float_copy },
	{ "float_arctan",   slang_asm_float_arctan,   slang_asm_float_copy },
	{ "float_power",    slang_asm_float_power,    slang_asm_float_copy },
	{ "float_log2",     slang_asm_float_log2,     slang_asm_float_copy },
	{ "float_floor",    slang_asm_float_floor,    slang_asm_float_copy },
	{ "float_ceil",     slang_asm_float_ceil,     slang_asm_float_copy },
	{ "float_noise1",   slang_asm_float_noise1,   slang_asm_float_copy },
	{ "float_noise2",   slang_asm_float_noise2,   slang_asm_float_copy },
	{ "float_noise3",   slang_asm_float_noise3,   slang_asm_float_copy },
	{ "float_noise4",   slang_asm_float_noise4,   slang_asm_float_copy },
	{ "int_to_float",   slang_asm_int_to_float,   slang_asm_float_copy },
	{ "vec4_tex1d",     slang_asm_vec4_tex1d,     slang_asm_none },
	{ "vec4_tex2d",     slang_asm_vec4_tex2d,     slang_asm_none },
	{ "vec4_tex3d",     slang_asm_vec4_tex3d,     slang_asm_none },
	{ "vec4_texcube",   slang_asm_vec4_texcube,   slang_asm_none },
	{ "vec4_shad1d",    slang_asm_vec4_shad1d,    slang_asm_none },
	{ "vec4_shad2d",    slang_asm_vec4_shad2d,    slang_asm_none },
	/* mesa-specific extensions */
	{ "float_print",    slang_asm_float_deref,    slang_asm_float_print },
	{ "int_print",      slang_asm_int_deref,      slang_asm_int_print },
	{ "bool_print",     slang_asm_bool_deref,     slang_asm_bool_print },
	{ NULL,             slang_asm_none,           slang_asm_none }
};

static GLboolean call_asm_instruction (slang_assemble_ctx *A, slang_atom a_name)
{
	const char *id;
	GLuint i;

	id = slang_atom_pool_id (A->atoms, a_name);

	for (i = 0; inst[i].name != NULL; i++)
		if (slang_string_compare (id, inst[i].name) == 0)
			break;
	if (inst[i].name == NULL)
		return GL_FALSE;

	if (!PLAB2 (A->file, inst[i].code1, 4, 0))
		return GL_FALSE;
	if (inst[i].code2 != slang_asm_none)
		if (!PLAB2 (A->file, inst[i].code2, 4, 0))
			return GL_FALSE;

	/* clean-up the stack from the remaining dst address */
	if (!PLAB (A->file, slang_asm_local_free, 4))
		return GL_FALSE;

	return GL_TRUE;
}

static GLboolean equality_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg,
	GLuint *index, GLuint size, GLuint z_label)
{
	GLuint i;

	for (i = 0; i < agg->count; i++)
	{
		const slang_storage_array *arr = &agg->arrays[i];
		GLuint j;

		for (j = 0; j < arr->length; j++)
		{
			if (arr->type == slang_stor_aggregate)
			{
				if (!equality_aggregate (A, arr->aggregate, index, size, z_label))
					return GL_FALSE;
			}
			else
			{
				if (!PLAB2 (A->file, slang_asm_float_equal_int, size + *index, *index))
					return GL_FALSE;
				*index += 4;
				if (!PLAB (A->file, slang_asm_jump_if_zero, z_label))
					return GL_FALSE;
			}
		}
	}

	return GL_TRUE;
}

static GLboolean equality (slang_assemble_ctx *A, slang_operation *op, GLboolean equal)
{
	slang_assembly_typeinfo ti;
	GLboolean result = GL_FALSE;
	slang_storage_aggregate agg;
	GLuint index, size;
	GLuint skip_jump, true_label, true_jump, false_label, false_jump;

	/* get type of operation */
	if (!slang_assembly_typeinfo_construct (&ti))
		return GL_FALSE;
	if (!_slang_typeof_operation (A, op, &ti))
		goto end1;

	/* convert it to an aggregate */
	if (!slang_storage_aggregate_construct (&agg))
		goto end1;
	if (!_slang_aggregate_variable (&agg, &ti.spec, 0, A->space.funcs, A->space.structs,
			A->space.vars, A->mach, A->file, A->atoms))
		goto end;

	/* compute the size of the agregate - there are two such aggregates on the stack */
	size = _slang_sizeof_aggregate (&agg);

	/* jump to the actual data-comparison code */
	skip_jump = A->file->count;
	if (!PUSH (A->file, slang_asm_jump))
		goto end;

	/* pop off the stack the compared data and push 1 */
	true_label = A->file->count;
	if (!PLAB (A->file, slang_asm_local_free, size * 2))
		goto end;
	if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 1))
		goto end;
	true_jump = A->file->count;
	if (!PUSH (A->file, slang_asm_jump))
		goto end;

	false_label = A->file->count;
	if (!PLAB (A->file, slang_asm_local_free, size * 2))
		goto end;
	if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 0))
		goto end;
	false_jump = A->file->count;
	if (!PUSH (A->file, slang_asm_jump))
		goto end;

	A->file->code[skip_jump].param[0] = A->file->count;

	/* compare the data on stack, it will eventually jump either to true or false label */
	index = 0;
	if (!equality_aggregate (A, &agg, &index, size, equal ? false_label : true_label))
		goto end;
	if (!PLAB (A->file, slang_asm_jump, equal ? true_label : false_label))
		goto end;

	A->file->code[true_jump].param[0] = A->file->count;
	A->file->code[false_jump].param[0] = A->file->count;

	result = GL_TRUE;
end:
	slang_storage_aggregate_destruct (&agg);
end1:
	slang_assembly_typeinfo_destruct (&ti);
	return result;
}

static GLboolean handle_subscript (slang_assemble_ctx *A, slang_assembly_typeinfo *tie,
	slang_assembly_typeinfo *tia, slang_operation *op, slang_ref_type ref)
{
	GLuint asize = 0, esize = 0;

	/* get type info of the master expression (matrix, vector or an array */
	if (!_slang_typeof_operation (A, &op->children[0], tia))
		return GL_FALSE;
	if (!sizeof_variable (A, &tia->spec, slang_qual_none, tia->array_len, &asize))
		return GL_FALSE;

	/* get type info of the result (matrix column, vector row or array element) */
	if (!_slang_typeof_operation (A, op, tie))
		return GL_FALSE;
	if (!sizeof_variable (A, &tie->spec, slang_qual_none, 0, &esize))
		return GL_FALSE;

	/* assemble the master expression */
	if (!_slang_assemble_operation (A, &op->children[0], ref))
		return GL_FALSE;

	/* when indexing an l-value swizzle, push the swizzle_tmp */
	if (ref == slang_ref_force && tia->is_swizzled)
		if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
			return GL_FALSE;

	/* assemble the subscript expression */
	if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
		return GL_FALSE;

	if (ref == slang_ref_force && tia->is_swizzled)
	{
		GLuint i;

		/* copy the swizzle indexes to the swizzle_tmp */
		for (i = 0; i < tia->swz.num_components; i++)
		{
			if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
				return GL_FALSE;
			if (!PLAB (A->file, slang_asm_addr_push, i * 4))
				return GL_FALSE;
			if (!PUSH (A->file, slang_asm_addr_add))
				return GL_FALSE;
			if (!PLAB (A->file, slang_asm_addr_push, tia->swz.swizzle[i]))
				return GL_FALSE;
			if (!PUSH (A->file, slang_asm_addr_copy))
				return GL_FALSE;
			if (!PLAB (A->file, slang_asm_local_free, 4))
				return GL_FALSE;
		}

		/* offset the pushed swizzle_tmp address and dereference it */
		if (!PUSH (A->file, slang_asm_int_to_addr))
			return GL_FALSE;
		if (!PLAB (A->file, slang_asm_addr_push, 4))
			return GL_FALSE;
		if (!PUSH (A->file, slang_asm_addr_multiply))
			return GL_FALSE;
		if (!PUSH (A->file, slang_asm_addr_add))
			return GL_FALSE;
		if (!PUSH (A->file, slang_asm_addr_deref))
			return GL_FALSE;
	}
	else
	{
		/* convert the integer subscript to a relative address */
		if (!PUSH (A->file, slang_asm_int_to_addr))
			return GL_FALSE;
	}

	if (!PLAB (A->file, slang_asm_addr_push, esize))
		return GL_FALSE;
	if (!PUSH (A->file, slang_asm_addr_multiply))
		return GL_FALSE;

	if (ref == slang_ref_force)
	{
		/* offset the base address with the relative address */
		if (!PUSH (A->file, slang_asm_addr_add))
			return GL_FALSE;
	}
	else
	{
		GLuint i;

		/* move the selected element to the beginning of the master expression */
		for (i = 0; i < esize; i += 4)
			if (!PLAB2 (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4))
				return GL_FALSE;
		if (!PLAB (A->file, slang_asm_local_free, 4))
			return GL_FALSE;

		/* free the rest of the master expression */
		if (!PLAB (A->file, slang_asm_local_free, asize - esize))
			return GL_FALSE;
	}

	return GL_TRUE;
}

static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *tia,
	slang_assembly_typeinfo *tib, slang_operation *op, slang_ref_type ref)
{
	/* get type info of the result (field or swizzle) */
	if (!_slang_typeof_operation (A, op, tia))
		return GL_FALSE;

	/* get type info of the master expression being accessed (struct or vector) */
	if (!_slang_typeof_operation (A, &op->children[0], tib))
		return GL_FALSE;

	/* if swizzling a vector in-place, the swizzle temporary is needed */
	if (ref == slang_ref_forbid && tia->is_swizzled)
		if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
			return GL_FALSE;

	/* assemble the master expression */
	if (!_slang_assemble_operation (A, &op->children[0], ref))
		return GL_FALSE;

	/* assemble the field expression */
	if (tia->is_swizzled)
	{
		if (ref == slang_ref_force)
		{
#if 0
			if (tia->swz.num_components == 1)
			{
				/* simple case - adjust the vector's address to point to the selected component */
				if (!PLAB (file, slang_asm_addr_push, tia->swz.swizzle[0] * 4))
					return 0;
				if (!PUSH (file, slang_asm_addr_add))
					return 0;
			}
			else
#endif
			{
				/* two or more vector components are being referenced - the so-called write mask
				 * must be passed to the upper operations and applied when assigning value
				 * to this swizzle */
				A->swz = tia->swz;
			}
		}
		else
		{
			/* swizzle the vector in-place using the swizzle temporary */
			if (!_slang_assemble_constructor_from_swizzle (A, &tia->swz, &tia->spec, &tib->spec))
				return GL_FALSE;
		}
	}
	else
	{
		GLuint i, struct_size = 0, field_offset = 0, field_size = 0;
		GLboolean relocate, shrink;

		/* calculate struct size, field offset and field size */
		for (i = 0; i < tib->spec._struct->fields->num_variables; i++)
		{
			slang_variable *field;
			slang_storage_aggregate agg;
			GLuint size;

			field = &tib->spec._struct->fields->variables[i];
			if (!slang_storage_aggregate_construct (&agg))
				return GL_FALSE;
			if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_len,
					A->space.funcs, A->space.structs, A->space.vars, A->mach, A->file, A->atoms))
			{
				slang_storage_aggregate_destruct (&agg);
				return GL_FALSE;
			}
			size = _slang_sizeof_aggregate (&agg);
			slang_storage_aggregate_destruct (&agg);

			if (op->a_id == field->a_name)
			{
				field_size = size;
				struct_size = field_offset + size;
			}
			else if (struct_size != 0)
				struct_size += size;
			else
				field_offset += size;
		}

		/*
		 * OPTIMIZATION: If selecting the last field, no relocation is needed.
		 */
		relocate = field_offset != struct_size - field_size;

		/*
		 * OPTIMIZATION: If field and struct sizes are equal, no partial free is needed.
		 */
		shrink = field_size != struct_size;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -