Files
gen1recomp/tests/engine/shaderfx_es_dialect.lua

89 lines
3.9 KiB
Lua

package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
local Fixup = require("src.render.ShaderFixup")
local FIXTURES = "tests/data/shaderfx"
local NAMES = { "bevel", "gameboy", "gb-palette-dmg", "lcd3x", "pixel_transparency", "zfast-lcd" }
local function loadFixture(dialect, name)
local chunk, err = loadfile(("%s/%s/%s.lua"):format(FIXTURES, dialect, name))
check(chunk ~= nil, ("fixture %s/%s loads (%s)"):format(dialect, name, tostring(err)))
return chunk and chunk()
end
local EFFECT_SIG = "EFFECT_PREC vec4 effect(EFFECT_PREC vec4 love_UnusedColor, Image love_UnusedTex, "
.. "EFFECT_PREC vec2 love_UnusedTc, EFFECT_PREC vec2 love_UnusedSc)"
local function countPlain(s, needle)
local n, at = 0, 1
while true do
local i, j = s:find(needle, at, true)
if not i then return n end
n, at = n + 1, j + 1
end
end
local function checkPass(label, dialect, pass)
local frag, fragManifest = Fixup.fragment(pass.fragment)
local vert, vertManifest = Fixup.vertex(pass.vertex)
eq(#fragManifest, #vertManifest, label .. ": push/UBO manifests agree between stages")
check(frag:find(EFFECT_SIG, 1, true) ~= nil,
label .. ": effect()'s return type carries the same EFFECT_PREC head as its parameters")
check(frag:find(EFFECT_SIG .. "\n{\n vec4 gbFragColor;", 1, true) ~= nil,
label .. ": gbFragColor is declared at the top of effect()")
check(not frag:find("void%s+main") and not vert:find("void%s+main"),
label .. ": no void main() survives in either stage")
for _, stage in ipairs({ { "frag", frag }, { "vert", vert } }) do
local src = stage[2]
check(not src:find("%f[%w_]uint%f[^%w_]"), label .. " " .. stage[1] .. ": no uint token")
check(not src:find("#extension", 1, true), label .. " " .. stage[1] .. ": no #extension directive")
check(not src:find("gl_FragData", 1, true) and not src:find("gl_Position", 1, true),
label .. " " .. stage[1] .. ": no gl_FragData / gl_Position")
end
eq(countPlain(frag, "precision highp float;"), 1,
label .. ": exactly one default float precision statement (the guarded one)")
local guardAt = frag:find("#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\nprecision highp int;\n#endif", 1, true)
check(guardAt ~= nil, label .. ": the highp pair sits under the GL_FRAGMENT_PRECISION_HIGH guard")
check(not vert:find("precision%s+%a+%s+float"), label .. ": the vertex stage never changes the default precision")
if dialect == "es" then
check(not frag:find("texture2DLod", 1, true) and not frag:find("dFdx", 1, true),
label .. ": ES 1.00 output uses no ES 3 only builtins")
check(not frag:find("[%w_%)]%s*%%%s*[%w_%(]"), label .. ": ES 1.00 output has no % operator")
end
end
for _, dialect in ipairs({ "es", "gl" }) do
for _, name in ipairs(NAMES) do
local preset = loadFixture(dialect, name)
if preset then
eq(preset.pass_count, #preset.passes, ("%s/%s: pass_count matches"):format(dialect, name))
for i, pass in ipairs(preset.passes) do
checkPass(("%s/%s pass%d"):format(dialect, name, i - 1), dialect, pass)
end
end
end
end
do
local raw = 0
for _, name in ipairs({ "bevel", "gb-palette-dmg", "lcd3x", "zfast-lcd" }) do
local preset = loadFixture("gl", name)
local v = preset and preset.passes[1].vertex or ""
if v:find("uint", 1, true) and v:find("#extension GL_EXT_gpu_shader4", 1, true) then raw = raw + 1 end
end
eq(raw, 4, "the GL fixtures really carry the bridge's uint FrameCount + GL_EXT_gpu_shader4 shape")
end
do
local src = "#extension GL_EXT_gpu_shader4 : require\nuniform uint FrameCount;\nuint x = uint(FrameCount) + uinty;\n"
local out = Fixup.rewriteGpuShader4(src)
eq(out, "uniform int FrameCount;\nint x = int(FrameCount) + uinty;\n",
"rewriteGpuShader4 rewrites whole uint tokens only and drops the extension line")
end
T.finish("shaderfx_es_dialect")