aboutsummaryrefslogtreecommitdiff
path: root/layers/shader_validation.cpp
diff options
context:
space:
mode:
authorChris Forbes <chrisforbes@google.com>2018-03-07 11:37:45 -0800
committerChris Forbes <chrisf@ijw.co.nz>2018-03-08 09:12:03 -0800
commit0cb687f3aa6d6afd205857eecbd61d5974d4b57e (patch)
treedce8e0c1269d58b12fe0765e839ff3ace05ea886 /layers/shader_validation.cpp
parent3f746dac981f5c9f3aba116d2c17762c669c1149 (diff)
downloadusermoji-0cb687f3aa6d6afd205857eecbd61d5974d4b57e.tar.xz
layers: Determine whether a shader uses any writable descriptors
Diffstat (limited to 'layers/shader_validation.cpp')
-rw-r--r--layers/shader_validation.cpp47
1 files changed, 45 insertions, 2 deletions
diff --git a/layers/shader_validation.cpp b/layers/shader_validation.cpp
index 621a4759..2c45bb3a 100644
--- a/layers/shader_validation.cpp
+++ b/layers/shader_validation.cpp
@@ -641,10 +641,44 @@ static std::vector<std::pair<uint32_t, interface_var>> collect_interface_by_inpu
return out;
}
+static bool is_writable_descriptor_type(shader_module const *module, uint32_t type_id) {
+ auto type = module->get_def(type_id);
+
+ // Strip off any array or ptrs. Where we remove array levels, adjust the descriptor count for each dimension.
+ while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer) {
+ if (type.opcode() == spv::OpTypeArray) {
+ type = module->get_def(type.word(2));
+ } else {
+ type = module->get_def(type.word(3));
+ }
+ }
+
+ switch (type.opcode()) {
+ case spv::OpTypeImage: {
+ auto dim = type.word(3);
+ auto sampled = type.word(7);
+ return sampled == 2 && dim != spv::DimSubpassData;
+ }
+
+ case spv::OpTypeStruct:
+ for (auto insn : *module) {
+ if (insn.opcode() == spv::OpDecorate && insn.word(1) == type.word(1)) {
+ if (insn.word(2) == spv::DecorationBufferBlock) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
static std::vector<std::pair<descriptor_slot_t, interface_var>> collect_interface_by_descriptor_slot(
- debug_report_data const *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids) {
+ debug_report_data const *report_data, shader_module const *src, std::unordered_set<uint32_t> const &accessible_ids,
+ bool *has_writable_descriptor) {
std::unordered_map<unsigned, unsigned> var_sets;
std::unordered_map<unsigned, unsigned> var_bindings;
+ std::unordered_map<unsigned, unsigned> var_nonwritable;
for (auto insn : *src) {
// All variables in the Uniform or UniformConstant storage classes are required to be decorated with both
@@ -657,6 +691,10 @@ static std::vector<std::pair<descriptor_slot_t, interface_var>> collect_interfac
if (insn.word(2) == spv::DecorationBinding) {
var_bindings[insn.word(1)] = insn.word(3);
}
+
+ if (insn.word(2) == spv::DecorationNonWritable) {
+ var_nonwritable[insn.word(1)] = 1;
+ }
}
}
@@ -675,6 +713,10 @@ static std::vector<std::pair<descriptor_slot_t, interface_var>> collect_interfac
v.id = insn.word(2);
v.type_id = insn.word(1);
out.emplace_back(std::make_pair(set, binding), v);
+
+ if (var_nonwritable.find(id) == var_nonwritable.end() && is_writable_descriptor_type(src, insn.word(1))) {
+ *has_writable_descriptor = true;
+ }
}
}
@@ -1326,7 +1368,8 @@ static bool validate_pipeline_shader_stage(layer_data *dev_data, VkPipelineShade
auto accessible_ids = mark_accessible_ids(module, entrypoint);
// Validate descriptor set layout against what the entrypoint actually uses
- auto descriptor_uses = collect_interface_by_descriptor_slot(report_data, module, accessible_ids);
+ bool has_writable_descriptor = false;
+ auto descriptor_uses = collect_interface_by_descriptor_slot(report_data, module, accessible_ids, &has_writable_descriptor);
skip |= validate_specialization_offsets(report_data, pStage);
skip |= validate_push_constant_usage(report_data, pipeline->pipeline_layout.push_constant_ranges.get(), module, accessible_ids,