drivers/gpu/drm/vc4/vc4_validate_shaders.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/vc4/vc4_validate_shaders.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/vc4/vc4_validate_shaders.c
Extension
.c
Size
27958 bytes
Lines
958
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct vc4_shader_validation_state {
	/* Current IP being validated. */
	uint32_t ip;

	/* IP at the end of the BO, do not read shader[max_ip] */
	uint32_t max_ip;

	uint64_t *shader;

	struct vc4_texture_sample_info tmu_setup[2];
	int tmu_write_count[2];

	/* For registers that were last written to by a MIN instruction with
	 * one argument being a uniform, the address of the uniform.
	 * Otherwise, ~0.
	 *
	 * This is used for the validation of direct address memory reads.
	 */
	uint32_t live_min_clamp_offsets[LIVE_REG_COUNT];
	bool live_max_clamp_regs[LIVE_REG_COUNT];
	uint32_t live_immediates[LIVE_REG_COUNT];

	/* Bitfield of which IPs are used as branch targets.
	 *
	 * Used for validation that the uniform stream is updated at the right
	 * points and clearing the texturing/clamping state.
	 */
	unsigned long *branch_targets;

	/* Set when entering a basic block, and cleared when the uniform
	 * address update is found.  This is used to make sure that we don't
	 * read uniforms when the address is undefined.
	 */
	bool needs_uniform_address_update;

	/* Set when we find a backwards branch.  If the branch is backwards,
	 * the taraget is probably doing an address reset to read uniforms,
	 * and so we need to be sure that a uniforms address is present in the
	 * stream, even if the shader didn't need to read uniforms in later
	 * basic blocks.
	 */
	bool needs_uniform_address_for_loop;

	/* Set when we find an instruction writing the top half of the
	 * register files.  If we allowed writing the unusable regs in
	 * a threaded shader, then the other shader running on our
	 * QPU's clamp validation would be invalid.
	 */
	bool all_registers_used;
};

static uint32_t
waddr_to_live_reg_index(uint32_t waddr, bool is_b)
{
	if (waddr < 32) {
		if (is_b)
			return 32 + waddr;
		else
			return waddr;
	} else if (waddr <= QPU_W_ACC3) {
		return 64 + waddr - QPU_W_ACC0;
	} else {
		return ~0;
	}
}

static uint32_t
raddr_add_a_to_live_reg_index(uint64_t inst)
{
	uint32_t sig = QPU_GET_FIELD(inst, QPU_SIG);
	uint32_t add_a = QPU_GET_FIELD(inst, QPU_ADD_A);
	uint32_t raddr_a = QPU_GET_FIELD(inst, QPU_RADDR_A);
	uint32_t raddr_b = QPU_GET_FIELD(inst, QPU_RADDR_B);

	if (add_a == QPU_MUX_A)
		return raddr_a;
	else if (add_a == QPU_MUX_B && sig != QPU_SIG_SMALL_IMM)
		return 32 + raddr_b;
	else if (add_a <= QPU_MUX_R3)
		return 64 + add_a;
	else
		return ~0;
}

static bool
live_reg_is_upper_half(uint32_t lri)
{
	return	(lri >= 16 && lri < 32) ||
		(lri >= 32 + 16 && lri < 32 + 32);
}

Annotation

Implementation Notes