aboutsummaryrefslogtreecommitdiff
path: root/layers
diff options
context:
space:
mode:
authorChris Forbes <chrisf@ijw.co.nz>2015-04-08 10:19:16 +1200
committerChris Forbes <chrisf@ijw.co.nz>2015-04-17 10:13:59 +1200
commite9bc1232e05e7d6cc528be380169eadee5ce5590 (patch)
tree24f5cbbb1fde140e0fcb7ce462dd25541a220387 /layers
parentac467fe5a180b209a8c01be2681afc873e06319e (diff)
downloadusermoji-e9bc1232e05e7d6cc528be380169eadee5ce5590.tar.xz
shader_checker: add validation of interface between vs and fs
Diffstat (limited to 'layers')
-rw-r--r--layers/shader_checker.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/layers/shader_checker.cpp b/layers/shader_checker.cpp
index 6d88b233..ad375dfa 100644
--- a/layers/shader_checker.cpp
+++ b/layers/shader_checker.cpp
@@ -26,6 +26,7 @@
#include <assert.h>
#include <map>
#include <unordered_map>
+#include <map>
#include <vector>
#include "loader_platform.h"
#include "vk_dispatch_table_helper.h"
@@ -250,6 +251,50 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateShader(VkDevice device, const VkShaderCre
}
+static void
+validate_interface_between_stages(shader_source const *producer, char const *producer_name,
+ shader_source const *consumer, char const *consumer_name)
+{
+ std::map<uint32_t, interface_var> outputs;
+ std::map<uint32_t, interface_var> inputs;
+
+ std::map<uint32_t, interface_var> builtin_outputs;
+ std::map<uint32_t, interface_var> builtin_inputs;
+
+ printf("Begin validate_interface_between_stages %s -> %s\n",
+ producer_name, consumer_name);
+
+ collect_interface_by_location(producer, spv::StorageOutput, outputs, builtin_outputs);
+ collect_interface_by_location(consumer, spv::StorageInput, inputs, builtin_inputs);
+
+ auto a_it = outputs.begin();
+ auto b_it = inputs.begin();
+
+ /* maps sorted by key (location); walk them together to find mismatches */
+ while (a_it != outputs.end() || b_it != inputs.end()) {
+ if (b_it == inputs.end() || a_it->first < b_it->first) {
+ printf(" WARN: %s writes to output location %d which is not consumed by %s\n",
+ producer_name, a_it->first, consumer_name);
+ a_it++;
+ }
+ else if (a_it == outputs.end() || a_it->first > b_it->first) {
+ printf(" ERR: %s consumes input location %d which is not written by %s\n",
+ consumer_name, b_it->first, producer_name);
+ b_it++;
+ }
+ else {
+ printf(" OK: match on location %d\n",
+ a_it->first);
+ /* TODO: typecheck */
+ a_it++;
+ b_it++;
+ }
+ }
+
+ printf("End validate_interface_between_stages\n");
+}
+
+
VK_LAYER_EXPORT VkResult VKAPI vkCreateGraphicsPipeline(VkDevice device,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
VkPipeline *pPipeline)
@@ -288,6 +333,11 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateGraphicsPipeline(VkDevice device,
printf("Pipeline: vi=%p vs=%p fs=%p cb=%p\n", vi, vs_source, fs_source, cb);
+ if (vs_source && fs_source) {
+ validate_interface_between_stages(vs_source, "vertex shader",
+ fs_source, "fragment shader");
+ }
+
VkLayerDispatchTable *pTable = tableMap[(VkBaseLayerObject *)device];
VkResult res = pTable->CreateGraphicsPipeline(device, pCreateInfo, pPipeline);
return res;