Like with `VK_KHR_device_group` and `VK_KHR_external_memory`, this just
adds the groundwork needed to support future extensions; it provides no
actual support for external fences.
We should be able to easily support `VK_KHR_external_fence_fd`, by using
a POSIX semaphore. Since the fence FDs produced by that extension are
opaque, only supporting `close(2)` and `dup(2)`, we shouldn't have to
worry about portable programs poking the FD in weird ways. Hopefully.
Other types of external fences we might support include GCD semaphores
(`dispatch_semaphore_t`) and Mach semaphores (`semaphore_t`). I really
think we want support for GCD semaphores, because that's the most likely
object we're going to see passed between processes on Darwin given GCD's
built-in support for XPC.
I have deliberately omitted mention of these extensions from the user
guide. `VK_KHR_external_memory` was not mentioned in there, presumably
because no actual external memory types are actually supported.
Also, add missing `vkGetInstanceProcAddr()` entry for
`vkGetPhysicalDeviceExternalBufferPropertiesKHR()`. We have the
function, and we export the extension's name string. We might as well
make it available via `vkGetInstanceProcAddr()`.
XCFramework headers are still unusable due to an Xcode bug (documented in
create_xcframework_func.sh), but in testing for this, modifications to
create_xcframework_func.sh were made to test for the header file so that this
will work correctly when the Xcode bug is fixed and headers can be reintroduced.
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.
Delegate to MVKImage's getMTLTexture() method to use the overriden one
for swapchain images.
Also, the _mtlTextureViews member should be cleared to prevent accidental
reuse of released views.
- Delete fat library and framework scripts and templates.
- MoltenVK build package now only includes one XCFramework, and separate platform dylibs.
- Modify fetchDependencies and Makefile targets to not build fat libraries,
and to build simulators separately than platforms instead.
- Script package_moltenvk.sh now copies dylibs for all built platforms.
- Consolidate package_all.sh and delete package_one_os.sh.
- Swap names of copy_lib_to_staging.sh and copy_to_staging.sh scripts.
- Cube demo now uses MoltenVK as XCFramework, and support Simulator builds.
- Hologram demo now uses MoltenVK as dylibs from new packaging location.
- API-Samples demo now uses MoltenVK as XCFramework.
- Update documentation.
Nothing will be drawn in that case. Nothing would've been drawn anyway,
but Metal's validation layer complains if you issue a draw command with
zero vertices or instances.
We unfortunately cannot do anything about indirect draws, since we won't
know how many vertices to draw until execute time.
Prior to this, we were assuming one layer per clear rect. When that
assumption were broken, we wound up smashing the stack. This will be
more important once multiview support lands, since all views must be
cleared by the clear command.
The attachment index in the `VkClearAttachment` struct is an index into
the current subpass attachment array, not the render pass attachment
array; so it's not enough to check `VkClearAttachment` for
`VK_ATTACHMENT_UNUSED`. We also need to check the current subpass.
If no attachments can be cleared, don't encode a command to the Metal
command buffer.
Perhaps I should bring back `recordBeginRenderPass()` and
`recordEndRenderPass()` and keep track of the current subpass; then we
can avoid recording the command entirely if the intersection of the sets
"attachments to clear" and "used attachments" is null.
The current code does not handle multiple subpasses, nor does it handle
secondary command buffers. Handling subpasses was easy enough. The
problem came with secondary command buffers. Tracking them became
extremely complicated, particularly since pipelines may be set either
inside or outside a render pass, and further, a pipeline set in one
buffer might be used in another.
I then realized a simpler and more elegant solution: Metal's deferred
store actions feature. This allows you to defer setting the store action
for a render pass until encoding time. This is exactly what we need,
since we won't know what store action we actually want until we start
encoding draws. This solution should now work with multiple subpasses
and secondary command buffers, with much less code.
Create shader converters as XCFrameworks.
Don't create shader converters as fat libs, dylibs, or regular frameworks.
Rename create_xcframework.sh to create_xcframework_func.sh.
Use separate MoltenVK packaging scripts for one or all OS's.
Add package_one_os.sh.
Remove package_shader_converter_lib.sh.
Remove redundant GLSL shader converter dependencies in MoltenVK packaging targets.
Exclude arm64 architectures on macOS and Simulators.
Exclude arm64e architectures on iOS and tvOS.
Stop building fat libraries for external libraries.
Remove package_ext_libs.sh script.
Don't include Headers in ext lib XCFrameworks because of Xcode12 bug in using them.
It's a hard validation error to do so. We originally had a check for
this, but it was erroneously completely removed in #988, instead of
being limited to `renderTargetArrayLength`.
Fixes#991.
This should hopefully reduce underutilization of the GPU, especially on
GPUs where the thread execution width is greater than the number of
control points.
This also eliminates the extra invocations previously needed to read the
varyings from the vertex shader into the tessellation shader. The number
of threads per workgroup is now lcm(SIMD-size, output control points).
This should ensure we always process a whole number of patches per
workgroup, and further reduce underutilization of the GPU's SIMD units.
To avoid complexity handling indices in the tessellation control shader,
I've also changed the way vertex shaders for tessellation are handled.
They are now compute kernels using Metal's support for vertex-style
stage input. This lets us always emit vertices into the buffer in order
of vertex shader execution. Now we no longer have to deal with indexing
in the tessellation control shader, nor do we always have to duplicate
the index buffer to insert gaps. This also fixes a long-standing issue
where if an index were greater than the number of vertices to draw, the
vertex shader would wind up writing outside the buffer, and the vertex
would be lost.
Since on macOS textures cannot be resident in shared (host-coherent) memory,
they need to be flushed before making the copy, to ensure that the modified
data is transferred.