Vulkan/Debug: Add VariableContainer::extend()
This allows VariableContainer to 'inherit' from one another.
Variables traversed and searched will try the direct VariableContainer, before falling back to searching the extended VariableContainers.
This allows for variable scopes to nest one another.
Bug: b/148401179
Change-Id: I58b317386d74ec54b9c1cc4fa223ef9cc50b160c
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/40532
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
diff --git a/src/Vulkan/Debug/Server.cpp b/src/Vulkan/Debug/Server.cpp
index d283aa9..c8751c1 100644
--- a/src/Vulkan/Debug/Server.cpp
+++ b/src/Vulkan/Debug/Server.cpp
@@ -250,22 +250,18 @@
}
dap::VariablesResponse response;
- vars->foreach(req.start.value(0), [&](const Variable &v) {
- if(!req.count.has_value() ||
- req.count.value() < int(response.variables.size()))
+ vars->foreach(req.start.value(0), req.count.value(~0), [&](const Variable &v) {
+ dap::Variable out;
+ out.evaluateName = v.name;
+ out.name = v.name;
+ out.type = v.value->type()->string();
+ out.value = v.value->string();
+ if(v.value->type()->kind == Kind::VariableContainer)
{
- dap::Variable out;
- out.evaluateName = v.name;
- out.name = v.name;
- out.type = v.value->type()->string();
- out.value = v.value->string();
- if(v.value->type()->kind == Kind::VariableContainer)
- {
- auto const vc = static_cast<const VariableContainer *>(v.value.get());
- out.variablesReference = vc->id.value();
- }
- response.variables.push_back(out);
+ auto const vc = static_cast<const VariableContainer *>(v.value.get());
+ out.variablesReference = vc->id.value();
}
+ response.variables.push_back(out);
});
return response;
});
diff --git a/src/Vulkan/Debug/Value.cpp b/src/Vulkan/Debug/Value.cpp
index 7aa111d..49420b4 100644
--- a/src/Vulkan/Debug/Value.cpp
+++ b/src/Vulkan/Debug/Value.cpp
@@ -62,7 +62,7 @@
auto subfmt = *fmt.subListFmt;
subfmt.listIndent = fmt.listIndent + fmt.subListFmt->listIndent;
bool first = true;
- vc->foreach(0, [&](const Variable &var) {
+ vc->foreach(0, ~0, [&](const Variable &var) {
if(!first) { out += fmt.listDelimiter; }
first = false;
out += fmt.listIndent;
diff --git a/src/Vulkan/Debug/Variable.hpp b/src/Vulkan/Debug/Variable.hpp
index acb62a6..08e802d 100644
--- a/src/Vulkan/Debug/Variable.hpp
+++ b/src/Vulkan/Debug/Variable.hpp
@@ -46,7 +46,7 @@
// foreach() calls cb with each of the variables in the container.
// F must be a function with the signature void(const Variable&).
template<typename F>
- inline void foreach(size_t startIndex, const F &cb) const;
+ inline void foreach(size_t startIndex, size_t count, const F &cb) const;
// find() looks up the variable with the given name.
// If the variable with the given name is found, cb is called with the
@@ -60,16 +60,30 @@
// put() places the variable with the given name and value into the container.
inline void put(const std::string &name, const std::shared_ptr<Value> &value);
+ // extend() adds base to the list of VariableContainers that will be
+ // searched and traversed for variables.
+ inline void extend(const std::shared_ptr<VariableContainer> &base);
+
// The unique identifier of the variable.
const ID id;
private:
+ struct ForeachIndex
+ {
+ size_t start;
+ size_t count;
+ };
+
+ template<typename F>
+ inline void foreach(ForeachIndex &index, const F &cb) const;
+
inline std::shared_ptr<Type> type() const override;
inline const void *get() const override;
mutable std::mutex mutex;
std::vector<Variable> variables;
std::unordered_map<std::string, int> indices;
+ std::vector<std::shared_ptr<VariableContainer>> extends;
};
VariableContainer::VariableContainer(ID id)
@@ -77,13 +91,28 @@
{}
template<typename F>
-void VariableContainer::foreach(size_t startIndex, const F &cb) const
+void VariableContainer::foreach(size_t startIndex, size_t count, const F &cb) const
+{
+ auto index = ForeachIndex{ startIndex, count };
+ foreach(index, cb);
+}
+
+template<typename F>
+void VariableContainer::foreach(ForeachIndex &index, const F &cb) const
{
std::unique_lock<std::mutex> lock(mutex);
- for(size_t i = startIndex; i < variables.size(); i++)
+ for(size_t i = index.start; i < variables.size() && i < index.count; i++)
{
cb(variables[i]);
}
+
+ index.start -= std::min(index.start, variables.size());
+ index.count -= std::min(index.count, variables.size());
+
+ for(auto &base : extends)
+ {
+ base->foreach(index, cb);
+ }
}
template<typename F>
@@ -98,6 +127,13 @@
return true;
}
}
+ for(auto &base : extends)
+ {
+ if(base->find(name, cb))
+ {
+ return true;
+ }
+ }
return false;
}
@@ -122,6 +158,12 @@
put({ name, value });
}
+void VariableContainer::extend(const std::shared_ptr<VariableContainer> &base)
+{
+ std::unique_lock<std::mutex> lock(mutex);
+ extends.emplace_back(base);
+}
+
std::shared_ptr<Type> VariableContainer::type() const
{
return TypeOf<VariableContainer>::get();