diff --git a/.travis.yml b/.travis.yml index d714b6a5..8e09d619 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: cpp os: - linux - osx -osx_image: xcode8.3 +osx_image: xcode9.3beta # Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment. sudo: required diff --git a/reference/opt/shaders-hlsl/frag/sampler-image-arrays.frag b/reference/opt/shaders-hlsl/frag/sampler-image-arrays.frag new file mode 100644 index 00000000..b6d0e942 --- /dev/null +++ b/reference/opt/shaders-hlsl/frag/sampler-image-arrays.frag @@ -0,0 +1,39 @@ +Texture2D uSampler[4] : register(t0); +SamplerState _uSampler_sampler[4] : register(s0); +Texture2D uTextures[4] : register(t8); +SamplerState uSamplers[4] : register(s4); + +static int vIndex; +static float2 vTex; +static float4 FragColor; + +struct SPIRV_Cross_Input +{ + nointerpolation float2 vTex : TEXCOORD0; + nointerpolation int vIndex : TEXCOORD1; +}; + +struct SPIRV_Cross_Output +{ + float4 FragColor : SV_Target0; +}; + +void frag_main() +{ + FragColor = 0.0f.xxxx; + FragColor += uTextures[2].Sample(uSamplers[1], vTex); + FragColor += uSampler[vIndex].Sample(_uSampler_sampler[vIndex], vTex); + FragColor += uSampler[vIndex].Sample(_uSampler_sampler[vIndex], vTex + 0.100000001490116119384765625f.xx); + FragColor += uSampler[vIndex].Sample(_uSampler_sampler[vIndex], vTex + 0.20000000298023223876953125f.xx); + FragColor += uSampler[3].Sample(_uSampler_sampler[3], vTex + 0.300000011920928955078125f.xx); +} + +SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) +{ + vIndex = stage_input.vIndex; + vTex = stage_input.vTex; + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.FragColor = FragColor; + return stage_output; +} diff --git a/reference/opt/shaders-msl/frag/sampler-image-arrays.msl2.frag b/reference/opt/shaders-msl/frag/sampler-image-arrays.msl2.frag new file mode 100644 index 00000000..44f01d20 --- /dev/null +++ b/reference/opt/shaders-msl/frag/sampler-image-arrays.msl2.frag @@ -0,0 +1,28 @@ +#include +#include + +using namespace metal; + +struct main0_in +{ + int vIndex [[user(locn1)]]; + float2 vTex [[user(locn0)]]; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], array, 4> uSampler [[texture(0)]], array, 4> uTextures [[texture(1)]], array uSamplerSmplr [[sampler(0)]], array uSamplers [[sampler(1)]]) +{ + main0_out out = {}; + out.FragColor = float4(0.0); + out.FragColor += uTextures[2].sample(uSamplers[1], in.vTex); + out.FragColor += uSampler[in.vIndex].sample(uSamplerSmplr[in.vIndex], in.vTex); + out.FragColor += uSampler[in.vIndex].sample(uSamplerSmplr[in.vIndex], (in.vTex + float2(0.100000001490116119384765625))); + out.FragColor += uSampler[in.vIndex].sample(uSamplerSmplr[in.vIndex], (in.vTex + float2(0.20000000298023223876953125))); + out.FragColor += uSampler[3].sample(uSamplerSmplr[3], (in.vTex + float2(0.300000011920928955078125))); + return out; +} + diff --git a/reference/shaders-hlsl/frag/sampler-image-arrays.frag b/reference/shaders-hlsl/frag/sampler-image-arrays.frag new file mode 100644 index 00000000..856f04cf --- /dev/null +++ b/reference/shaders-hlsl/frag/sampler-image-arrays.frag @@ -0,0 +1,54 @@ +Texture2D uSampler[4] : register(t0); +SamplerState _uSampler_sampler[4] : register(s0); +Texture2D uTextures[4] : register(t8); +SamplerState uSamplers[4] : register(s4); + +static int vIndex; +static float2 vTex; +static float4 FragColor; + +struct SPIRV_Cross_Input +{ + nointerpolation float2 vTex : TEXCOORD0; + nointerpolation int vIndex : TEXCOORD1; +}; + +struct SPIRV_Cross_Output +{ + float4 FragColor : SV_Target0; +}; + +float4 sample_from_global() +{ + return uSampler[vIndex].Sample(_uSampler_sampler[vIndex], vTex + 0.100000001490116119384765625f.xx); +} + +float4 sample_from_argument(Texture2D samplers[4], SamplerState _samplers_sampler[4]) +{ + return samplers[vIndex].Sample(_samplers_sampler[vIndex], vTex + 0.20000000298023223876953125f.xx); +} + +float4 sample_single_from_argument(Texture2D samp, SamplerState _samp_sampler) +{ + return samp.Sample(_samp_sampler, vTex + 0.300000011920928955078125f.xx); +} + +void frag_main() +{ + FragColor = 0.0f.xxxx; + FragColor += uTextures[2].Sample(uSamplers[1], vTex); + FragColor += uSampler[vIndex].Sample(_uSampler_sampler[vIndex], vTex); + FragColor += sample_from_global(); + FragColor += sample_from_argument(uSampler, _uSampler_sampler); + FragColor += sample_single_from_argument(uSampler[3], _uSampler_sampler[3]); +} + +SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) +{ + vIndex = stage_input.vIndex; + vTex = stage_input.vTex; + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.FragColor = FragColor; + return stage_output; +} diff --git a/reference/shaders-msl/frag/sampler-image-arrays.msl2.frag b/reference/shaders-msl/frag/sampler-image-arrays.msl2.frag new file mode 100644 index 00000000..9c829cda --- /dev/null +++ b/reference/shaders-msl/frag/sampler-image-arrays.msl2.frag @@ -0,0 +1,45 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" + +#include +#include + +using namespace metal; + +struct main0_in +{ + int vIndex [[user(locn1)]]; + float2 vTex [[user(locn0)]]; +}; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +float4 sample_from_global(thread int& vIndex, thread float2& vTex, thread const array, 4> uSampler, thread const array uSamplerSmplr) +{ + return uSampler[vIndex].sample(uSamplerSmplr[vIndex], (vTex + float2(0.100000001490116119384765625))); +} + +float4 sample_from_argument(thread const array, 4> samplers, thread const array samplersSmplr, thread int& vIndex, thread float2& vTex) +{ + return samplers[vIndex].sample(samplersSmplr[vIndex], (vTex + float2(0.20000000298023223876953125))); +} + +float4 sample_single_from_argument(thread const texture2d samp, thread const sampler sampSmplr, thread float2& vTex) +{ + return samp.sample(sampSmplr, (vTex + float2(0.300000011920928955078125))); +} + +fragment main0_out main0(main0_in in [[stage_in]], array, 4> uSampler [[texture(0)]], array, 4> uTextures [[texture(1)]], array uSamplerSmplr [[sampler(0)]], array uSamplers [[sampler(1)]]) +{ + main0_out out = {}; + out.FragColor = float4(0.0); + out.FragColor += uTextures[2].sample(uSamplers[1], in.vTex); + out.FragColor += uSampler[in.vIndex].sample(uSamplerSmplr[in.vIndex], in.vTex); + out.FragColor += sample_from_global(in.vIndex, in.vTex, uSampler, uSamplerSmplr); + out.FragColor += sample_from_argument(uSampler, uSamplerSmplr, in.vIndex, in.vTex); + out.FragColor += sample_single_from_argument(uSampler[3], uSamplerSmplr[3], in.vTex); + return out; +} + diff --git a/reference/shaders-msl/frag/sampler.frag b/reference/shaders-msl/frag/sampler.frag index 5d234929..2ccdacca 100644 --- a/reference/shaders-msl/frag/sampler.frag +++ b/reference/shaders-msl/frag/sampler.frag @@ -16,7 +16,7 @@ struct main0_out float4 FragColor [[color(0)]]; }; -float4 sample_texture(thread const texture2d tex, thread const sampler& texSmplr, thread const float2& uv) +float4 sample_texture(thread const texture2d tex, thread const sampler texSmplr, thread const float2& uv) { return tex.sample(texSmplr, uv); } diff --git a/shaders-hlsl/frag/sampler-image-arrays.frag b/shaders-hlsl/frag/sampler-image-arrays.frag new file mode 100644 index 00000000..42370d97 --- /dev/null +++ b/shaders-hlsl/frag/sampler-image-arrays.frag @@ -0,0 +1,33 @@ +#version 450 + +layout(location = 0) out vec4 FragColor; +layout(location = 0) flat in vec2 vTex; +layout(location = 1) flat in int vIndex; +layout(binding = 0) uniform sampler2D uSampler[4]; +layout(binding = 4) uniform sampler uSamplers[4]; +layout(binding = 8) uniform texture2D uTextures[4]; + +vec4 sample_from_argument(sampler2D samplers[4]) +{ + return texture(samplers[vIndex], vTex + 0.2); +} + +vec4 sample_single_from_argument(sampler2D samp) +{ + return texture(samp, vTex + 0.3); +} + +vec4 sample_from_global() +{ + return texture(uSampler[vIndex], vTex + 0.1); +} + +void main() +{ + FragColor = vec4(0.0); + FragColor += texture(sampler2D(uTextures[2], uSamplers[1]), vTex); + FragColor += texture(uSampler[vIndex], vTex); + FragColor += sample_from_global(); + FragColor += sample_from_argument(uSampler); + FragColor += sample_single_from_argument(uSampler[3]); +} diff --git a/shaders-msl/frag/sampler-image-arrays.msl2.frag b/shaders-msl/frag/sampler-image-arrays.msl2.frag new file mode 100644 index 00000000..42370d97 --- /dev/null +++ b/shaders-msl/frag/sampler-image-arrays.msl2.frag @@ -0,0 +1,33 @@ +#version 450 + +layout(location = 0) out vec4 FragColor; +layout(location = 0) flat in vec2 vTex; +layout(location = 1) flat in int vIndex; +layout(binding = 0) uniform sampler2D uSampler[4]; +layout(binding = 4) uniform sampler uSamplers[4]; +layout(binding = 8) uniform texture2D uTextures[4]; + +vec4 sample_from_argument(sampler2D samplers[4]) +{ + return texture(samplers[vIndex], vTex + 0.2); +} + +vec4 sample_single_from_argument(sampler2D samp) +{ + return texture(samp, vTex + 0.3); +} + +vec4 sample_from_global() +{ + return texture(uSampler[vIndex], vTex + 0.1); +} + +void main() +{ + FragColor = vec4(0.0); + FragColor += texture(sampler2D(uTextures[2], uSamplers[1]), vTex); + FragColor += texture(uSampler[vIndex], vTex); + FragColor += sample_from_global(); + FragColor += sample_from_argument(uSampler); + FragColor += sample_single_from_argument(uSampler[3]); +} diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 8882f9de..ee45abd8 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -2292,11 +2292,7 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &) // Manufacture automatic sampler arg for SampledImage texture auto &arg_type = get(arg.type); if (arg_type.basetype == SPIRType::SampledImage && arg_type.image.dim != DimBuffer) - { - //const char *reference = arg_type.array.empty() ? "& " : " "; - const char *reference = " "; - decl += join(", thread const ", sampler_type(arg_type), reference, to_sampler_expression(arg.id)); - } + decl += join(", thread const ", sampler_type(arg_type), " ", to_sampler_expression(arg.id)); if (&arg != &func.arguments.back()) decl += ", "; @@ -3119,13 +3115,13 @@ string CompilerMSL::entry_point_args(bool append_comma) case SPIRType::Sampler: if (!ep_args.empty()) ep_args += ", "; - ep_args += type_to_glsl(type) + " " + r.name; + ep_args += sampler_type(type) + " " + r.name; ep_args += " [[sampler(" + convert_to_string(r.index) + ")]]"; break; case SPIRType::Image: if (!ep_args.empty()) ep_args += ", "; - ep_args += type_to_glsl(type, var_id) + " " + r.name; + ep_args += image_type_glsl(type, var_id) + " " + r.name; ep_args += " [[texture(" + convert_to_string(r.index) + ")]]"; break; default: @@ -3456,6 +3452,9 @@ std::string CompilerMSL::sampler_type(const SPIRType &type) { if (!type.array.empty()) { + if (!msl_options.supports_msl_version(2)) + SPIRV_CROSS_THROW("MSL 2.0 or greater is required for arrays of samplers."); + // Arrays of samplers in MSL must be declared with a special array syntax ala C++11 std::array. auto *parent = &type; while (parent->pointer) @@ -3478,6 +3477,9 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id) { if (!type.array.empty()) { + if (!msl_options.supports_msl_version(2)) + SPIRV_CROSS_THROW("MSL 2.0 or greater is required for arrays of textures."); + // Arrays of images in MSL must be declared with a special array syntax ala C++11 std::array. auto *parent = &type; while (parent->pointer) diff --git a/test_shaders.py b/test_shaders.py index 1ca8f9af..8ea6a61e 100755 --- a/test_shaders.py +++ b/test_shaders.py @@ -73,11 +73,12 @@ def print_msl_compiler_version(): raise def validate_shader_msl(shader, opt): + msl2 = '.msl2.' in shader msl_path = reference_path(shader[0], shader[1], opt) try: msl_os = 'macosx' # msl_os = 'iphoneos' - subprocess.check_call(['xcrun', '--sdk', msl_os, 'metal', '-x', 'metal', '-std=osx-metal1.2', '-Werror', '-Wno-unused-variable', msl_path]) + subprocess.check_call(['xcrun', '--sdk', msl_os, 'metal', '-x', 'metal', '-std=osx-metal{}'.format('2.0' if msl2 else '1.2'), '-Werror', '-Wno-unused-variable', msl_path]) print('Compiled Metal shader: ' + msl_path) # display after so xcrun FNF is silent except OSError as oe: if (oe.errno != os.errno.ENOENT): # Ignore xcrun not found error @@ -87,6 +88,7 @@ def validate_shader_msl(shader, opt): sys.exit(1) def cross_compile_msl(shader, spirv, opt): + msl2 = '.msl2.' in shader spirv_f, spirv_path = tempfile.mkstemp() msl_f, msl_path = tempfile.mkstemp(suffix = os.path.basename(shader)) os.close(spirv_f) @@ -101,7 +103,13 @@ def cross_compile_msl(shader, spirv, opt): subprocess.check_call(['spirv-opt', '-O', '-o', spirv_path, spirv_path]) spirv_cross_path = './spirv-cross' - subprocess.check_call([spirv_cross_path, '--entry', 'main', '--output', msl_path, spirv_path, '--msl']) + + msl_args = [spirv_cross_path, '--entry', 'main', '--output', msl_path, spirv_path, '--msl'] + if msl2: + msl_args.append('--msl-version') + msl_args.append('20000') + + subprocess.check_call(msl_args) subprocess.check_call(['spirv-val', spirv_path]) return (spirv_path, msl_path)