SpirvShaderDebugger: Implement Array types
and move pointer typeinfo value construction from build time to runtime.
While this may seem counter-intuitive for performance, it's actually a
big win, as shader compilation can take a significant amount of time
with the amount of debug logic generated. This is also a first step
towards lazy/static `vk::dbg::Value` generation for array types.
Bug: b/124388146
Change-Id: I3448ffdabd553db17a22090081ac4809e0555b1d
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/45488
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/Pipeline/SpirvShaderDebugger.cpp b/src/Pipeline/SpirvShaderDebugger.cpp
index 2933a81..a93a1a3 100644
--- a/src/Pipeline/SpirvShaderDebugger.cpp
+++ b/src/Pipeline/SpirvShaderDebugger.cpp
@@ -18,6 +18,9 @@
#define PRINT_EACH_PROCESSED_INSTRUCTION 0
// If enabled, each instruction will be printed before executing.
#define PRINT_EACH_EXECUTED_INSTRUCTION 0
+// If enabled, debugger variables will contain debug information (addresses,
+// byte offset, etc).
+#define DEBUG_ANNOTATE_VARIABLE_KEYS 0
#ifdef ENABLE_VK_DEBUGGER
@@ -85,9 +88,16 @@
{
return s;
}
+template<typename T>
+std::string tostring(T *s)
+{
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%p", s);
+ return buf;
+}
std::string tostring(sw::SpirvShader::Object::ID id)
{
- return "%" + std::to_string(id.value());
+ return "%" + tostring(id.value());
}
////////////////////////////////////////////////////////////////////////////////
@@ -243,6 +253,13 @@
kind == Kind::CompositeType ||
kind == Kind::TemplateType;
}
+
+ // sizeInBytes() returns the number of bytes of the given debug type.
+ virtual uint32_t sizeInBytes() const = 0;
+
+ // value() returns a shared pointer to a vk::dbg::Value that views the data
+ // at ptr of this type.
+ virtual std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const = 0;
};
struct CompilationUnit : ObjectImpl<CompilationUnit, Scope, Object::Kind::CompilationUnit>
@@ -264,18 +281,170 @@
std::string name;
uint32_t size = 0; // in bits.
OpenCLDebugInfo100DebugBaseTypeAttributeEncoding encoding = OpenCLDebugInfo100Unspecified;
+
+ uint32_t sizeInBytes() const override { return size / 8; }
+
+ std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
+ {
+ switch(encoding)
+ {
+ case OpenCLDebugInfo100Address:
+ // return vk::dbg::make_reference(*static_cast<void **>(ptr));
+ UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100 OpenCLDebugInfo100Address BasicType");
+ return nullptr;
+ case OpenCLDebugInfo100Boolean:
+ return vk::dbg::make_reference(*static_cast<bool *>(ptr));
+ case OpenCLDebugInfo100Float:
+ return vk::dbg::make_reference(*static_cast<float *>(ptr));
+ case OpenCLDebugInfo100Signed:
+ return vk::dbg::make_reference(*static_cast<int32_t *>(ptr));
+ case OpenCLDebugInfo100SignedChar:
+ return vk::dbg::make_reference(*static_cast<int8_t *>(ptr));
+ case OpenCLDebugInfo100Unsigned:
+ return vk::dbg::make_reference(*static_cast<uint32_t *>(ptr));
+ case OpenCLDebugInfo100UnsignedChar:
+ return vk::dbg::make_reference(*static_cast<uint8_t *>(ptr));
+ default:
+ UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100 encoding %d", int(encoding));
+ return nullptr;
+ }
+ }
};
struct ArrayType : ObjectImpl<ArrayType, Type, Object::Kind::ArrayType>
{
Type *base = nullptr;
std::vector<uint32_t> dimensions;
+
+ // build() loops over each element of the multi-dimensional array, calling
+ // enter() for building each new dimension group, and element() for each
+ // inner-most dimension element.
+ //
+ // enter must be a function of the signature:
+ // std::shared_ptr<vk::dbg::VariableContainer>
+ // (std::shared_ptr<vk::dbg::VariableContainer>& parent, uint32_t idx)
+ // where:
+ // parent is the outer dimension group
+ // idx is the index of the next deepest dimension.
+ //
+ // element must be a function of the signature:
+ // void(std::shared_ptr<vk::dbg::VariableContainer> &parent,
+ // uint32_t idx, uint32_t offset)
+ // where:
+ // parent is the penultimate deepest dimension group
+ // idx is the index of the element in parent group
+ // offset is the 'flattened array' index for the element.
+ template<typename GROUP, typename ENTER_FUNC, typename ELEMENT_FUNC>
+ void build(const GROUP &group, ENTER_FUNC &&enter, ELEMENT_FUNC &&element) const
+ {
+ if(dimensions.size() == 0) { return; }
+
+ struct Dimension
+ {
+ uint32_t idx = 0;
+ GROUP group;
+ bool built = false;
+ };
+
+ std::vector<Dimension> dims;
+ dims.resize(dimensions.size());
+
+ uint32_t offset = 0;
+
+ int dimIdx = 0;
+ const int n = static_cast<int>(dimensions.size()) - 1;
+ while(dimIdx >= 0)
+ {
+ // (Re)build groups to inner dimensions.
+ for(; dimIdx <= n; dimIdx++)
+ {
+ if(!dims[dimIdx].built)
+ {
+ dims[dimIdx].group = (dimIdx == 0)
+ ? group
+ : enter(dims[dimIdx - 1].group, dims[dimIdx - 1].idx);
+ dims[dimIdx].built = true;
+ }
+ }
+
+ // Emit each of the inner-most dimension elements.
+ for(dims[n].idx = 0; dims[n].idx < dimensions[n]; dims[n].idx++)
+ {
+ ASSERT(dims[n].built);
+ element(dims[n].group, dims[n].idx, offset++);
+ }
+
+ dimIdx = n;
+ while(dims[dimIdx].idx == dimensions[dimIdx])
+ {
+ dims[dimIdx] = {}; // Clear the the current dimension
+ dimIdx--; // Step up a dimension
+ if(dimIdx < 0) { break; }
+ dims[dimIdx].idx++; // Increment the next dimension index
+ }
+ }
+ }
+
+ uint32_t sizeInBytes() const override
+ {
+ auto numBytes = base->sizeInBytes();
+ for(auto dim : dimensions)
+ {
+ numBytes *= dim;
+ }
+ return numBytes;
+ }
+
+ std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
+ {
+ auto vc = lock.createVariableContainer();
+ build(
+ vc,
+ [&](std::shared_ptr<vk::dbg::VariableContainer> &parent, uint32_t idx) {
+ auto child = lock.createVariableContainer();
+ parent->put(tostring(idx), child);
+ return child;
+ },
+ [&](std::shared_ptr<vk::dbg::VariableContainer> &parent, uint32_t idx, uint32_t offset) {
+ offset = offset * base->sizeInBytes() * (interleaved ? sw::SIMD::Width : 1);
+ auto addr = static_cast<uint8_t *>(ptr) + offset;
+ auto child = base->value(lock, addr, interleaved);
+ auto key = tostring(idx);
+# if DEBUG_ANNOTATE_VARIABLE_KEYS
+ key += " (" + tostring(addr) + " +" + tostring(offset) + ", idx: " + tostring(idx) + ")" + (interleaved ? "I" : "F");
+# endif
+ parent->put(key, child);
+ });
+ return vc;
+ }
};
struct VectorType : ObjectImpl<VectorType, Type, Object::Kind::VectorType>
{
Type *base = nullptr;
uint32_t components = 0;
+
+ uint32_t sizeInBytes() const override
+ {
+ return base->sizeInBytes() * components;
+ }
+
+ std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
+ {
+ const auto elSize = base->sizeInBytes();
+ auto vc = lock.createVariableContainer();
+ for(uint32_t i = 0; i < components; i++)
+ {
+ auto offset = elSize * i * (interleaved ? sw::SIMD::Width : 1);
+ auto elPtr = static_cast<uint8_t *>(ptr) + offset;
+ auto elKey = tostring(i);
+# if DEBUG_ANNOTATE_VARIABLE_KEYS
+ elKey += " (" + tostring(elPtr) + " +" + tostring(offset) + ")" + (interleaved ? "I" : "F");
+# endif
+ vc->put(elKey, base->value(lock, elPtr, interleaved));
+ }
+ return vc;
+ }
};
struct FunctionType : ObjectImpl<FunctionType, Type, Object::Kind::FunctionType>
@@ -283,6 +452,22 @@
uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
Type *returnTy = nullptr;
std::vector<Type *> paramTys;
+
+ uint32_t sizeInBytes() const override { return 0; }
+ std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override { return nullptr; }
+};
+
+struct Member : ObjectImpl<Member, Object, Object::Kind::Member>
+{
+ std::string name;
+ Type *type = nullptr;
+ Source *source = nullptr;
+ uint32_t line = 0;
+ uint32_t column = 0;
+ struct CompositeType *parent = nullptr;
+ uint32_t offset = 0; // in bits
+ uint32_t size = 0; // in bits
+ uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
};
struct CompositeType : ObjectImpl<CompositeType, Type, Object::Kind::CompositeType>
@@ -297,6 +482,23 @@
uint32_t size = 0; // in bits.
uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
std::vector<Member *> members;
+
+ uint32_t sizeInBytes() const override { return size / 8; }
+ std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
+ {
+ auto vc = lock.createVariableContainer();
+ for(auto &member : members)
+ {
+ auto offset = (member->offset / 8) * (interleaved ? sw::SIMD::Width : 1);
+ auto elPtr = static_cast<uint8_t *>(ptr) + offset;
+ auto elKey = member->name;
+# if DEBUG_ANNOTATE_VARIABLE_KEYS
+ // elKey += " (" + tostring(elPtr) + " +" + tostring(offset) + ")" + (interleaved ? "I" : "F");
+# endif
+ vc->put(elKey, member->type->value(lock, elPtr, interleaved));
+ }
+ return vc;
+ }
};
struct TemplateParameter : ObjectImpl<TemplateParameter, Object, Object::Kind::TemplateParameter>
@@ -313,19 +515,12 @@
{
Type *target = nullptr; // Class, struct or function.
std::vector<TemplateParameter *> parameters;
-};
-struct Member : ObjectImpl<Member, Object, Object::Kind::Member>
-{
- std::string name;
- Type *type = nullptr;
- Source *source = nullptr;
- uint32_t line = 0;
- uint32_t column = 0;
- CompositeType *parent = nullptr;
- uint32_t offset = 0; // in bits
- uint32_t size = 0; // in bits
- uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
+ uint32_t sizeInBytes() const override { return target->sizeInBytes(); }
+ std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
+ {
+ return target->value(lock, ptr, interleaved);
+ }
};
struct Function : ObjectImpl<Function, Scope, Object::Kind::Function>
@@ -576,6 +771,9 @@
template<typename K, typename V>
void putVal(vk::dbg::VariableContainer *vc, K key, V value);
+ template<typename K>
+ void putPtr(vk::dbg::VariableContainer *vc, K key, void *ptr, bool interleaved, const debug::Type *type);
+
template<typename K, typename V>
void putRef(vk::dbg::VariableContainer *vc, K key, V *ptr);
@@ -685,6 +883,13 @@
vc->put(tostring(key), vk::dbg::make_constant(value));
}
+template<typename K>
+void SpirvShader::Impl::Debugger::State::putPtr(vk::dbg::VariableContainer *vc, K key, void *ptr, bool interleaved, const debug::Type *type)
+{
+ auto lock = debugger->ctx->lock();
+ vc->put(tostring(key), type->value(lock, ptr, interleaved));
+}
+
template<typename K, typename V>
void SpirvShader::Impl::Debugger::State::putRef(vk::dbg::VariableContainer *vc, K key, V *ptr)
{
@@ -798,7 +1003,10 @@
static Group localsLane(Ptr state, const debug::Scope *scope, int lane);
static Group globals(Ptr state, int lane);
- Group(Ptr state, Ptr group);
+ inline Group();
+ inline Group(Ptr state, Ptr group);
+
+ inline bool isValid() const;
template<typename K, typename RK>
Group group(RK key) const;
@@ -806,6 +1014,9 @@
template<typename K, typename V, typename RK, typename RV>
void put(RK key, RV value) const;
+ template<typename K, typename RK>
+ void putPtr(RK key, RValue<Pointer<Byte>> ptr, bool interleaved, const debug::Type *type) const;
+
template<typename K, typename V, typename RK>
void putRef(RK key, RValue<Pointer<Byte>> ref) const;
@@ -824,6 +1035,7 @@
private:
Ptr state;
Ptr ptr;
+ bool valid = false;
};
SpirvShader::Impl::Debugger::Group
@@ -844,26 +1056,44 @@
return localsLane(state, &debug::Scope::Global, lane);
}
+SpirvShader::Impl::Debugger::Group::Group() {}
+
SpirvShader::Impl::Debugger::Group::Group(Ptr state, Ptr group)
: state(state)
, ptr(group)
+ , valid(true)
{}
+bool SpirvShader::Impl::Debugger::Group::isValid() const
+{
+ return valid;
+}
+
template<typename K, typename RK>
SpirvShader::Impl::Debugger::Group SpirvShader::Impl::Debugger::Group::group(RK key) const
{
+ ASSERT(isValid());
return Group(state, rr::Call(&State::group<K>, state, ptr, key));
}
template<typename K, typename V, typename RK, typename RV>
void SpirvShader::Impl::Debugger::Group::put(RK key, RV value) const
{
+ ASSERT(isValid());
rr::Call(&State::putVal<K, V>, state, ptr, key, value);
}
+template<typename K, typename RK>
+void SpirvShader::Impl::Debugger::Group::putPtr(RK key, RValue<Pointer<Byte>> addr, bool interleaved, const debug::Type *type) const
+{
+ ASSERT(isValid());
+ rr::Call(&State::putPtr<K>, state, ptr, key, addr, interleaved, type);
+}
+
template<typename K, typename V, typename RK>
void SpirvShader::Impl::Debugger::Group::putRef(RK key, RValue<Pointer<Byte>> ref) const
{
+ ASSERT(isValid());
rr::Call(&State::putRef<K, V>, state, ptr, key, ref);
}
@@ -948,9 +1178,10 @@
case OpenCLDebugInfo100DebugTypeArray:
defineOrEmit(insn, pass, [&](debug::ArrayType *type) {
type->base = get(debug::Type::ID(insn.word(5)));
- auto &components = shader->getObject(insn.word(6));
- ASSERT(components.kind == SpirvShader::Object::Kind::Constant);
- type->dimensions = components.constantValue;
+ for(uint32_t i = 6; i < insn.wordCount(); i++)
+ {
+ type->dimensions.emplace_back(shader->GetConstScalarInt(insn.word(i)));
+ }
});
break;
case OpenCLDebugInfo100DebugTypeVector:
@@ -1260,7 +1491,7 @@
void SpirvShader::Impl::Debugger::exposeVariable(
const SpirvShader *shader,
const Group &group,
- int l,
+ int lane,
const Key &key,
const debug::Type *type,
Object::ID id,
@@ -1271,55 +1502,31 @@
if(type != nullptr)
{
- if(auto ty = debug::cast<debug::BasicType>(type))
+ switch(obj.kind)
{
- SIMD::Int val;
- switch(obj.kind)
+ case Object::Kind::InterfaceVariable:
+ case Object::Kind::Pointer:
+ case Object::Kind::DescriptorSet:
{
- case Object::Kind::InterfaceVariable:
- case Object::Kind::Pointer:
+ ASSERT(wordOffset == 0); // TODO.
+ auto ptr = shader->GetPointerToData(id, 0, state); // + sizeof(uint32_t) * wordOffset;
+ auto &ptrTy = shader->getType(obj);
+ auto interleaved = IsStorageInterleavedByLane(ptrTy.storageClass);
+ if(interleaved)
{
- auto ptr = shader->GetPointerToData(id, 0, state) + sizeof(uint32_t) * wordOffset;
- auto &ptrTy = shader->getType(obj);
- if(IsStorageInterleavedByLane(ptrTy.storageClass))
- {
- ptr = InterleaveByLane(ptr);
- }
- auto addr = &ptr.base[Extract(ptr.offsets(), l)];
- switch(ty->encoding)
- {
- case OpenCLDebugInfo100Address:
- // TODO: This function takes a SIMD vector, and pointers cannot
- // be held in them.
- break;
- case OpenCLDebugInfo100Boolean:
- group.putRef<Key, bool>(key, addr);
- break;
- case OpenCLDebugInfo100Float:
- group.putRef<Key, float>(key, addr);
- break;
- case OpenCLDebugInfo100Signed:
- group.putRef<Key, int>(key, addr);
- break;
- case OpenCLDebugInfo100SignedChar:
- group.putRef<Key, int8_t>(key, addr);
- break;
- case OpenCLDebugInfo100Unsigned:
- group.putRef<Key, unsigned int>(key, addr);
- break;
- case OpenCLDebugInfo100UnsignedChar:
- group.putRef<Key, uint8_t>(key, addr);
- break;
- default:
- break;
- }
+ ptr = InterleaveByLane(ptr);
}
- break;
- case Object::Kind::Constant:
- case Object::Kind::Intermediate:
+ auto addr = &ptr.base[Extract(ptr.offsets(), lane)];
+ group.putPtr<Key>(key, addr, interleaved, type);
+ }
+ break;
+
+ case Object::Kind::Constant:
+ case Object::Kind::Intermediate:
+ {
+ if(auto ty = debug::cast<debug::BasicType>(type))
{
auto val = Operand(shader, state, id).Int(wordOffset);
-
switch(ty->encoding)
{
case OpenCLDebugInfo100Address:
@@ -1327,87 +1534,92 @@
// be held in them.
break;
case OpenCLDebugInfo100Boolean:
- group.put<Key, bool>(key, Extract(val, l) != 0);
+ group.put<Key, bool>(key, Extract(val, lane) != 0);
break;
case OpenCLDebugInfo100Float:
- group.put<Key, float>(key, Extract(As<SIMD::Float>(val), l));
+ group.put<Key, float>(key, Extract(As<SIMD::Float>(val), lane));
break;
case OpenCLDebugInfo100Signed:
- group.put<Key, int>(key, Extract(val, l));
+ group.put<Key, int>(key, Extract(val, lane));
break;
case OpenCLDebugInfo100SignedChar:
- group.put<Key, int8_t>(key, SByte(Extract(val, l)));
+ group.put<Key, int8_t>(key, SByte(Extract(val, lane)));
break;
case OpenCLDebugInfo100Unsigned:
- group.put<Key, unsigned int>(key, Extract(val, l));
+ group.put<Key, unsigned int>(key, Extract(val, lane));
break;
case OpenCLDebugInfo100UnsignedChar:
- group.put<Key, uint8_t>(key, Byte(Extract(val, l)));
+ group.put<Key, uint8_t>(key, Byte(Extract(val, lane)));
break;
default:
break;
}
}
- break;
- default:
- break;
- }
- return;
- }
- else if(auto ty = debug::cast<debug::VectorType>(type))
- {
- auto elWords = 1; // Currently vector elements must only be basic types, 32-bit wide
- auto elTy = ty->base;
- auto vecGroup = group.group<Key>(key);
- switch(ty->components)
- {
- case 1:
- exposeVariable(shader, vecGroup, l, "x", elTy, id, state, wordOffset + 0 * elWords);
- break;
- case 2:
- exposeVariable(shader, vecGroup, l, "x", elTy, id, state, wordOffset + 0 * elWords);
- exposeVariable(shader, vecGroup, l, "y", elTy, id, state, wordOffset + 1 * elWords);
- break;
- case 3:
- exposeVariable(shader, vecGroup, l, "x", elTy, id, state, wordOffset + 0 * elWords);
- exposeVariable(shader, vecGroup, l, "y", elTy, id, state, wordOffset + 1 * elWords);
- exposeVariable(shader, vecGroup, l, "z", elTy, id, state, wordOffset + 2 * elWords);
- break;
- case 4:
- exposeVariable(shader, vecGroup, l, "x", elTy, id, state, wordOffset + 0 * elWords);
- exposeVariable(shader, vecGroup, l, "y", elTy, id, state, wordOffset + 1 * elWords);
- exposeVariable(shader, vecGroup, l, "z", elTy, id, state, wordOffset + 2 * elWords);
- exposeVariable(shader, vecGroup, l, "w", elTy, id, state, wordOffset + 3 * elWords);
- break;
- default:
- for(uint32_t i = 0; i < ty->components; i++)
+ else if(auto ty = debug::cast<debug::VectorType>(type))
+ {
+ auto elWords = 1; // Currently vector elements must only be basic types, 32-bit wide
+ auto elTy = ty->base;
+ auto vecGroup = group.group<Key>(key);
+ switch(ty->components)
{
- exposeVariable(shader, vecGroup, l, std::to_string(i).c_str(), elTy, id, state, wordOffset + i * elWords);
+ case 1:
+ exposeVariable(shader, vecGroup, lane, "x", elTy, id, state, wordOffset + 0 * elWords);
+ break;
+ case 2:
+ exposeVariable(shader, vecGroup, lane, "x", elTy, id, state, wordOffset + 0 * elWords);
+ exposeVariable(shader, vecGroup, lane, "y", elTy, id, state, wordOffset + 1 * elWords);
+ break;
+ case 3:
+ exposeVariable(shader, vecGroup, lane, "x", elTy, id, state, wordOffset + 0 * elWords);
+ exposeVariable(shader, vecGroup, lane, "y", elTy, id, state, wordOffset + 1 * elWords);
+ exposeVariable(shader, vecGroup, lane, "z", elTy, id, state, wordOffset + 2 * elWords);
+ break;
+ case 4:
+ exposeVariable(shader, vecGroup, lane, "x", elTy, id, state, wordOffset + 0 * elWords);
+ exposeVariable(shader, vecGroup, lane, "y", elTy, id, state, wordOffset + 1 * elWords);
+ exposeVariable(shader, vecGroup, lane, "z", elTy, id, state, wordOffset + 2 * elWords);
+ exposeVariable(shader, vecGroup, lane, "w", elTy, id, state, wordOffset + 3 * elWords);
+ break;
+ default:
+ for(uint32_t i = 0; i < ty->components; i++)
+ {
+ exposeVariable(shader, vecGroup, lane, tostring(i).c_str(), elTy, id, state, wordOffset + i * elWords);
+ }
+ break;
}
- break;
- }
- return;
- }
- else if(auto ty = debug::cast<debug::CompositeType>(type))
- {
- auto objectGroup = group.group<Key>(key);
+ }
+ else if(auto ty = debug::cast<debug::CompositeType>(type))
+ {
+ auto objectGroup = group.group<Key>(key);
- for(auto member : ty->members)
- {
- exposeVariable(shader, objectGroup, l, member->name.c_str(), member->type, id, state, member->offset / 32);
+ for(auto member : ty->members)
+ {
+ exposeVariable(shader, objectGroup, lane, member->name.c_str(), member->type, id, state, member->offset / 32);
+ }
+ }
+ else if(auto ty = debug::cast<debug::ArrayType>(type))
+ {
+ ty->build(
+ group.group<Key>(key),
+ [&](Debugger::Group &parent, uint32_t idx) {
+ return parent.template group<int>(idx);
+ },
+ [&](Debugger::Group &parent, uint32_t idx, uint32_t offset) {
+ exposeVariable(shader, parent, lane, idx, ty->base, id, state, offset);
+ });
+ }
+ else
+ {
+ UNIMPLEMENTED("b/145351270: Debug type: %s", cstr(type->kind));
+ }
+ return;
}
+ break;
- return;
+ case Object::Kind::Unknown:
+ UNIMPLEMENTED("b/145351270: Object kind: %d", (int)obj.kind);
}
- else if(auto ty = debug::cast<debug::ArrayType>(type))
- {
- // TODO(bclayton): Expose array types.
- return;
- }
- else
- {
- UNIMPLEMENTED("b/145351270: Debug type: %s", cstr(type->kind));
- }
+ return;
}
// No debug type information. Derive from SPIR-V.
@@ -1416,13 +1628,13 @@
case spv::OpTypeInt:
{
Operand val(shader, state, id);
- group.put<Key, int>(key, Extract(val.Int(0), l));
+ group.put<Key, int>(key, Extract(val.Int(0), lane));
}
break;
case spv::OpTypeFloat:
{
Operand val(shader, state, id);
- group.put<Key, float>(key, Extract(val.Float(0), l));
+ group.put<Key, float>(key, Extract(val.Float(0), lane));
}
break;
case spv::OpTypeVector:
@@ -1432,23 +1644,23 @@
switch(count)
{
case 1:
- group.put<Key, float>(key, Extract(val.Float(0), l));
+ group.put<Key, float>(key, Extract(val.Float(0), lane));
break;
case 2:
- group.put<Key, float>(key, Extract(val.Float(0), l), Extract(val.Float(1), l));
+ group.put<Key, float>(key, Extract(val.Float(0), lane), Extract(val.Float(1), lane));
break;
case 3:
- group.put<Key, float>(key, Extract(val.Float(0), l), Extract(val.Float(1), l), Extract(val.Float(2), l));
+ group.put<Key, float>(key, Extract(val.Float(0), lane), Extract(val.Float(1), lane), Extract(val.Float(2), lane));
break;
case 4:
- group.put<Key, float>(key, Extract(val.Float(0), l), Extract(val.Float(1), l), Extract(val.Float(2), l), Extract(val.Float(3), l));
+ group.put<Key, float>(key, Extract(val.Float(0), lane), Extract(val.Float(1), lane), Extract(val.Float(2), lane), Extract(val.Float(3), lane));
break;
default:
{
auto vec = group.group<Key>(key);
for(uint32_t i = 0; i < count; i++)
{
- vec.template put<int, float>(i, Extract(val.Float(i), l));
+ vec.template put<int, float>(i, Extract(val.Float(i), lane));
}
}
break;
@@ -1465,7 +1677,7 @@
auto p = ptr + el.offset;
if(interleavedByLane) { p = InterleaveByLane(p); } // TODO: Interleave once, then add offset?
auto simd = p.Load<SIMD::Float>(sw::OutOfBoundsBehavior::Nullify, state->activeLaneMask());
- ptrGroup.template put<int, float>(el.index, Extract(simd, l));
+ ptrGroup.template put<int, float>(el.index, Extract(simd, lane));
});
}
break;
@@ -1521,7 +1733,7 @@
default: name = "SPIR-V Shader"; break;
}
static std::atomic<int> id = { 0 };
- name += std::to_string(id++) + ".spvasm";
+ name += tostring(id++) + ".spvasm";
dbg->spirvFile = dbg->ctx->lock().createVirtualFile(name.c_str(), source.c_str());
}