Skip to content

Commit 65d2958

Browse files
committed
Keep renderer self-tests within platform stack and capability limits
1 parent 9725828 commit 65d2958

7 files changed

Lines changed: 65 additions & 32 deletions

File tree

docs/dev/release-completion.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# openQ4 Release Completion List
22

3-
- [ ] Release CI exposed existing Apple GL 2.1 startup errors from unsupported texture swizzles, multisample textures, eager SMAA shader validation and GPU timestamp queries. Resource creation and direct texture binding now check the context's advertised capabilities, SMAA checks its backend before material compilation, and GPU timing distinguishes EXT elapsed queries from ARB/core timestamp support. The production timestamp capability regression passes on Windows and Linux. Awaiting the hosted macOS runtime rerun.
3+
- [x] Release CI exposed existing Apple GL 2.1 startup errors from unsupported texture swizzles, multisample textures, eager SMAA shader validation and GPU timestamp queries. Resource creation and direct texture binding now check the context's advertised capabilities, SMAA checks its backend before material compilation, and GPU timing distinguishes EXT elapsed queries from ARB/core timestamp support. The production timestamp capability regression passes on Windows and Linux; hosted macOS now has zero GL/shader/framebuffer errors and passes the default-renderer safety test.
4+
- [ ] Modern-renderer diagnostics exposed oversized simultaneous draw/submit/PBR fixtures on the macOS stack and unsupported-feature assumptions. The large fixtures now use heap storage, while unavailable PBR and clustered-light GPU paths produce explicit skip markers. Awaiting the complete hosted runtime matrix.
45

56
- [x] The 0.13.0 integration pass wires the new source contracts into local and CI validation, includes syntax checks for gameplay drivers, synchronizes the shared memory-file header, and pins both repositories' CI inputs. Windows build/staging, 12 native tests, all 54 competitive contracts and OpenGL/Vulkan chat gameplay checks pass. Stock `q4dm1` still logs missing AAS sizes, the optional `mp_buying_givecash` sound and non-precached declarations during these no-bot chat checks; those content diagnostics remain outside this release-tooling change.
67

docs/dev/releases/v0.13.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
- Fixed the manual macOS release audit so the exact bundled OpenAL Soft `@rpath` dependency is accepted only after its architecture, dependencies, signature, and install name pass validation.
7979
- Fixed publication of previously staged draft releases so validated downloads can go live and trigger their Discord announcement.
8080
- Prevented legacy OpenGL contexts from attempting unsupported SMAA shaders, texture swizzles, multisample textures, direct texture binding and GPU timestamp queries, retaining the available rendering paths.
81+
- Made renderer self-tests safer on macOS and explicit about optional features unavailable on the current OpenGL context.
8182
- Fixed SDL swap-interval updates after temporary context detachment, Linux save paths containing legitimate repeated dots, and case-insensitive package path collisions.
8283
- Restored `dmap` handling of `func_group` geometry, initialized geometry-tool surface allocation, and accepted generated AAS 1.08 face settings.
8384
- Added contributing and community-conduct documentation and packaged the relevant project guidance with releases.

src/renderer/ModernClusteredLighting.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4172,6 +4172,10 @@ bool RendererClusterGrid_RunSelfTest( void ) {
41724172
if ( !R_ModernClusteredLighting_RunProbeRecordSelfTest() ) {
41734173
return false;
41744174
}
4175+
if ( !rg_clusteredLightingAvailable ) {
4176+
common->Printf( "RendererClusterGrid self-test skipped: modern clustered lighting unavailable\n" );
4177+
return true;
4178+
}
41754179
if ( !r_rendererModernExecutor.GetBool() && r_rendererClusterDebug.GetInteger() <= 0 ) {
41764180
common->Printf( "RendererClusterGrid self-test passed (disabled)\n" );
41774181
return true;

src/renderer/ModernGLExecutor.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11124,7 +11124,7 @@ bool RendererGBuffer_RunSelfTest( void ) {
1112411124
bool RendererPBRVisible_RunSelfTest( void ) {
1112511125
const modernGLShaderLibraryStats_t &shaderStats = R_ModernGLShaderLibrary_Stats();
1112611126
if ( !shaderStats.available ) {
11127-
common->Printf( "RendererPBRVisible self-test passed (shader library unavailable)\n" );
11127+
common->Printf( "RendererPBRVisible self-test skipped: modern shader library unavailable\n" );
1112811128
return true;
1112911129
}
1113011130
const modernGLShaderProgramInfo_t *opaqueProgram = R_ModernGLShaderLibrary_FindProgram( MODERN_GL_SHADER_GBUFFER_OPAQUE, shaderStats.highestGLSLVersion );
@@ -11152,7 +11152,10 @@ bool RendererPBRVisible_RunSelfTest( void ) {
1115211152
r_rendererModernOpaque.SetBool( true );
1115311153
r_rendererForwardPlus.SetBool( false );
1115411154

11155-
idScenePacketFrame packetFrame;
11155+
// Packet, draw and submit arenas exceed the macOS main-thread stack when
11156+
// the two PBR fixtures are alive together. Keep their storage on the heap.
11157+
idAutoPtr<idScenePacketFrame> packetFrameStorage( new idScenePacketFrame );
11158+
idScenePacketFrame &packetFrame = *packetFrameStorage;
1115611159
idRenderGraph graph;
1115711160
rendererModernGLSelfTestSurfaceScene_t scene;
1115811161
const idMaterial *pbrMaterial = scene.InitPBROpaqueMaterial( "RendererPBRVisible" );
@@ -11174,9 +11177,11 @@ bool RendererPBRVisible_RunSelfTest( void ) {
1117411177
}
1117511178
r_rendererModernQuality.SetBool( true );
1117611179

11177-
idModernGLDrawPlan drawPlan;
11180+
idAutoPtr<idModernGLDrawPlan> drawPlanStorage( new idModernGLDrawPlan );
11181+
idModernGLDrawPlan &drawPlan = *drawPlanStorage;
1117811182
drawPlan.Build( packetFrame, graph );
11179-
idModernGLSubmitPlan submitPlan;
11183+
idAutoPtr<idModernGLSubmitPlan> submitPlanStorage( new idModernGLSubmitPlan );
11184+
idModernGLSubmitPlan &submitPlan = *submitPlanStorage;
1118011185
submitPlan.Build( drawPlan );
1118111186
const int expectedDraws = packetFrame.NumDrawPackets();
1118211187
if ( drawPlan.Stats().materialDraws != expectedDraws || submitPlan.Stats().materialReadyDraws != expectedDraws || submitPlan.NumCommands() != expectedDraws ) {
@@ -11208,7 +11213,8 @@ bool RendererPBRVisible_RunSelfTest( void ) {
1120811213
// two per-light interaction packets for each surface and prove that the
1120911214
// stable ambient packet is the sole ordered surface owner.
1121011215
r_rendererForwardPlus.SetBool( true );
11211-
idScenePacketFrame clusteredFrame;
11216+
idAutoPtr<idScenePacketFrame> clusteredFrameStorage( new idScenePacketFrame );
11217+
idScenePacketFrame &clusteredFrame = *clusteredFrameStorage;
1121211218
if ( !clusteredFrame.AddScene( &scene.worldView, true )
1121311219
|| !clusteredFrame.AddPass( RENDER_PASS_ARB2_INTERACTION, true ) ) {
1121411220
common->Printf( "RendererPBRVisible self-test failed: clustered interaction frame setup\n" );
@@ -11252,9 +11258,11 @@ bool RendererPBRVisible_RunSelfTest( void ) {
1125211258
idRenderGraph clusteredGraph;
1125311259
R_RenderGraph_BuildFromScenePackets( clusteredFrame, clusteredGraph );
1125411260
R_MaterialResourceTable_PrepareFrame( clusteredFrame );
11255-
idModernGLDrawPlan clusteredDrawPlan;
11261+
idAutoPtr<idModernGLDrawPlan> clusteredDrawPlanStorage( new idModernGLDrawPlan );
11262+
idModernGLDrawPlan &clusteredDrawPlan = *clusteredDrawPlanStorage;
1125611263
clusteredDrawPlan.Build( clusteredFrame, clusteredGraph );
11257-
idModernGLSubmitPlan clusteredSubmitPlan;
11264+
idAutoPtr<idModernGLSubmitPlan> clusteredSubmitPlanStorage( new idModernGLSubmitPlan );
11265+
idModernGLSubmitPlan &clusteredSubmitPlan = *clusteredSubmitPlanStorage;
1125811266
clusteredSubmitPlan.Build( clusteredDrawPlan );
1125911267
const modernGLDrawPlanStats_t &clusteredStats = clusteredDrawPlan.Stats();
1126011268
if ( clusteredStats.sourceDrawPackets != 6

src/renderer/ModernGLSubmitPlan.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,17 +1139,18 @@ bool RendererModernGLSubmitPlan_RunSelfTest( void ) {
11391139
return true;
11401140
}
11411141

1142-
// This fixture keeps four fixed-capacity packet arenas alive at once. Keep
1143-
// them off the finite render-thread stack; sealed geometry contracts make
1144-
// the arenas deliberately substantial even though each fixture uses only a
1145-
// handful of records.
1142+
// Four packet, draw and submit arenas remain alive together. All three
1143+
// arena types must stay off the finite render-thread stack, even though
1144+
// each fixture uses only a handful of records.
11461145
idAutoPtr<idScenePacketFrame> packetFrame( new idScenePacketFrame );
11471146
idRenderGraph graph;
1148-
idModernGLDrawPlan drawPlan;
1147+
idAutoPtr<idModernGLDrawPlan> drawPlanStorage( new idModernGLDrawPlan );
1148+
idModernGLDrawPlan &drawPlan = *drawPlanStorage;
11491149
R_ModernGLSubmitPlan_BuildSelfTestDrawPlan( true, true, TAG_USED, false,
11501150
drawPlan, *packetFrame, graph );
11511151

1152-
idModernGLSubmitPlan submitPlan;
1152+
idAutoPtr<idModernGLSubmitPlan> submitPlanStorage( new idModernGLSubmitPlan );
1153+
idModernGLSubmitPlan &submitPlan = *submitPlanStorage;
11531154
submitPlan.Build( drawPlan );
11541155
const modernGLSubmitPlanStats_t &readyStats = submitPlan.Stats();
11551156
const bool expectedDepthEligible = tr.defaultMaterial != NULL
@@ -1207,13 +1208,15 @@ bool RendererModernGLSubmitPlan_RunSelfTest( void ) {
12071208
}
12081209
}
12091210

1210-
idModernGLDrawPlan missingCacheDrawPlan;
1211+
idAutoPtr<idModernGLDrawPlan> missingCacheDrawPlanStorage( new idModernGLDrawPlan );
1212+
idModernGLDrawPlan &missingCacheDrawPlan = *missingCacheDrawPlanStorage;
12111213
idAutoPtr<idScenePacketFrame> missingCachePacketFrame(
12121214
new idScenePacketFrame );
12131215
idRenderGraph missingCacheGraph;
12141216
R_ModernGLSubmitPlan_BuildSelfTestDrawPlan( false, false, TAG_FREE, false,
12151217
missingCacheDrawPlan, *missingCachePacketFrame, missingCacheGraph );
1216-
idModernGLSubmitPlan missingCacheSubmitPlan;
1218+
idAutoPtr<idModernGLSubmitPlan> missingCacheSubmitPlanStorage( new idModernGLSubmitPlan );
1219+
idModernGLSubmitPlan &missingCacheSubmitPlan = *missingCacheSubmitPlanStorage;
12171220
missingCacheSubmitPlan.Build( missingCacheDrawPlan );
12181221
const modernGLDrawPlanStats_t &missingDrawStats = missingCacheDrawPlan.Stats();
12191222
const modernGLSubmitPlanStats_t &fallbackStats = missingCacheSubmitPlan.Stats();
@@ -1229,13 +1232,15 @@ bool RendererModernGLSubmitPlan_RunSelfTest( void ) {
12291232
return false;
12301233
}
12311234

1232-
idModernGLDrawPlan tempIndexDrawPlan;
1235+
idAutoPtr<idModernGLDrawPlan> tempIndexDrawPlanStorage( new idModernGLDrawPlan );
1236+
idModernGLDrawPlan &tempIndexDrawPlan = *tempIndexDrawPlanStorage;
12331237
idAutoPtr<idScenePacketFrame> tempIndexPacketFrame(
12341238
new idScenePacketFrame );
12351239
idRenderGraph tempIndexGraph;
12361240
R_ModernGLSubmitPlan_BuildSelfTestDrawPlan( true, true, TAG_TEMP, false,
12371241
tempIndexDrawPlan, *tempIndexPacketFrame, tempIndexGraph );
1238-
idModernGLSubmitPlan tempIndexSubmitPlan;
1242+
idAutoPtr<idModernGLSubmitPlan> tempIndexSubmitPlanStorage( new idModernGLSubmitPlan );
1243+
idModernGLSubmitPlan &tempIndexSubmitPlan = *tempIndexSubmitPlanStorage;
12391244
tempIndexSubmitPlan.Build( tempIndexDrawPlan );
12401245
const modernGLSubmitPlanStats_t &tempIndexStats = tempIndexSubmitPlan.Stats();
12411246
if ( tempIndexStats.sourcePlanDraws != expectedReadyDraws || tempIndexStats.readyDraws != expectedReadyDraws || tempIndexStats.fallbackDraws != 0 || tempIndexStats.indexCacheReadyDraws != expectedReadyDraws || tempIndexStats.indexUploadDraws != 0 ) {
@@ -1247,13 +1252,15 @@ bool RendererModernGLSubmitPlan_RunSelfTest( void ) {
12471252
return false;
12481253
}
12491254

1250-
idModernGLDrawPlan uploadIndexDrawPlan;
1255+
idAutoPtr<idModernGLDrawPlan> uploadIndexDrawPlanStorage( new idModernGLDrawPlan );
1256+
idModernGLDrawPlan &uploadIndexDrawPlan = *uploadIndexDrawPlanStorage;
12511257
idAutoPtr<idScenePacketFrame> uploadIndexPacketFrame(
12521258
new idScenePacketFrame );
12531259
idRenderGraph uploadIndexGraph;
12541260
R_ModernGLSubmitPlan_BuildSelfTestDrawPlan( true, false, TAG_FREE, true,
12551261
uploadIndexDrawPlan, *uploadIndexPacketFrame, uploadIndexGraph );
1256-
idModernGLSubmitPlan uploadIndexSubmitPlan;
1262+
idAutoPtr<idModernGLSubmitPlan> uploadIndexSubmitPlanStorage( new idModernGLSubmitPlan );
1263+
idModernGLSubmitPlan &uploadIndexSubmitPlan = *uploadIndexSubmitPlanStorage;
12571264
uploadIndexSubmitPlan.Build( uploadIndexDrawPlan );
12581265
const modernGLSubmitPlanStats_t &uploadStats = uploadIndexSubmitPlan.Stats();
12591266
if ( uploadStats.sourcePlanDraws != expectedReadyDraws || uploadStats.readyDraws != expectedReadyDraws || uploadStats.fallbackDraws != 0 || uploadStats.indexUploadDraws != expectedReadyDraws || uploadStats.indexCacheReadyDraws != 0 ) {

tools/tests/renderer_classic_deform_domain.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,16 @@ def validate_frontend_packet_provenance() -> None:
404404
"idScenePacketFrame packetFrame;",
405405
"render-thread stack packet fixture",
406406
)
407+
for arena in ("idModernGLDrawPlan", "idModernGLSubmitPlan"):
408+
require_count(submit_plan, f"idAutoPtr<{arena}>", 4, "heap-backed draw/submit fixtures")
409+
410+
pbr_test = braced_body(
411+
read("src/renderer/ModernGLExecutor.cpp"),
412+
"bool RendererPBRVisible_RunSelfTest(",
413+
"PBR fixture stack budget",
414+
)
415+
for arena in ("idScenePacketFrame", "idModernGLDrawPlan", "idModernGLSubmitPlan"):
416+
require_count(pbr_test, f"idAutoPtr<{arena}>", 2, "heap-backed simultaneous PBR fixtures")
407417

408418

409419
def validate_shared_domain_admission() -> None:

tools/tests/renderer_validation_matrix.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
# silently ignores any "+command" beyond this limit, which would drop "+quit"
3535
# and leave the case running until the timeout.
3636
ENGINE_MAX_STARTUP_COMMANDS = 64
37+
PBR_UNAVAILABLE_MARKER = "RendererPBRVisible self-test skipped: modern shader library unavailable"
38+
CLUSTER_UNAVAILABLE_MARKER = "RendererClusterGrid self-test skipped: modern clustered lighting unavailable"
3739

3840
SELFTEST_CHECKS = [
3941
["RendererModule self-test passed"],
@@ -739,10 +741,10 @@ def build_safe_cases(tiers: tuple[str, ...]) -> list[dict[str, Any]]:
739741
"+gfxInfo",
740742
],
741743
"checks": [
742-
["RendererPBRVisible self-test passed"],
743-
["gbuffer=1"],
744-
["deferred=1"],
745-
["forward=1"],
744+
["RendererPBRVisible self-test passed", PBR_UNAVAILABLE_MARKER],
745+
["gbuffer=1", PBR_UNAVAILABLE_MARKER],
746+
["deferred=1", PBR_UNAVAILABLE_MARKER],
747+
["forward=1", PBR_UNAVAILABLE_MARKER],
746748
["Selected renderer tier:"],
747749
["GL context request:"],
748750
],
@@ -781,14 +783,14 @@ def build_safe_cases(tiers: tuple[str, ...]) -> list[dict[str, Any]]:
781783
"+gfxInfo",
782784
],
783785
"checks": [
784-
["RendererClusterGrid self-test passed"],
785-
["lights=6"],
786-
["shadowDesc="],
787-
["shadowBuffer=1"],
788-
["uploadedShadow="],
789-
["overflow="],
790-
["ubo=1"],
791-
["overlay=1"],
786+
["RendererClusterGrid self-test passed", CLUSTER_UNAVAILABLE_MARKER],
787+
["lights=6", CLUSTER_UNAVAILABLE_MARKER],
788+
["shadowDesc=", CLUSTER_UNAVAILABLE_MARKER],
789+
["shadowBuffer=1", CLUSTER_UNAVAILABLE_MARKER],
790+
["uploadedShadow=", CLUSTER_UNAVAILABLE_MARKER],
791+
["overflow=", CLUSTER_UNAVAILABLE_MARKER],
792+
["ubo=1", CLUSTER_UNAVAILABLE_MARKER],
793+
["overlay=1", CLUSTER_UNAVAILABLE_MARKER],
792794
["Modern clustered lighting:"],
793795
["Selected renderer tier:"],
794796
["GL context request:"],

0 commit comments

Comments
 (0)