Commit Graph

182 Commits

Author SHA1 Message Date
Hans-Kristian Arntzen
3fe57d3798 Do not use SmallVector as input type in public interfaces.
This is an API break, which we need to be careful with.
Handing out SmallVectors is easier since the interface is basically the
same.
2019-04-09 15:09:44 +02:00
Hans-Kristian Arntzen
a489ba7fd1 Reduce pressure on global allocation.
- Replace ostringstream with custom implementation.
  ~30% performance uplift on vector-shuffle-oom test.
  Allocations are measurably reduced in Valgrind.

- Replace std::vector with SmallVector.
  Classic malloc optimization, small vectors are backed by inline data.
  ~ 7-8% gain on vector-shuffle-oom on GCC 8 on Linux.

- Use an object pool for IVariant type.
  We generally allocate a lot of SPIR* objects. We can amortize these
  allocations neatly by pooling them.

- ~15% overall uplift on ./test_shaders.py --iterations 10000 shaders/.
2019-04-09 15:09:44 +02:00
Hans-Kristian Arntzen
23db744e35 Deal with case where we need to emit SpvImplArrayCopy late.
We cannot deduce if OpLoad needs ArrayCopy templates early since it's
heavily context dependent, and we might only know on 3rd iteration of
the compile loop.
2019-04-09 12:28:46 +02:00
Hans-Kristian Arntzen
9b92e68d71 Add an option to override the namespace used for spirv_cross.
This is a pragmatic trick to avoid symbol collision where a project
links against SPIRV-Cross statically, while linking to other projects
which also use SPIRV-Cross statically. We can end up with very awkward
symbol collisions which can resolve themselves silently because
SPIRV-Cross is pulled in as necessary. To fix this, we must use
different symbols and embed two copies of SPIRV-Cross in this scenario,
now with different namespaces, which in turn leads to different symbols.
2019-03-29 10:29:44 +01:00
Hans-Kristian Arntzen
e2aadf8995 Rename "push descriptor set" to "discrete descriptor set".
Check for case where iOS doesn't support writable argument buffer
textures.
2019-03-15 21:53:21 +01:00
Hans-Kristian Arntzen
b3380ec9dd MSL: Support VK_KHR_push_descriptor.
If we have argument buffers, we also need to support using plain
descriptor sets for certain cases where API wants it.
2019-03-15 14:08:47 +01:00
Hans-Kristian Arntzen
a5f072d2ab MSL: Add some comments about how we remap bindings for IAB. 2019-03-15 13:07:59 +01:00
Hans-Kristian Arntzen
bc21ccb7ce MSL: Emit correct SSBO constness for argument buffers. 2019-03-15 12:05:35 +01:00
Hans-Kristian Arntzen
e47a77d596 MSL: Implement Metal 2.0 indirect argument buffers. 2019-03-15 11:01:27 +01:00
Hans-Kristian Arntzen
e74c21a39b Review fixups. 2019-03-04 10:08:31 +01:00
Hans-Kristian Arntzen
9bbdccddb7 Add a stable C API for SPIRV-Cross.
This adds a new C API for SPIRV-Cross which is intended to be stable,
both API and ABI wise.

The C++ API has been refactored a bit to make the C wrapper easier and
cleaner to write. Especially the vertex attribute / resource interfaces
for MSL has been rewritten to avoid taking mutable pointers into the
interface. This would be very annoying to wrap and it didn't fit well
with the rest of the C++ API to begin with. While doing this, I went
ahead and removed all the old deprecated interfaces.

The CMake build system has also seen an overhaul.
It is now possible to build static/shared/CLI separately with -D
options.
The shared library only exposes the C API, as it is the only ABI-stable
API. pkg-configs as well as CMake modules are exported and installed for
the shared library configuration.
2019-03-01 11:53:51 +01:00
Chip Davis
f3c0942d10 MSL: Use vectors for the tessellation level builtins in tese shaders.
The tessellation levels in Metal are stored as a densely-packed array of
half-precision floating point values. But, stage-in attributes in Metal
have to have offsets and strides aligned to a multiple of four, so we
can't add them individually. Luckily for us, the arrays have lengths
less than 4. So, let's use vectors for them!

Triangles get a single attribute with a `float4`, where the outer levels
are in `.xyz` and the inner levels are in `.w`. The arrays are unpacked
as though we had added the elements individually. Quads get two: a
`float4` with the outer levels and a `float2` with the inner levels.
Further, since vectors can be indexed as arrays, there's no need to
unpack them in this case.

This also saves on precious vertex attributes. Before, we were using up
to 6 of them. Now we need two at most.
2019-02-22 12:18:51 -06:00
Chip Davis
5069ec72bb MSL: Set location of builtins based on client input.
Builtin attributes in SPIR-V aren't linked by location, but by their
built-in-ness. This poses a problem for MSL, since builtin inputs in
the vertex pipeline are just regular attributes. We must then assign
them locations so that they can be matched up to the attributes in the
stage input descriptor--and also to avoid duplicate attribute numbers in
tessellation evaluation shaders, where there are two different
stage-in structs, so the member index therein is no longer unique!
2019-02-20 22:16:51 -06:00
Chip Davis
8095434dc4 MSL: Drop stores to nonexistent tess levels.
In SPIR-V, there are always two inner levels and four outer levels, even
if the input patch isn't a quad patch. But in MSL, due to requirements
imposed by Metal, only one inner level and three outer levels exist when
the input patch is a triangle patch. We must explicitly ignore any write
to the nonexistent second inner and fourth outer levels in this case.
2019-02-20 09:11:24 -06:00
Chip Davis
68b09f2a34 MSL: Set rasterization disabled for tese shaders, too. 2019-02-20 09:11:20 -06:00
Chip Davis
41d9424233 MSL: Add an option to set the tessellation domain origin.
This is intended to be used to support `VK_KHR_maintenance2`'s
tessellation domain origin feature. If `tess_domain_origin_lower_left`
is `true`, the `v` coordinate will be inverted with respect to the
domain. Additionally, in `Triangles` mode, the `v` and `w` coordinates
will be swapped. This is because the winding order is interpreted
differently in lower-left mode.
2019-02-18 14:25:42 -06:00
Chip Davis
6b7988046d Handle blocks of patch I/O.
In this case, each member of the block will be decorated with
`DecorationPatch`, rather than the block variable having the decoration.
2019-02-15 17:21:38 -06:00
Chip Davis
e75add42c9 MSL: Add support for tessellation evaluation shaders.
These are mapped to Metal's post-tessellation vertex functions. The
semantic difference is much less here, so this change should be simpler
than the previous one. There are still some hairy parts, though.

In MSL, the array of control point data is represented by a special
type, `patch_control_point<T>`, where `T` is a valid stage-input type.
This object must be embedded inside the patch-level stage input. For
this reason, I've added a new type to the type system to represent this.

On Mac, the number of input control points to the function must be
specified in the `patch()` attribute. This is optional on iOS.
SPIRV-Cross takes this from the `OutputVertices` execution mode; the
intent is that if it's not set in the shader itself, MoltenVK will set
it from the tessellation control shader. If you're translating these
offline, you'll have to update the control point count manually, since
this number must match the number that is passed to the
`drawPatches:...` family of methods.

Fixes #120.
2019-02-14 10:00:08 -06:00
Hans-Kristian Arntzen
878c502f96 MSL: Hoist out complicated tesc workaround code. 2019-02-14 09:28:17 +01:00
Chip Davis
eb89c3a428 MSL: Add support for tessellation control shaders.
These are transpiled to kernel functions that write the output of the
shader to three buffers: one for per-vertex varyings, one for per-patch
varyings, and one for the tessellation levels. This structure is
mandated by the way Metal works, where the tessellation factors are
supplied to the draw method in their own buffer, while the per-patch and
per-vertex varyings are supplied as though they were vertex attributes;
since they have different step rates, they must be in separate buffers.

The kernel is expected to be run in a workgroup whose size is the
greater of the number of input or output control points. It uses Metal's
support for vertex-style stage input to a compute shader to get the
input values; therefore, at least one instance must run per input point.
Meanwhile, Vulkan mandates that it run at least once per output point.
Overrunning the output array is a concern, but any values written should
either be discarded or overwritten by subsequent patches. I'm probably
going to put some slop space in the buffer when I integrate this into
MoltenVK to be on the safe side.
2019-02-07 08:51:22 -06:00
Chip Davis
ae87c41b96 Provide feedback on whether or not an output buffer is needed. 2019-02-06 17:22:12 -06:00
Chip Davis
056c0e207d Take the vertex count from any indirect parameters passed.
This is necessary to deal with indirect draws, where the draw parameters
are given in a buffer instead of passed by the CPU. For normal draws,
the draw parameters are set with Metal's `setVertexBytes:` method.

This undoes the change to add the vertex count to the aux buffer,
rendering that entire discussion largely moot. Oh well. It was a
discussion that needed to happen anyway.
2019-02-06 15:17:14 -06:00
Chip Davis
f55253dc1b On second thought, don't use a feature struct for the aux buffer. 2019-02-06 14:45:26 -06:00
Chip Davis
ea74e453e3 Use a macro instead of a field for the struct version. 2019-02-06 14:43:03 -06:00
Chip Davis
d86adbe550 Add a structure to hold optional members of the aux buffer.
Programs can query the version to know what features are present, and
turn them on and off at will.
2019-02-06 14:26:06 -06:00
Chip Davis
c51e5b7911 MSL: Add a setting to capture vertex shader output to a buffer.
This will be necessary to support transform feedback, as well as
tessellation shaders.
2019-02-05 20:00:10 -06:00
Hans-Kristian Arntzen
1040cf6cc1
Merge pull request #831 from cdavis5e/force-recompile-hooks
MSL: Hoist fixup hooks in entry_point_args() out of the compile loop.
2019-01-17 19:42:05 +01:00
Chip Davis
f500d2f70c MSL: Hoist fixup hooks in entry_point_args() out of the compile loop.
Otherwise, in the event of a forced recompile, we could end up adding
them twice.
2019-01-17 10:18:38 -06:00
Hans-Kristian Arntzen
73d9da7070 Avoid unintentional name conflict with HLSL backend. 2019-01-17 12:21:16 +01:00
Hans-Kristian Arntzen
432aaed737 Need to know the original packed type when unpacking loads. 2019-01-17 11:39:46 +01:00
Hans-Kristian Arntzen
15b52bee48 Deal with packing/unpacking on store.
Still a bit buggy, since we cannot deduce between float2[] and
packed_float2. Need a deeper refactor to plumb this through ...
2019-01-17 10:06:23 +01:00
Hans-Kristian Arntzen
9e3a41ad00
Merge pull request #821 from cdavis5e/pass-sampled-images
MSL: Fix passing a sampled image to a function.
2019-01-15 09:05:54 +01:00
Chip Davis
664df22d12 MSL: Fix passing a sampled image to a function.
In the past, SPIRV-Cross threw an error in this case because it couldn't
work out which swizzle from the auxiliary buffer needs to be passed.
Now, we pass the swizzle around with the texture object, like a combined
image-sampler and its associated sampler.
2019-01-14 09:29:31 -06:00
Hans-Kristian Arntzen
b8033d7525 MSL: Add option to pad fragment outputs.
If not enough components are provided in the shader,
the shader MSL compiler throws an error rather than make components
undefined. This hurts portability, so we need to add explicit padding
here.
2019-01-14 15:11:52 +01:00
Hans-Kristian Arntzen
d92de00cc1 Rewrite how IDs are iterated over.
This is a fairly fundamental change on how IDs are handled.
It serves many purposes:

- Improve performance. We only need to iterate over IDs which are
  relevant at any one time.
- Makes sure we iterate through IDs in SPIR-V module declaration order
  rather than ID space. IDs don't have to be monotonically increasing,
  which was an assumption SPIRV-Cross used to have. It has apparently
  never been a problem until now.
- Support LUTs of structs. We do this by interleaving declaration of
  constants and struct types in SPIR-V module order.

To support this, the ParsedIR interface needed to change slightly.
Before setting any ID with variant_set<T> we let ParsedIR know
that an ID with a specific type has been added. The surface for change
should be minimal.

ParsedIR will maintain a per-type list of IDs which the cross-compiler
will need to consider for later.

Instead of looping over ir.ids[] (which can be extremely large), we loop
over types now, using:

ir.for_each_typed_id<SPIRVariable>([&](uint32_t id, SPIRVariable &var) {
	handle_variable(var);
});

Now we make sure that we're never looking at irrelevant types.
2019-01-10 12:52:56 +01:00
Hans-Kristian Arntzen
5345756cab MSL: Support composites inside I/O blocks
I had to refactor the existing add_interface_block as it was
getting extremely large. Now it's all split up into different readable
functions.
2019-01-09 09:33:10 +01:00
Chip Davis
3bfb2f94d4 MSL: Support SPV_KHR_variable_pointers.
This allows shaders to declare and use pointer-type variables. Pointers
may be loaded and stored, be the result of an `OpSelect`, be passed to
and returned from functions, and even be passed as inputs to the `OpPhi`
instruction. All types of pointers may be used as variable pointers.
Variable pointers to storage buffers and workgroup memory may even be
loaded from and stored to, as though they were ordinary variables. In
addition, this enables using an interior pointer to an array as though
it were an array pointer itself using the `OpPtrAccessChain`
instruction.

This is a rather large and involved change, mostly because this is
somewhat complicated with a lot of moving parts. It's a wonder
SPIRV-Cross's output is largely unchanged. Indeed, many of these changes
are to accomplish exactly that! Perhaps the largest source of changes
was the violation of the assumption that, when emitting types, the
pointer type didn't matter.

One of the test cases added by the change doesn't optimize very well;
the output of `spirv-opt` here is invalid SPIR-V. I need to file a bug
with SPIRV-Tools about this.

I wanted to test that variable pointers to images worked too, but I
couldn't figure out how to propagate the access qualifier properly--in
MSL, it's part of the type, so getting this right is important. I've
punted on that for now.
2019-01-07 11:19:10 -06:00
Hans-Kristian Arntzen
318c17cbb2 Nonfunctional: Update copyright headers for 2019. 2019-01-04 12:38:35 +01:00
Chip Davis
6db79b80c1 MSL: Use an enum instead of two mutually exclusive booleans.
NFCI.
2018-12-04 13:54:29 -06:00
Chip Davis
06d483459b MSL: Force signedness of shader vertex attributes to match the host.
Based on a patch by Stefan Dösinger.

Metal cannot do signedness conversion on vertex attributes, and for good
reason. Putting a `uint4` into an `int4`, or a `char4` into a `uint4`,
would lose those values that are outside the range of the target type.
But putting a `uchar4` into a `short4` or an `int4`, or a `ushort4` into
an `int4`, should work. In that case, force the signedness in the shader
to match the declared type of the host.

Unfortunately, I don't really know how to automatically test this. This
remapping is done based on input parameters normally supplied by
MoltenVK. I'm not sure how we'd set this up for the command-line
`spirv-cross` tool.
2018-11-28 17:53:56 -06:00
Connor McLaughlin
1dd676c1de MSL: Emit wrapper for SSign (sign() for int types)
Metal does not define the sign() function for integer types, only
floating-point types.
2018-11-08 13:08:34 +10:00
Hans-Kristian Arntzen
480acdad18 Deal with OpSpecConstantOp used as array size.
When trying to validate buffer sizes, we usually need to bail out when
using SpecConstantOps, but for some very specific cases where we allow
unsized arrays currently, we can safely allow "unknown" sized arrays as
well.

This is probably the best we can do, when we have even more difficult
cases than this, we throw a more sensible error message.
2018-11-01 14:58:02 +01:00
Hans-Kristian Arntzen
62db535b3f Update tests. 2018-11-01 11:23:48 +01:00
Hans-Kristian Arntzen
5bcf02f7c9 Hoist out parsing module from spirv_cross::Compiler.
This is a large refactor which splits out the SPIR-V parser from
Compiler and moves it into its more appropriately named Parser module.

The Parser is responsible for building a ParsedIR structure which is
then consumed by one or more compilers.

Compiler can take a ParsedIR by value or move reference. This should
allow for optimal case for both multiple compilations and single
compilation scenarios.
2018-10-19 12:01:31 +02:00
Chip Davis
3a9af9681c MSL: Expand arrays of buffers passed as input.
Even as of Metal 2.1, MSL still doesn't support arrays of buffers
directly. Therefore, we must manually expand them. In the prologue, we
define arrays holding the argument pointers; these arrays are what the
transpiled code ends up referencing. We might be able to do similar
things for textures and samplers prior to MSL 2.0.

Speaking of which, also enable texture arrays on iOS MSL 1.2.
2018-09-26 20:48:09 -05:00
Chip Davis
7107f40f99 Provide feedback on whether or not the auxiliary buffer is needed. 2018-09-24 13:38:27 -05:00
Chip Davis
8855ea0a3e Move is_sampled_image_type() onto the Compiler class.
While I'm at it, don't use a bitwise op with a `bool` variable.
Apparently, MSVC doesn't like that.
2018-09-24 12:24:58 -05:00
Chip Davis
c11374c3cf Don't override Compiler::analyze_image_and_sampler_usage().
Just add our own separate function for analyzing sampled image usage.
2018-09-24 12:10:27 -05:00
Chip Davis
4302c5abfb Pass the swizzle constants as a buffer.
It'll be useful to have an "auxiliary buffer" for other builtins--e.g.
`DrawIndex` (which should be easier to implement now), or `ViewIndex`
when someone gets around to implementing multiview.

Pass this buffer to leaf functions as well.

Test that we handle this for integer textures as well.
2018-09-22 19:36:11 -05:00
Chip Davis
2583321657 MSL: Add an option to insert texture swizzles into generated shaders.
It's intended to be used with MoltenVK to support arbitrary
`VkComponentMapping` settings. The idea is that MoltenVK will pass a
buffer (which it set to some buffer index that isn't being used)
containing packed versions of the `VkComponentMapping` struct, one for
each sampled image.

Yes, this is horribly ugly. It is unfortunately necessary. Much of the
ugliness is to support swizzling gather operations, where we need to
alter the component that the gather operates on--something complicated
by the `gather()` method requiring the passed-in component to be a
constant expression. It doesn't even support swizzling gathers on depth
textures, though I could add that if it turns out we need it.
2018-09-19 22:32:24 -05:00