From 6957618926b6f01879e9510df73c044f4453a268 Mon Sep 17 00:00:00 2001 From: Yanrishatum Date: Mon, 20 Jan 2025 01:42:04 +0300 Subject: [PATCH 1/2] feat: Add global shader list support to s2d --- h2d/RenderContext.hx | 71 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/h2d/RenderContext.hx b/h2d/RenderContext.hx index fe936781d6..0f72d37724 100644 --- a/h2d/RenderContext.hx +++ b/h2d/RenderContext.hx @@ -93,8 +93,11 @@ class RenderContext extends h3d.impl.RenderContext { var compiledShader : hxsl.RuntimeShader; var fixedBuffer : h3d.Buffer; var pass : h3d.mat.Pass; + // ...Tail points at an end of global shader list, and shaders afterwards belong to specific objects. var currentShaders : hxsl.ShaderList; + var currentShadersTail : hxsl.ShaderList; var baseShaderList : hxsl.ShaderList; + var baseShaderListTail : hxsl.ShaderList; var needInitShaders : Bool; var currentObj : Drawable; var stride : Int; @@ -145,6 +148,7 @@ class RenderContext extends h3d.impl.RenderContext { baseShader.setPriority(100); baseShader.zValue = 0.; baseShaderList = new hxsl.ShaderList(baseShader); + baseShaderListTail = baseShaderList; targetsStack = []; targetsStackIndex = 0; cameraStack = []; @@ -194,8 +198,8 @@ class RenderContext extends h3d.impl.RenderContext { baseShader.viewportB.set(0, scene.viewportD * -baseFlipY, scene.viewportY * -baseFlipY); baseShader.filterMatrixA.set(1, 0, 0); baseShader.filterMatrixB.set(0, 1, 0); - baseShaderList.next = null; - initShaders(baseShaderList); + baseShaderListTail.next = null; + initShaders(baseShaderList, baseShaderListTail); engine.selectMaterial(pass); textures.begin(); } @@ -217,9 +221,10 @@ class RenderContext extends h3d.impl.RenderContext { engine.clear(color); } - function initShaders( shaders ) { + function initShaders( shaders : hxsl.ShaderList, tail : hxsl.ShaderList ) { needInitShaders = false; currentShaders = shaders; + currentShadersTail = tail; compiledShader = output.compileShaders(globals, shaders); var buffers = shaderBuffers; buffers.grow(compiledShader); @@ -237,7 +242,7 @@ class RenderContext extends h3d.impl.RenderContext { flush(); texture = null; currentObj = null; - baseShaderList.next = null; + baseShaderListTail.next = null; clearCurrent(); if ( targetsStackIndex != 0 ) throw "Missing popTarget()"; if ( cameraStackIndex != 0 ) throw "Missing popCamera()"; @@ -305,6 +310,50 @@ class RenderContext extends h3d.impl.RenderContext { baseShader.viewportB.set(viewB * flipY, viewD * flipY, viewY * flipY); } + /** + Adds a shader the global shader list. + + Global shaders are present in all draw operations along with base2d shader. + **/ + public function addGlobalShader( shader : hxsl.Shader ) { + var list = new hxsl.ShaderList(shader, baseShaderListTail.next); + baseShaderListTail.next = list; + baseShaderListTail = list; + needInitShaders = true; + } + + /** + Removes the shader from the global shader list. + + @returns `true` if shader was removed, `false` otherwise. + **/ + public function removeGlobalShader( shader : hxsl.Shader ) { + if ( shader == baseShader ) throw "Cannot remove base shader!"; + var prev : hxsl.ShaderList = null; + var hd = baseShaderList; + while ( hd != baseShaderListTail.next ) { + if ( hd.s == shader ) { + prev?.next = hd.next; + needInitShaders = true; + if ( hd == baseShaderListTail ) { + baseShaderListTail = prev; + } + return true; + } + prev = hd; + hd = hd.next; + } + return false; + } + + function updateGlobals() { + var hd = baseShaderList; + while ( hd != baseShaderListTail.next ) { + hd.s.updateConstants(globals); + hd = hd.next; + } + } + /** Internal usage @@ -383,7 +432,7 @@ class RenderContext extends h3d.impl.RenderContext { public function pushTarget( t : h3d.mat.Texture, startX = 0, startY = 0, width = -1, height = -1 ) { flush(); engine.pushTarget(t); - initShaders(baseShaderList); + initShaders(baseShaderList, baseShaderListTail.next); var entry = targetsStack[targetsStackIndex++]; if ( entry == null ) { @@ -451,7 +500,7 @@ class RenderContext extends h3d.impl.RenderContext { viewY = tinf.vy; var flipY = t == null ? -baseFlipY : -targetFlipY; - initShaders(baseShaderList); + initShaders(baseShaderList, baseShaderListTail.next); baseShader.halfPixelInverse.set(0.5 / (t == null ? engine.width : t.width), 0.5 / (t == null ? engine.height : t.height)); baseShader.viewportA.set(viewA, viewC, viewX); baseShader.viewportB.set(viewB * flipY, viewD * flipY, viewY * flipY); @@ -781,7 +830,7 @@ class RenderContext extends h3d.impl.RenderContext { flush(); var shaderChanged = needInitShaders, paramsChanged = false; var objShaders = obj.shaders; - var curShaders = currentShaders.next; + var curShaders = currentShadersTail.next; while( objShaders != null && curShaders != null ) { var s = objShaders.s; var t = curShaders.s; @@ -801,14 +850,14 @@ class RenderContext extends h3d.impl.RenderContext { baseShader.hasUVPos = hasUVPos; baseShader.isRelative = isRelative; baseShader.killAlpha = killAlpha; - baseShader.updateConstants(globals); - baseShaderList.next = obj.shaders; - initShaders(baseShaderList); + updateGlobals(); + baseShaderListTail.next = obj.shaders; + initShaders(baseShaderList, baseShaderListTail); } else if( paramsChanged ) { flush(); if( currentShaders != baseShaderList ) throw "!"; // the next flush will fetch their params - currentShaders.next = obj.shaders; + currentShadersTail.next = obj.shaders; } this.texture = texture; From 626533d82966162dc7df783a9d91b931f6023d1a Mon Sep 17 00:00:00 2001 From: Yanrishatum Date: Mon, 3 Feb 2025 12:50:01 +0300 Subject: [PATCH 2/2] fix: Use non-null-coalesce syntax --- h2d/RenderContext.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/h2d/RenderContext.hx b/h2d/RenderContext.hx index 0f72d37724..af4883a7ce 100644 --- a/h2d/RenderContext.hx +++ b/h2d/RenderContext.hx @@ -333,7 +333,7 @@ class RenderContext extends h3d.impl.RenderContext { var hd = baseShaderList; while ( hd != baseShaderListTail.next ) { if ( hd.s == shader ) { - prev?.next = hd.next; + if ( prev != null ) prev.next = hd.next; needInitShaders = true; if ( hd == baseShaderListTail ) { baseShaderListTail = prev;