The emission seam — issues the indexed draw call from a typed `Poseidon::render::frame::Draw` value: bind the mesh VAO, rebind TEXTURE0/TEXTURE1, upload the per-draw world matrix, flush PS constants, issue glDrawElements with the index byte offset computed from `d.indexBegin`. Pass-level state (descriptor, shader, sampler) was bound by `ApplyPassState` before the `DrawSectionTL` call. Bails on a
| 299 | // crash the GL driver — the I-22 runtime check fires the warning, |
| 300 | // this path just stays defensive. |
| 301 | void EngineGL33::EmitDraw(const Poseidon::render::frame::Draw& d) |
| 302 | { |
| 303 | if (!_glContext) |
| 304 | return; |
| 305 | if (d.mesh.vao == 0 || d.indexCount <= 0) |
| 306 | return; |
| 307 | |
| 308 | GL33Bind::Vao(d.mesh.vao); |
| 309 | |
| 310 | // TEXTURE0 + TEXTURE1 binds. Both handles were captured from the |
| 311 | // `SetTexture` / `SetMultiTexturing` callsites, so this rebinds |
| 312 | // the same multi-tex configuration regardless of what's currently |
| 313 | // bound. Handle 0 is skipped (sentinel). The TEXTURE1 bind ends |
| 314 | // with the active unit back on TEXTURE0 — every subsequent call |
| 315 | // assumes that. |
| 316 | if (d.textures[1].id != 0) |
| 317 | GL33Bind::Tex2D(1, d.textures[1].id); |
| 318 | if (d.textures[0].id != 0) |
| 319 | GL33Bind::Tex2D(0, d.textures[0].id); |
| 320 | else |
| 321 | GL33Bind::ActiveUnit(0); |
| 322 | |
| 323 | // Per-draw world-matrix upload from the typed `Draw.world` — |
| 324 | // never inherited from whatever was last in `_currentDrawItem`. |
| 325 | // `UploadVSWorldMatrix` flushes VS constants internally; |
| 326 | // FlushPSConstants is explicit because PS-side state (material, |
| 327 | // sampler, texture-color routing) is bound by the descriptor / |
| 328 | // `ApplyPipeline` path. |
| 329 | UploadVSWorldMatrix(reinterpret_cast<const float*>(&d.world)); |
| 330 | FlushPSConstants(); |
| 331 | |
| 332 | const std::intptr_t offsetBytes = Poseidon::render::frame::ComputeIndexByteOffset(d.indexBegin, sizeof(VertexIndex)); |
| 333 | if (_instCount > 1) |
| 334 | { |
| 335 | // Instanced run: the WorldInstances UBO already holds the matrices; |
| 336 | // the per-draw upload above wrote slot 0 (= matrices[0]) again, |
| 337 | // which is harmless. gl_InstanceID selects the rest. |
| 338 | glDrawElementsInstanced(GL_TRIANGLES, d.indexCount, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(offsetBytes), |
| 339 | _instCount); |
| 340 | } |
| 341 | else |
| 342 | { |
| 343 | glDrawElements(GL_TRIANGLES, d.indexCount, GL_UNSIGNED_SHORT, reinterpret_cast<void*>(offsetBytes)); |
| 344 | } |
| 345 | ++Poseidon::gPerfDrawCalls; |
| 346 | } |
| 347 | |
| 348 | void EngineGL33::Clear(bool clearZ, bool clear, PackedColor color) |
| 349 | { |
nothing calls this directly
no test coverage detected