Originally, Metal did not support this directly, and still largely
doesn't on GPUs other than Apple family 6. Therefore, this
implementation uses vertex instancing to draw the needed views. To
support the Vulkan requirement that only the layers for the enabled
views are loaded and stored in a multiview render pass, this
implementation uses multiple Metal render passes for multiple "clumps"
of enabled views.
For indirect draws, as with tessellation, we must adjust the draw
parameters at execution time to account for the extra views, so we need
to use deferred store actions here. Without them, tracking the state
becomes too involved.
If the implementation doesn't support either layered rendering or
deferred store actions, multiview render passes are instead unrolled and
rendered one view at a time. This will enable us to support the
extension even on older devices and OSes, but at the cost of additional
command buffer memory and (possibly) worse performance.
Eventually, we should consider using vertex amplification to accelerate
this, particularly since indirect multiview draws are terrible and
currently require a compute pass to adjust the instance count. Also,
instanced drawing in itself is terrible due to its subpar performance.
But, since vertex amplification on family 6 only supports two views,
when `VK_KHR_multiview` mandates a minimum of 6, we'll still need to use
instancing to support more than two views.
I have tested this extensively against the CTS. I'm very confident in
its correctness. The only failing tests are
`dEQP-VK.multiview.queries.*`, due to our inadequate implementation of
timestamp queries; and `dEQP-VK.multiview.depth.*`, due to what I assume
is a bug in the way Metal handles arrayed packed depth/stencil textures,
and which may only be a problem on Mojave. I need to test this on
Catalina and Big Sur.
Update SPIRV-Cross to pull in some fixes necessary for this to work.
Fixes#347.
fetchDependencies support option to skip all library builds.
fetchDependencies avoid sync locks if not building in parallel.
fetchDependencies build glslang headers.
Update ExternalRevisions/README.md glslang build integration section.
Update What's New.
SPIRV-Cross can now AND the `gl_SampleMask` output with an additional
fixed mask, presumably from the pipeline. Use this new functionality to
implement pipeline sample mask handling.
Special thanks to Tomek Pontika and Corentin Wallez of Google for
graciously contributing their implementation to SPIRV-Cross.
Update SPIRV-Cross to pull in the change necessary for this.
Metal is picky about interface matching. If the types of a vertex output
and its corresponding fragment input don't match, down to the number of
vector components, it fails pipeline compilation. To support cases where
the number of components in the fragment input is less than the
corresponding vertex output, we need to fix up the fragment shader to
accept the extra components.
Add Scripts/packagePregenSpirvToolsHeaders script to automate packaging Spirv-Tools
headers in support of the fetchDependencies --skip-spirv-tools-build option.
Update Docs/Whats_New.md.
Update Cereal archive structs to match latest MoltenVK and SPIRV-Cross structs.
Fix recent error that caused pipeline cache data to be ignored during loading.
Update to Vulkan-Headers version 1.2.135.
Update to latest SPIRV-Cross version.
Update Whats_New.md document.
Add SPIRVShaderOutput::isUsed retrieved from shader reflection.
mvk::sizeOfOutput() returns zero if output var is not used.
Update to latest SPIRV-Cross version.
Add `MVK_CONFIG_TEXTURE_1D_AS_2D` environment variable, enabled by default.
Modify 1D warning messages to recommend use of `MVK_CONFIG_TEXTURE_1D_AS_2D`.
Update to latest version of SPIRV-Cross.
Align pipeline cache contents to latest CompilerMSL::Options structure.
Clean up code signing on demo Xcode projects.
Remove obsolescence log message for vkCreateMacOSSurfaceMVK()
and vkCreateIOSSurfaceMVK() functions.
Fix test for alignment of invalid pixel formats.
Update dependency libraries to match Vulkan SDK 1.1.121.
Update to renaming of VK_INTEL_shader_integer_functions2
enums and structs in latest Vulkan headers.
Update Whats_New.md document.
This extension allows fragment shaders to delineate critical sections
where pairs of invocations may not execute simultaneously. In Metal, the
nearest equivalent functionality is raster order groups. This
implementation is thus implemented on top of them.
Update SPIRV-Cross to pull in SPIR-V support for this new extension.
Largely minimal for now. Much of it, particularly most of the
interactions with `VK_KHR_swapchain`, was already implemented
previously. The only interesting bits are the `vkCmdDispatchBase()`
command, and the ability to create arbitrary swapchain images and bind
them to swapchain memory, which requires the use of the previously
implemented `VK_KHR_bind_memory2` extension. Most everything else can be
safely ignored for now.
Non-zero dispatch bases use the compute stage-input region to pass the
dispatch base group to the shader, which must manually adjust the
`WorkgroupId` and `GlobalInvocationId` builtins, since Metal does not do
this for us. I have tested that this approach works well--at least, well
enough to pass the CTS.
Because of the ability to bind arbitrary images to swapchain memory,
I've sucked the guts out of `MVKSwapchainImage` and into `MVKSwapchain`
itself. Availability and drawable management is now performed by the
swapchain object. `MVKSwapchainImage` is now just a specialized kind of
image, created when requested with a `VkImageCreateSwapchainInfoKHR`
structure.
Update SPIRV-Cross so we can support the `vkCmdDispatchBase()` command.
One more step towards Vulkan 1.1.
Update to latest external dependency libraries.
Rename components of VK_INTEL_shader_integer_functions2 to match 1.1.114 Vulkan spec.
Update What's New document.
This extension lets implementations report separate limits for uniform
and storage texel buffers, as well as whether or not the required
alignment is only a single texel of the buffer view's format.
This information is available in Metal, but only through an API query.
We must query the required alignment for every buffer view format we
support.
Update Vulkan-Headers to pull in support for this new extension.
Refactor SPIRVToMSLConverterContext into distinct SPIRVToMSLConversionConfiguration
and SPIRVToMSLConversionResults for conversion input and output, respectively.
Update to latest SPIRV-Cross version.
Update What's New document.
Support runtime shader compilation from GLSL.
Return VK_ERROR_INVALID_SHADER_NV on shader and pipeline compilation errors.
Add MVKShaderCompilationPerformance::glslToSPRIV to track GLSL conversion performance.
Rename MoltenVKGLSLToSPIRVConverter MVKShaderStage enum to MVKGLSLConversionShaderStage
to avoid naming conflicts with MoltenVK MVKShaderStage enum.
Hologram demo load SPIR-V directly instead of using GLSL through either
MoltenVKGLSLToSPIRVConverter or VK_NV_glsl_shader extension.
Update to latest version of VulkanSamples that supports MVKGLSLConversionShaderStage.
Add ExternalDependencies (Debug) scheme to ExternalDependencies Xcode project.
Add --debug option to fetchDependencies script.
Support Release, Debug & Latest directories in External/build directory.
Enable DEPLOYMENT_POSTPROCESSING build setting when compiling
SPIRV-Tools to avoid warning spam when building dylibs.
Disable visibility warnings when building MoltenVKShaderConverter
in Release mode from external libraries built in Debug mode.
Always use -Xlinker -w option when creating dylibs to disable visibility warnings.
Some projects also link against SPIRV-Cross statically, and in order to
avoid ABI conflicts, we should use a private namespace for the
SPIRV-Cross dependency to avoid bugs. See SPIRV-Cross issue #902 for
more information. The new namespace is MVK_spirv_cross, and the code
now makes use of the SPIRV_CROSS_NAMESPACE macro rather than spirv_cross.
This allows clients to reset query pools on the host, instead of with a
GPU command.
This updates Vulkan headers to 1.1.104... but, there's a problem. This
change has not been merged to `master` in the `Vulkan-Headers` repo yet,
because of an issue building the C++ binding headers. Luckily, we only
need the core C header.
At long last, tessellation comes to MoltenVK! With this change, clients
will now be able to specify tessellation shaders when creating
pipelines, and then draw tessellated patches with them.
Unfortunately, there seem to be a few gotchas with tessellation in
Metal. For one thing, tessellation pipelines in Metal are structured
very differently from Vulkan. There is no tessellation control or even
vertex stage. Instead, the tessellation evaluation shader takes the
place of the vertex function as a "post-tessellation vertex function."
The tessellation levels are supplied in a buffer to the tessellator,
which you are expected to populate. The most common way to do this is by
running a compute shader. MoltenVK thus runs the vertex shader and
tessellation control shader by themselves; a single `VkPipeline` object
then requires at least *three* `MTLPipelineState` objects.
But wait, there's more! The tessellation-control-as-compute stage uses
Metal's support for vertex-style stage input to a compute shader. But,
this support requires one to declare indexing *ahead of time*, when the
pipeline state is created. So a single `VkPipeline` object could have as
many as *five* `MTLPipelineState` objects.
Further, if there are more output than input control points for the
tessellation control stage, then later invocations may end up fetching
the wrong attributes! To get around this, this change uses index buffers
to ensure that all tessellation control shaders see the correct input.
Unfortunately, in the indexed draw case, this means that the incoming
index buffer needs to be munged.
Instancing is another pain point here. In Vulkan, as in OpenGL and
Direct3D, instancing is done in the vertex shader; but in Metal, it is
done at the tessellation evaluation stage. For this reason, only the
vertex stage of a tessellated draw supports instancing. Additional
memory is required to hold data for the extra vertices generated by
instancing. This also requires still more munging of index buffers for
indexed draws.
Indirect draws are even more painful. Because the number of vertices and
instances is unknown, storage for the maximum possible number of
vertices must be allocated. This change imposes a totally arbitrary
limit of 131072 vertices from a single draw, including all vertices
generated by instancing. On a Mac, this requires about 194-256 MB of
VRAM for all the temporary buffers.
There are some possible optimizations here. If we could prove that the
vertex shader's output doesn't depend on the instance ID, either
directly or through a per-instance attribute, then we could avoid
running the vertex and tess. control stages per instance, and take
advantage of Metal's support for tess. eval instancing. If we could
also prove that the vertex shader simply passes instance attributes
through (similarly with the tess. control shader), we could do this for
many more instanced draws as well. It should also be possible to cache
the output from the tess. control stage; if the draw comes up again, we
can then skip the vertex and tess. control stages entirely!
Fixes#56 and #501.
Track version of spvAux buffer struct in SPRIV-Cross and
fail build if different than version expected by MoltenVK.
Update MoltenVK version to 1.0.33.
Update What's New document.