Add basic setup for regression testing Metal output.
This commit is contained in:
parent
3535f88bc1
commit
1c28ec6885
@ -24,3 +24,4 @@ script:
|
|||||||
- make -j2
|
- make -j2
|
||||||
- PATH=./glslang/StandAlone:./SPIRV-Tools/tools:$PATH
|
- PATH=./glslang/StandAlone:./SPIRV-Tools/tools:$PATH
|
||||||
- ./test_shaders.py shaders
|
- ./test_shaders.py shaders
|
||||||
|
- ./test_shaders.py --metal shaders-msl
|
||||||
|
@ -93,6 +93,9 @@ if (${PYTHONINTERP_FOUND})
|
|||||||
add_test(NAME spirv-cross-test
|
add_test(NAME spirv-cross-test
|
||||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py
|
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders)
|
${CMAKE_CURRENT_SOURCE_DIR}/shaders)
|
||||||
|
add_test(NAME spirv-cross-test-metal
|
||||||
|
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test_shaders.py --metal
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/shaders-msl)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
message(WARNING "Testing disabled. Could not find python3. If you have python3 installed try running "
|
message(WARNING "Testing disabled. Could not find python3. If you have python3 installed try running "
|
||||||
|
@ -171,6 +171,8 @@ In these cases, run `./test_shaders.py shaders --update` to update the reference
|
|||||||
Always make sure you are running up to date glslangValidator as well as SPIRV-Tools when updating reference files.
|
Always make sure you are running up to date glslangValidator as well as SPIRV-Tools when updating reference files.
|
||||||
|
|
||||||
In short, the master branch should always be able to run `./test_shaders.py shaders` without failure.
|
In short, the master branch should always be able to run `./test_shaders.py shaders` without failure.
|
||||||
|
SPIRV-Cross uses Travis CI to test all pull requests, so it is not strictly needed to perform testing yourself if you have problems running it locally.
|
||||||
|
A pull request which does not pass testing on Travis will not be accepted however.
|
||||||
|
|
||||||
When adding support for new features to SPIRV-Cross, a new shader and reference file should be added which covers usage of the new shader features in question.
|
When adding support for new features to SPIRV-Cross, a new shader and reference file should be added which covers usage of the new shader features in question.
|
||||||
|
|
||||||
@ -205,6 +207,10 @@ The current reference output is contained in reference/.
|
|||||||
|
|
||||||
See `./test_shaders.py --help` for more.
|
See `./test_shaders.py --help` for more.
|
||||||
|
|
||||||
|
### Metal backend
|
||||||
|
|
||||||
|
To test the roundtrip path GLSL -> SPIR-V -> MSL, `--metal` can be added, e.g. `./test_shaders.py --metal shaders-msl`.
|
||||||
|
|
||||||
### Updating regression tests
|
### Updating regression tests
|
||||||
|
|
||||||
When legitimate changes are found, use `--update` flag to update regression files.
|
When legitimate changes are found, use `--update` flag to update regression files.
|
||||||
|
32
reference/shaders-msl/vert/basic.vert
Normal file
32
reference/shaders-msl/vert/basic.vert
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct UBO
|
||||||
|
{
|
||||||
|
float4x4 uMVP;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_in
|
||||||
|
{
|
||||||
|
float4 aVertex [[attribute(0)]];
|
||||||
|
float3 aNormal [[attribute(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_out
|
||||||
|
{
|
||||||
|
float3 vNormal [[user(locn0)]];
|
||||||
|
float4 gl_Position [[position]];
|
||||||
|
float gl_PointSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _16 [[buffer(0)]])
|
||||||
|
{
|
||||||
|
main0_out out = {};
|
||||||
|
out.gl_Position = _16.uMVP * in.aVertex;
|
||||||
|
out.vNormal = in.aNormal;
|
||||||
|
out.gl_Position.y = -(out.gl_Position.y); // Invert Y-axis for Metal
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
15
shaders-msl/vert/basic.vert
Normal file
15
shaders-msl/vert/basic.vert
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
layout(std140) uniform UBO
|
||||||
|
{
|
||||||
|
uniform mat4 uMVP;
|
||||||
|
};
|
||||||
|
in vec4 aVertex;
|
||||||
|
in vec3 aNormal;
|
||||||
|
out vec3 vNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = uMVP * aVertex;
|
||||||
|
vNormal = aNormal;
|
||||||
|
}
|
@ -66,6 +66,19 @@ def validate_shader(shader, vulkan):
|
|||||||
else:
|
else:
|
||||||
subprocess.check_call(['glslangValidator', shader])
|
subprocess.check_call(['glslangValidator', shader])
|
||||||
|
|
||||||
|
def cross_compile_msl(shader):
|
||||||
|
spirv_f, spirv_path = tempfile.mkstemp()
|
||||||
|
msl_f, msl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
|
||||||
|
os.close(spirv_f)
|
||||||
|
os.close(msl_f)
|
||||||
|
subprocess.check_call(['glslangValidator', '-V', '-o', spirv_path, shader])
|
||||||
|
spirv_cross_path = './spirv-cross'
|
||||||
|
subprocess.check_call([spirv_cross_path, '--entry', 'main', '--output', msl_path, spirv_path, '--metal'])
|
||||||
|
subprocess.check_call(['spirv-val', spirv_path])
|
||||||
|
|
||||||
|
# TODO: Add optional validation of the MSL output.
|
||||||
|
return (spirv_path, msl_path)
|
||||||
|
|
||||||
def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, flatten_ubo):
|
def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, flatten_ubo):
|
||||||
spirv_f, spirv_path = tempfile.mkstemp()
|
spirv_f, spirv_path = tempfile.mkstemp()
|
||||||
glsl_f, glsl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
|
glsl_f, glsl_path = tempfile.mkstemp(suffix = os.path.basename(shader))
|
||||||
@ -212,20 +225,30 @@ def test_shader(stats, shader, update, keep):
|
|||||||
a.append(str(i))
|
a.append(str(i))
|
||||||
print(','.join(a), file = stats)
|
print(','.join(a), file = stats)
|
||||||
|
|
||||||
def test_shaders_helper(stats, shader_dir, update, malisc, keep):
|
def test_shader_msl(stats, shader, update, keep):
|
||||||
|
joined_path = os.path.join(shader[0], shader[1])
|
||||||
|
print('Testing MSL shader:', joined_path)
|
||||||
|
spirv, msl = cross_compile_msl(joined_path)
|
||||||
|
regression_check(shader, msl, update, keep)
|
||||||
|
os.remove(spirv)
|
||||||
|
|
||||||
|
def test_shaders_helper(stats, shader_dir, update, malisc, keep, backend):
|
||||||
for root, dirs, files in os.walk(os.path.join(shader_dir)):
|
for root, dirs, files in os.walk(os.path.join(shader_dir)):
|
||||||
for i in files:
|
for i in files:
|
||||||
path = os.path.join(root, i)
|
path = os.path.join(root, i)
|
||||||
relpath = os.path.relpath(path, shader_dir)
|
relpath = os.path.relpath(path, shader_dir)
|
||||||
test_shader(stats, (shader_dir, relpath), update, keep)
|
if backend == 'metal':
|
||||||
|
test_shader_msl(stats, (shader_dir, relpath), update, keep)
|
||||||
|
else:
|
||||||
|
test_shader(stats, (shader_dir, relpath), update, keep)
|
||||||
|
|
||||||
def test_shaders(shader_dir, update, malisc, keep):
|
def test_shaders(shader_dir, update, malisc, keep, backend):
|
||||||
if malisc:
|
if malisc:
|
||||||
with open('stats.csv', 'w') as stats:
|
with open('stats.csv', 'w') as stats:
|
||||||
print('Shader,OrigRegs,OrigUniRegs,OrigALUShort,OrigLSShort,OrigTEXShort,OrigALULong,OrigLSLong,OrigTEXLong,CrossRegs,CrossUniRegs,CrossALUShort,CrossLSShort,CrossTEXShort,CrossALULong,CrossLSLong,CrossTEXLong', file = stats)
|
print('Shader,OrigRegs,OrigUniRegs,OrigALUShort,OrigLSShort,OrigTEXShort,OrigALULong,OrigLSLong,OrigTEXLong,CrossRegs,CrossUniRegs,CrossALUShort,CrossLSShort,CrossTEXShort,CrossALULong,CrossLSLong,CrossTEXLong', file = stats)
|
||||||
test_shaders_helper(stats, shader_dir, update, malisc, keep)
|
test_shaders_helper(stats, shader_dir, update, malisc, keep, backend)
|
||||||
else:
|
else:
|
||||||
test_shaders_helper(None, shader_dir, update, malisc, keep)
|
test_shaders_helper(None, shader_dir, update, malisc, keep, backend)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description = 'Script for regression testing.')
|
parser = argparse.ArgumentParser(description = 'Script for regression testing.')
|
||||||
@ -240,13 +263,16 @@ def main():
|
|||||||
parser.add_argument('--malisc',
|
parser.add_argument('--malisc',
|
||||||
action = 'store_true',
|
action = 'store_true',
|
||||||
help = 'Use malisc offline compiler to determine static cycle counts before and after spirv-cross.')
|
help = 'Use malisc offline compiler to determine static cycle counts before and after spirv-cross.')
|
||||||
|
parser.add_argument('--metal',
|
||||||
|
action = 'store_true',
|
||||||
|
help = 'Test Metal backend.')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if not args.folder:
|
if not args.folder:
|
||||||
sys.stderr.write('Need shader folder.\n')
|
sys.stderr.write('Need shader folder.\n')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
test_shaders(args.folder, args.update, args.malisc, args.keep)
|
test_shaders(args.folder, args.update, args.malisc, args.keep, 'metal' if args.metal else 'glsl')
|
||||||
if args.malisc:
|
if args.malisc:
|
||||||
print('Stats in stats.csv!')
|
print('Stats in stats.csv!')
|
||||||
print('Tests completed!')
|
print('Tests completed!')
|
||||||
|
Loading…
Reference in New Issue
Block a user