summaryrefslogtreecommitdiff
path: root/lib/mesa/src/gallium/drivers/vc4/kernel
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2017-08-14 09:45:54 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2017-08-14 09:45:54 +0000
commit4c58069f5013f0a621503525f7d5193bfe9976b3 (patch)
treebd8f8a08b889e9a8b99c9de01ae12459d527ea6d /lib/mesa/src/gallium/drivers/vc4/kernel
parent5caa025e6b62d0456faad86c89f239a14d1eaadb (diff)
Import Mesa 17.1.6
Diffstat (limited to 'lib/mesa/src/gallium/drivers/vc4/kernel')
-rw-r--r--lib/mesa/src/gallium/drivers/vc4/kernel/README6
-rw-r--r--lib/mesa/src/gallium/drivers/vc4/kernel/vc4_drv.h2
-rw-r--r--lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate.c24
-rw-r--r--lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate_shaders.c81
4 files changed, 97 insertions, 16 deletions
diff --git a/lib/mesa/src/gallium/drivers/vc4/kernel/README b/lib/mesa/src/gallium/drivers/vc4/kernel/README
new file mode 100644
index 000000000..89e4442b4
--- /dev/null
+++ b/lib/mesa/src/gallium/drivers/vc4/kernel/README
@@ -0,0 +1,6 @@
+This is a mirror of the kernel validation code into the userspace GL library.
+It is only built when USE_VC4_SIMULATOR is defined, for compiling the driver
+on an x86 system with the simpenrose simulator. It allows testing of changes
+across the kernel and userspace with exposure to most of the software stack,
+on a higher-performance and more-debuggable environment than the native
+hardware.
diff --git a/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_drv.h b/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_drv.h
index 90f45397d..8f5ed00d9 100644
--- a/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_drv.h
+++ b/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_drv.h
@@ -150,6 +150,8 @@ struct vc4_validated_shader_info
uint32_t num_uniform_addr_offsets;
uint32_t *uniform_addr_offsets;
+
+ bool is_threaded;
};
/* vc4_validate.c */
diff --git a/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate.c b/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate.c
index 4ef01108b..bd193b993 100644
--- a/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate.c
+++ b/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate.c
@@ -640,6 +640,13 @@ reloc_tex(struct vc4_exec_info *exec,
cpp = 1;
break;
case VC4_TEXTURE_TYPE_ETC1:
+ /* ETC1 is arranged as 64-bit blocks, where each block is 4x4
+ * pixels.
+ */
+ cpp = 8;
+ width = (width + 3) >> 2;
+ height = (height + 3) >> 2;
+ break;
case VC4_TEXTURE_TYPE_BW1:
case VC4_TEXTURE_TYPE_A4:
case VC4_TEXTURE_TYPE_A1:
@@ -773,11 +780,6 @@ validate_gl_shader_rec(struct drm_device *dev,
exec->shader_rec_v += roundup(packet_size, 16);
exec->shader_rec_size -= packet_size;
- if (!(*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD)) {
- DRM_ERROR("Multi-threaded fragment shaders not supported.\n");
- return -EINVAL;
- }
-
for (i = 0; i < shader_reloc_count; i++) {
if (src_handles[i] > exec->bo_count) {
DRM_ERROR("Shader handle %d too big\n", src_handles[i]);
@@ -794,6 +796,18 @@ validate_gl_shader_rec(struct drm_device *dev,
return -EINVAL;
}
+ if (((*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD) == 0) !=
+ to_vc4_bo(&bo[0]->base)->validated_shader->is_threaded) {
+ DRM_ERROR("Thread mode of CL and FS do not match\n");
+ return -EINVAL;
+ }
+
+ if (to_vc4_bo(&bo[1]->base)->validated_shader->is_threaded ||
+ to_vc4_bo(&bo[2]->base)->validated_shader->is_threaded) {
+ DRM_ERROR("cs and vs cannot be threaded\n");
+ return -EINVAL;
+ }
+
for (i = 0; i < shader_reloc_count; i++) {
struct vc4_validated_shader_info *validated_shader;
uint32_t o = shader_reloc_offsets[i];
diff --git a/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate_shaders.c b/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate_shaders.c
index 82717ca55..d93f5239d 100644
--- a/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate_shaders.c
+++ b/lib/mesa/src/gallium/drivers/vc4/kernel/vc4_validate_shaders.c
@@ -84,6 +84,14 @@ struct vc4_shader_validation_state {
* basic blocks.
*/
bool needs_uniform_address_for_loop;
+
+ /* Set when we find an instruction which violates the criterion for a
+ * threaded shader. These are:
+ * - only write the lower half of the register space
+ * - last thread switch signaled at the end
+ * So track the usage of the thread switches and the register usage.
+ */
+ bool all_registers_used;
};
static uint32_t
@@ -119,6 +127,12 @@ raddr_add_a_to_live_reg_index(uint64_t inst)
return ~0;
}
+static bool live_reg_is_upper_half(uint32_t lri)
+{
+ return (lri >=16 && lri < 32) ||
+ (lri >=32 + 16 && lri < 32 + 32);
+}
+
static bool
is_tmu_submit(uint32_t waddr)
{
@@ -385,6 +399,9 @@ check_reg_write(struct vc4_validated_shader_info *validated_shader,
} else {
validation_state->live_immediates[lri] = ~0;
}
+
+ if (live_reg_is_upper_half(lri))
+ validation_state->all_registers_used = true;
}
switch (waddr) {
@@ -593,6 +610,11 @@ check_instruction_reads(struct vc4_validated_shader_info *validated_shader,
}
}
+ if ((raddr_a >= 16 && raddr_a < 32) ||
+ (raddr_b >= 16 && raddr_b < 32 && sig != QPU_SIG_SMALL_IMM)) {
+ validation_state->all_registers_used = true;
+ }
+
return true;
}
@@ -603,9 +625,7 @@ static bool
vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
{
uint32_t max_branch_target = 0;
- bool found_shader_end = false;
int ip;
- int shader_end_ip = 0;
int last_branch = -2;
for (ip = 0; ip < validation_state->max_ip; ip++) {
@@ -616,8 +636,13 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
uint32_t branch_target_ip;
if (sig == QPU_SIG_PROG_END) {
- shader_end_ip = ip;
- found_shader_end = true;
+ /* There are two delay slots after program end is
+ * signaled that are still executed, then we're
+ * finished. validation_state->max_ip is the
+ * instruction after the last valid instruction in the
+ * program.
+ */
+ validation_state->max_ip = ip + 3;
continue;
}
@@ -671,15 +696,9 @@ vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
}
set_bit(after_delay_ip, validation_state->branch_targets);
max_branch_target = max(max_branch_target, after_delay_ip);
-
- /* There are two delay slots after program end is signaled
- * that are still executed, then we're finished.
- */
- if (found_shader_end && ip == shader_end_ip + 2)
- break;
}
- if (max_branch_target > shader_end_ip) {
+ if (max_branch_target > validation_state->max_ip - 3) {
DRM_ERROR("Branch landed after QPU_SIG_PROG_END");
return false;
}
@@ -751,6 +770,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
{
bool found_shader_end = false;
int shader_end_ip = 0;
+ uint32_t last_thread_switch_ip = -3;
uint32_t ip;
struct vc4_validated_shader_info *validated_shader = NULL;
struct vc4_shader_validation_state validation_state;
@@ -783,6 +803,16 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
if (!vc4_handle_branch_target(&validation_state))
goto fail;
+ if (ip == last_thread_switch_ip + 3) {
+ /* Reset r0-r3 live clamp data */
+ int i;
+ for (i = 64; i < LIVE_REG_COUNT; i++) {
+ validation_state.live_min_clamp_offsets[i] = ~0;
+ validation_state.live_max_clamp_regs[i] = false;
+ validation_state.live_immediates[i] = ~0;
+ }
+ }
+
switch (sig) {
case QPU_SIG_NONE:
case QPU_SIG_WAIT_FOR_SCOREBOARD:
@@ -792,6 +822,8 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
case QPU_SIG_LOAD_TMU1:
case QPU_SIG_PROG_END:
case QPU_SIG_SMALL_IMM:
+ case QPU_SIG_THREAD_SWITCH:
+ case QPU_SIG_LAST_THREAD_SWITCH:
if (!check_instruction_writes(validated_shader,
&validation_state)) {
DRM_ERROR("Bad write at ip %d\n", ip);
@@ -807,6 +839,18 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
shader_end_ip = ip;
}
+ if (sig == QPU_SIG_THREAD_SWITCH ||
+ sig == QPU_SIG_LAST_THREAD_SWITCH) {
+ validated_shader->is_threaded = true;
+
+ if (ip < last_thread_switch_ip + 3) {
+ DRM_ERROR("Thread switch too soon after "
+ "last switch at ip %d\n", ip);
+ goto fail;
+ }
+ last_thread_switch_ip = ip;
+ }
+
break;
case QPU_SIG_LOAD_IMM:
@@ -821,6 +865,13 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
if (!check_branch(inst, validated_shader,
&validation_state, ip))
goto fail;
+
+ if (ip < last_thread_switch_ip + 3) {
+ DRM_ERROR("Branch in thread switch at ip %d",
+ ip);
+ goto fail;
+ }
+
break;
default:
DRM_ERROR("Unsupported QPU signal %d at "
@@ -842,6 +893,14 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
goto fail;
}
+ /* Might corrupt other thread */
+ if (validated_shader->is_threaded &&
+ validation_state.all_registers_used) {
+ DRM_ERROR("Shader uses threading, but uses the upper "
+ "half of the registers, too\n");
+ goto fail;
+ }
+
/* If we did a backwards branch and we haven't emitted a uniforms
* reset since then, we still need the uniforms stream to have the
* uniforms address available so that the backwards branch can do its