Skip to content

Commit 8272f07

Browse files
committed
[Fixup] Restore upstream comment formatting and fflush(stdout) in LlvmRuntimeExecutor::synchronize
1 parent 4240699 commit 8272f07

5 files changed

Lines changed: 31 additions & 20 deletions

File tree

quadrants/program/program.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,10 @@ class QD_DLL_EXPORT Program {
202202
return snode_rw_accessors_bank_;
203203
}
204204

205-
// Resolve an `SNode *` from its global `SNode::id`. Lazy `snode_id_cache_` lookup; the cache is wiped by
206-
// `add_snode_tree` and `destroy_snode_tree`.
205+
// Look up an `SNode` in this `Program`'s snode trees by its global `SNode::id`. Used by the host-side adstack
206+
// size-expression evaluator to rehydrate an `SNode *` from a `snode_id` that survived the offline cache. Linear
207+
// over all snode trees; called at most once per adstack leaf per kernel launch so the cost is negligible in
208+
// practice.
207209
SNode *get_snode_by_id(int snode_id);
208210

209211
// One input read observed during a `evaluate_adstack_size_expr` walk. The cache entry records these so

quadrants/program/program_impl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,9 @@ class ProgramImpl {
143143
virtual void finalize() {
144144
}
145145

146-
// Invoked by `Program::finalize()` before any teardown sync, so the backend can flip state that
147-
// silences user-visible asserts during destructor unwinding.
146+
// Hook invoked by `Program::finalize()` before any teardown sync. Lets backends flip state (e.g. the LLVM
147+
// `finalizing_` flag used to suppress adstack-overflow polling) so the two `Program::synchronize()` calls that
148+
// precede `finalize()` do not throw into the Program destructor path.
148149
virtual void pre_finalize() {
149150
}
150151

quadrants/rhi/metal/metal_device.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,18 @@ struct MetalShaderBindingMapping {
175175
// Map GLSL binding to MSL index (buffer/texture index, sampler index)
176176
std::unordered_map<int, std::pair<int, int>> vertex;
177177
std::unordered_map<int, std::pair<int, int>> fragment;
178-
// The highest used buffer index used in the MSL vertex function Vertex attributes use up vertex buffer indices in
179-
// Metal, but SPIRV-cross generated MSL doesn't know how many buffer indices the vertex attributes will take. So bind
180-
// vertex input after the other buffers.
178+
// The highest used buffer index used in the MSL vertex function
179+
// Vertex attributes use up vertex buffer indices in Metal, but
180+
// SPIRV-cross generated MSL doesn't know how many buffer indices
181+
// the vertex attributes will take. So bind vertex input after the other
182+
// buffers.
181183
int max_vert_buffer_index{-1};
182184
};
183185

184186
class MetalPipeline final : public Pipeline, public rhi_impl::NonAssignable {
185187
public:
186-
// `mtl_library`, `mtl_function`, `mtl_compute_pipeline_state` should be already retained.
188+
// `mtl_library`, `mtl_function`, `mtl_compute_pipeline_state` should be
189+
// already retained.
187190
explicit MetalPipeline(const MetalDevice &device,
188191
MTLLibrary_id mtl_library,
189192
MTLFunction_id mtl_function,
@@ -379,7 +382,8 @@ class MetalCommandList final : public CommandList {
379382
void set_line_width(float width) override;
380383

381384
MTLCommandBuffer_id finalize();
382-
// If noclear is false, ignore whatever is set in details This may be used to "resume" the current renderpass
385+
// If noclear is false, ignore whatever is set in details
386+
// This may be used to "resume" the current renderpass
383387
MTLRenderPassDescriptor *create_render_pass_desc(bool depth_write, bool noclear = false);
384388

385389
bool is_renderpass_active() const;
@@ -405,12 +409,12 @@ class MetalCommandList final : public CommandList {
405409
std::vector<MTLTexture_id> render_targets_;
406410
MTLTexture_id depth_target_;
407411

408-
// Buffers accessed via physical storage buffer pointers in the next dispatch. Needed for Metal hazard tracking since
409-
// these are not explicitly bound.
412+
// Buffers accessed via physical storage buffer pointers in the next dispatch.
413+
// Needed for Metal hazard tracking since these are not explicitly bound.
410414
std::vector<DeviceAllocation> tracked_physical_buffers_;
411415

412-
// For renderpass resuming, track whether a renderpass has been started Used to override LoadAction, to prevent
413-
// uninteded clearing when resuming
416+
// For renderpass resuming, track whether a renderpass has been started
417+
// Used to override LoadAction, to prevent uninteded clearing when resuming
414418
bool is_renderpass_active_{false};
415419

416420
// Persistent compute command encoder reused across consecutive `dispatch()` calls so the GPU sees one

quadrants/runtime/llvm/llvm_runtime_executor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ void LlvmRuntimeExecutor::synchronize() {
207207
QD_ERROR("No AMDGPU support");
208208
#endif
209209
}
210+
fflush(stdout);
210211
}
211212

212213
uint64 LlvmRuntimeExecutor::fetch_result_uint64(int i, uint64 *result_buffer) {

quadrants/runtime/program_impls/llvm/llvm_program.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#pragma once
22

33
#include <cstddef>
4-
#include <cstdio>
54
#include <memory>
65

76
#include "quadrants/runtime/llvm/llvm_offline_cache.h"
@@ -100,8 +99,11 @@ class LlvmProgramImpl : public ProgramImpl {
10099
return runtime_exec_->fetch_result<T>(i, result_buffer);
101100
}
102101

103-
// Mark the impl as shutting down so `synchronize_and_assert()` skips the overflow poll, preventing a
104-
// `qd.sync()` racing with destruction from throwing inside `~Program()` unwinding.
102+
// Skip the adstack-overflow poll from this point on: `Program::finalize()` invokes `pre_finalize()` before the
103+
// two teardown `synchronize()` calls, and we do not want `check_adstack_overflow()` to throw into a
104+
// `~Program()` unwinding path - that would terminate the process with a bare `QuadrantsAssertionError` instead
105+
// of letting the user handle it at their own `qd.sync()` site. The flag only affects the internal poll; the
106+
// user can still call `qd.sync()` explicitly before finalize to observe the raise.
105107
void pre_finalize() override {
106108
finalizing_ = true;
107109
}
@@ -165,8 +167,6 @@ class LlvmProgramImpl : public ProgramImpl {
165167
if (!finalizing_) {
166168
runtime_exec_->check_adstack_overflow();
167169
}
168-
// Flush JIT-generated `qd.print()` output at every user-visible sync.
169-
fflush(stdout);
170170
}
171171

172172
LLVMRuntime *get_llvm_runtime() {
@@ -267,8 +267,11 @@ class LlvmProgramImpl : public ProgramImpl {
267267
std::size_t num_snode_trees_processed_{0};
268268
std::unique_ptr<LlvmRuntimeExecutor> runtime_exec_;
269269
std::unique_ptr<LlvmOfflineCache> cache_data_;
270-
// Set by `pre_finalize()` / `finalize()` so `synchronize_and_assert()` skips the overflow poll while
271-
// teardown is in progress.
270+
// Flipped on by `pre_finalize()` (with a defensive re-assignment in `finalize()`) so the `synchronize()`
271+
// override stops polling the adstack-overflow flag during teardown. `Program::finalize()` invokes
272+
// `pre_finalize()` before its two teardown syncs, so the flag is already true when those syncs run; moving
273+
// the assignment back into `finalize()` alone would silently re-introduce the `std::terminate()` teardown bug
274+
// this field was introduced to fix.
272275
bool finalizing_{false};
273276
};
274277

0 commit comments

Comments
 (0)