Skip to content

Commit f41f110

Browse files
Fix blending issues on AMD RX GPUs & optimize
1 parent edf1e81 commit f41f110

File tree

2 files changed

+64
-51
lines changed

2 files changed

+64
-51
lines changed

source/inochi2d/core/nodes/common.d

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,19 @@ private {
8282
/**
8383
Whether a multi-stage rendering pass should be used for blending
8484
*/
85-
bool inUseMultistageBlending() {
86-
return hasKHRBlendEquationAdvanced;
85+
bool inUseMultistageBlending(BlendMode blendingMode) {
86+
switch(blendingMode) {
87+
case BlendMode.Normal,
88+
BlendMode.LinearDodge,
89+
BlendMode.AddGlow,
90+
BlendMode.Subtract,
91+
BlendMode.Inverse,
92+
BlendMode.DestinationIn,
93+
BlendMode.ClipToLower,
94+
BlendMode.SliceFromLower:
95+
return false;
96+
default: return hasKHRBlendEquationAdvanced;
97+
}
8798
}
8899

89100
void inInitBlending() {
@@ -201,60 +212,51 @@ enum BlendMode {
201212
SliceFromLower
202213
}
203214

215+
bool inIsAdvancedBlendMode(BlendMode mode) {
216+
if (!inAdvancedBlending) return false;
217+
switch(mode) {
218+
case BlendMode.Multiply:
219+
case BlendMode.Screen:
220+
case BlendMode.Overlay:
221+
case BlendMode.Darken:
222+
case BlendMode.Lighten:
223+
case BlendMode.ColorDodge:
224+
case BlendMode.ColorBurn:
225+
case BlendMode.HardLight:
226+
case BlendMode.SoftLight:
227+
case BlendMode.Difference:
228+
case BlendMode.Exclusion:
229+
return true;
230+
231+
// Fallback to legacy
232+
default:
233+
return false;
234+
}
235+
}
236+
204237
void inSetBlendMode(BlendMode blendingMode, bool legacyOnly=false) {
205238
if (!inAdvancedBlending || legacyOnly) inSetBlendModeLegacy(blendingMode);
206239
else switch(blendingMode) {
207-
case BlendMode.Normal:
208-
glBlendEquation(GL_FUNC_ADD);
209-
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); break;
210-
211240
case BlendMode.Multiply: glBlendEquation(GL_MULTIPLY_KHR); break;
212241
case BlendMode.Screen: glBlendEquation(GL_SCREEN_KHR); break;
213242
case BlendMode.Overlay: glBlendEquation(GL_OVERLAY_KHR); break;
214243
case BlendMode.Darken: glBlendEquation(GL_DARKEN_KHR); break;
215244
case BlendMode.Lighten: glBlendEquation(GL_LIGHTEN_KHR); break;
216245
case BlendMode.ColorDodge: glBlendEquation(GL_COLORDODGE_KHR); break;
217-
case BlendMode.LinearDodge:
218-
glBlendEquation(GL_FUNC_ADD);
219-
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); break;
220-
221-
case BlendMode.AddGlow:
222-
glBlendEquation(GL_FUNC_ADD);
223-
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); break;
224-
225246
case BlendMode.ColorBurn: glBlendEquation(GL_COLORBURN_KHR); break;
226247
case BlendMode.HardLight: glBlendEquation(GL_HARDLIGHT_KHR); break;
227248
case BlendMode.SoftLight: glBlendEquation(GL_SOFTLIGHT_KHR); break;
228249
case BlendMode.Difference: glBlendEquation(GL_DIFFERENCE_KHR); break;
229250
case BlendMode.Exclusion: glBlendEquation(GL_EXCLUSION_KHR); break;
230-
231-
case BlendMode.Subtract:
232-
glBlendEquationSeparate(GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD);
233-
glBlendFunc(GL_ONE, GL_ONE); break;
234-
235-
case BlendMode.Inverse:
236-
glBlendEquation(GL_FUNC_ADD);
237-
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break;
238-
239-
case BlendMode.DestinationIn:
240-
glBlendEquation(GL_FUNC_ADD);
241-
glBlendFunc(GL_ZERO, GL_SRC_ALPHA); break;
242-
243-
case BlendMode.ClipToLower:
244-
glBlendEquation(GL_FUNC_ADD);
245-
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break;
246-
247-
case BlendMode.SliceFromLower:
248-
glBlendEquation(GL_FUNC_ADD);
249-
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA); break;
250251

251252
// Fallback to legacy
252253
default: inSetBlendModeLegacy(blendingMode); break;
253254
}
254255
}
255256

256-
void inBlendModeBarrier() {
257-
if (inAdvancedBlending && !inAdvancedBlendingCoherent) glBlendBarrierKHR();
257+
void inBlendModeBarrier(BlendMode mode) {
258+
if (inAdvancedBlending && !inAdvancedBlendingCoherent && inIsAdvancedBlendMode(mode))
259+
glBlendBarrierKHR();
258260
}
259261

260262
/**

source/inochi2d/core/nodes/part/package.d

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ private:
210210
case 0:
211211
// STAGE 1 - Advanced blending
212212

213-
glDrawBuffers(3, [GL_COLOR_ATTACHMENT0, GL_NONE, GL_NONE].ptr);
213+
glDrawBuffers(1, [GL_COLOR_ATTACHMENT0].ptr);
214214

215215
partShaderStage1.use();
216216
partShaderStage1.setUniform(gs1offset, data.origin);
@@ -225,23 +225,23 @@ private:
225225
case 1:
226226

227227
// STAGE 2 - Basic blending (albedo, bump)
228-
glDrawBuffers(3, [GL_NONE, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2].ptr);
228+
glDrawBuffers(2, [GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2].ptr);
229229

230230
partShaderStage2.use();
231231
partShaderStage2.setUniform(gs2offset, data.origin);
232232
partShaderStage2.setUniform(gs2mvp, inGetCamera().matrix * puppet.transform.matrix * matrix);
233233
partShaderStage2.setUniform(gs2opacity, clamp(offsetOpacity * opacity, 0, 1));
234234
partShaderStage2.setUniform(gs2EmissionStrength, emissionStrength*offsetEmissionStrength);
235235

236-
partShaderStage2.setUniform(partShaderStage2.getUniformLocation("emission"), 1);
237-
partShaderStage2.setUniform(partShaderStage2.getUniformLocation("bump"), 2);
236+
partShaderStage2.setUniform(partShaderStage2.getUniformLocation("emission"), 0);
237+
partShaderStage2.setUniform(partShaderStage2.getUniformLocation("bump"), 1);
238238

239239
// These can be reused from stage 2
240240
partShaderStage1.setUniform(gs2MultColor, clampedTint);
241241
partShaderStage1.setUniform(gs2ScreenColor, clampedScreen);
242242
inSetBlendMode(blendingMode, true);
243243
break;
244-
case 3:
244+
case 2:
245245

246246
// Basic blending
247247
glDrawBuffers(3, [GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2].ptr);
@@ -274,7 +274,7 @@ private:
274274

275275
}
276276

277-
void renderStage() {
277+
void renderStage(bool advanced=true)(BlendMode mode) {
278278

279279
// Enable points array
280280
glEnableVertexAttribArray(0);
@@ -299,8 +299,10 @@ private:
299299
glDisableVertexAttribArray(1);
300300
glDisableVertexAttribArray(2);
301301

302-
// Blending barrier
303-
inBlendModeBarrier();
302+
static if (advanced) {
303+
// Blending barrier
304+
inBlendModeBarrier(mode);
305+
}
304306
}
305307

306308
/*
@@ -342,28 +344,37 @@ private:
342344
partMaskShader.setUniform(offset, data.origin);
343345
partMaskShader.setUniform(mmvp, inGetCamera().matrix * puppet.transform.matrix * matrix);
344346
partMaskShader.setUniform(mthreshold, clamp(offsetMaskThreshold + maskAlphaThreshold, 0, 1));
347+
348+
// Make sure the equation is correct
349+
glBlendEquation(GL_FUNC_ADD);
345350
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
346351

347-
renderStage();
352+
renderStage!false(blendingMode);
348353
} else {
349354

350-
if (inUseMultistageBlending()) {
355+
bool hasEmissionOrBumpmap = (textures[1] || textures[2]);
356+
357+
if (inUseMultistageBlending(blendingMode)) {
351358

352359
// TODO: Detect if this Part is NOT in a composite,
353360
// If so, we can relatively safely assume that we may skip stage 1.
354361
setupShaderStage(0, matrix);
355-
renderStage();
356-
setupShaderStage(1, matrix);
357-
renderStage();
358-
362+
renderStage(blendingMode);
363+
364+
// Only do stage 2 if we have emission or bumpmap textures.
365+
if (hasEmissionOrBumpmap) {
366+
setupShaderStage(1, matrix);
367+
renderStage!false(blendingMode);
368+
}
359369
} else {
360370
setupShaderStage(2, matrix);
361-
renderStage();
371+
renderStage!false(blendingMode);
362372
}
363373
}
364374

365375
// Reset draw buffers
366376
glDrawBuffers(3, [GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2].ptr);
377+
glBlendEquation(GL_FUNC_ADD);
367378
}
368379

369380
protected:

0 commit comments

Comments
 (0)