summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>2019-04-23 13:58:45 +0200
committerDylan Baker <dylan@pnwbakers.com>2019-04-24 08:50:34 -0700
commitba1bf6c3ea54f2ece07770088b026a4322dfccd7 (patch)
tree580a0358b8204f4056d11f1dbeb3ce93b138285a
parentf223fb98e9aea2e60f4bfd25bf43c108c9a0d6bc (diff)
radv: do not load vertex attributes that are not provided by the pipeline
Per the Vulkan spec this is definitely invalid but X4 Foundations does that and it ends up by hanging the GPU. Found while enabling validation layers with the game. The issue will be reported to the developers. Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl> (cherry picked from commit 381e38aaaa47c5aa38bc4f504b325fb68b7caea8)
-rw-r--r--src/amd/vulkan/radv_nir_to_llvm.c30
-rw-r--r--src/amd/vulkan/radv_pipeline.c3
-rw-r--r--src/amd/vulkan/radv_private.h1
-rw-r--r--src/amd/vulkan/radv_shader.h3
4 files changed, 33 insertions, 4 deletions
diff --git a/src/amd/vulkan/radv_nir_to_llvm.c b/src/amd/vulkan/radv_nir_to_llvm.c
index bb8ebca0dab..b1eeb2cc1f7 100644
--- a/src/amd/vulkan/radv_nir_to_llvm.c
+++ b/src/amd/vulkan/radv_nir_to_llvm.c
@@ -2027,10 +2027,32 @@ handle_vs_input_decl(struct radv_shader_context *ctx,
t_list = ac_build_load_to_sgpr(&ctx->ac, t_list_ptr, t_offset);
- input = ac_build_buffer_load_format(&ctx->ac, t_list,
- buffer_index,
- ctx->ac.i32_0,
- num_channels, false, true);
+ if (ctx->options->key.vs.vertex_attribute_provided & (1u << attrib_index)) {
+ input = ac_build_buffer_load_format(&ctx->ac, t_list,
+ buffer_index,
+ ctx->ac.i32_0,
+ num_channels, false, true);
+ } else {
+ /* Per the Vulkan spec, it's invalid to consume vertex
+ * attributes that are not provided by the pipeline but
+ * some (invalid) apps appear to do that. Fill the
+ * input array with (eg. (0, 0, 0, 1)) to workaround
+ * the problem and to avoid possible GPU hangs.
+ */
+ LLVMValueRef chan[4];
+
+ /* The input_usage mask might be 0 if input variables
+ * are not removed by the compiler.
+ */
+ num_channels = CLAMP(num_channels, 1, 4);
+
+ for (unsigned i = 0; i < num_channels; i++) {
+ chan[i] = i == 3 ? ctx->ac.f32_1 : ctx->ac.f32_0;
+ chan[i] = ac_to_float(&ctx->ac, chan[i]);
+ }
+
+ input = ac_build_gather_values(&ctx->ac, chan, num_channels);
+ }
input = ac_build_expand_to_vec4(&ctx->ac, input, num_channels);
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index 61bdfc5cd2d..91f468910f1 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -1922,6 +1922,8 @@ radv_generate_graphics_pipeline_key(struct radv_pipeline *pipeline,
}
key.vertex_alpha_adjust |= adjust << (2 * location);
}
+
+ key.vertex_attribute_provided |= 1 << location;
}
if (pCreateInfo->pTessellationState)
@@ -1950,6 +1952,7 @@ radv_fill_shader_keys(struct radv_shader_variant_key *keys,
{
keys[MESA_SHADER_VERTEX].vs.instance_rate_inputs = key->instance_rate_inputs;
keys[MESA_SHADER_VERTEX].vs.alpha_adjust = key->vertex_alpha_adjust;
+ keys[MESA_SHADER_VERTEX].vs.vertex_attribute_provided = key->vertex_attribute_provided;
for (unsigned i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
keys[MESA_SHADER_VERTEX].vs.instance_rate_divisors[i] = key->instance_rate_divisors[i];
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index aaf057ea919..cd025cd5c4c 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -365,6 +365,7 @@ struct radv_pipeline_cache {
struct radv_pipeline_key {
uint32_t instance_rate_inputs;
uint32_t instance_rate_divisors[MAX_VERTEX_ATTRIBS];
+ uint32_t vertex_attribute_provided;
uint64_t vertex_alpha_adjust;
unsigned tess_input_vertices;
uint32_t col_format;
diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h
index 31839c3a85e..f6f9dd2bbf1 100644
--- a/src/amd/vulkan/radv_shader.h
+++ b/src/amd/vulkan/radv_shader.h
@@ -66,6 +66,9 @@ struct radv_vs_variant_key {
uint32_t instance_rate_inputs;
uint32_t instance_rate_divisors[MAX_VERTEX_ATTRIBS];
+ /* Mask of vertex attributes that are provided by the pipeline. */
+ uint32_t vertex_attribute_provided;
+
/* For 2_10_10_10 formats the alpha is handled as unsigned by pre-vega HW.
* so we may need to fix it up. */
uint64_t alpha_adjust;