Skip to content
This repository was archived by the owner on Apr 29, 2021. It is now read-only.

Commit d05c906

Browse files
committed
fix compute buffer bug on Unity 2019 and above on low-level machines
1 parent 891c332 commit d05c906

File tree

4 files changed

+165
-66
lines changed

4 files changed

+165
-66
lines changed

Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_impl.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,10 @@ void _drawTextBlob(TextBlob? textBlob, uiOffset offset, uiPaint paint) {
10351035
}
10361036

10371037
public void flush(uiPicture picture) {
1038+
if (!CanvasShader.isReady()) {
1039+
return;
1040+
}
1041+
10381042
this._reset();
10391043
this._resetRenderTextureId();
10401044
this._resetComputeBuffer();

Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs

Lines changed: 14 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,18 @@ public Material getMaterial(BlendMode blend, bool ignoreClip) {
143143
}
144144
}
145145

146-
static class CanvasShader {
147-
static readonly MaterialByBlendModeStencilComp _convexFillMat;
148-
static readonly MaterialByStencilComp _fill0Mat;
149-
static readonly MaterialByBlendMode _fill1Mat;
150-
static readonly MaterialByBlendModeStencilComp _stroke0Mat;
151-
static readonly Material _stroke1Mat;
152-
static readonly MaterialByBlendModeStencilComp _texMat;
153-
static readonly Material _stencilMat;
154-
static readonly Material _filterMat;
155-
static readonly MaterialByBlendModeStencilComp _strokeAlphaMat;
156-
static readonly Material _shadowBox;
157-
static readonly Material _shadowRBox;
146+
static partial class CanvasShader {
147+
static MaterialByBlendModeStencilComp _convexFillMat;
148+
static MaterialByStencilComp _fill0Mat;
149+
static MaterialByBlendMode _fill1Mat;
150+
static MaterialByBlendModeStencilComp _stroke0Mat;
151+
static Material _stroke1Mat;
152+
static MaterialByBlendModeStencilComp _texMat;
153+
static Material _stencilMat;
154+
static Material _filterMat;
155+
static MaterialByBlendModeStencilComp _strokeAlphaMat;
156+
static Material _shadowBox;
157+
static Material _shadowRBox;
158158

159159
static Shader GetShader(string shaderName) {
160160
var shader = Shader.Find(shaderName);
@@ -167,62 +167,10 @@ static Shader GetShader(string shaderName) {
167167

168168
public static bool enableComputeBuffer = true;
169169

170-
public static readonly bool supportComputeBuffer;
170+
public static bool supportComputeBuffer;
171171

172172
static CanvasShader() {
173-
var convexFillShaderCompute = GetShader("UIWidgets/canvas_convexFill_cb");
174-
supportComputeBuffer = enableComputeBuffer && SystemInfo.supportsComputeShaders && convexFillShaderCompute.isSupported;
175173

176-
//if compute buffer is not supported, load normal shader
177-
if (!supportComputeBuffer) {
178-
var convexFillShader = GetShader("UIWidgets/canvas_convexFill");
179-
var fill0Shader = GetShader("UIWidgets/canvas_fill0");
180-
var fill1Shader = GetShader("UIWidgets/canvas_fill1");
181-
var stroke0Shader = GetShader("UIWidgets/canvas_stroke0");
182-
var stroke1Shader = GetShader("UIWidgets/canvas_stroke1");
183-
var texShader = GetShader("UIWidgets/canvas_tex");
184-
var stencilShader = GetShader("UIWidgets/canvas_stencil");
185-
var filterShader = GetShader("UIWidgets/canvas_filter");
186-
var shadowBoxShader = GetShader("UIWidgets/ShadowBox");
187-
var shadowRBoxShader = GetShader("UIWidgets/ShadowRBox");
188-
var strokeAlphaShader = GetShader("UIWidgets/canvas_strokeAlpha");
189-
190-
_convexFillMat = new MaterialByBlendModeStencilComp(convexFillShader);
191-
_fill0Mat = new MaterialByStencilComp(fill0Shader);
192-
_fill1Mat = new MaterialByBlendMode(fill1Shader);
193-
_stroke0Mat = new MaterialByBlendModeStencilComp(stroke0Shader);
194-
_stroke1Mat = new Material(stroke1Shader) {hideFlags = HideFlags.HideAndDontSave};
195-
_strokeAlphaMat = new MaterialByBlendModeStencilComp(strokeAlphaShader);
196-
_texMat = new MaterialByBlendModeStencilComp(texShader);
197-
_stencilMat = new Material(stencilShader) {hideFlags = HideFlags.HideAndDontSave};
198-
_filterMat = new Material(filterShader) {hideFlags = HideFlags.HideAndDontSave};
199-
_shadowBox = new Material(shadowBoxShader) {hideFlags = HideFlags.HideAndDontSave};
200-
_shadowRBox = new Material(shadowRBoxShader) {hideFlags = HideFlags.HideAndDontSave};
201-
}
202-
else {
203-
var fill0ShaderCompute = GetShader("UIWidgets/canvas_fill0_cb");
204-
var fill1ShaderCompute = GetShader("UIWidgets/canvas_fill1_cb");
205-
var stroke0ShaderCompute = GetShader("UIWidgets/canvas_stroke0_cb");
206-
var stroke1ShaderCompute = GetShader("UIWidgets/canvas_stroke1_cb");
207-
var texShaderCompute = GetShader("UIWidgets/canvas_tex_cb");
208-
var stencilShaderCompute = GetShader("UIWidgets/canvas_stencil_cb");
209-
var filterShaderCompute = GetShader("UIWidgets/canvas_filter_cb");
210-
var shadowBoxShaderCompute = GetShader("UIWidgets/ShadowBox_cb");
211-
var shadowRBoxShaderCompute = GetShader("UIWidgets/ShadowRBox_cb");
212-
var strokeAlphaShaderCompute = GetShader("UIWidgets/canvas_strokeAlpha_cb");
213-
214-
_convexFillMat = new MaterialByBlendModeStencilComp(convexFillShaderCompute);
215-
_fill0Mat = new MaterialByStencilComp(fill0ShaderCompute);
216-
_fill1Mat = new MaterialByBlendMode(fill1ShaderCompute);
217-
_stroke0Mat = new MaterialByBlendModeStencilComp(stroke0ShaderCompute);
218-
_stroke1Mat = new Material(stroke1ShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
219-
_strokeAlphaMat = new MaterialByBlendModeStencilComp(strokeAlphaShaderCompute);
220-
_texMat = new MaterialByBlendModeStencilComp(texShaderCompute);
221-
_stencilMat = new Material(stencilShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
222-
_filterMat= new Material(filterShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
223-
_shadowBox = new Material(shadowBoxShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
224-
_shadowRBox = new Material(shadowRBoxShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
225-
}
226174
}
227175

228176
static readonly int _viewportId = Shader.PropertyToID("_viewport");
@@ -337,7 +285,7 @@ static void _getShaderPassAndProps(
337285
public static PictureFlusher.CmdDraw convexFill(PictureFlusher.RenderLayer layer, uiPaint paint,
338286
uiMeshMesh mesh) {
339287
var mat = _convexFillMat.getMaterial(paint.blendMode, layer.ignoreClip);
340-
288+
341289
_getShaderPassAndProps(layer, paint, mesh.matrix, 1.0f, 0.0f, out var pass, out var props);
342290

343291
return PictureFlusher.CmdDraw.create(
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
using System;
2+
using Unity.UIWidgets.foundation;
3+
using UnityEngine;
4+
using UnityEngine.Rendering;
5+
6+
namespace Unity.UIWidgets.ui {
7+
enum InitStage {
8+
NotPrepared,
9+
Prepared,
10+
Ready
11+
}
12+
13+
static partial class CanvasShader {
14+
static InitStage initStage = InitStage.NotPrepared;
15+
static int initialFrameCount;
16+
static Shader testShader;
17+
const string testShaderName = "UIWidgets/canvas_convexFill_cb";
18+
19+
static bool OnNotPrepared() {
20+
initStage = InitStage.Prepared;
21+
22+
initialFrameCount = Time.frameCount;
23+
testShader = GetShader(testShaderName);
24+
var material = new Material(testShader);
25+
//for Unity 2018 or below, shader is compiled after Shader.Find() call immediately,
26+
//therefore we can just skip the manually preload if the compilation fails
27+
if (!material.shader.isSupported) {
28+
ObjectUtils.SafeDestroy(material);
29+
return OnPrepared(true);
30+
}
31+
32+
using (var cmdBuf = new CommandBuffer()) {
33+
var renderTarget = new RenderTexture(1, 1, 1);
34+
cmdBuf.SetRenderTarget(renderTarget);
35+
36+
var mesh = new Mesh {
37+
vertices = new[] {new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0)},
38+
uv = new[] {new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1)},
39+
triangles = new[] {0, 1, 2}
40+
};
41+
cmdBuf.DrawMesh(mesh, Matrix4x4.identity, material);
42+
cmdBuf.DisableScissorRect();
43+
Graphics.ExecuteCommandBuffer(cmdBuf);
44+
45+
ObjectUtils.SafeDestroy(renderTarget);
46+
ObjectUtils.SafeDestroy(mesh);
47+
}
48+
49+
ObjectUtils.SafeDestroy(material);
50+
51+
return false;
52+
}
53+
54+
static bool OnPrepared(bool forceReady = false) {
55+
D.assert(initStage == InitStage.Prepared);
56+
if (!forceReady && initialFrameCount >= Time.frameCount) {
57+
return false;
58+
}
59+
60+
initStage = InitStage.Ready;
61+
DoPrepare();
62+
return true;
63+
}
64+
65+
static void DoPrepare() {
66+
D.assert(testShader != null);
67+
var isShaderSupported = testShader.isSupported;
68+
testShader = null;
69+
supportComputeBuffer = enableComputeBuffer && SystemInfo.supportsComputeShaders && isShaderSupported;
70+
71+
if (!supportComputeBuffer) {
72+
var convexFillShader = GetShader("UIWidgets/canvas_convexFill");
73+
var fill0Shader = GetShader("UIWidgets/canvas_fill0");
74+
var fill1Shader = GetShader("UIWidgets/canvas_fill1");
75+
var stroke0Shader = GetShader("UIWidgets/canvas_stroke0");
76+
var stroke1Shader = GetShader("UIWidgets/canvas_stroke1");
77+
var texShader = GetShader("UIWidgets/canvas_tex");
78+
var stencilShader = GetShader("UIWidgets/canvas_stencil");
79+
var filterShader = GetShader("UIWidgets/canvas_filter");
80+
var shadowBoxShader = GetShader("UIWidgets/ShadowBox");
81+
var shadowRBoxShader = GetShader("UIWidgets/ShadowRBox");
82+
var strokeAlphaShader = GetShader("UIWidgets/canvas_strokeAlpha");
83+
84+
_convexFillMat = new MaterialByBlendModeStencilComp(convexFillShader);
85+
_fill0Mat = new MaterialByStencilComp(fill0Shader);
86+
_fill1Mat = new MaterialByBlendMode(fill1Shader);
87+
_stroke0Mat = new MaterialByBlendModeStencilComp(stroke0Shader);
88+
_stroke1Mat = new Material(stroke1Shader) {hideFlags = HideFlags.HideAndDontSave};
89+
_strokeAlphaMat = new MaterialByBlendModeStencilComp(strokeAlphaShader);
90+
_texMat = new MaterialByBlendModeStencilComp(texShader);
91+
_stencilMat = new Material(stencilShader) {hideFlags = HideFlags.HideAndDontSave};
92+
_filterMat = new Material(filterShader) {hideFlags = HideFlags.HideAndDontSave};
93+
_shadowBox = new Material(shadowBoxShader) {hideFlags = HideFlags.HideAndDontSave};
94+
_shadowRBox = new Material(shadowRBoxShader) {hideFlags = HideFlags.HideAndDontSave};
95+
}
96+
else {
97+
var convexFillShaderCompute = GetShader("UIWidgets/canvas_convexFill_cb");
98+
var fill0ShaderCompute = GetShader("UIWidgets/canvas_fill0_cb");
99+
var fill1ShaderCompute = GetShader("UIWidgets/canvas_fill1_cb");
100+
var stroke0ShaderCompute = GetShader("UIWidgets/canvas_stroke0_cb");
101+
var stroke1ShaderCompute = GetShader("UIWidgets/canvas_stroke1_cb");
102+
var texShaderCompute = GetShader("UIWidgets/canvas_tex_cb");
103+
var stencilShaderCompute = GetShader("UIWidgets/canvas_stencil_cb");
104+
var filterShaderCompute = GetShader("UIWidgets/canvas_filter_cb");
105+
var shadowBoxShaderCompute = GetShader("UIWidgets/ShadowBox_cb");
106+
var shadowRBoxShaderCompute = GetShader("UIWidgets/ShadowRBox_cb");
107+
var strokeAlphaShaderCompute = GetShader("UIWidgets/canvas_strokeAlpha_cb");
108+
109+
_convexFillMat = new MaterialByBlendModeStencilComp(convexFillShaderCompute);
110+
_fill0Mat = new MaterialByStencilComp(fill0ShaderCompute);
111+
_fill1Mat = new MaterialByBlendMode(fill1ShaderCompute);
112+
_stroke0Mat = new MaterialByBlendModeStencilComp(stroke0ShaderCompute);
113+
_stroke1Mat = new Material(stroke1ShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
114+
_strokeAlphaMat = new MaterialByBlendModeStencilComp(strokeAlphaShaderCompute);
115+
_texMat = new MaterialByBlendModeStencilComp(texShaderCompute);
116+
_stencilMat = new Material(stencilShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
117+
_filterMat = new Material(filterShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
118+
_shadowBox = new Material(shadowBoxShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
119+
_shadowRBox = new Material(shadowRBoxShaderCompute) {hideFlags = HideFlags.HideAndDontSave};
120+
}
121+
}
122+
123+
public static bool isReady() {
124+
switch (initStage) {
125+
case InitStage.NotPrepared:
126+
return OnNotPrepared();
127+
case InitStage.Prepared:
128+
return OnPrepared();
129+
case InitStage.Ready:
130+
return true;
131+
default:
132+
throw new ArgumentOutOfRangeException();
133+
}
134+
}
135+
}
136+
}

Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader_initializer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)