blob: 795fd783542b9ecfad342c7ac2d3df9743403067 [file] [log] [blame]
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "SpirvShader.hpp"
16
Ben Claytonb3805902020-01-13 17:00:15 +000017// If enabled, each instruction will be printed before processing.
18#define PRINT_EACH_PROCESSED_INSTRUCTION 0
Ben Claytonb8bae182020-03-12 14:19:27 +000019// If enabled, each instruction will be printed before executing.
20#define PRINT_EACH_EXECUTED_INSTRUCTION 0
Ben Clayton907433b2020-06-01 13:52:07 +010021// If enabled, debugger variables will contain debug information (addresses,
22// byte offset, etc).
23#define DEBUG_ANNOTATE_VARIABLE_KEYS 0
Ben Claytonb3805902020-01-13 17:00:15 +000024
Ben Claytonb0ca2a82020-01-08 13:00:57 +000025#ifdef ENABLE_VK_DEBUGGER
26
27# include "Vulkan/Debug/Context.hpp"
28# include "Vulkan/Debug/File.hpp"
29# include "Vulkan/Debug/Thread.hpp"
30# include "Vulkan/Debug/Variable.hpp"
31
Nicolas Capens11dd7182020-05-25 15:22:09 -040032# include "spirv/unified1/OpenCLDebugInfo100.h"
Ben Claytonb0ca2a82020-01-08 13:00:57 +000033# include "spirv-tools/libspirv.h"
34
35# include <algorithm>
36
Ben Clayton2cb1db02020-01-15 18:38:25 +000037namespace {
38
39// ArgTy<F>::type resolves to the single argument type of the function F.
40template<typename F>
41struct ArgTy
42{
43 using type = typename ArgTy<decltype(&F::operator())>::type;
44};
45
46template<typename R, typename C, typename Arg>
47struct ArgTy<R (C::*)(Arg) const>
48{
49 using type = typename std::decay<Arg>::type;
50};
51
52template<typename T>
53using ArgTyT = typename ArgTy<T>::type;
54
55} // anonymous namespace
56
Ben Claytonb0ca2a82020-01-08 13:00:57 +000057namespace spvtools {
58
59// Function implemented in third_party/SPIRV-Tools/source/disassemble.cpp
60// but with no public header.
61// This is a C++ function, so the name is mangled, and signature changes will
62// result in a linker error instead of runtime signature mismatches.
63extern std::string spvInstructionBinaryToText(const spv_target_env env,
64 const uint32_t *inst_binary,
65 const size_t inst_word_count,
66 const uint32_t *binary,
67 const size_t word_count,
68 const uint32_t options);
69
70} // namespace spvtools
71
72namespace {
73
74const char *laneNames[] = { "Lane 0", "Lane 1", "Lane 2", "Lane 3" };
75static_assert(sizeof(laneNames) / sizeof(laneNames[0]) == sw::SIMD::Width,
76 "laneNames must have SIMD::Width entries");
77
78template<typename T>
79std::string tostring(const T &s)
80{
81 return std::to_string(s);
82}
Ben Clayton2cb1db02020-01-15 18:38:25 +000083std::string tostring(char *s)
84{
85 return s;
86}
Ben Claytonb0ca2a82020-01-08 13:00:57 +000087std::string tostring(const char *s)
88{
89 return s;
90}
Ben Clayton907433b2020-06-01 13:52:07 +010091template<typename T>
92std::string tostring(T *s)
93{
94 char buf[32];
95 snprintf(buf, sizeof(buf), "%p", s);
96 return buf;
97}
Ben Claytonb0ca2a82020-01-08 13:00:57 +000098std::string tostring(sw::SpirvShader::Object::ID id)
99{
Ben Clayton907433b2020-06-01 13:52:07 +0100100 return "%" + tostring(id.value());
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000101}
102
Ben Clayton2cb1db02020-01-15 18:38:25 +0000103////////////////////////////////////////////////////////////////////////////////
104// OpenCL.Debug.100 data structures
105////////////////////////////////////////////////////////////////////////////////
106namespace debug {
107
108struct Member;
109
110struct Object
111{
112 enum class Kind
113 {
114 Object,
115 Declare,
116 Expression,
117 Function,
118 InlinedAt,
Ben Clayton00e4a7c2020-04-23 16:50:26 +0100119 GlobalVariable,
Ben Clayton2cb1db02020-01-15 18:38:25 +0000120 LocalVariable,
121 Member,
122 Operation,
123 Source,
124 SourceScope,
125 Value,
Ben Clayton0aec9b62020-05-27 09:52:55 +0100126 TemplateParameter,
Ben Clayton2cb1db02020-01-15 18:38:25 +0000127
128 // Scopes
129 CompilationUnit,
130 LexicalBlock,
131
132 // Types
133 BasicType,
Ben Clayton00e4a7c2020-04-23 16:50:26 +0100134 ArrayType,
Ben Clayton2cb1db02020-01-15 18:38:25 +0000135 VectorType,
136 FunctionType,
137 CompositeType,
Ben Clayton0aec9b62020-05-27 09:52:55 +0100138 TemplateType,
Ben Clayton2cb1db02020-01-15 18:38:25 +0000139 };
140
141 using ID = sw::SpirvID<Object>;
142 static constexpr auto KIND = Kind::Object;
143 inline Object(Kind kind)
144 : kind(kind)
Ben Clayton1e512622020-05-27 10:05:45 +0100145 {
146 (void)KIND; // Used in debug builds. Avoid unused variable warnings in NDEBUG builds.
147 }
Ben Clayton2cb1db02020-01-15 18:38:25 +0000148 const Kind kind;
149
150 // kindof() returns true iff kind is of this type, or any type deriving from
151 // this type.
152 static constexpr bool kindof(Object::Kind kind) { return true; }
Ben Clayton3011de52020-06-09 12:13:42 +0100153
154 virtual ~Object() = default;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000155};
156
Ben Clayton2fecfc52020-03-12 12:46:00 +0000157// cstr() returns the c-string name of the given Object::Kind.
158constexpr const char *cstr(Object::Kind k)
159{
160 switch(k)
161 {
162 case Object::Kind::Object: return "Object";
163 case Object::Kind::Declare: return "Declare";
164 case Object::Kind::Expression: return "Expression";
165 case Object::Kind::Function: return "Function";
166 case Object::Kind::InlinedAt: return "InlinedAt";
Ben Clayton00e4a7c2020-04-23 16:50:26 +0100167 case Object::Kind::GlobalVariable: return "GlobalVariable";
Ben Clayton2fecfc52020-03-12 12:46:00 +0000168 case Object::Kind::LocalVariable: return "LocalVariable";
169 case Object::Kind::Member: return "Member";
170 case Object::Kind::Operation: return "Operation";
171 case Object::Kind::Source: return "Source";
172 case Object::Kind::SourceScope: return "SourceScope";
173 case Object::Kind::Value: return "Value";
Ben Clayton0aec9b62020-05-27 09:52:55 +0100174 case Object::Kind::TemplateParameter: return "TemplateParameter";
Ben Clayton2fecfc52020-03-12 12:46:00 +0000175 case Object::Kind::CompilationUnit: return "CompilationUnit";
176 case Object::Kind::LexicalBlock: return "LexicalBlock";
177 case Object::Kind::BasicType: return "BasicType";
Ben Clayton00e4a7c2020-04-23 16:50:26 +0100178 case Object::Kind::ArrayType: return "ArrayType";
Ben Clayton2fecfc52020-03-12 12:46:00 +0000179 case Object::Kind::VectorType: return "VectorType";
180 case Object::Kind::FunctionType: return "FunctionType";
181 case Object::Kind::CompositeType: return "CompositeType";
Ben Clayton0aec9b62020-05-27 09:52:55 +0100182 case Object::Kind::TemplateType: return "TemplateType";
Ben Clayton2fecfc52020-03-12 12:46:00 +0000183 }
184 return "<unknown>";
185}
186
Ben Clayton2cb1db02020-01-15 18:38:25 +0000187template<typename TYPE_, typename BASE, Object::Kind KIND_>
188struct ObjectImpl : public BASE
189{
190 using ID = sw::SpirvID<TYPE_>;
191 static constexpr auto KIND = KIND_;
192
193 ObjectImpl()
194 : BASE(KIND)
195 {}
196 static_assert(BASE::kindof(KIND), "BASE::kindof() returned false");
197
198 // kindof() returns true iff kind is of this type, or any type deriving from
199 // this type.
200 static constexpr bool kindof(Object::Kind kind) { return kind == KIND; }
201};
202
203template<typename TO, typename FROM>
204TO *cast(FROM *obj)
205{
Ben Claytonda384012020-03-12 12:45:02 +0000206 if(obj == nullptr) { return nullptr; } // None
Ben Clayton2cb1db02020-01-15 18:38:25 +0000207 return (TO::kindof(obj->kind)) ? static_cast<TO *>(obj) : nullptr;
208}
209
210template<typename TO, typename FROM>
211const TO *cast(const FROM *obj)
212{
Ben Claytonda384012020-03-12 12:45:02 +0000213 if(obj == nullptr) { return nullptr; } // None
Ben Clayton2cb1db02020-01-15 18:38:25 +0000214 return (TO::kindof(obj->kind)) ? static_cast<const TO *>(obj) : nullptr;
215}
216
217struct Scope : public Object
218{
Ben Claytonafb18672020-05-27 10:35:51 +0100219 // Global represents the global scope.
220 static const Scope Global;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000221
222 using ID = sw::SpirvID<Scope>;
223 inline Scope(Kind kind)
224 : Object(kind)
225 {}
226
227 // kindof() returns true iff kind is of this type, or any type deriving from
228 // this type.
229 static constexpr bool kindof(Kind kind)
230 {
231 return kind == Kind::CompilationUnit ||
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000232 kind == Kind::Function ||
Ben Clayton2cb1db02020-01-15 18:38:25 +0000233 kind == Kind::LexicalBlock;
234 }
235
236 struct Source *source = nullptr;
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000237 Scope *parent = nullptr;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000238};
239
240struct Type : public Object
241{
242 using ID = sw::SpirvID<Type>;
243 inline Type(Kind kind)
244 : Object(kind)
245 {}
246
247 // kindof() returns true iff kind is of this type, or any type deriving from
248 // this type.
249 static constexpr bool kindof(Kind kind)
250 {
251 return kind == Kind::BasicType ||
Ben Clayton00e4a7c2020-04-23 16:50:26 +0100252 kind == Kind::ArrayType ||
Ben Clayton2cb1db02020-01-15 18:38:25 +0000253 kind == Kind::VectorType ||
254 kind == Kind::FunctionType ||
Ben Clayton0aec9b62020-05-27 09:52:55 +0100255 kind == Kind::CompositeType ||
256 kind == Kind::TemplateType;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000257 }
Ben Clayton907433b2020-06-01 13:52:07 +0100258
259 // sizeInBytes() returns the number of bytes of the given debug type.
260 virtual uint32_t sizeInBytes() const = 0;
261
262 // value() returns a shared pointer to a vk::dbg::Value that views the data
263 // at ptr of this type.
264 virtual std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const = 0;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000265};
266
267struct CompilationUnit : ObjectImpl<CompilationUnit, Scope, Object::Kind::CompilationUnit>
268{
269};
270
271struct Source : ObjectImpl<Source, Object, Object::Kind::Source>
272{
273 spv::SourceLanguage language;
274 uint32_t version = 0;
275 std::string file;
276 std::string source;
277
278 std::shared_ptr<vk::dbg::File> dbgFile;
279};
280
281struct BasicType : ObjectImpl<BasicType, Type, Object::Kind::BasicType>
282{
283 std::string name;
284 uint32_t size = 0; // in bits.
285 OpenCLDebugInfo100DebugBaseTypeAttributeEncoding encoding = OpenCLDebugInfo100Unspecified;
Ben Clayton907433b2020-06-01 13:52:07 +0100286
287 uint32_t sizeInBytes() const override { return size / 8; }
288
289 std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
290 {
291 switch(encoding)
292 {
293 case OpenCLDebugInfo100Address:
294 // return vk::dbg::make_reference(*static_cast<void **>(ptr));
295 UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100 OpenCLDebugInfo100Address BasicType");
296 return nullptr;
297 case OpenCLDebugInfo100Boolean:
298 return vk::dbg::make_reference(*static_cast<bool *>(ptr));
299 case OpenCLDebugInfo100Float:
300 return vk::dbg::make_reference(*static_cast<float *>(ptr));
301 case OpenCLDebugInfo100Signed:
302 return vk::dbg::make_reference(*static_cast<int32_t *>(ptr));
303 case OpenCLDebugInfo100SignedChar:
304 return vk::dbg::make_reference(*static_cast<int8_t *>(ptr));
305 case OpenCLDebugInfo100Unsigned:
306 return vk::dbg::make_reference(*static_cast<uint32_t *>(ptr));
307 case OpenCLDebugInfo100UnsignedChar:
308 return vk::dbg::make_reference(*static_cast<uint8_t *>(ptr));
309 default:
310 UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100 encoding %d", int(encoding));
311 return nullptr;
312 }
313 }
Ben Clayton2cb1db02020-01-15 18:38:25 +0000314};
315
Ben Clayton00e4a7c2020-04-23 16:50:26 +0100316struct ArrayType : ObjectImpl<ArrayType, Type, Object::Kind::ArrayType>
317{
318 Type *base = nullptr;
319 std::vector<uint32_t> dimensions;
Ben Clayton907433b2020-06-01 13:52:07 +0100320
321 // build() loops over each element of the multi-dimensional array, calling
322 // enter() for building each new dimension group, and element() for each
323 // inner-most dimension element.
324 //
325 // enter must be a function of the signature:
326 // std::shared_ptr<vk::dbg::VariableContainer>
327 // (std::shared_ptr<vk::dbg::VariableContainer>& parent, uint32_t idx)
328 // where:
329 // parent is the outer dimension group
330 // idx is the index of the next deepest dimension.
331 //
332 // element must be a function of the signature:
333 // void(std::shared_ptr<vk::dbg::VariableContainer> &parent,
334 // uint32_t idx, uint32_t offset)
335 // where:
336 // parent is the penultimate deepest dimension group
337 // idx is the index of the element in parent group
338 // offset is the 'flattened array' index for the element.
339 template<typename GROUP, typename ENTER_FUNC, typename ELEMENT_FUNC>
340 void build(const GROUP &group, ENTER_FUNC &&enter, ELEMENT_FUNC &&element) const
341 {
342 if(dimensions.size() == 0) { return; }
343
344 struct Dimension
345 {
346 uint32_t idx = 0;
347 GROUP group;
348 bool built = false;
349 };
350
351 std::vector<Dimension> dims;
352 dims.resize(dimensions.size());
353
354 uint32_t offset = 0;
355
356 int dimIdx = 0;
357 const int n = static_cast<int>(dimensions.size()) - 1;
358 while(dimIdx >= 0)
359 {
360 // (Re)build groups to inner dimensions.
361 for(; dimIdx <= n; dimIdx++)
362 {
363 if(!dims[dimIdx].built)
364 {
365 dims[dimIdx].group = (dimIdx == 0)
366 ? group
367 : enter(dims[dimIdx - 1].group, dims[dimIdx - 1].idx);
368 dims[dimIdx].built = true;
369 }
370 }
371
372 // Emit each of the inner-most dimension elements.
373 for(dims[n].idx = 0; dims[n].idx < dimensions[n]; dims[n].idx++)
374 {
375 ASSERT(dims[n].built);
376 element(dims[n].group, dims[n].idx, offset++);
377 }
378
379 dimIdx = n;
380 while(dims[dimIdx].idx == dimensions[dimIdx])
381 {
382 dims[dimIdx] = {}; // Clear the the current dimension
383 dimIdx--; // Step up a dimension
384 if(dimIdx < 0) { break; }
385 dims[dimIdx].idx++; // Increment the next dimension index
386 }
387 }
388 }
389
390 uint32_t sizeInBytes() const override
391 {
392 auto numBytes = base->sizeInBytes();
393 for(auto dim : dimensions)
394 {
395 numBytes *= dim;
396 }
397 return numBytes;
398 }
399
400 std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
401 {
402 auto vc = lock.createVariableContainer();
403 build(
404 vc,
405 [&](std::shared_ptr<vk::dbg::VariableContainer> &parent, uint32_t idx) {
406 auto child = lock.createVariableContainer();
407 parent->put(tostring(idx), child);
408 return child;
409 },
410 [&](std::shared_ptr<vk::dbg::VariableContainer> &parent, uint32_t idx, uint32_t offset) {
411 offset = offset * base->sizeInBytes() * (interleaved ? sw::SIMD::Width : 1);
412 auto addr = static_cast<uint8_t *>(ptr) + offset;
413 auto child = base->value(lock, addr, interleaved);
414 auto key = tostring(idx);
415# if DEBUG_ANNOTATE_VARIABLE_KEYS
416 key += " (" + tostring(addr) + " +" + tostring(offset) + ", idx: " + tostring(idx) + ")" + (interleaved ? "I" : "F");
417# endif
418 parent->put(key, child);
419 });
420 return vc;
421 }
Ben Clayton00e4a7c2020-04-23 16:50:26 +0100422};
423
Ben Clayton2cb1db02020-01-15 18:38:25 +0000424struct VectorType : ObjectImpl<VectorType, Type, Object::Kind::VectorType>
425{
426 Type *base = nullptr;
427 uint32_t components = 0;
Ben Clayton907433b2020-06-01 13:52:07 +0100428
429 uint32_t sizeInBytes() const override
430 {
431 return base->sizeInBytes() * components;
432 }
433
434 std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
435 {
436 const auto elSize = base->sizeInBytes();
437 auto vc = lock.createVariableContainer();
438 for(uint32_t i = 0; i < components; i++)
439 {
440 auto offset = elSize * i * (interleaved ? sw::SIMD::Width : 1);
441 auto elPtr = static_cast<uint8_t *>(ptr) + offset;
Ben Claytond68844f2020-06-09 12:25:31 +0100442 auto elKey = (components > 4) ? tostring(i) : &"x\0y\0z\0w\0"[i * 2];
Ben Clayton907433b2020-06-01 13:52:07 +0100443# if DEBUG_ANNOTATE_VARIABLE_KEYS
444 elKey += " (" + tostring(elPtr) + " +" + tostring(offset) + ")" + (interleaved ? "I" : "F");
445# endif
446 vc->put(elKey, base->value(lock, elPtr, interleaved));
447 }
448 return vc;
449 }
Ben Clayton2cb1db02020-01-15 18:38:25 +0000450};
451
452struct FunctionType : ObjectImpl<FunctionType, Type, Object::Kind::FunctionType>
453{
454 uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
455 Type *returnTy = nullptr;
456 std::vector<Type *> paramTys;
Ben Clayton907433b2020-06-01 13:52:07 +0100457
458 uint32_t sizeInBytes() const override { return 0; }
459 std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override { return nullptr; }
460};
461
462struct Member : ObjectImpl<Member, Object, Object::Kind::Member>
463{
464 std::string name;
465 Type *type = nullptr;
466 Source *source = nullptr;
467 uint32_t line = 0;
468 uint32_t column = 0;
469 struct CompositeType *parent = nullptr;
470 uint32_t offset = 0; // in bits
471 uint32_t size = 0; // in bits
472 uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
Ben Clayton2cb1db02020-01-15 18:38:25 +0000473};
474
475struct CompositeType : ObjectImpl<CompositeType, Type, Object::Kind::CompositeType>
476{
477 std::string name;
478 OpenCLDebugInfo100DebugCompositeType tag = OpenCLDebugInfo100Class;
479 Source *source = nullptr;
480 uint32_t line = 0;
481 uint32_t column = 0;
482 Object *parent = nullptr;
483 std::string linkage;
484 uint32_t size = 0; // in bits.
485 uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
486 std::vector<Member *> members;
Ben Clayton907433b2020-06-01 13:52:07 +0100487
488 uint32_t sizeInBytes() const override { return size / 8; }
489 std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
490 {
491 auto vc = lock.createVariableContainer();
492 for(auto &member : members)
493 {
494 auto offset = (member->offset / 8) * (interleaved ? sw::SIMD::Width : 1);
495 auto elPtr = static_cast<uint8_t *>(ptr) + offset;
496 auto elKey = member->name;
497# if DEBUG_ANNOTATE_VARIABLE_KEYS
498 // elKey += " (" + tostring(elPtr) + " +" + tostring(offset) + ")" + (interleaved ? "I" : "F");
499# endif
500 vc->put(elKey, member->type->value(lock, elPtr, interleaved));
501 }
502 return vc;
503 }
Ben Clayton2cb1db02020-01-15 18:38:25 +0000504};
505
Ben Clayton0aec9b62020-05-27 09:52:55 +0100506struct TemplateParameter : ObjectImpl<TemplateParameter, Object, Object::Kind::TemplateParameter>
507{
508 std::string name;
509 Type *type = nullptr;
510 uint32_t value = 0;
511 Source *source = nullptr;
512 uint32_t line = 0;
513 uint32_t column = 0;
514};
515
516struct TemplateType : ObjectImpl<TemplateType, Type, Object::Kind::TemplateType>
517{
518 Type *target = nullptr; // Class, struct or function.
519 std::vector<TemplateParameter *> parameters;
Ben Clayton0aec9b62020-05-27 09:52:55 +0100520
Ben Clayton907433b2020-06-01 13:52:07 +0100521 uint32_t sizeInBytes() const override { return target->sizeInBytes(); }
522 std::shared_ptr<vk::dbg::Value> value(vk::dbg::Context::Lock &lock, void *ptr, bool interleaved) const override
523 {
524 return target->value(lock, ptr, interleaved);
525 }
Ben Clayton2cb1db02020-01-15 18:38:25 +0000526};
527
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000528struct Function : ObjectImpl<Function, Scope, Object::Kind::Function>
Ben Clayton2cb1db02020-01-15 18:38:25 +0000529{
530 std::string name;
531 FunctionType *type = nullptr;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000532 uint32_t line = 0;
533 uint32_t column = 0;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000534 std::string linkage;
535 uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
536 uint32_t scopeLine = 0;
537 sw::SpirvShader::Function::ID function;
538};
539
540struct LexicalBlock : ObjectImpl<LexicalBlock, Scope, Object::Kind::LexicalBlock>
541{
542 uint32_t line = 0;
543 uint32_t column = 0;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000544 std::string name;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000545};
546
547struct InlinedAt : ObjectImpl<InlinedAt, Object, Object::Kind::InlinedAt>
548{
549 uint32_t line = 0;
550 Scope *scope = nullptr;
551 InlinedAt *inlined = nullptr;
552};
553
554struct SourceScope : ObjectImpl<SourceScope, Object, Object::Kind::SourceScope>
555{
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000556 Scope *scope = nullptr;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000557 InlinedAt *inlinedAt = nullptr;
558};
559
Ben Clayton00e4a7c2020-04-23 16:50:26 +0100560struct GlobalVariable : ObjectImpl<GlobalVariable, Object, Object::Kind::GlobalVariable>
561{
562 std::string name;
563 Type *type = nullptr;
564 Source *source = nullptr;
565 uint32_t line = 0;
566 uint32_t column = 0;
567 Scope *parent = nullptr;
568 std::string linkage;
569 sw::SpirvShader::Object::ID variable;
570 uint32_t flags = 0; // OR'd from OpenCLDebugInfo100DebugInfoFlags
571};
572
Ben Clayton2cb1db02020-01-15 18:38:25 +0000573struct LocalVariable : ObjectImpl<LocalVariable, Object, Object::Kind::LocalVariable>
574{
575 static constexpr uint32_t NoArg = ~uint32_t(0);
576
577 std::string name;
578 Type *type = nullptr;
579 Source *source = nullptr;
580 uint32_t line = 0;
581 uint32_t column = 0;
582 Scope *parent = nullptr;
583 uint32_t arg = NoArg;
584};
585
586struct Operation : ObjectImpl<Operation, Object, Object::Kind::Operation>
587{
588 uint32_t opcode = 0;
589 std::vector<uint32_t> operands;
590};
591
592struct Expression : ObjectImpl<Expression, Object, Object::Kind::Expression>
593{
594 std::vector<Operation *> operations;
595};
596
597struct Declare : ObjectImpl<Declare, Object, Object::Kind::Declare>
598{
599 LocalVariable *local = nullptr;
600 sw::SpirvShader::Object::ID variable;
601 Expression *expression = nullptr;
602};
603
604struct Value : ObjectImpl<Value, Object, Object::Kind::Value>
605{
606 LocalVariable *local = nullptr;
607 sw::SpirvShader::Object::ID variable;
608 Expression *expression = nullptr;
609 std::vector<uint32_t> indexes;
610};
611
Ben Claytonafb18672020-05-27 10:35:51 +0100612const Scope Scope::Global = CompilationUnit{};
Ben Clayton2cb1db02020-01-15 18:38:25 +0000613
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000614// find<T>() searches the nested scopes, returning for the first scope that is
615// castable to type T. If no scope can be found of type T, then nullptr is
616// returned.
617template<typename T>
618T *find(Scope *scope)
619{
620 if(auto out = cast<T>(scope)) { return out; }
621 return scope->parent ? find<T>(scope->parent) : nullptr;
622}
623
Ben Clayton3a50a432020-03-13 18:13:42 +0000624bool hasDebuggerScope(debug::Scope *spirvScope)
625{
626 return debug::cast<debug::Function>(spirvScope) != nullptr ||
627 debug::cast<debug::LexicalBlock>(spirvScope) != nullptr;
628}
629
Ben Clayton2cb1db02020-01-15 18:38:25 +0000630} // namespace debug
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000631} // anonymous namespace
632
633namespace rr {
634
635////////////////////////////////////////////////////////////////////////////////
636// rr::CToReactor<T> specializations.
637////////////////////////////////////////////////////////////////////////////////
638template<typename T>
639struct CToReactor<sw::SpirvID<T>>
640{
641 using type = rr::Int;
642 static rr::Int cast(sw::SpirvID<T> id) { return rr::Int(id.value()); }
643};
644
645template<typename T>
646struct CToReactor<vk::dbg::ID<T>>
647{
648 using type = rr::Int;
649 static rr::Int cast(vk::dbg::ID<T> id) { return rr::Int(id.value()); }
650};
651
652} // namespace rr
653
654namespace sw {
655
656////////////////////////////////////////////////////////////////////////////////
657// sw::SpirvShader::Impl::Debugger
658//
659// Private struct holding debugger information for the SpirvShader.
660////////////////////////////////////////////////////////////////////////////////
661struct SpirvShader::Impl::Debugger
662{
663 class Group;
664 class State;
665
Ben Clayton2cb1db02020-01-15 18:38:25 +0000666 enum class Pass
667 {
668 Define,
669 Emit
670 };
671
672 void process(const SpirvShader *shader, const InsnIterator &insn, EmitState *state, Pass pass);
673
Ben Clayton694e2142020-04-30 16:46:53 +0100674 void setNextSetLocationIsStep();
Ben Clayton3a50a432020-03-13 18:13:42 +0000675 void setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &, int line, int column);
676 void setLocation(EmitState *state, const std::string &path, int line, int column);
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000677
678 // exposeVariable exposes the variable with the given ID to the debugger
679 // using the specified key.
680 template<typename Key>
681 void exposeVariable(
682 const SpirvShader *shader,
683 const Key &key,
Ben Clayton2cb1db02020-01-15 18:38:25 +0000684 const debug::Scope *scope,
685 const debug::Type *type,
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000686 Object::ID id,
687 EmitState *state) const;
688
689 // exposeVariable exposes the variable with the given ID to the
690 // debugger under the specified group, for the specified SIMD lane.
691 template<typename Key>
692 void exposeVariable(
693 const SpirvShader *shader,
694 const Group &group,
695 int lane,
696 const Key &key,
Ben Clayton2cb1db02020-01-15 18:38:25 +0000697 const debug::Type *type,
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000698 Object::ID id,
699 EmitState *state,
700 int wordOffset = 0) const;
701
702 std::shared_ptr<vk::dbg::Context> ctx;
703 std::shared_ptr<vk::dbg::File> spirvFile;
704 std::unordered_map<const void *, int> spirvLineMappings; // instruction pointer to line
705 std::unordered_map<const void *, Object::ID> results; // instruction pointer to result ID
706
707private:
Ben Clayton2cb1db02020-01-15 18:38:25 +0000708 // add() registers the debug object with the given id.
Ben Clayton3011de52020-06-09 12:13:42 +0100709 template<typename ID>
710 void add(ID id, std::unique_ptr<debug::Object> &&);
Ben Clayton2cb1db02020-01-15 18:38:25 +0000711
Ben Claytonda384012020-03-12 12:45:02 +0000712 // addNone() registers given id as a None value or type.
713 void addNone(debug::Object::ID id);
714
Ben Clayton248ef6f2020-05-27 09:54:06 +0100715 // isNone() returns true if the given id was registered as none with
716 // addNone().
717 bool isNone(debug::Object::ID id) const;
718
Ben Clayton2cb1db02020-01-15 18:38:25 +0000719 // get() returns the debug object with the given id.
720 // The object must exist and be of type (or derive from type) T.
Ben Claytonda384012020-03-12 12:45:02 +0000721 // A returned nullptr represents a None value or type.
Ben Clayton2cb1db02020-01-15 18:38:25 +0000722 template<typename T>
723 T *get(SpirvID<T> id) const;
724
725 // use get() and add() to access this
726 std::unordered_map<debug::Object::ID, std::unique_ptr<debug::Object>> objects;
727
Ben Clayton2cb1db02020-01-15 18:38:25 +0000728 // defineOrEmit() when called in Pass::Define, creates and stores a
729 // zero-initialized object into the Debugger::objects map using the
730 // object identifier held by second instruction operand.
731 // When called in Pass::Emit, defineOrEmit() calls the function F with the
732 // previously-built object.
733 //
734 // F must be a function with the signature:
735 // void(OBJECT_TYPE *)
736 //
737 // The object type is automatically inferred from the function signature.
738 template<typename F, typename T = typename std::remove_pointer<ArgTyT<F>>::type>
739 void defineOrEmit(InsnIterator insn, Pass pass, F &&emit);
Ben Clayton3a50a432020-03-13 18:13:42 +0000740
741 std::unordered_map<std::string, std::shared_ptr<vk::dbg::File>> files;
Ben Clayton694e2142020-04-30 16:46:53 +0100742 bool nextSetLocationIsStep = true;
743 int lastSetLocationLine = 0;
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000744};
745
746////////////////////////////////////////////////////////////////////////////////
747// sw::SpirvShader::Impl::Debugger::State
748//
749// State holds the runtime data structures for the shader debug session.
750////////////////////////////////////////////////////////////////////////////////
751class SpirvShader::Impl::Debugger::State
752{
753public:
754 static State *create(const Debugger *debugger, const char *name);
755 static void destroy(State *);
756
757 State(const Debugger *debugger, const char *stackBase, vk::dbg::Context::Lock &lock);
758 ~State();
759
760 void enter(vk::dbg::Context::Lock &lock, const char *name);
761 void exit();
762 void updateActiveLaneMask(int lane, bool enabled);
Ben Clayton694e2142020-04-30 16:46:53 +0100763 void updateLocation(bool isStep, vk::dbg::File::ID file, int line, int column);
Ben Clayton2cb1db02020-01-15 18:38:25 +0000764 void createScope(const debug::Scope *);
765 void setScope(debug::SourceScope *newScope);
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000766
Ben Clayton2cb1db02020-01-15 18:38:25 +0000767 vk::dbg::VariableContainer *hovers(const debug::Scope *);
768 vk::dbg::VariableContainer *localsLane(const debug::Scope *, int lane);
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000769
770 template<typename K>
771 vk::dbg::VariableContainer *group(vk::dbg::VariableContainer *vc, K key);
772
773 template<typename K, typename V>
774 void putVal(vk::dbg::VariableContainer *vc, K key, V value);
775
Ben Clayton907433b2020-06-01 13:52:07 +0100776 template<typename K>
777 void putPtr(vk::dbg::VariableContainer *vc, K key, void *ptr, bool interleaved, const debug::Type *type);
778
Ben Clayton2cb1db02020-01-15 18:38:25 +0000779 template<typename K, typename V>
780 void putRef(vk::dbg::VariableContainer *vc, K key, V *ptr);
781
782 // Scopes holds pointers to the vk::dbg::Scopes for local variables, hover
783 // variables and the locals indexed by SIMD lane.
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000784 struct Scopes
785 {
786 std::shared_ptr<vk::dbg::Scope> locals;
787 std::shared_ptr<vk::dbg::Scope> hovers;
788 std::array<std::shared_ptr<vk::dbg::VariableContainer>, sw::SIMD::Width> localsByLane;
789 };
790
Ben Clayton2cb1db02020-01-15 18:38:25 +0000791 // getScopes() returns the Scopes object for the given debug::Scope.
792 const Scopes &getScopes(const debug::Scope *scope);
793
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000794 const Debugger *debugger;
795 const std::shared_ptr<vk::dbg::Thread> thread;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000796 std::unordered_map<const debug::Scope *, Scopes> scopes;
Ben Claytonafb18672020-05-27 10:35:51 +0100797 Scopes globals; // Scope for globals.
798 debug::SourceScope *srcScope = nullptr; // Current source scope.
Ben Claytonf42c6982020-04-23 16:52:32 +0100799
800 const size_t initialThreadDepth = 0;
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000801};
802
803SpirvShader::Impl::Debugger::State *SpirvShader::Impl::Debugger::State::create(const Debugger *debugger, const char *name)
804{
805 auto lock = debugger->ctx->lock();
806 return new State(debugger, name, lock);
807}
808
809void SpirvShader::Impl::Debugger::State::destroy(State *state)
810{
811 delete state;
812}
813
814SpirvShader::Impl::Debugger::State::State(const Debugger *debugger, const char *stackBase, vk::dbg::Context::Lock &lock)
815 : debugger(debugger)
816 , thread(lock.currentThread())
Ben Claytonf42c6982020-04-23 16:52:32 +0100817 , initialThreadDepth(thread->depth())
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000818{
819 enter(lock, stackBase);
Ben Clayton7a53cb62020-01-27 21:40:18 +0000820
Ben Clayton694e2142020-04-30 16:46:53 +0100821 thread->update(true, [&](vk::dbg::Frame &frame) {
Ben Claytonafb18672020-05-27 10:35:51 +0100822 globals.locals = frame.locals;
823 globals.hovers = frame.hovers;
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000824 for(int i = 0; i < sw::SIMD::Width; i++)
825 {
Ben Clayton7a53cb62020-01-27 21:40:18 +0000826 auto locals = lock.createVariableContainer();
Ben Clayton7a53cb62020-01-27 21:40:18 +0000827 frame.locals->variables->put(laneNames[i], locals);
Ben Claytonafb18672020-05-27 10:35:51 +0100828 globals.localsByLane[i] = locals;
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000829 }
830 });
831}
832
833SpirvShader::Impl::Debugger::State::~State()
834{
Ben Claytonf42c6982020-04-23 16:52:32 +0100835 for(auto depth = thread->depth(); depth > initialThreadDepth; depth--)
836 {
837 exit();
838 }
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000839}
840
841void SpirvShader::Impl::Debugger::State::enter(vk::dbg::Context::Lock &lock, const char *name)
842{
843 thread->enter(lock, debugger->spirvFile, name);
844}
845
846void SpirvShader::Impl::Debugger::State::exit()
847{
848 thread->exit();
849}
850
851void SpirvShader::Impl::Debugger::State::updateActiveLaneMask(int lane, bool enabled)
852{
Ben Claytonafb18672020-05-27 10:35:51 +0100853 globals.localsByLane[lane]->put("enabled", vk::dbg::make_constant(enabled));
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000854}
855
Ben Clayton694e2142020-04-30 16:46:53 +0100856void SpirvShader::Impl::Debugger::State::updateLocation(bool isStep, vk::dbg::File::ID fileID, int line, int column)
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000857{
858 auto file = debugger->ctx->lock().get(fileID);
Ben Clayton694e2142020-04-30 16:46:53 +0100859 thread->update(isStep, [&](vk::dbg::Frame &frame) {
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000860 frame.location = { file, line, column };
861 });
862}
863
Ben Clayton2cb1db02020-01-15 18:38:25 +0000864vk::dbg::VariableContainer *SpirvShader::Impl::Debugger::State::hovers(const debug::Scope *scope)
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000865{
Ben Clayton2cb1db02020-01-15 18:38:25 +0000866 return getScopes(scope).hovers->variables.get();
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000867}
868
Ben Clayton2cb1db02020-01-15 18:38:25 +0000869vk::dbg::VariableContainer *SpirvShader::Impl::Debugger::State::localsLane(const debug::Scope *scope, int i)
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000870{
Ben Clayton2cb1db02020-01-15 18:38:25 +0000871 return getScopes(scope).localsByLane[i].get();
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000872}
873
874template<typename K>
875vk::dbg::VariableContainer *SpirvShader::Impl::Debugger::State::group(vk::dbg::VariableContainer *vc, K key)
876{
877 auto out = debugger->ctx->lock().createVariableContainer();
878 vc->put(tostring(key), out);
879 return out.get();
880}
881
882template<typename K, typename V>
883void SpirvShader::Impl::Debugger::State::putVal(vk::dbg::VariableContainer *vc, K key, V value)
884{
885 vc->put(tostring(key), vk::dbg::make_constant(value));
886}
887
Ben Clayton907433b2020-06-01 13:52:07 +0100888template<typename K>
889void SpirvShader::Impl::Debugger::State::putPtr(vk::dbg::VariableContainer *vc, K key, void *ptr, bool interleaved, const debug::Type *type)
890{
891 auto lock = debugger->ctx->lock();
892 vc->put(tostring(key), type->value(lock, ptr, interleaved));
893}
894
Ben Clayton2cb1db02020-01-15 18:38:25 +0000895template<typename K, typename V>
896void SpirvShader::Impl::Debugger::State::putRef(vk::dbg::VariableContainer *vc, K key, V *ptr)
897{
898 vc->put(tostring(key), vk::dbg::make_reference(*ptr));
899}
900
901void SpirvShader::Impl::Debugger::State::createScope(const debug::Scope *spirvScope)
902{
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000903 // TODO(b/151338669): We're creating scopes per-shader invocation.
904 // This is all really static information, and should only be created
905 // once *per program*.
906
Ben Clayton2cb1db02020-01-15 18:38:25 +0000907 ASSERT(spirvScope != nullptr);
908
Ben Clayton2cb1db02020-01-15 18:38:25 +0000909 auto lock = debugger->ctx->lock();
910 Scopes s = {};
911 s.locals = lock.createScope(spirvScope->source->dbgFile);
912 s.hovers = lock.createScope(spirvScope->source->dbgFile);
Ben Clayton3a50a432020-03-13 18:13:42 +0000913
Ben Clayton2cb1db02020-01-15 18:38:25 +0000914 for(int i = 0; i < sw::SIMD::Width; i++)
915 {
Ben Clayton7a53cb62020-01-27 21:40:18 +0000916 auto locals = lock.createVariableContainer();
Ben Clayton7a53cb62020-01-27 21:40:18 +0000917 s.localsByLane[i] = locals;
918 s.locals->variables->put(laneNames[i], locals);
Ben Clayton2cb1db02020-01-15 18:38:25 +0000919 }
Ben Clayton3a50a432020-03-13 18:13:42 +0000920
921 if(hasDebuggerScope(spirvScope->parent))
922 {
923 auto parent = getScopes(spirvScope->parent);
924 for(int i = 0; i < sw::SIMD::Width; i++)
925 {
926 s.localsByLane[i]->extend(parent.localsByLane[i]);
927 }
928 s.hovers->variables->extend(parent.hovers->variables);
929 }
930 else
931 {
Ben Claytonafb18672020-05-27 10:35:51 +0100932 // Scope has no parent. Ensure the globals are inherited for this stack
933 // frame.
934 //
935 // Note: We're combining globals with locals as DAP doesn't have a
936 // 'globals' enum value for Scope::presentationHint.
937 // TODO(bclayton): We should probably keep globals separate from locals
938 // and combine them at the server interface. That way we can easily
939 // provide globals if DAP later supports it as a Scope::presentationHint
940 // type.
Ben Clayton3a50a432020-03-13 18:13:42 +0000941 for(int i = 0; i < sw::SIMD::Width; i++)
942 {
Ben Claytonafb18672020-05-27 10:35:51 +0100943 s.localsByLane[i]->extend(globals.localsByLane[i]);
Ben Clayton3a50a432020-03-13 18:13:42 +0000944 }
945 }
946
Ben Clayton2cb1db02020-01-15 18:38:25 +0000947 scopes.emplace(spirvScope, std::move(s));
948}
949
950void SpirvShader::Impl::Debugger::State::setScope(debug::SourceScope *newSrcScope)
951{
952 auto oldSrcScope = srcScope;
953 if(oldSrcScope == newSrcScope) { return; }
954 srcScope = newSrcScope;
955
Ben Clayton3a50a432020-03-13 18:13:42 +0000956 if(hasDebuggerScope(srcScope->scope))
Ben Clayton2cb1db02020-01-15 18:38:25 +0000957 {
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000958 auto lock = debugger->ctx->lock();
959 auto thread = lock.currentThread();
Ben Clayton2cb1db02020-01-15 18:38:25 +0000960
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000961 debug::Function *oldFunction = oldSrcScope ? debug::find<debug::Function>(oldSrcScope->scope) : nullptr;
962 debug::Function *newFunction = newSrcScope ? debug::find<debug::Function>(newSrcScope->scope) : nullptr;
963
964 if(oldFunction != newFunction)
965 {
966 if(oldFunction) { thread->exit(); }
967 if(newFunction) { thread->enter(lock, newFunction->source->dbgFile, newFunction->name); }
968 }
969
970 auto dbgScope = getScopes(srcScope->scope);
Ben Clayton694e2142020-04-30 16:46:53 +0100971 thread->update(true, [&](vk::dbg::Frame &frame) {
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000972 frame.locals = dbgScope.locals;
973 frame.hovers = dbgScope.hovers;
974 });
975 }
Ben Clayton2cb1db02020-01-15 18:38:25 +0000976}
977
978const SpirvShader::Impl::Debugger::State::Scopes &SpirvShader::Impl::Debugger::State::getScopes(const debug::Scope *scope)
979{
Ben Claytonafb18672020-05-27 10:35:51 +0100980 if(scope == &debug::Scope::Global)
Ben Clayton2cb1db02020-01-15 18:38:25 +0000981 {
Ben Claytonafb18672020-05-27 10:35:51 +0100982 return globals;
Ben Clayton2cb1db02020-01-15 18:38:25 +0000983 }
984
985 auto dbgScopeIt = scopes.find(scope);
Ben Claytonb2d7dff2020-03-12 14:17:54 +0000986 ASSERT_MSG(dbgScopeIt != scopes.end(),
987 "createScope() not called for debug::Scope %s %p",
988 cstr(scope->kind), scope);
Ben Clayton2cb1db02020-01-15 18:38:25 +0000989 return dbgScopeIt->second;
990}
991
Ben Claytonb0ca2a82020-01-08 13:00:57 +0000992////////////////////////////////////////////////////////////////////////////////
993// sw::SpirvShader::Impl::Debugger::Group
994//
995// This provides a convenient C++ interface for adding debugger values to
996// VariableContainers.
997////////////////////////////////////////////////////////////////////////////////
998class SpirvShader::Impl::Debugger::Group
999{
1000public:
1001 using Ptr = rr::Pointer<rr::Byte>;
1002
Ben Clayton2cb1db02020-01-15 18:38:25 +00001003 static Group hovers(Ptr state, const debug::Scope *scope);
1004 static Group locals(Ptr state, const debug::Scope *scope);
1005 static Group localsLane(Ptr state, const debug::Scope *scope, int lane);
Ben Claytonafb18672020-05-27 10:35:51 +01001006 static Group globals(Ptr state, int lane);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001007
Ben Clayton907433b2020-06-01 13:52:07 +01001008 inline Group();
1009 inline Group(Ptr state, Ptr group);
1010
1011 inline bool isValid() const;
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001012
1013 template<typename K, typename RK>
1014 Group group(RK key) const;
1015
1016 template<typename K, typename V, typename RK, typename RV>
1017 void put(RK key, RV value) const;
1018
Ben Clayton907433b2020-06-01 13:52:07 +01001019 template<typename K, typename RK>
1020 void putPtr(RK key, RValue<Pointer<Byte>> ptr, bool interleaved, const debug::Type *type) const;
1021
Ben Clayton2cb1db02020-01-15 18:38:25 +00001022 template<typename K, typename V, typename RK>
1023 void putRef(RK key, RValue<Pointer<Byte>> ref) const;
1024
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001025 template<typename K, typename V, typename RK, typename RV>
1026 void put(RK key, RV x, RV y) const;
1027
1028 template<typename K, typename V, typename RK, typename RV>
1029 void put(RK key, RV x, RV y, RV z) const;
1030
1031 template<typename K, typename V, typename RK, typename RV>
1032 void put(RK key, RV x, RV y, RV z, RV w) const;
1033
1034 template<typename K, typename V, typename VEC>
1035 void putVec3(K key, const VEC &v) const;
1036
1037private:
1038 Ptr state;
1039 Ptr ptr;
Ben Clayton907433b2020-06-01 13:52:07 +01001040 bool valid = false;
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001041};
1042
1043SpirvShader::Impl::Debugger::Group
Ben Clayton2cb1db02020-01-15 18:38:25 +00001044SpirvShader::Impl::Debugger::Group::hovers(Ptr state, const debug::Scope *scope)
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001045{
Ben Clayton2cb1db02020-01-15 18:38:25 +00001046 return Group(state, rr::Call(&State::hovers, state, scope));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001047}
1048
1049SpirvShader::Impl::Debugger::Group
Ben Clayton2cb1db02020-01-15 18:38:25 +00001050SpirvShader::Impl::Debugger::Group::localsLane(Ptr state, const debug::Scope *scope, int lane)
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001051{
Ben Clayton2cb1db02020-01-15 18:38:25 +00001052 return Group(state, rr::Call(&State::localsLane, state, scope, lane));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001053}
1054
Ben Clayton7a53cb62020-01-27 21:40:18 +00001055SpirvShader::Impl::Debugger::Group
Ben Claytonafb18672020-05-27 10:35:51 +01001056SpirvShader::Impl::Debugger::Group::globals(Ptr state, int lane)
Ben Clayton7a53cb62020-01-27 21:40:18 +00001057{
Ben Claytonafb18672020-05-27 10:35:51 +01001058 return localsLane(state, &debug::Scope::Global, lane);
Ben Clayton7a53cb62020-01-27 21:40:18 +00001059}
1060
Ben Clayton907433b2020-06-01 13:52:07 +01001061SpirvShader::Impl::Debugger::Group::Group() {}
1062
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001063SpirvShader::Impl::Debugger::Group::Group(Ptr state, Ptr group)
1064 : state(state)
1065 , ptr(group)
Ben Clayton907433b2020-06-01 13:52:07 +01001066 , valid(true)
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001067{}
1068
Ben Clayton907433b2020-06-01 13:52:07 +01001069bool SpirvShader::Impl::Debugger::Group::isValid() const
1070{
1071 return valid;
1072}
1073
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001074template<typename K, typename RK>
1075SpirvShader::Impl::Debugger::Group SpirvShader::Impl::Debugger::Group::group(RK key) const
1076{
Ben Clayton907433b2020-06-01 13:52:07 +01001077 ASSERT(isValid());
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001078 return Group(state, rr::Call(&State::group<K>, state, ptr, key));
1079}
1080
1081template<typename K, typename V, typename RK, typename RV>
1082void SpirvShader::Impl::Debugger::Group::put(RK key, RV value) const
1083{
Ben Clayton907433b2020-06-01 13:52:07 +01001084 ASSERT(isValid());
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001085 rr::Call(&State::putVal<K, V>, state, ptr, key, value);
1086}
1087
Ben Clayton907433b2020-06-01 13:52:07 +01001088template<typename K, typename RK>
1089void SpirvShader::Impl::Debugger::Group::putPtr(RK key, RValue<Pointer<Byte>> addr, bool interleaved, const debug::Type *type) const
1090{
1091 ASSERT(isValid());
1092 rr::Call(&State::putPtr<K>, state, ptr, key, addr, interleaved, type);
1093}
1094
Ben Clayton2cb1db02020-01-15 18:38:25 +00001095template<typename K, typename V, typename RK>
1096void SpirvShader::Impl::Debugger::Group::putRef(RK key, RValue<Pointer<Byte>> ref) const
1097{
Ben Clayton907433b2020-06-01 13:52:07 +01001098 ASSERT(isValid());
Ben Clayton2cb1db02020-01-15 18:38:25 +00001099 rr::Call(&State::putRef<K, V>, state, ptr, key, ref);
1100}
1101
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001102template<typename K, typename V, typename RK, typename RV>
1103void SpirvShader::Impl::Debugger::Group::put(RK key, RV x, RV y) const
1104{
1105 auto vec = group<K>(key);
1106 vec.template put<const char *, V>("x", x);
1107 vec.template put<const char *, V>("y", y);
1108}
1109
1110template<typename K, typename V, typename RK, typename RV>
1111void SpirvShader::Impl::Debugger::Group::put(RK key, RV x, RV y, RV z) const
1112{
1113 auto vec = group<K>(key);
1114 vec.template put<const char *, V>("x", x);
1115 vec.template put<const char *, V>("y", y);
1116 vec.template put<const char *, V>("z", z);
1117}
1118
1119template<typename K, typename V, typename RK, typename RV>
1120void SpirvShader::Impl::Debugger::Group::put(RK key, RV x, RV y, RV z, RV w) const
1121{
1122 auto vec = group<K>(key);
1123 vec.template put<const char *, V>("x", x);
1124 vec.template put<const char *, V>("y", y);
1125 vec.template put<const char *, V>("z", z);
1126 vec.template put<const char *, V>("w", w);
1127}
1128
1129template<typename K, typename V, typename VEC>
1130void SpirvShader::Impl::Debugger::Group::putVec3(K key, const VEC &v) const
1131{
1132 auto vec = group<K>(key);
1133 vec.template put<const char *, V>("x", Extract(v, 0));
1134 vec.template put<const char *, V>("y", Extract(v, 1));
1135 vec.template put<const char *, V>("z", Extract(v, 2));
1136}
1137
1138////////////////////////////////////////////////////////////////////////////////
1139// sw::SpirvShader::Impl::Debugger methods
1140////////////////////////////////////////////////////////////////////////////////
Ben Clayton2cb1db02020-01-15 18:38:25 +00001141template<typename F, typename T>
1142void SpirvShader::Impl::Debugger::defineOrEmit(InsnIterator insn, Pass pass, F &&emit)
1143{
1144 auto id = SpirvID<T>(insn.word(2));
1145 switch(pass)
1146 {
1147 case Pass::Define:
Ben Clayton3011de52020-06-09 12:13:42 +01001148 add(id, std::unique_ptr<debug::Object>(new T()));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001149 break;
1150 case Pass::Emit:
1151 emit(get<T>(id));
1152 break;
1153 }
1154}
1155
1156void SpirvShader::Impl::Debugger::process(const SpirvShader *shader, const InsnIterator &insn, EmitState *state, Pass pass)
1157{
1158 auto dbg = shader->impl.debugger;
1159 auto extInstIndex = insn.word(4);
1160 switch(extInstIndex)
1161 {
Ben Claytonda384012020-03-12 12:45:02 +00001162 case OpenCLDebugInfo100DebugInfoNone:
1163 if(pass == Pass::Define)
1164 {
1165 addNone(debug::Object::ID(insn.word(2)));
1166 }
1167 break;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001168 case OpenCLDebugInfo100DebugCompilationUnit:
1169 defineOrEmit(insn, pass, [&](debug::CompilationUnit *cu) {
1170 cu->source = get(debug::Source::ID(insn.word(7)));
1171 });
1172 break;
1173 case OpenCLDebugInfo100DebugTypeBasic:
1174 defineOrEmit(insn, pass, [&](debug::BasicType *type) {
1175 type->name = shader->getString(insn.word(5));
1176 type->size = shader->GetConstScalarInt(insn.word(6));
1177 type->encoding = static_cast<OpenCLDebugInfo100DebugBaseTypeAttributeEncoding>(insn.word(7));
1178 });
1179 break;
Ben Clayton00e4a7c2020-04-23 16:50:26 +01001180 case OpenCLDebugInfo100DebugTypeArray:
1181 defineOrEmit(insn, pass, [&](debug::ArrayType *type) {
1182 type->base = get(debug::Type::ID(insn.word(5)));
Ben Clayton907433b2020-06-01 13:52:07 +01001183 for(uint32_t i = 6; i < insn.wordCount(); i++)
1184 {
1185 type->dimensions.emplace_back(shader->GetConstScalarInt(insn.word(i)));
1186 }
Ben Clayton00e4a7c2020-04-23 16:50:26 +01001187 });
1188 break;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001189 case OpenCLDebugInfo100DebugTypeVector:
1190 defineOrEmit(insn, pass, [&](debug::VectorType *type) {
1191 type->base = get(debug::Type::ID(insn.word(5)));
1192 type->components = insn.word(6);
1193 });
1194 break;
1195 case OpenCLDebugInfo100DebugTypeFunction:
1196 defineOrEmit(insn, pass, [&](debug::FunctionType *type) {
1197 type->flags = insn.word(5);
1198 type->returnTy = get(debug::Type::ID(insn.word(6)));
1199 for(uint32_t i = 7; i < insn.wordCount(); i++)
1200 {
1201 type->paramTys.push_back(get(debug::Type::ID(insn.word(i))));
1202 }
1203 });
1204 break;
1205 case OpenCLDebugInfo100DebugTypeComposite:
1206 defineOrEmit(insn, pass, [&](debug::CompositeType *type) {
1207 type->name = shader->getString(insn.word(5));
1208 type->tag = static_cast<OpenCLDebugInfo100DebugCompositeType>(insn.word(6));
1209 type->source = get(debug::Source::ID(insn.word(7)));
1210 type->line = insn.word(8);
1211 type->column = insn.word(9);
1212 type->parent = get(debug::Object::ID(insn.word(10)));
1213 type->linkage = shader->getString(insn.word(11));
Ben Clayton248ef6f2020-05-27 09:54:06 +01001214 type->size = isNone(insn.word(12)) ? 0 : shader->GetConstScalarInt(insn.word(12));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001215 type->flags = insn.word(13);
1216 for(uint32_t i = 14; i < insn.wordCount(); i++)
1217 {
1218 auto obj = get(debug::Object::ID(insn.word(i)));
1219 if(auto member = debug::cast<debug::Member>(obj)) // Can also be Function or TypeInheritance, which we don't care about.
1220 {
1221 type->members.push_back(member);
1222 }
1223 }
1224 });
1225 break;
1226 case OpenCLDebugInfo100DebugTypeMember:
1227 defineOrEmit(insn, pass, [&](debug::Member *member) {
1228 member->name = shader->getString(insn.word(5));
1229 member->type = get(debug::Type::ID(insn.word(6)));
1230 member->source = get(debug::Source::ID(insn.word(7)));
1231 member->line = insn.word(8);
1232 member->column = insn.word(9);
1233 member->parent = get(debug::CompositeType::ID(insn.word(10)));
1234 member->offset = shader->GetConstScalarInt(insn.word(11));
1235 member->size = shader->GetConstScalarInt(insn.word(12));
1236 member->flags = insn.word(13);
1237 });
1238 break;
Ben Clayton0aec9b62020-05-27 09:52:55 +01001239 case OpenCLDebugInfo100DebugTypeTemplate:
1240 defineOrEmit(insn, pass, [&](debug::TemplateType *tpl) {
1241 tpl->target = get(debug::Type::ID(insn.word(5)));
1242 for(size_t i = 6, c = insn.wordCount(); i < c; i++)
1243 {
1244 tpl->parameters.emplace_back(get(debug::TemplateParameter::ID(insn.word(i))));
1245 }
1246 });
1247 break;
1248 case OpenCLDebugInfo100DebugTypeTemplateParameter:
1249 defineOrEmit(insn, pass, [&](debug::TemplateParameter *param) {
1250 param->name = shader->getString(insn.word(5));
1251 param->type = get(debug::Type::ID(insn.word(6)));
1252 param->value = 0; // TODO: Get value from OpConstant if "a template value parameter".
1253 param->source = get(debug::Source::ID(insn.word(8)));
1254 param->line = insn.word(9);
1255 param->column = insn.word(10);
1256 });
1257 break;
Ben Clayton00e4a7c2020-04-23 16:50:26 +01001258 case OpenCLDebugInfo100DebugGlobalVariable:
1259 defineOrEmit(insn, pass, [&](debug::GlobalVariable *var) {
1260 var->name = shader->getString(insn.word(5));
1261 var->type = get(debug::Type::ID(insn.word(6)));
1262 var->source = get(debug::Source::ID(insn.word(7)));
1263 var->line = insn.word(8);
1264 var->column = insn.word(9);
1265 var->parent = get(debug::Scope::ID(insn.word(10)));
1266 var->linkage = shader->getString(insn.word(11));
1267 var->variable = insn.word(12);
1268 var->flags = insn.word(13);
1269 // static member declaration: word(14)
1270
Ben Claytonafb18672020-05-27 10:35:51 +01001271 exposeVariable(shader, var->name.c_str(), &debug::Scope::Global, var->type, var->variable, state);
Ben Clayton00e4a7c2020-04-23 16:50:26 +01001272 });
1273 break;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001274 case OpenCLDebugInfo100DebugFunction:
1275 defineOrEmit(insn, pass, [&](debug::Function *func) {
1276 func->name = shader->getString(insn.word(5));
1277 func->type = get(debug::FunctionType::ID(insn.word(6)));
1278 func->source = get(debug::Source::ID(insn.word(7)));
1279 func->line = insn.word(8);
1280 func->column = insn.word(9);
Ben Claytonb2d7dff2020-03-12 14:17:54 +00001281 func->parent = get(debug::Scope::ID(insn.word(10)));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001282 func->linkage = shader->getString(insn.word(11));
1283 func->flags = insn.word(12);
1284 func->scopeLine = insn.word(13);
1285 func->function = Function::ID(insn.word(14));
1286 // declaration: word(13)
1287
Ben Claytonb2d7dff2020-03-12 14:17:54 +00001288 rr::Call(&State::createScope, state->routine->dbgState, func);
Ben Clayton2cb1db02020-01-15 18:38:25 +00001289 });
1290 break;
1291 case OpenCLDebugInfo100DebugLexicalBlock:
1292 defineOrEmit(insn, pass, [&](debug::LexicalBlock *scope) {
1293 scope->source = get(debug::Source::ID(insn.word(5)));
1294 scope->line = insn.word(6);
1295 scope->column = insn.word(7);
1296 scope->parent = get(debug::Scope::ID(insn.word(8)));
1297 if(insn.wordCount() > 9)
1298 {
1299 scope->name = shader->getString(insn.word(9));
1300 }
1301
Ben Clayton2cb1db02020-01-15 18:38:25 +00001302 rr::Call(&State::createScope, state->routine->dbgState, scope);
1303 });
1304 break;
1305 case OpenCLDebugInfo100DebugScope:
1306 defineOrEmit(insn, pass, [&](debug::SourceScope *ss) {
Ben Claytonb2d7dff2020-03-12 14:17:54 +00001307 ss->scope = get(debug::Scope::ID(insn.word(5)));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001308 if(insn.wordCount() > 6)
1309 {
1310 ss->inlinedAt = get(debug::InlinedAt::ID(insn.word(6)));
1311 }
1312
1313 rr::Call(&State::setScope, state->routine->dbgState, ss);
1314 });
1315 break;
1316 case OpenCLDebugInfo100DebugNoScope:
1317 break;
Ben Clayton875d98b2020-03-11 13:43:20 +00001318 case OpenCLDebugInfo100DebugInlinedAt:
1319 defineOrEmit(insn, pass, [&](debug::InlinedAt *ia) {
1320 ia->line = insn.word(5);
Ben Claytonb2d7dff2020-03-12 14:17:54 +00001321 ia->scope = get(debug::Scope::ID(insn.word(6)));
Ben Clayton875d98b2020-03-11 13:43:20 +00001322 if(insn.wordCount() > 7)
1323 {
1324 ia->inlined = get(debug::InlinedAt::ID(insn.word(7)));
1325 }
1326 });
1327 break;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001328 case OpenCLDebugInfo100DebugLocalVariable:
1329 defineOrEmit(insn, pass, [&](debug::LocalVariable *var) {
1330 var->name = shader->getString(insn.word(5));
1331 var->type = get(debug::Type::ID(insn.word(6)));
1332 var->source = get(debug::Source::ID(insn.word(7)));
1333 var->line = insn.word(8);
1334 var->column = insn.word(9);
1335 var->parent = get(debug::Scope::ID(insn.word(10)));
1336 if(insn.wordCount() > 11)
1337 {
1338 var->arg = insn.word(11);
1339 }
1340 });
1341 break;
1342 case OpenCLDebugInfo100DebugDeclare:
1343 defineOrEmit(insn, pass, [&](debug::Declare *decl) {
1344 decl->local = get(debug::LocalVariable::ID(insn.word(5)));
1345 decl->variable = Object::ID(insn.word(6));
1346 decl->expression = get(debug::Expression::ID(insn.word(7)));
1347 exposeVariable(
1348 shader,
1349 decl->local->name.c_str(),
1350 decl->local->parent,
1351 decl->local->type,
1352 decl->variable,
1353 state);
1354 });
1355 break;
1356 case OpenCLDebugInfo100DebugValue:
1357 defineOrEmit(insn, pass, [&](debug::Value *value) {
1358 value->local = get(debug::LocalVariable::ID(insn.word(5)));
1359 value->variable = Object::ID(insn.word(6));
1360 value->expression = get(debug::Expression::ID(insn.word(7)));
1361 for(uint32_t i = 8; i < insn.wordCount(); i++)
1362 {
1363 value->indexes.push_back(insn.word(i));
1364 }
1365 });
1366 break;
1367 case OpenCLDebugInfo100DebugExpression:
1368 defineOrEmit(insn, pass, [&](debug::Expression *expr) {
1369 for(uint32_t i = 5; i < insn.wordCount(); i++)
1370 {
1371 expr->operations.push_back(get(debug::Operation::ID(insn.word(i))));
1372 }
1373 });
1374 break;
1375 case OpenCLDebugInfo100DebugSource:
1376 defineOrEmit(insn, pass, [&](debug::Source *source) {
1377 source->file = shader->getString(insn.word(5));
1378 if(insn.wordCount() > 6)
1379 {
1380 source->source = shader->getString(insn.word(6));
Ben Clayton534d0152020-04-03 13:03:40 +01001381 auto file = dbg->ctx->lock().createVirtualFile(source->file.c_str(), source->source.c_str());
1382 source->dbgFile = file;
1383 files.emplace(source->file.c_str(), file);
Ben Clayton2cb1db02020-01-15 18:38:25 +00001384 }
Ben Clayton534d0152020-04-03 13:03:40 +01001385 else
1386 {
1387 auto file = dbg->ctx->lock().createPhysicalFile(source->file.c_str());
1388 source->dbgFile = file;
1389 files.emplace(source->file.c_str(), file);
1390 }
Ben Clayton2cb1db02020-01-15 18:38:25 +00001391 });
1392 break;
Ben Clayton041fa9e2020-03-12 11:56:44 +00001393
Ben Clayton041fa9e2020-03-12 11:56:44 +00001394 case OpenCLDebugInfo100DebugTypePointer:
1395 case OpenCLDebugInfo100DebugTypeQualifier:
Ben Clayton041fa9e2020-03-12 11:56:44 +00001396 case OpenCLDebugInfo100DebugTypedef:
1397 case OpenCLDebugInfo100DebugTypeEnum:
1398 case OpenCLDebugInfo100DebugTypeInheritance:
1399 case OpenCLDebugInfo100DebugTypePtrToMember:
Ben Clayton041fa9e2020-03-12 11:56:44 +00001400 case OpenCLDebugInfo100DebugTypeTemplateTemplateParameter:
1401 case OpenCLDebugInfo100DebugTypeTemplateParameterPack:
Ben Clayton041fa9e2020-03-12 11:56:44 +00001402 case OpenCLDebugInfo100DebugFunctionDeclaration:
1403 case OpenCLDebugInfo100DebugLexicalBlockDiscriminator:
1404 case OpenCLDebugInfo100DebugInlinedVariable:
1405 case OpenCLDebugInfo100DebugOperation:
1406 case OpenCLDebugInfo100DebugMacroDef:
1407 case OpenCLDebugInfo100DebugMacroUndef:
1408 case OpenCLDebugInfo100DebugImportedEntity:
1409 UNIMPLEMENTED("b/148401179 OpenCLDebugInfo100 instruction %d", int(extInstIndex));
1410 break;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001411 default:
Ben Clayton041fa9e2020-03-12 11:56:44 +00001412 UNSUPPORTED("OpenCLDebugInfo100 instruction %d", int(extInstIndex));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001413 }
1414}
1415
Ben Clayton694e2142020-04-30 16:46:53 +01001416void SpirvShader::Impl::Debugger::setNextSetLocationIsStep()
1417{
1418 nextSetLocationIsStep = true;
1419}
1420
Ben Clayton3a50a432020-03-13 18:13:42 +00001421void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::shared_ptr<vk::dbg::File> &file, int line, int column)
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001422{
Ben Clayton694e2142020-04-30 16:46:53 +01001423 if(line != lastSetLocationLine)
1424 {
1425 // If the line number has changed, then this is always a step.
1426 nextSetLocationIsStep = true;
1427 lastSetLocationLine = line;
1428 }
1429 rr::Call(&State::updateLocation, state->routine->dbgState, nextSetLocationIsStep, file->id, line, column);
1430 nextSetLocationIsStep = false;
Ben Clayton3a50a432020-03-13 18:13:42 +00001431}
1432
1433void SpirvShader::Impl::Debugger::setLocation(EmitState *state, const std::string &path, int line, int column)
1434{
1435 auto it = files.find(path);
1436 if(it != files.end())
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001437 {
Ben Clayton3a50a432020-03-13 18:13:42 +00001438 setLocation(state, it->second, line, column);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001439 }
1440}
1441
Ben Clayton3011de52020-06-09 12:13:42 +01001442template<typename ID>
1443void SpirvShader::Impl::Debugger::add(ID id, std::unique_ptr<debug::Object> &&obj)
Ben Clayton2cb1db02020-01-15 18:38:25 +00001444{
Ben Claytonda384012020-03-12 12:45:02 +00001445 ASSERT_MSG(obj != nullptr, "add() called with nullptr obj");
Ben Clayton3011de52020-06-09 12:13:42 +01001446 bool added = objects.emplace(debug::Object::ID(id.value()), std::move(obj)).second;
Ben Claytonda384012020-03-12 12:45:02 +00001447 ASSERT_MSG(added, "Debug object with %d already exists", id.value());
1448}
1449
1450void SpirvShader::Impl::Debugger::addNone(debug::Object::ID id)
1451{
1452 bool added = objects.emplace(debug::Object::ID(id.value()), nullptr).second;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001453 ASSERT_MSG(added, "Debug object with %d already exists", id.value());
1454}
1455
Ben Clayton248ef6f2020-05-27 09:54:06 +01001456bool SpirvShader::Impl::Debugger::isNone(debug::Object::ID id) const
1457{
1458 auto it = objects.find(debug::Object::ID(id.value()));
1459 if(it == objects.end()) { return false; }
1460 return it->second.get() == nullptr;
1461}
1462
Ben Clayton2cb1db02020-01-15 18:38:25 +00001463template<typename T>
1464T *SpirvShader::Impl::Debugger::get(SpirvID<T> id) const
1465{
1466 auto it = objects.find(debug::Object::ID(id.value()));
1467 ASSERT_MSG(it != objects.end(), "Unknown debug object %d", id.value());
1468 auto ptr = debug::cast<T>(it->second.get());
Ben Clayton2fecfc52020-03-12 12:46:00 +00001469 ASSERT_MSG(ptr, "Debug object %d is not of the correct type. Got: %s, want: %s",
1470 id.value(), cstr(it->second->kind), cstr(T::KIND));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001471 return ptr;
1472}
1473
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001474template<typename Key>
1475void SpirvShader::Impl::Debugger::exposeVariable(
1476 const SpirvShader *shader,
1477 const Key &key,
Ben Clayton2cb1db02020-01-15 18:38:25 +00001478 const debug::Scope *scope,
1479 const debug::Type *type,
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001480 Object::ID id,
1481 EmitState *state) const
1482{
1483 auto dbgState = state->routine->dbgState;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001484 auto hover = Group::hovers(dbgState, scope).group<Key>(key);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001485 for(int lane = 0; lane < SIMD::Width; lane++)
1486 {
Ben Clayton2cb1db02020-01-15 18:38:25 +00001487 exposeVariable(shader, Group::localsLane(dbgState, scope, lane), lane, key, type, id, state);
1488 exposeVariable(shader, hover, lane, laneNames[lane], type, id, state);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001489 }
1490}
1491
1492template<typename Key>
1493void SpirvShader::Impl::Debugger::exposeVariable(
1494 const SpirvShader *shader,
1495 const Group &group,
Ben Clayton907433b2020-06-01 13:52:07 +01001496 int lane,
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001497 const Key &key,
Ben Clayton2cb1db02020-01-15 18:38:25 +00001498 const debug::Type *type,
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001499 Object::ID id,
1500 EmitState *state,
1501 int wordOffset /* = 0 */) const
1502{
Nicolas Capens2f4b6032020-04-09 02:01:50 -04001503 auto &obj = shader->getObject(id);
1504
Ben Clayton2cb1db02020-01-15 18:38:25 +00001505 if(type != nullptr)
1506 {
Ben Clayton907433b2020-06-01 13:52:07 +01001507 switch(obj.kind)
Ben Clayton2cb1db02020-01-15 18:38:25 +00001508 {
Ben Clayton907433b2020-06-01 13:52:07 +01001509 case Object::Kind::InterfaceVariable:
1510 case Object::Kind::Pointer:
1511 case Object::Kind::DescriptorSet:
Ben Clayton2cb1db02020-01-15 18:38:25 +00001512 {
Ben Clayton907433b2020-06-01 13:52:07 +01001513 ASSERT(wordOffset == 0); // TODO.
1514 auto ptr = shader->GetPointerToData(id, 0, state); // + sizeof(uint32_t) * wordOffset;
1515 auto &ptrTy = shader->getType(obj);
1516 auto interleaved = IsStorageInterleavedByLane(ptrTy.storageClass);
1517 if(interleaved)
Ben Clayton2cb1db02020-01-15 18:38:25 +00001518 {
Ben Clayton907433b2020-06-01 13:52:07 +01001519 ptr = InterleaveByLane(ptr);
Ben Clayton2cb1db02020-01-15 18:38:25 +00001520 }
Ben Clayton907433b2020-06-01 13:52:07 +01001521 auto addr = &ptr.base[Extract(ptr.offsets(), lane)];
1522 group.putPtr<Key>(key, addr, interleaved, type);
1523 }
1524 break;
1525
1526 case Object::Kind::Constant:
1527 case Object::Kind::Intermediate:
1528 {
1529 if(auto ty = debug::cast<debug::BasicType>(type))
Ben Clayton2cb1db02020-01-15 18:38:25 +00001530 {
Nicolas Capense6f65d92020-04-08 21:55:43 -04001531 auto val = Operand(shader, state, id).Int(wordOffset);
Ben Clayton2cb1db02020-01-15 18:38:25 +00001532 switch(ty->encoding)
1533 {
1534 case OpenCLDebugInfo100Address:
1535 // TODO: This function takes a SIMD vector, and pointers cannot
1536 // be held in them.
1537 break;
1538 case OpenCLDebugInfo100Boolean:
Ben Clayton907433b2020-06-01 13:52:07 +01001539 group.put<Key, bool>(key, Extract(val, lane) != 0);
Ben Clayton2cb1db02020-01-15 18:38:25 +00001540 break;
1541 case OpenCLDebugInfo100Float:
Ben Clayton907433b2020-06-01 13:52:07 +01001542 group.put<Key, float>(key, Extract(As<SIMD::Float>(val), lane));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001543 break;
1544 case OpenCLDebugInfo100Signed:
Ben Clayton907433b2020-06-01 13:52:07 +01001545 group.put<Key, int>(key, Extract(val, lane));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001546 break;
1547 case OpenCLDebugInfo100SignedChar:
Ben Clayton907433b2020-06-01 13:52:07 +01001548 group.put<Key, int8_t>(key, SByte(Extract(val, lane)));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001549 break;
1550 case OpenCLDebugInfo100Unsigned:
Ben Clayton907433b2020-06-01 13:52:07 +01001551 group.put<Key, unsigned int>(key, Extract(val, lane));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001552 break;
1553 case OpenCLDebugInfo100UnsignedChar:
Ben Clayton907433b2020-06-01 13:52:07 +01001554 group.put<Key, uint8_t>(key, Byte(Extract(val, lane)));
Ben Clayton2cb1db02020-01-15 18:38:25 +00001555 break;
1556 default:
1557 break;
1558 }
1559 }
Ben Clayton907433b2020-06-01 13:52:07 +01001560 else if(auto ty = debug::cast<debug::VectorType>(type))
1561 {
1562 auto elWords = 1; // Currently vector elements must only be basic types, 32-bit wide
1563 auto elTy = ty->base;
1564 auto vecGroup = group.group<Key>(key);
1565 switch(ty->components)
Ben Clayton2cb1db02020-01-15 18:38:25 +00001566 {
Ben Clayton907433b2020-06-01 13:52:07 +01001567 case 1:
1568 exposeVariable(shader, vecGroup, lane, "x", elTy, id, state, wordOffset + 0 * elWords);
1569 break;
1570 case 2:
1571 exposeVariable(shader, vecGroup, lane, "x", elTy, id, state, wordOffset + 0 * elWords);
1572 exposeVariable(shader, vecGroup, lane, "y", elTy, id, state, wordOffset + 1 * elWords);
1573 break;
1574 case 3:
1575 exposeVariable(shader, vecGroup, lane, "x", elTy, id, state, wordOffset + 0 * elWords);
1576 exposeVariable(shader, vecGroup, lane, "y", elTy, id, state, wordOffset + 1 * elWords);
1577 exposeVariable(shader, vecGroup, lane, "z", elTy, id, state, wordOffset + 2 * elWords);
1578 break;
1579 case 4:
1580 exposeVariable(shader, vecGroup, lane, "x", elTy, id, state, wordOffset + 0 * elWords);
1581 exposeVariable(shader, vecGroup, lane, "y", elTy, id, state, wordOffset + 1 * elWords);
1582 exposeVariable(shader, vecGroup, lane, "z", elTy, id, state, wordOffset + 2 * elWords);
1583 exposeVariable(shader, vecGroup, lane, "w", elTy, id, state, wordOffset + 3 * elWords);
1584 break;
1585 default:
1586 for(uint32_t i = 0; i < ty->components; i++)
1587 {
1588 exposeVariable(shader, vecGroup, lane, tostring(i).c_str(), elTy, id, state, wordOffset + i * elWords);
1589 }
1590 break;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001591 }
Ben Clayton907433b2020-06-01 13:52:07 +01001592 }
1593 else if(auto ty = debug::cast<debug::CompositeType>(type))
1594 {
1595 auto objectGroup = group.group<Key>(key);
Ben Clayton2cb1db02020-01-15 18:38:25 +00001596
Ben Clayton907433b2020-06-01 13:52:07 +01001597 for(auto member : ty->members)
1598 {
1599 exposeVariable(shader, objectGroup, lane, member->name.c_str(), member->type, id, state, member->offset / 32);
1600 }
1601 }
1602 else if(auto ty = debug::cast<debug::ArrayType>(type))
1603 {
1604 ty->build(
1605 group.group<Key>(key),
1606 [&](Debugger::Group &parent, uint32_t idx) {
1607 return parent.template group<int>(idx);
1608 },
1609 [&](Debugger::Group &parent, uint32_t idx, uint32_t offset) {
1610 exposeVariable(shader, parent, lane, idx, ty->base, id, state, offset);
1611 });
1612 }
1613 else
1614 {
1615 UNIMPLEMENTED("b/145351270: Debug type: %s", cstr(type->kind));
1616 }
1617 return;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001618 }
Ben Clayton907433b2020-06-01 13:52:07 +01001619 break;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001620
Ben Clayton907433b2020-06-01 13:52:07 +01001621 case Object::Kind::Unknown:
1622 UNIMPLEMENTED("b/145351270: Object kind: %d", (int)obj.kind);
Ben Clayton2cb1db02020-01-15 18:38:25 +00001623 }
Ben Clayton907433b2020-06-01 13:52:07 +01001624 return;
Ben Clayton2cb1db02020-01-15 18:38:25 +00001625 }
1626
1627 // No debug type information. Derive from SPIR-V.
Nicolas Capens2f4b6032020-04-09 02:01:50 -04001628 switch(shader->getType(obj).opcode())
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001629 {
1630 case spv::OpTypeInt:
1631 {
Ben Claytonea663202020-04-17 13:07:46 +01001632 Operand val(shader, state, id);
Ben Clayton907433b2020-06-01 13:52:07 +01001633 group.put<Key, int>(key, Extract(val.Int(0), lane));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001634 }
1635 break;
1636 case spv::OpTypeFloat:
1637 {
Ben Claytonea663202020-04-17 13:07:46 +01001638 Operand val(shader, state, id);
Ben Clayton907433b2020-06-01 13:52:07 +01001639 group.put<Key, float>(key, Extract(val.Float(0), lane));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001640 }
1641 break;
1642 case spv::OpTypeVector:
1643 {
Ben Claytonea663202020-04-17 13:07:46 +01001644 Operand val(shader, state, id);
Nicolas Capens2f4b6032020-04-09 02:01:50 -04001645 auto count = shader->getType(obj).definition.word(3);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001646 switch(count)
1647 {
1648 case 1:
Ben Clayton907433b2020-06-01 13:52:07 +01001649 group.put<Key, float>(key, Extract(val.Float(0), lane));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001650 break;
1651 case 2:
Ben Clayton907433b2020-06-01 13:52:07 +01001652 group.put<Key, float>(key, Extract(val.Float(0), lane), Extract(val.Float(1), lane));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001653 break;
1654 case 3:
Ben Clayton907433b2020-06-01 13:52:07 +01001655 group.put<Key, float>(key, Extract(val.Float(0), lane), Extract(val.Float(1), lane), Extract(val.Float(2), lane));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001656 break;
1657 case 4:
Ben Clayton907433b2020-06-01 13:52:07 +01001658 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));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001659 break;
1660 default:
1661 {
1662 auto vec = group.group<Key>(key);
1663 for(uint32_t i = 0; i < count; i++)
1664 {
Ben Clayton907433b2020-06-01 13:52:07 +01001665 vec.template put<int, float>(i, Extract(val.Float(i), lane));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001666 }
1667 }
1668 break;
1669 }
1670 }
1671 break;
1672 case spv::OpTypePointer:
1673 {
Nicolas Capens72f089c2020-04-08 23:37:08 -04001674 auto objectTy = shader->getType(shader->getObject(id));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001675 bool interleavedByLane = IsStorageInterleavedByLane(objectTy.storageClass);
1676 auto ptr = state->getPointer(id);
1677 auto ptrGroup = group.group<Key>(key);
1678 shader->VisitMemoryObject(id, [&](const MemoryElement &el) {
1679 auto p = ptr + el.offset;
1680 if(interleavedByLane) { p = InterleaveByLane(p); } // TODO: Interleave once, then add offset?
1681 auto simd = p.Load<SIMD::Float>(sw::OutOfBoundsBehavior::Nullify, state->activeLaneMask());
Ben Clayton907433b2020-06-01 13:52:07 +01001682 ptrGroup.template put<int, float>(el.index, Extract(simd, lane));
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001683 });
1684 }
1685 break;
1686 default:
1687 break;
1688 }
1689}
1690
1691////////////////////////////////////////////////////////////////////////////////
1692// sw::SpirvShader
1693////////////////////////////////////////////////////////////////////////////////
1694void SpirvShader::dbgInit(const std::shared_ptr<vk::dbg::Context> &dbgctx)
1695{
1696 impl.debugger = new Impl::Debugger();
1697 impl.debugger->ctx = dbgctx;
1698}
1699
1700void SpirvShader::dbgTerm()
1701{
1702 if(impl.debugger)
1703 {
1704 delete impl.debugger;
1705 }
1706}
1707
1708void SpirvShader::dbgCreateFile()
1709{
1710 auto dbg = impl.debugger;
1711 if(!dbg) { return; }
1712
1713 int currentLine = 1;
1714 std::string source;
1715 for(auto insn : *this)
1716 {
1717 auto instruction = spvtools::spvInstructionBinaryToText(
1718 SPV_ENV_VULKAN_1_1,
1719 insn.wordPointer(0),
1720 insn.wordCount(),
1721 insns.data(),
1722 insns.size(),
1723 SPV_BINARY_TO_TEXT_OPTION_NO_HEADER) +
1724 "\n";
1725 dbg->spirvLineMappings[insn.wordPointer(0)] = currentLine;
1726 currentLine += std::count(instruction.begin(), instruction.end(), '\n');
1727 source += instruction;
1728 }
1729 std::string name;
1730 switch(executionModel)
1731 {
1732 case spv::ExecutionModelVertex: name = "VertexShader"; break;
1733 case spv::ExecutionModelFragment: name = "FragmentShader"; break;
1734 case spv::ExecutionModelGLCompute: name = "ComputeShader"; break;
1735 default: name = "SPIR-V Shader"; break;
1736 }
1737 static std::atomic<int> id = { 0 };
Ben Clayton907433b2020-06-01 13:52:07 +01001738 name += tostring(id++) + ".spvasm";
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001739 dbg->spirvFile = dbg->ctx->lock().createVirtualFile(name.c_str(), source.c_str());
1740}
1741
1742void SpirvShader::dbgBeginEmit(EmitState *state) const
1743{
1744 auto dbg = impl.debugger;
1745 if(!dbg) { return; }
1746
1747 using Group = Impl::Debugger::Group;
1748
1749 auto routine = state->routine;
1750
1751 auto type = "SPIR-V";
1752 switch(executionModel)
1753 {
1754 case spv::ExecutionModelVertex: type = "VertexShader"; break;
1755 case spv::ExecutionModelFragment: type = "FragmentShader"; break;
1756 case spv::ExecutionModelGLCompute: type = "ComputeShader"; break;
1757 default: type = "SPIR-V Shader"; break;
1758 }
1759 auto dbgState = rr::Call(&Impl::Debugger::State::create, dbg, type);
1760
1761 routine->dbgState = dbgState;
1762
1763 SetActiveLaneMask(state->activeLaneMask(), state);
1764
Ben Clayton7a53cb62020-01-27 21:40:18 +00001765 for(int i = 0; i < SIMD::Width; i++)
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001766 {
Ben Claytonafb18672020-05-27 10:35:51 +01001767 auto globals = Group::globals(dbgState, i);
1768 globals.put<const char *, int>("subgroupSize", routine->invocationsPerSubgroup);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001769
Ben Clayton7a53cb62020-01-27 21:40:18 +00001770 switch(executionModel)
1771 {
1772 case spv::ExecutionModelGLCompute:
Ben Claytonafb18672020-05-27 10:35:51 +01001773 globals.putVec3<const char *, int>("numWorkgroups", routine->numWorkgroups);
1774 globals.putVec3<const char *, int>("workgroupID", routine->workgroupID);
1775 globals.putVec3<const char *, int>("workgroupSize", routine->workgroupSize);
1776 globals.put<const char *, int>("numSubgroups", routine->subgroupsPerWorkgroup);
1777 globals.put<const char *, int>("subgroupIndex", routine->subgroupIndex);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001778
Ben Claytonafb18672020-05-27 10:35:51 +01001779 globals.put<const char *, int>("globalInvocationId",
1780 rr::Extract(routine->globalInvocationID[0], i),
1781 rr::Extract(routine->globalInvocationID[1], i),
1782 rr::Extract(routine->globalInvocationID[2], i));
1783 globals.put<const char *, int>("localInvocationId",
1784 rr::Extract(routine->localInvocationID[0], i),
1785 rr::Extract(routine->localInvocationID[1], i),
1786 rr::Extract(routine->localInvocationID[2], i));
1787 globals.put<const char *, int>("localInvocationIndex", rr::Extract(routine->localInvocationIndex, i));
Ben Clayton7a53cb62020-01-27 21:40:18 +00001788 break;
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001789
Ben Clayton7a53cb62020-01-27 21:40:18 +00001790 case spv::ExecutionModelFragment:
Ben Claytonafb18672020-05-27 10:35:51 +01001791 globals.put<const char *, int>("viewIndex", routine->viewID);
1792 globals.put<const char *, float>("fragCoord",
1793 rr::Extract(routine->fragCoord[0], i),
1794 rr::Extract(routine->fragCoord[1], i),
1795 rr::Extract(routine->fragCoord[2], i),
1796 rr::Extract(routine->fragCoord[3], i));
1797 globals.put<const char *, float>("pointCoord",
1798 rr::Extract(routine->pointCoord[0], i),
1799 rr::Extract(routine->pointCoord[1], i));
1800 globals.put<const char *, int>("windowSpacePosition",
1801 rr::Extract(routine->windowSpacePosition[0], i),
1802 rr::Extract(routine->windowSpacePosition[1], i));
1803 globals.put<const char *, int>("helperInvocation", rr::Extract(routine->helperInvocation, i));
Ben Clayton7a53cb62020-01-27 21:40:18 +00001804 break;
1805
1806 case spv::ExecutionModelVertex:
Ben Claytonafb18672020-05-27 10:35:51 +01001807 globals.put<const char *, int>("viewIndex", routine->viewID);
1808 globals.put<const char *, int>("instanceIndex", routine->instanceID);
1809 globals.put<const char *, int>("vertexIndex",
1810 rr::Extract(routine->vertexIndex, i));
Ben Clayton7a53cb62020-01-27 21:40:18 +00001811 break;
1812
1813 default:
1814 break;
1815 }
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001816 }
1817}
1818
1819void SpirvShader::dbgEndEmit(EmitState *state) const
1820{
1821 auto dbg = impl.debugger;
1822 if(!dbg) { return; }
1823
1824 rr::Call(&Impl::Debugger::State::destroy, state->routine->dbgState);
1825}
1826
1827void SpirvShader::dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) const
1828{
Ben Claytonb3805902020-01-13 17:00:15 +00001829# if PRINT_EACH_PROCESSED_INSTRUCTION
Ben Claytonb8bae182020-03-12 14:19:27 +00001830 {
1831 auto instruction = spvtools::spvInstructionBinaryToText(
1832 SPV_ENV_VULKAN_1_1,
1833 insn.wordPointer(0),
1834 insn.wordCount(),
1835 insns.data(),
1836 insns.size(),
1837 SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
1838 printf("%s\n", instruction.c_str());
1839 }
Ben Claytonb3805902020-01-13 17:00:15 +00001840# endif // PRINT_EACH_PROCESSED_INSTRUCTION
1841
Ben Claytonb8bae182020-03-12 14:19:27 +00001842# if PRINT_EACH_EXECUTED_INSTRUCTION
1843 {
1844 auto instruction = spvtools::spvInstructionBinaryToText(
1845 SPV_ENV_VULKAN_1_1,
1846 insn.wordPointer(0),
1847 insn.wordCount(),
1848 insns.data(),
1849 insns.size(),
1850 SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
1851 rr::Print("{0}\n", instruction);
1852 }
1853# endif // PRINT_EACH_EXECUTED_INSTRUCTION
1854
Ben Clayton3a50a432020-03-13 18:13:42 +00001855 // Only single line step over statement instructions.
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001856
Ben Clayton3a50a432020-03-13 18:13:42 +00001857 if(auto dbg = impl.debugger)
1858 {
Ben Clayton694e2142020-04-30 16:46:53 +01001859 if(insn.opcode() == spv::OpLabel)
1860 {
1861 // Whenever we hit a label, force the next OpLine to be steppable.
1862 // This handles the case where we have control flow on the same line
1863 // For example:
1864 // while(true) { foo(); }
1865 // foo() should be repeatedly steppable.
1866 dbg->setNextSetLocationIsStep();
1867 }
1868
Ben Clayton3a50a432020-03-13 18:13:42 +00001869 if(extensionsImported.count(Extension::OpenCLDebugInfo100) == 0)
1870 {
1871 // We're emitting debugger logic for SPIR-V.
1872 if(IsStatement(insn.opcode()))
1873 {
1874 auto line = dbg->spirvLineMappings.at(insn.wordPointer(0));
1875 auto column = 0;
1876 dbg->setLocation(state, dbg->spirvFile, line, column);
1877 }
Ben Clayton54d16b82020-02-03 15:32:06 +00001878 }
Ben Clayton2cb1db02020-01-15 18:38:25 +00001879 }
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001880}
1881
1882void SpirvShader::dbgEndEmitInstruction(InsnIterator insn, EmitState *state) const
1883{
1884 auto dbg = impl.debugger;
1885 if(!dbg) { return; }
1886
Ben Claytonfbb12e12020-05-27 09:49:28 +01001887 // Don't display SSA values if rich debug info is available
1888 if(extensionsImported.count(Extension::OpenCLDebugInfo100) == 0)
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001889 {
Ben Claytonfbb12e12020-05-27 09:49:28 +01001890 // We're emitting debugger logic for SPIR-V.
1891 // Does this instruction emit a result that should be exposed to the
1892 // debugger?
1893 auto resIt = dbg->results.find(insn.wordPointer(0));
1894 if(resIt != dbg->results.end())
1895 {
1896 auto id = resIt->second;
1897 dbgExposeIntermediate(id, state);
1898 }
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001899 }
1900}
1901
1902void SpirvShader::dbgExposeIntermediate(Object::ID id, EmitState *state) const
1903{
1904 auto dbg = impl.debugger;
1905 if(!dbg) { return; }
1906
Ben Claytonafb18672020-05-27 10:35:51 +01001907 dbg->exposeVariable(this, id, &debug::Scope::Global, nullptr, id, state);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001908}
1909
1910void SpirvShader::dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask, EmitState *state) const
1911{
1912 auto dbg = impl.debugger;
1913 if(!dbg) { return; }
1914
1915 for(int lane = 0; lane < SIMD::Width; lane++)
1916 {
1917 rr::Call(&Impl::Debugger::State::updateActiveLaneMask, state->routine->dbgState, lane, rr::Extract(mask, lane) != 0);
1918 }
1919}
1920
1921void SpirvShader::dbgDeclareResult(const InsnIterator &insn, Object::ID resultId) const
1922{
1923 auto dbg = impl.debugger;
1924 if(!dbg) { return; }
1925
1926 dbg->results.emplace(insn.wordPointer(0), resultId);
1927}
1928
1929SpirvShader::EmitResult SpirvShader::EmitLine(InsnIterator insn, EmitState *state) const
1930{
1931 if(auto dbg = impl.debugger)
1932 {
1933 auto path = getString(insn.word(1));
1934 auto line = insn.word(2);
1935 auto column = insn.word(3);
Ben Clayton3a50a432020-03-13 18:13:42 +00001936 dbg->setLocation(state, path, line, column);
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001937 }
1938 return EmitResult::Continue;
1939}
1940
Ben Claytoncd55f052020-01-14 11:56:00 +00001941void SpirvShader::DefineOpenCLDebugInfo100(const InsnIterator &insn)
1942{
Ben Clayton2cb1db02020-01-15 18:38:25 +00001943 auto dbg = impl.debugger;
1944 if(!dbg) { return; }
1945
1946 dbg->process(this, insn, nullptr, Impl::Debugger::Pass::Define);
Ben Claytoncd55f052020-01-14 11:56:00 +00001947}
1948
1949SpirvShader::EmitResult SpirvShader::EmitOpenCLDebugInfo100(InsnIterator insn, EmitState *state) const
1950{
Ben Clayton2cb1db02020-01-15 18:38:25 +00001951 if(auto dbg = impl.debugger)
1952 {
1953 dbg->process(this, insn, state, Impl::Debugger::Pass::Emit);
1954 }
Ben Claytoncd55f052020-01-14 11:56:00 +00001955 return EmitResult::Continue;
1956}
1957
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001958} // namespace sw
1959
1960#else // ENABLE_VK_DEBUGGER
1961
1962// Stub implementations of the dbgXXX functions.
1963namespace sw {
1964
1965void SpirvShader::dbgInit(const std::shared_ptr<vk::dbg::Context> &dbgctx) {}
1966void SpirvShader::dbgTerm() {}
1967void SpirvShader::dbgCreateFile() {}
1968void SpirvShader::dbgBeginEmit(EmitState *state) const {}
1969void SpirvShader::dbgEndEmit(EmitState *state) const {}
1970void SpirvShader::dbgBeginEmitInstruction(InsnIterator insn, EmitState *state) const {}
1971void SpirvShader::dbgEndEmitInstruction(InsnIterator insn, EmitState *state) const {}
1972void SpirvShader::dbgExposeIntermediate(Object::ID id, EmitState *state) const {}
1973void SpirvShader::dbgUpdateActiveLaneMask(RValue<SIMD::Int> mask, EmitState *state) const {}
1974void SpirvShader::dbgDeclareResult(const InsnIterator &insn, Object::ID resultId) const {}
1975
Ben Claytoncd55f052020-01-14 11:56:00 +00001976void SpirvShader::DefineOpenCLDebugInfo100(const InsnIterator &insn) {}
1977
1978SpirvShader::EmitResult SpirvShader::EmitOpenCLDebugInfo100(InsnIterator insn, EmitState *state) const
1979{
1980 return EmitResult::Continue;
1981}
1982
Ben Claytonb0ca2a82020-01-08 13:00:57 +00001983SpirvShader::EmitResult SpirvShader::EmitLine(InsnIterator insn, EmitState *state) const
1984{
1985 return EmitResult::Continue;
1986}
1987
1988} // namespace sw
1989
1990#endif // ENABLE_VK_DEBUGGER