1 // Copyright 2020 The Amber Authors. 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 #ifndef SRC_DEBUG_H_ 16 #define SRC_DEBUG_H_ 17 18 #include <stdint.h> 19 20 #include <functional> 21 #include <memory> 22 #include <string> 23 #include <vector> 24 25 #include "amber/result.h" 26 27 /// amber::debug holds the types used for testing a graphics debugger. 28 namespace amber { 29 namespace debug { 30 31 // Forward declaration. 32 class ThreadScript; 33 34 /// Location holds a file path and a 1-based line number. 35 struct Location { 36 std::string file; // empty represents unspecified. 37 uint32_t line = 0; // 0 represents unspecified. 38 }; 39 40 // StackFrame holds name and location of a stack frame. 41 struct StackFrame { 42 std::string name; 43 Location location; 44 }; 45 46 /// Thread is the interface used to control a single debugger thread of 47 /// execution. 48 class Thread { 49 public: 50 virtual ~Thread(); 51 52 /// StepOver instructs the debugger to perform a single line step on the given 53 /// thread of execution, stepping over any function call instructions. 54 virtual void StepOver() = 0; 55 56 /// StepIn instructs the debugger to perform a single line step on the given 57 /// thread of execution, stepping into any function call instructions. 58 virtual void StepIn() = 0; 59 60 /// StepOut instructs the debugger to resume execution of the given thread of 61 /// execution. If the current function is not the top most of the call stack, 62 /// then the debugger will pause at the next line after the call to the 63 /// current function. 64 virtual void StepOut() = 0; 65 66 /// Continue instructs the debugger to resume execution of the given thread of 67 /// execution. 68 virtual void Continue() = 0; 69 70 /// ExpectLocation verifies that the debugger is currently suspended for the 71 /// given thread of execution at the specified source location. If |line| is 72 /// non-empty, then the line's textual source will also be verified. 73 virtual void ExpectLocation(const Location& location, 74 const std::string& line) = 0; 75 76 /// ExpectCallstack verifies that the debugger is currently suspended for the 77 /// given thread of execution with the specified callstack. 78 /// callstack is ordered with the 0th element representing the most nested 79 /// call. 80 virtual void ExpectCallstack(const std::vector<StackFrame>& callstack) = 0; 81 82 /// ExpectLocal verifies that the local variable with the given name has the 83 /// expected value. |name| may contain `.` delimiters to index structure or 84 /// array types. 85 virtual void ExpectLocal(const std::string& name, int64_t value) = 0; 86 virtual void ExpectLocal(const std::string& name, double value) = 0; 87 virtual void ExpectLocal(const std::string& name, 88 const std::string& value) = 0; 89 }; 90 91 /// Events is the interface used to control the debugger. 92 class Events { 93 public: 94 virtual ~Events(); 95 96 /// BreakOnComputeGlobalInvocation instructs the debugger to set a breakpoint 97 /// at the start of the compute shader program for the invocation with the 98 /// global invocation identifier [|x|, |y|, |z|], and run the |ThreadScript| 99 /// once the breakpoint is hit. 100 virtual void BreakOnComputeGlobalInvocation( 101 uint32_t x, 102 uint32_t y, 103 uint32_t z, 104 const std::shared_ptr<const ThreadScript>&) = 0; 105 106 /// BreakOnVertexIndex instructs the debugger to set a breakpoint at the start 107 /// of the vertex shader program for the invocation with the vertex index 108 /// |index|, and run the |ThreadScript| once the breakpoint is hit. 109 virtual void BreakOnVertexIndex( 110 uint32_t index, 111 const std::shared_ptr<const ThreadScript>&) = 0; 112 113 /// BreakOnFragmentWindowSpacePosition instructs the debugger to set a 114 /// breakpoint at the start of the fragment shader program for the invocation 115 /// with the window space coordinate [x, y], and run the |ThreadScript| once 116 /// the breakpoint is hit. 117 virtual void BreakOnFragmentWindowSpacePosition( 118 uint32_t x, 119 uint32_t y, 120 const std::shared_ptr<const ThreadScript>&) = 0; 121 }; 122 123 /// ThreadScript is a specialization of the |amber::debug::Thread| interface, 124 /// and is used to record all the calls made on it, which can be later replayed 125 /// with |ThreadScript::Run|. 126 class ThreadScript : public Thread { 127 public: 128 ~ThreadScript() override; 129 130 /// Run replays all the calls made to the |ThreadScript| on the given |Thread| 131 /// parameter. 132 virtual void Run(Thread*) const = 0; 133 134 // Create constructs and returns a new ThreadScript. 135 static std::shared_ptr<ThreadScript> Create(); 136 }; 137 138 /// Script is an specialization of the |amber::debug::Events| interface, and is 139 /// used to record all the calls made on it, which can be later replayed with 140 /// |Script::Run|. 141 class Script : public Events { 142 public: 143 ~Script() override; 144 145 /// Run replays all the calls made to the |Script| on the given |Events| 146 /// parameter. 147 virtual void Run(Events*) const = 0; 148 149 // Create constructs and returns a new Script. 150 static std::unique_ptr<Script> Create(); 151 }; 152 153 } // namespace debug 154 } // namespace amber 155 156 #endif // SRC_DEBUG_H_ 157