Merge pull request #2036 from billhollings/VK_EXT_extended_dynamic_state

Add support for VK_EXT_extended_dynamic_state & VK_EXT_extended_dynamic_state2 extensions.
This commit is contained in:
Bill Hollings 2023-10-11 17:37:11 -04:00 committed by GitHub
commit 61b8712178
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 1665 additions and 929 deletions

View File

@ -312,7 +312,8 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
- `VK_KHR_16bit_storage`
- `VK_KHR_8bit_storage`
- `VK_KHR_bind_memory2`
- `VK_KHR_buffer_device_address` *(requires GPU Tier 2 argument buffers support)*
- `VK_KHR_buffer_device_address`
- *Requires GPU Tier 2 argument buffers support.*
- `VK_KHR_copy_commands2`
- `VK_KHR_create_renderpass2`
- `VK_KHR_dedicated_allocation`
@ -322,7 +323,8 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
- `VK_KHR_device_group_creation`
- `VK_KHR_driver_properties`
- `VK_KHR_dynamic_rendering`
- `VK_KHR_fragment_shader_barycentric` *(requires Metal 2.2 on Mac or Metal 2.3 on iOS)*
- `VK_KHR_fragment_shader_barycentric`
- *Requires Metal 2.2 on Mac or Metal 2.3 on iOS.*
- `VK_KHR_get_memory_requirements2`
- `VK_KHR_get_physical_device_properties2`
- `VK_KHR_get_surface_capabilities2`
@ -337,14 +339,16 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
- `VK_KHR_portability_subset`
- `VK_KHR_push_descriptor`
- `VK_KHR_relaxed_block_layout`
- `VK_KHR_sampler_mirror_clamp_to_edge` *(requires a Mac GPU or Apple family 7 GPU)*
- `VK_KHR_sampler_mirror_clamp_to_edge`
- *Requires a Mac GPU or Apple family 7 GPU.*
- `VK_KHR_sampler_ycbcr_conversion`
- `VK_KHR_separate_depth_stencil_layouts`
- `VK_KHR_shader_draw_parameters`
- `VK_KHR_shader_float_controls`
- `VK_KHR_shader_float16_int8`
- `VK_KHR_shader_non_semantic_info`
- `VK_KHR_shader_subgroup_extended_types` *(requires Metal 2.1 on Mac or Metal 2.2 and Apple family 4 on iOS)*
- `VK_KHR_shader_subgroup_extended_types`
- *Requires Metal 2.1 on Mac or Metal 2.2 and Apple family 4 on iOS.*
- `VK_KHR_spirv_1_4`
- `VK_KHR_storage_buffer_storage_class`
- `VK_KHR_surface`
@ -354,53 +358,78 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
- `VK_KHR_timeline_semaphore`
- `VK_KHR_uniform_buffer_standard_layout`
- `VK_KHR_variable_pointers`
- `VK_EXT_4444_formats` *(requires 16-bit formats and either native texture swizzling or manual swizzling to be enabled)*
- `VK_EXT_buffer_device_address` *(requires GPU Tier 2 argument buffers support)*
- `VK_EXT_calibrated_timestamps` *(requires Metal 2.2)*
- `VK_EXT_4444_formats`
- *Requires 16-bit formats and either native texture swizzling or manual swizzling to be enabled.*
- `VK_EXT_buffer_device_address`
- *Requires GPU Tier 2 argument buffers support.*
- `VK_EXT_calibrated_timestamps`
- *Requires Metal 2.2.*
- `VK_EXT_debug_marker`
- `VK_EXT_debug_report`
- `VK_EXT_debug_utils`
- `VK_EXT_descriptor_indexing` *(initial release limited to Metal Tier 1: 96/128 textures,
- `VK_EXT_descriptor_indexing`
- *Initial release limited to Metal Tier 1: 96/128 textures,
16 samplers, except macOS 11.0 (Big Sur) or later, or on older versions of macOS using
an Intel GPU, and if Metal argument buffers enabled in config)*
an Intel GPU, and if Metal argument buffers enabled in config.*
- `VK_EXT_extended_dynamic_state`
- *Requires Metal 3.1 for `VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE`.*
- `VK_EXT_extended_dynamic_state2`
- *Primitive restart is always enabled, as Metal does not support disabling it (`VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT`).*
- `VK_EXT_external_memory_host`
- `VK_EXT_fragment_shader_interlock` *(requires Metal 2.0 and Raster Order Groups)*
- `VK_EXT_fragment_shader_interlock`
- *Requires Metal 2.0 and Raster Order Groups.*
- `VK_EXT_host_query_reset`
- `VK_EXT_image_robustness`
- `VK_EXT_inline_uniform_block`
- `VK_EXT_memory_budget` *(requires Metal 2.0)*
- `VK_EXT_memory_budget`
- *Requires Metal 2.0.*
- `VK_EXT_metal_objects`
- `VK_EXT_metal_surface`
- `VK_EXT_pipeline_creation_cache_control`
- `VK_EXT_pipeline_creation_feedback`
- `VK_EXT_post_depth_coverage` *(iOS and macOS, requires family 4 (A11) or better Apple GPU)*
- `VK_EXT_post_depth_coverage`
- *iOS and macOS, requires family 4 (A11) or better Apple GPU.*
- `VK_EXT_private_data `
- `VK_EXT_robustness2`
- `VK_EXT_sample_locations`
- `VK_EXT_scalar_block_layout`
- `VK_EXT_separate_stencil_usage`
- `VK_EXT_shader_atomic_float` *(requires Metal 3.0)*
- `VK_EXT_shader_demote_to_helper_invocation` *(requires Metal Shading Language 2.3)*
- `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)*
- `VK_EXT_shader_subgroup_ballot` *(requires Mac GPU family 2 or Apple GPU family 4)*
- `VK_EXT_shader_subgroup_vote` *(requires Mac GPU family 2 or Apple GPU family 4)*
- `VK_EXT_shader_atomic_float`
- *Requires Metal 3.0.*
- `VK_EXT_shader_demote_to_helper_invocation`
- *Requires Metal Shading Language 2.3.*
- `VK_EXT_shader_stencil_export`
- *Requires Mac GPU family 2 or iOS GPU family 5.*
- `VK_EXT_shader_subgroup_ballot`
- *Requires Mac GPU family 2 or Apple GPU family 4.*
- `VK_EXT_shader_subgroup_vote`
- *Requires Mac GPU family 2 or Apple GPU family 4.*
- `VK_EXT_shader_viewport_index_layer`
- `VK_EXT_subgroup_size_control` *(requires Metal 2.1 on Mac or Metal 2.2 and Apple family 4 on iOS)*
- `VK_EXT_subgroup_size_control`
- *Requires Metal 2.1 on Mac or Metal 2.2 and Apple family 4 on iOS.*
- `VK_EXT_surface_maintenance1`
- `VK_EXT_swapchain_colorspace`
- `VK_EXT_swapchain_maintenance1`
- `VK_EXT_vertex_attribute_divisor`
- `VK_EXT_texel_buffer_alignment` *(requires Metal 2.0)*
- `VK_EXT_texture_compression_astc_hdr` *(iOS and macOS, requires family 6 (A13) or better Apple GPU)*
- `VK_MVK_ios_surface` *(iOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*
- `VK_MVK_macos_surface` *(macOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*
- `VK_EXT_texel_buffer_alignment`
- *Requires Metal 2.0.*
- `VK_EXT_texture_compression_astc_hdr`
- *iOS and macOS, requires family 6 (A13) or better Apple GPU.*
- `VK_MVK_ios_surface`
- *Obsolete. Use `VK_EXT_metal_surface` instead.*
- `VK_MVK_macos_surface`
- *Obsolete. Use `VK_EXT_metal_surface` instead.*
- `VK_AMD_gpu_shader_half_float`
- `VK_AMD_negative_viewport_height`
- `VK_AMD_shader_image_load_store_lod` *(requires Apple GPU)*
- `VK_AMD_shader_trinary_minmax` *(requires Metal 2.1)*
- `VK_IMG_format_pvrtc` *(requires Apple GPU)*
- `VK_AMD_shader_image_load_store_lod`
- *Requires Apple GPU.*
- `VK_AMD_shader_trinary_minmax`
- *Requires Metal 2.1.*
- `VK_IMG_format_pvrtc`
- *Requires Apple GPU.*
- `VK_INTEL_shader_integer_functions2`
- `VK_NV_fragment_shader_barycentric` *(requires Metal 2.2 on Mac or Metal 2.3 on iOS)*
- `VK_NV_fragment_shader_barycentric`
- *Requires Metal 2.2 on Mac or Metal 2.3 on iOS.*
- `VK_NV_glsl_shader`
In order to visibly display your content on *macOS*, *iOS*, or *tvOS*, you must enable the
@ -623,6 +652,8 @@ Known **MoltenVK** Limitations
This section documents the known limitations in this version of **MoltenVK**.
- See [above](#interaction) for known limitations for specific Vulkan extensions.
- On *macOS* versions prior to *macOS 10.15.6*, native host-coherent image device memory is not available.
Because of this, changes made to `VkImage VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` device memory by the CPU
or GPU will not be available to the GPU or CPU, respectively, until the memory is flushed or unmapped by
@ -645,4 +676,3 @@ This section documents the known limitations in this version of **MoltenVK**.
use the *Vulkan Loader and Layers* from the *[Vulkan SDK](https://vulkan.lunarg.com/sdk/home)*.
Refer to the *Vulkan SDK [Getting Started](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html)*
document for more info.

View File

@ -20,6 +20,8 @@ Released TBD
- Add support for extensions:
- `VK_KHR_synchronization2`
- `VK_EXT_extended_dynamic_state` *(requires Metal 3.1 for `VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE`)*
- `VK_EXT_extended_dynamic_state2`
- Fix rare case where vertex attribute buffers are not bound to Metal
when no other bindings change between pipelines.
- Ensure objects retained for life of `MTLCommandBuffer` during `vkCmdBlitImage()` & `vkQueuePresentKHR()`.

View File

@ -46,7 +46,7 @@
2FEA0A6724902F9F00EEF3AD /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F0429D1FB4CF82009FCCB8 /* MVKCommonEnvironment.h */; };
2FEA0A6824902F9F00EEF3AD /* MVKWatermark.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149491FB6A3F7005F00B4 /* MVKWatermark.h */; };
2FEA0A6924902F9F00EEF3AD /* MVKOSExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.h */; };
2FEA0A6A24902F9F00EEF3AD /* MVKCmdRenderPass.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */; };
2FEA0A6A24902F9F00EEF3AD /* MVKCmdRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */; };
2FEA0A6B24902F9F00EEF3AD /* MVKCmdPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB76E1C7DFB4800632CA3 /* MVKCmdPipeline.h */; };
2FEA0A6C24902F9F00EEF3AD /* MVKSmallVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */; };
2FEA0A6D24902F9F00EEF3AD /* MVKPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB78D1C7DFB4800632CA3 /* MVKPipeline.h */; };
@ -90,7 +90,7 @@
2FEA0A9424902F9F00EEF3AD /* MVKCommandPool.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB77B1C7DFB4800632CA3 /* MVKCommandPool.mm */; };
2FEA0A9524902F9F00EEF3AD /* MVKCmdDraw.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */; };
2FEA0A9624902F9F00EEF3AD /* MVKCommandBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7791C7DFB4800632CA3 /* MVKCommandBuffer.mm */; };
2FEA0A9724902F9F00EEF3AD /* MVKCmdRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */; };
2FEA0A9724902F9F00EEF3AD /* MVKCmdRendering.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */; };
2FEA0A9824902F9F00EEF3AD /* MVKBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7801C7DFB4800632CA3 /* MVKBuffer.mm */; };
2FEA0A9924902F9F00EEF3AD /* mvk_datatypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */; };
2FEA0A9A24902F9F00EEF3AD /* MVKExtensions.mm in Sources */ = {isa = PBXBuildFile; fileRef = A909F65E213B190700FCD6BE /* MVKExtensions.mm */; };
@ -172,10 +172,10 @@
A94FB7C11C7DFB4800632CA3 /* MVKCmdQueries.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7701C7DFB4800632CA3 /* MVKCmdQueries.h */; };
A94FB7C21C7DFB4800632CA3 /* MVKCmdQueries.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */; };
A94FB7C31C7DFB4800632CA3 /* MVKCmdQueries.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */; };
A94FB7C41C7DFB4800632CA3 /* MVKCmdRenderPass.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */; };
A94FB7C51C7DFB4800632CA3 /* MVKCmdRenderPass.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */; };
A94FB7C61C7DFB4800632CA3 /* MVKCmdRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */; };
A94FB7C71C7DFB4800632CA3 /* MVKCmdRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */; };
A94FB7C41C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */; };
A94FB7C51C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */; };
A94FB7C61C7DFB4800632CA3 /* MVKCmdRendering.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */; };
A94FB7C71C7DFB4800632CA3 /* MVKCmdRendering.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */; };
A94FB7C81C7DFB4800632CA3 /* MVKCmdDraw.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7741C7DFB4800632CA3 /* MVKCmdDraw.h */; };
A94FB7C91C7DFB4800632CA3 /* MVKCmdDraw.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7741C7DFB4800632CA3 /* MVKCmdDraw.h */; };
A94FB7CA1C7DFB4800632CA3 /* MVKCmdDraw.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */; };
@ -420,7 +420,7 @@
DCFD7F0B2A45BC6E007BBBF7 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F0429D1FB4CF82009FCCB8 /* MVKCommonEnvironment.h */; };
DCFD7F0C2A45BC6E007BBBF7 /* MVKWatermark.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149491FB6A3F7005F00B4 /* MVKWatermark.h */; };
DCFD7F0D2A45BC6E007BBBF7 /* MVKOSExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.h */; };
DCFD7F0E2A45BC6E007BBBF7 /* MVKCmdRenderPass.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */; };
DCFD7F0E2A45BC6E007BBBF7 /* MVKCmdRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */; };
DCFD7F0F2A45BC6E007BBBF7 /* MVKCmdPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB76E1C7DFB4800632CA3 /* MVKCmdPipeline.h */; };
DCFD7F102A45BC6E007BBBF7 /* MVKSmallVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */; };
DCFD7F112A45BC6E007BBBF7 /* MVKPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB78D1C7DFB4800632CA3 /* MVKPipeline.h */; };
@ -466,7 +466,7 @@
DCFD7F3A2A45BC6E007BBBF7 /* MVKCommandPool.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB77B1C7DFB4800632CA3 /* MVKCommandPool.mm */; };
DCFD7F3B2A45BC6E007BBBF7 /* MVKCmdDraw.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */; };
DCFD7F3C2A45BC6E007BBBF7 /* MVKCommandBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7791C7DFB4800632CA3 /* MVKCommandBuffer.mm */; };
DCFD7F3D2A45BC6E007BBBF7 /* MVKCmdRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */; };
DCFD7F3D2A45BC6E007BBBF7 /* MVKCmdRendering.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */; };
DCFD7F3E2A45BC6E007BBBF7 /* MVKBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7801C7DFB4800632CA3 /* MVKBuffer.mm */; };
DCFD7F3F2A45BC6E007BBBF7 /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; };
DCFD7F402A45BC6E007BBBF7 /* mvk_datatypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */; };
@ -595,8 +595,8 @@
A94FB76F1C7DFB4800632CA3 /* MVKCmdPipeline.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCmdPipeline.mm; sourceTree = "<group>"; };
A94FB7701C7DFB4800632CA3 /* MVKCmdQueries.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCmdQueries.h; sourceTree = "<group>"; };
A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCmdQueries.mm; sourceTree = "<group>"; };
A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCmdRenderPass.h; sourceTree = "<group>"; };
A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCmdRenderPass.mm; sourceTree = "<group>"; };
A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCmdRendering.h; sourceTree = "<group>"; };
A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCmdRendering.mm; sourceTree = "<group>"; };
A94FB7741C7DFB4800632CA3 /* MVKCmdDraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCmdDraw.h; sourceTree = "<group>"; };
A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCmdDraw.mm; sourceTree = "<group>"; };
A94FB7761C7DFB4800632CA3 /* MVKCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCommand.h; sourceTree = "<group>"; };
@ -744,8 +744,8 @@
A94FB76F1C7DFB4800632CA3 /* MVKCmdPipeline.mm */,
A94FB7701C7DFB4800632CA3 /* MVKCmdQueries.h */,
A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */,
A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */,
A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */,
A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */,
A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */,
A94FB76C1C7DFB4800632CA3 /* MVKCmdTransfer.h */,
A94FB76D1C7DFB4800632CA3 /* MVKCmdTransfer.mm */,
A94FB7761C7DFB4800632CA3 /* MVKCommand.h */,
@ -995,7 +995,7 @@
2FEA0A6724902F9F00EEF3AD /* MVKCommonEnvironment.h in Headers */,
2FEA0A6824902F9F00EEF3AD /* MVKWatermark.h in Headers */,
2FEA0A6924902F9F00EEF3AD /* MVKOSExtensions.h in Headers */,
2FEA0A6A24902F9F00EEF3AD /* MVKCmdRenderPass.h in Headers */,
2FEA0A6A24902F9F00EEF3AD /* MVKCmdRendering.h in Headers */,
2FEA0A6B24902F9F00EEF3AD /* MVKCmdPipeline.h in Headers */,
2FEA0A6C24902F9F00EEF3AD /* MVKSmallVectorAllocator.h in Headers */,
2FEA0A6D24902F9F00EEF3AD /* MVKPipeline.h in Headers */,
@ -1074,7 +1074,7 @@
A9F042A41FB4CF83009FCCB8 /* MVKCommonEnvironment.h in Headers */,
A981495D1FB6A3F7005F00B4 /* MVKWatermark.h in Headers */,
A9B51BD9225E986A00AC74D2 /* MVKOSExtensions.h in Headers */,
A94FB7C41C7DFB4800632CA3 /* MVKCmdRenderPass.h in Headers */,
A94FB7C41C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */,
A94FB7BC1C7DFB4800632CA3 /* MVKCmdPipeline.h in Headers */,
A9F3D9DC24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */,
A9C327562AAFBD390025EE79 /* MVKConfigMembers.def in Headers */,
@ -1151,7 +1151,7 @@
A9F042A51FB4CF83009FCCB8 /* MVKCommonEnvironment.h in Headers */,
A981495E1FB6A3F7005F00B4 /* MVKWatermark.h in Headers */,
A9B51BDA225E986A00AC74D2 /* MVKOSExtensions.h in Headers */,
A94FB7C51C7DFB4800632CA3 /* MVKCmdRenderPass.h in Headers */,
A94FB7C51C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */,
A94FB7BD1C7DFB4800632CA3 /* MVKCmdPipeline.h in Headers */,
A9F3D9DD24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */,
A94FB7F91C7DFB4800632CA3 /* MVKPipeline.h in Headers */,
@ -1228,7 +1228,7 @@
DCFD7F0B2A45BC6E007BBBF7 /* MVKCommonEnvironment.h in Headers */,
DCFD7F0C2A45BC6E007BBBF7 /* MVKWatermark.h in Headers */,
DCFD7F0D2A45BC6E007BBBF7 /* MVKOSExtensions.h in Headers */,
DCFD7F0E2A45BC6E007BBBF7 /* MVKCmdRenderPass.h in Headers */,
DCFD7F0E2A45BC6E007BBBF7 /* MVKCmdRendering.h in Headers */,
DCFD7F0F2A45BC6E007BBBF7 /* MVKCmdPipeline.h in Headers */,
DCFD7F102A45BC6E007BBBF7 /* MVKSmallVectorAllocator.h in Headers */,
DCFD7F112A45BC6E007BBBF7 /* MVKPipeline.h in Headers */,
@ -1674,7 +1674,7 @@
2FEA0A9424902F9F00EEF3AD /* MVKCommandPool.mm in Sources */,
2FEA0A9524902F9F00EEF3AD /* MVKCmdDraw.mm in Sources */,
2FEA0A9624902F9F00EEF3AD /* MVKCommandBuffer.mm in Sources */,
2FEA0A9724902F9F00EEF3AD /* MVKCmdRenderPass.mm in Sources */,
2FEA0A9724902F9F00EEF3AD /* MVKCmdRendering.mm in Sources */,
2FEA0A9824902F9F00EEF3AD /* MVKBuffer.mm in Sources */,
2FEA0A9924902F9F00EEF3AD /* mvk_datatypes.mm in Sources */,
2FEA0A9A24902F9F00EEF3AD /* MVKExtensions.mm in Sources */,
@ -1734,7 +1734,7 @@
A94FB7D61C7DFB4800632CA3 /* MVKCommandPool.mm in Sources */,
A94FB7CA1C7DFB4800632CA3 /* MVKCmdDraw.mm in Sources */,
A94FB7D21C7DFB4800632CA3 /* MVKCommandBuffer.mm in Sources */,
A94FB7C61C7DFB4800632CA3 /* MVKCmdRenderPass.mm in Sources */,
A94FB7C61C7DFB4800632CA3 /* MVKCmdRendering.mm in Sources */,
A94FB7DE1C7DFB4800632CA3 /* MVKBuffer.mm in Sources */,
A9A5E9C725C0822700E9085E /* MVKEnvironment.cpp in Sources */,
A94FB82A1C7DFB4800632CA3 /* mvk_datatypes.mm in Sources */,
@ -1794,7 +1794,7 @@
A94FB7D71C7DFB4800632CA3 /* MVKCommandPool.mm in Sources */,
A94FB7CB1C7DFB4800632CA3 /* MVKCmdDraw.mm in Sources */,
A94FB7D31C7DFB4800632CA3 /* MVKCommandBuffer.mm in Sources */,
A94FB7C71C7DFB4800632CA3 /* MVKCmdRenderPass.mm in Sources */,
A94FB7C71C7DFB4800632CA3 /* MVKCmdRendering.mm in Sources */,
A94FB7DF1C7DFB4800632CA3 /* MVKBuffer.mm in Sources */,
A9A5E9C925C0822700E9085E /* MVKEnvironment.cpp in Sources */,
A94FB82B1C7DFB4800632CA3 /* mvk_datatypes.mm in Sources */,
@ -1854,7 +1854,7 @@
DCFD7F3A2A45BC6E007BBBF7 /* MVKCommandPool.mm in Sources */,
DCFD7F3B2A45BC6E007BBBF7 /* MVKCmdDraw.mm in Sources */,
DCFD7F3C2A45BC6E007BBBF7 /* MVKCommandBuffer.mm in Sources */,
DCFD7F3D2A45BC6E007BBBF7 /* MVKCmdRenderPass.mm in Sources */,
DCFD7F3D2A45BC6E007BBBF7 /* MVKCmdRendering.mm in Sources */,
DCFD7F3E2A45BC6E007BBBF7 /* MVKBuffer.mm in Sources */,
DCFD7F3F2A45BC6E007BBBF7 /* MVKEnvironment.cpp in Sources */,
DCFD7F402A45BC6E007BBBF7 /* mvk_datatypes.mm in Sources */,

View File

@ -383,6 +383,9 @@ MTLViewport mvkMTLViewportFromVkViewport(VkViewport vkViewport);
/** Returns the Metal MTLScissorRect corresponding to the specified Vulkan VkRect2D. */
MTLScissorRect mvkMTLScissorRectFromVkRect2D(VkRect2D vkRect);
/** Returns the Vulkan VkRect2D corresponding to the specified Metal MTLScissorRect. */
VkRect2D mvkVkRect2DFromMTLScissorRect(MTLScissorRect mtlScissorRect);
/** Returns the Metal MTLCompareFunction corresponding to the specified Vulkan VkCompareOp, */
MTLCompareFunction mvkMTLCompareFunctionFromVkCompareOp(VkCompareOp vkOp);

View File

@ -151,6 +151,7 @@ typedef struct {
MTLArgumentBuffersTier argumentBuffersTier; /**< The argument buffer tier available on this device, as a Metal enumeration. */
VkBool32 needsSampleDrefLodArrayWorkaround; /**< If true, sampling from arrayed depth images with explicit LoD is broken and needs a workaround. */
VkDeviceSize hostMemoryPageSize; /**< The size of a page of host memory on this platform. */
VkBool32 dynamicVertexStride; /**< If true, VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE is supported. */
} MVKPhysicalDeviceMetalFeatures;
/**

View File

@ -46,7 +46,7 @@ void MVKCmdDispatch::encode(MVKCommandEncoder* cmdEncoder) {
MTLRegion mtlThreadgroupCount = MTLRegionMake3D(_baseGroupX, _baseGroupY, _baseGroupZ, _groupCountX, _groupCountY, _groupCountZ);
cmdEncoder->finalizeDispatchState(); // Ensure all updated state has been submitted to Metal
id<MTLComputeCommandEncoder> mtlEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch);
auto* pipeline = (MVKComputePipeline*)cmdEncoder->_computePipelineState.getPipeline();
auto* pipeline = cmdEncoder->_computePipelineState.getComputePipeline();
if (pipeline->allowsDispatchBase()) {
if ([mtlEncoder respondsToSelector: @selector(setStageInRegion:)]) {
// We'll use the stage-input region to pass the base along to the shader.

View File

@ -37,10 +37,12 @@ class MVKCmdBindVertexBuffers : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
uint32_t startBinding,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets);
const VkDeviceSize* pOffsets,
const VkDeviceSize* pSizes,
const VkDeviceSize* pStrides);
void encode(MVKCommandEncoder* cmdEncoder) override;

View File

@ -30,20 +30,23 @@
template <size_t N>
VkResult MVKCmdBindVertexBuffers<N>::setContent(MVKCommandBuffer* cmdBuff,
uint32_t startBinding,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets) {
const VkDeviceSize* pOffsets,
const VkDeviceSize* pSizes,
const VkDeviceSize* pStrides) {
MVKDevice* mvkDvc = cmdBuff->getDevice();
_bindings.clear(); // Clear for reuse
_bindings.reserve(bindingCount);
MVKMTLBufferBinding b;
for (uint32_t bindIdx = 0; bindIdx < bindingCount; bindIdx++) {
MVKBuffer* mvkBuffer = (MVKBuffer*)pBuffers[bindIdx];
b.index = mvkDvc->getMetalBufferIndexForVertexAttributeBinding(startBinding + bindIdx);
b.index = mvkDvc->getMetalBufferIndexForVertexAttributeBinding(firstBinding + bindIdx);
b.mtlBuffer = mvkBuffer->getMTLBuffer();
b.offset = mvkBuffer->getMTLBufferOffset() + pOffsets[bindIdx];
b.size = pSizes ? (uint32_t)pSizes[bindIdx] : 0;
b.stride = pStrides ? (uint32_t)pStrides[bindIdx] : 0;
_bindings.push_back(b);
}
@ -146,7 +149,7 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) {
return;
}
auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline();
auto* pipeline = cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
// Metal doesn't support triangle fans, so encode it as triangles via an indexed indirect triangles command instead.
if (pipeline->getVkPrimitiveTopology() == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) {
@ -169,7 +172,7 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) {
} tessParams;
uint32_t outControlPointCount = 0;
if (pipeline->isTessellationPipeline()) {
tessParams.inControlPointCount = pipeline->getInputControlPointCount();
tessParams.inControlPointCount = cmdEncoder->_graphicsPipelineState.getPatchControlPoints();
outControlPointCount = pipeline->getOutputControlPointCount();
tessParams.patchCount = mvkCeilingDivide(_vertexCount, tessParams.inControlPointCount) * _instanceCount;
}
@ -296,13 +299,13 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) {
uint32_t instanceCount = _instanceCount * viewCount;
cmdEncoder->_graphicsResourcesState.offsetZeroDivisorVertexBuffers(stage, pipeline, _firstInstance);
if (cmdEncoder->_pDeviceMetalFeatures->baseVertexInstanceDrawing) {
[cmdEncoder->_mtlRenderEncoder drawPrimitives: cmdEncoder->_mtlPrimitiveType
[cmdEncoder->_mtlRenderEncoder drawPrimitives: cmdEncoder->_renderingState.getPrimitiveType()
vertexStart: _firstVertex
vertexCount: _vertexCount
instanceCount: instanceCount
baseInstance: _firstInstance];
} else {
[cmdEncoder->_mtlRenderEncoder drawPrimitives: cmdEncoder->_mtlPrimitiveType
[cmdEncoder->_mtlRenderEncoder drawPrimitives: cmdEncoder->_renderingState.getPrimitiveType()
vertexStart: _firstVertex
vertexCount: _vertexCount
instanceCount: instanceCount];
@ -371,7 +374,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) {
return;
}
auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline();
auto* pipeline = cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
// Metal doesn't support triangle fans, so encode it as triangles via an indexed indirect triangles command instead.
if (pipeline->getVkPrimitiveTopology() == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) {
@ -398,7 +401,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) {
} tessParams;
uint32_t outControlPointCount = 0;
if (pipeline->isTessellationPipeline()) {
tessParams.inControlPointCount = pipeline->getInputControlPointCount();
tessParams.inControlPointCount = cmdEncoder->_graphicsPipelineState.getPatchControlPoints();
outControlPointCount = pipeline->getOutputControlPointCount();
tessParams.patchCount = mvkCeilingDivide(_indexCount, tessParams.inControlPointCount) * _instanceCount;
}
@ -530,7 +533,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) {
uint32_t instanceCount = _instanceCount * viewCount;
cmdEncoder->_graphicsResourcesState.offsetZeroDivisorVertexBuffers(stage, pipeline, _firstInstance);
if (cmdEncoder->_pDeviceMetalFeatures->baseVertexInstanceDrawing) {
[cmdEncoder->_mtlRenderEncoder drawIndexedPrimitives: cmdEncoder->_mtlPrimitiveType
[cmdEncoder->_mtlRenderEncoder drawIndexedPrimitives: cmdEncoder->_renderingState.getPrimitiveType()
indexCount: _indexCount
indexType: (MTLIndexType)ibb.mtlIndexType
indexBuffer: ibb.mtlBuffer
@ -539,7 +542,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) {
baseVertex: _vertexOffset
baseInstance: _firstInstance];
} else {
[cmdEncoder->_mtlRenderEncoder drawIndexedPrimitives: cmdEncoder->_mtlPrimitiveType
[cmdEncoder->_mtlRenderEncoder drawIndexedPrimitives: cmdEncoder->_renderingState.getPrimitiveType()
indexCount: _indexCount
indexType: (MTLIndexType)ibb.mtlIndexType
indexBuffer: ibb.mtlBuffer
@ -646,7 +649,7 @@ void MVKCmdDrawIndirect::encodeIndexedIndirect(MVKCommandEncoder* cmdEncoder) {
void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline();
auto* pipeline = cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
// Metal doesn't support triangle fans, so encode it as indexed indirect triangles instead.
if (pipeline->getVkPrimitiveTopology() == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) {
@ -683,7 +686,7 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
// encoding and execution. So we don't know how big to make the buffers.
// We must assume an arbitrarily large number of vertices may be submitted.
// But not too many, or we'll exhaust available VRAM.
inControlPointCount = pipeline->getInputControlPointCount();
inControlPointCount = cmdEncoder->_graphicsPipelineState.getPatchControlPoints();
outControlPointCount = pipeline->getOutputControlPointCount();
vertexCount = kMVKMaxDrawIndirectVertexCount;
patchCount = mvkCeilingDivide(vertexCount, inControlPointCount);
@ -925,7 +928,7 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_graphicsResourcesState.beginMetalRenderPass();
cmdEncoder->getPushConstants(VK_SHADER_STAGE_VERTEX_BIT)->beginMetalRenderPass();
} else {
[cmdEncoder->_mtlRenderEncoder drawPrimitives: cmdEncoder->_mtlPrimitiveType
[cmdEncoder->_mtlRenderEncoder drawPrimitives: cmdEncoder->_renderingState.getPrimitiveType()
indirectBuffer: mtlIndBuff
indirectBufferOffset: mtlIndBuffOfst];
mtlIndBuffOfst += needsInstanceAdjustment ? sizeof(MTLDrawPrimitivesIndirectArguments) : _mtlIndirectBufferStride;
@ -996,7 +999,7 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder, const MVKI
MVKIndexMTLBufferBinding ibb = ibbOrig;
MVKIndexMTLBufferBinding ibbTriFan = ibb;
auto* pipeline = (MVKGraphicsPipeline*)cmdEncoder->_graphicsPipelineState.getPipeline();
auto* pipeline = cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
MVKVertexAdjustments vtxAdjmts;
vtxAdjmts.mtlIndexType = ibb.mtlIndexType;
@ -1031,7 +1034,7 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder, const MVKI
// encoding and execution. So we don't know how big to make the buffers.
// We must assume an arbitrarily large number of vertices may be submitted.
// But not too many, or we'll exhaust available VRAM.
inControlPointCount = pipeline->getInputControlPointCount();
inControlPointCount = cmdEncoder->_graphicsPipelineState.getPatchControlPoints();
outControlPointCount = pipeline->getOutputControlPointCount();
vertexCount = kMVKMaxDrawIndirectVertexCount;
patchCount = mvkCeilingDivide(vertexCount, inControlPointCount);
@ -1312,7 +1315,7 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder, const MVKI
cmdEncoder->getPushConstants(VK_SHADER_STAGE_VERTEX_BIT)->beginMetalRenderPass();
} else {
cmdEncoder->_graphicsResourcesState.offsetZeroDivisorVertexBuffers(stage, pipeline, _directCmdFirstInstance);
[cmdEncoder->_mtlRenderEncoder drawIndexedPrimitives: cmdEncoder->_mtlPrimitiveType
[cmdEncoder->_mtlRenderEncoder drawIndexedPrimitives: cmdEncoder->_renderingState.getPrimitiveType()
indexType: (MTLIndexType)ibb.mtlIndexType
indexBuffer: ibb.mtlBuffer
indexBufferOffset: ibb.offset

View File

@ -30,6 +30,34 @@ class MVKDescriptorSet;
class MVKDescriptorUpdateTemplate;
#pragma mark -
#pragma mark MVKCmdExecuteCommands
/**
* Vulkan command to execute secondary command buffers.
* Template class to balance vector pre-allocations between very common low counts and fewer larger counts.
*/
template <size_t N>
class MVKCmdExecuteCommands : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
uint32_t commandBuffersCount,
const VkCommandBuffer* pCommandBuffers);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
MVKSmallVector<MVKCommandBuffer*, N> _secondaryCommandBuffers;
};
// Concrete template class implementations.
typedef MVKCmdExecuteCommands<1> MVKCmdExecuteCommands1;
typedef MVKCmdExecuteCommands<16> MVKCmdExecuteCommandsMulti;
#pragma mark -
#pragma mark MVKCmdPipelineBarrier

View File

@ -26,6 +26,33 @@
#include "mvk_datatypes.hpp"
#pragma mark -
#pragma mark MVKCmdExecuteCommands
template <size_t N>
VkResult MVKCmdExecuteCommands<N>::setContent(MVKCommandBuffer* cmdBuff,
uint32_t commandBuffersCount,
const VkCommandBuffer* pCommandBuffers) {
// Add clear values
_secondaryCommandBuffers.clear(); // Clear for reuse
_secondaryCommandBuffers.reserve(commandBuffersCount);
for (uint32_t cbIdx = 0; cbIdx < commandBuffersCount; cbIdx++) {
_secondaryCommandBuffers.push_back(MVKCommandBuffer::getMVKCommandBuffer(pCommandBuffers[cbIdx]));
}
cmdBuff->recordExecuteCommands(_secondaryCommandBuffers.contents());
return VK_SUCCESS;
}
template <size_t N>
void MVKCmdExecuteCommands<N>::encode(MVKCommandEncoder* cmdEncoder) {
for (auto& cb : _secondaryCommandBuffers) { cmdEncoder->encodeSecondary(cb); }
}
template class MVKCmdExecuteCommands<1>;
template class MVKCmdExecuteCommands<16>;
#pragma mark -
#pragma mark MVKCmdPipelineBarrier

View File

@ -1,5 +1,5 @@
/*
* MVKCmdRenderPass.h
* MVKCmdRendering.h
*
* Copyright (c) 2015-2023 The Brenwill Workshop Ltd. (http://www.brenwill.com)
*
@ -207,34 +207,6 @@ protected:
};
#pragma mark -
#pragma mark MVKCmdExecuteCommands
/**
* Vulkan command to execute secondary command buffers.
* Template class to balance vector pre-allocations between very common low counts and fewer larger counts.
*/
template <size_t N>
class MVKCmdExecuteCommands : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
uint32_t commandBuffersCount,
const VkCommandBuffer* pCommandBuffers);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
MVKSmallVector<MVKCommandBuffer*, N> _secondaryCommandBuffers;
};
// Concrete template class implementations.
typedef MVKCmdExecuteCommands<1> MVKCmdExecuteCommands1;
typedef MVKCmdExecuteCommands<16> MVKCmdExecuteCommandsMulti;
#pragma mark -
#pragma mark MVKCmdSetViewport
@ -295,25 +267,6 @@ typedef MVKCmdSetScissor<1> MVKCmdSetScissor1;
typedef MVKCmdSetScissor<kMVKMaxViewportScissorCount> MVKCmdSetScissorMulti;
#pragma mark -
#pragma mark MVKCmdSetLineWidth
/** Vulkan command to set the line width. */
class MVKCmdSetLineWidth : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
float lineWidth);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
float _lineWidth;
};
#pragma mark -
#pragma mark MVKCmdSetDepthBias
@ -337,6 +290,25 @@ protected:
};
#pragma mark -
#pragma mark MVKCmdSetDepthBiasEnable
/** Vulkan command to dynamically enable or disable depth bias. */
class MVKCmdSetDepthBiasEnable : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkBool32 depthBiasEnable);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkBool32 _depthBiasEnable;
};
#pragma mark -
#pragma mark MVKCmdSetBlendConstants
@ -352,31 +324,110 @@ public:
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
float _red;
float _green;
float _blue;
float _alpha;
float _blendConstants[4] = {};
};
#pragma mark -
#pragma mark MVKCmdSetDepthBounds
#pragma mark MVKCmdSetDepthTestEnable
/** Vulkan command to set depth bounds. */
class MVKCmdSetDepthBounds : public MVKCommand {
/** Vulkan command to dynamically enable depth testing. */
class MVKCmdSetDepthTestEnable : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
float minDepthBounds,
float maxDepthBounds);
VkBool32 depthTestEnable);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
float _minDepthBounds;
float _maxDepthBounds;
VkBool32 _depthTestEnable;
};
#pragma mark -
#pragma mark MVKCmdSetDepthWriteEnable
/** Vulkan command to dynamically enable depth writing. */
class MVKCmdSetDepthWriteEnable : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkBool32 depthWriteEnable);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkBool32 _depthWriteEnable;
};
#pragma mark -
#pragma mark MVKCmdSetDepthCompareOp
/** Vulkan command to dynamically set the depth compare operation. */
class MVKCmdSetDepthCompareOp : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkCompareOp depthCompareOp);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkCompareOp _depthCompareOp;
};
#pragma mark -
#pragma mark MVKCmdSetStencilTestEnable
/** Vulkan command to dynamically enable stencil testing. */
class MVKCmdSetStencilTestEnable : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkBool32 stencilTestEnable);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkBool32 _stencilTestEnable;
};
#pragma mark -
#pragma mark MVKCmdSetStencilOp
/** Vulkan command to dynamically set the stencil operations. */
class MVKCmdSetStencilOp : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkStencilFaceFlags faceMask,
VkStencilOp failOp,
VkStencilOp passOp,
VkStencilOp depthFailOp,
VkCompareOp compareOp);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkStencilFaceFlags _faceMask;
VkStencilOp _failOp;
VkStencilOp _passOp;
VkStencilOp _depthFailOp;
VkCompareOp _compareOp;
};
@ -442,3 +493,115 @@ protected:
uint32_t _stencilReference;
};
#pragma mark -
#pragma mark MVKCmdSetCullMode
/** Vulkan command to dynamically set the cull mode. */
class MVKCmdSetCullMode : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkCullModeFlags cullMode);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkCullModeFlags _cullMode;
};
#pragma mark -
#pragma mark MVKCmdSetFrontFace
/** Vulkan command to dynamically set the front facing winding order. */
class MVKCmdSetFrontFace : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkFrontFace frontFace);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkFrontFace _frontFace;
};
#pragma mark -
#pragma mark MVKCmdSetPatchControlPoints
/** Vulkan command to dynamically set the number of patch control points. */
class MVKCmdSetPatchControlPoints : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
uint32_t patchControlPoints);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
uint32_t _patchControlPoints;
};
#pragma mark -
#pragma mark MVKCmdSetPrimitiveTopology
/** Vulkan command to dynamically set the primitive topology. */
class MVKCmdSetPrimitiveTopology : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkPrimitiveTopology primitiveTopology);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkPrimitiveTopology _primitiveTopology;
};
#pragma mark -
#pragma mark MVKCmdSetPrimitiveRestartEnable
/** Vulkan command to dynamically enable or disable primitive restart functionality. */
class MVKCmdSetPrimitiveRestartEnable : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkBool32 primitiveRestartEnable);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
};
#pragma mark -
#pragma mark MVKCmdSetRasterizerDiscardEnable
/** Vulkan command to dynamically enable or disable rasterization. */
class MVKCmdSetRasterizerDiscardEnable : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuff,
VkBool32 rasterizerDiscardEnable);
void encode(MVKCommandEncoder* cmdEncoder) override;
protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
VkBool32 _rasterizerDiscardEnable;
};

View File

@ -1,5 +1,5 @@
/*
* MVKCmdRenderPass.mm
* MVKCmdRendering.mm
*
* Copyright (c) 2015-2023 The Brenwill Workshop Ltd. (http://www.brenwill.com)
*
@ -16,7 +16,7 @@
* limitations under the License.
*/
#include "MVKCmdRenderPass.h"
#include "MVKCmdRendering.h"
#include "MVKCommandBuffer.h"
#include "MVKCommandPool.h"
#include "MVKFramebuffer.h"
@ -231,33 +231,6 @@ void MVKCmdSetSampleLocations::encode(MVKCommandEncoder* cmdEncoder) {
}
#pragma mark -
#pragma mark MVKCmdExecuteCommands
template <size_t N>
VkResult MVKCmdExecuteCommands<N>::setContent(MVKCommandBuffer* cmdBuff,
uint32_t commandBuffersCount,
const VkCommandBuffer* pCommandBuffers) {
// Add clear values
_secondaryCommandBuffers.clear(); // Clear for reuse
_secondaryCommandBuffers.reserve(commandBuffersCount);
for (uint32_t cbIdx = 0; cbIdx < commandBuffersCount; cbIdx++) {
_secondaryCommandBuffers.push_back(MVKCommandBuffer::getMVKCommandBuffer(pCommandBuffers[cbIdx]));
}
cmdBuff->recordExecuteCommands(_secondaryCommandBuffers.contents());
return VK_SUCCESS;
}
template <size_t N>
void MVKCmdExecuteCommands<N>::encode(MVKCommandEncoder* cmdEncoder) {
for (auto& cb : _secondaryCommandBuffers) { cmdEncoder->encodeSecondary(cb); }
}
template class MVKCmdExecuteCommands<1>;
template class MVKCmdExecuteCommands<16>;
#pragma mark -
#pragma mark MVKCmdSetViewport
@ -278,7 +251,7 @@ VkResult MVKCmdSetViewport<N>::setContent(MVKCommandBuffer* cmdBuff,
template <size_t N>
void MVKCmdSetViewport<N>::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_viewportState.setViewports(_viewports.contents(), _firstViewport, true);
cmdEncoder->_renderingState.setViewports(_viewports.contents(), _firstViewport, true);
}
template class MVKCmdSetViewport<1>;
@ -305,31 +278,13 @@ VkResult MVKCmdSetScissor<N>::setContent(MVKCommandBuffer* cmdBuff,
template <size_t N>
void MVKCmdSetScissor<N>::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_scissorState.setScissors(_scissors.contents(), _firstScissor, true);
cmdEncoder->_renderingState.setScissors(_scissors.contents(), _firstScissor, true);
}
template class MVKCmdSetScissor<1>;
template class MVKCmdSetScissor<kMVKMaxViewportScissorCount>;
#pragma mark -
#pragma mark MVKCmdSetLineWidth
VkResult MVKCmdSetLineWidth::setContent(MVKCommandBuffer* cmdBuff,
float lineWidth) {
_lineWidth = lineWidth;
// Validate
if (_lineWidth != 1.0 || cmdBuff->getDevice()->_enabledFeatures.wideLines) {
return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetLineWidth(): The current device does not support wide lines.");
}
return VK_SUCCESS;
}
void MVKCmdSetLineWidth::encode(MVKCommandEncoder* cmdEncoder) {}
#pragma mark -
#pragma mark MVKCmdSetDepthBias
@ -345,48 +300,116 @@ VkResult MVKCmdSetDepthBias::setContent(MVKCommandBuffer* cmdBuff,
}
void MVKCmdSetDepthBias::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_depthBiasState.setDepthBias(_depthBiasConstantFactor,
cmdEncoder->_renderingState.setDepthBias(_depthBiasConstantFactor,
_depthBiasSlopeFactor,
_depthBiasClamp);
}
#pragma mark -
#pragma mark MVKCmdSetDepthBiasEnable
VkResult MVKCmdSetDepthBiasEnable::setContent(MVKCommandBuffer* cmdBuff,
VkBool32 depthBiasEnable) {
_depthBiasEnable = depthBiasEnable;
return VK_SUCCESS;
}
void MVKCmdSetDepthBiasEnable::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_renderingState.setDepthBiasEnable(_depthBiasEnable);
}
#pragma mark -
#pragma mark MVKCmdSetBlendConstants
VkResult MVKCmdSetBlendConstants::setContent(MVKCommandBuffer* cmdBuff,
const float blendConst[4]) {
_red = blendConst[0];
_green = blendConst[1];
_blue = blendConst[2];
_alpha = blendConst[3];
mvkCopy(_blendConstants, blendConst, 4);
return VK_SUCCESS;
}
void MVKCmdSetBlendConstants::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_blendColorState.setBlendColor(_red, _green, _blue, _alpha, true);
cmdEncoder->_renderingState.setBlendConstants(_blendConstants, true);
}
#pragma mark -
#pragma mark MVKCmdSetDepthBounds
VkResult MVKCmdSetDepthBounds::setContent(MVKCommandBuffer* cmdBuff,
float minDepthBounds,
float maxDepthBounds) {
_minDepthBounds = minDepthBounds;
_maxDepthBounds = maxDepthBounds;
// Validate
if (cmdBuff->getDevice()->_enabledFeatures.depthBounds) {
return cmdBuff->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdSetDepthBounds(): The current device does not support setting depth bounds.");
}
#pragma mark MVKCmdSetDepthTestEnable
VkResult MVKCmdSetDepthTestEnable::setContent(MVKCommandBuffer* cmdBuff,
VkBool32 depthTestEnable) {
_depthTestEnable = depthTestEnable;
return VK_SUCCESS;
}
void MVKCmdSetDepthBounds::encode(MVKCommandEncoder* cmdEncoder) {}
void MVKCmdSetDepthTestEnable::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_depthStencilState.setDepthTestEnable(_depthTestEnable);
}
#pragma mark -
#pragma mark MVKCmdSetDepthWriteEnable
VkResult MVKCmdSetDepthWriteEnable::setContent(MVKCommandBuffer* cmdBuff,
VkBool32 depthWriteEnable) {
_depthWriteEnable = depthWriteEnable;
return VK_SUCCESS;
}
void MVKCmdSetDepthWriteEnable::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_depthStencilState.setDepthWriteEnable(_depthWriteEnable);
}
#pragma mark -
#pragma mark MVKCmdSetDepthCompareOp
VkResult MVKCmdSetDepthCompareOp::setContent(MVKCommandBuffer* cmdBuff,
VkCompareOp depthCompareOp) {
_depthCompareOp = depthCompareOp;
return VK_SUCCESS;
}
void MVKCmdSetDepthCompareOp::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_depthStencilState.setDepthCompareOp(_depthCompareOp);
}
#pragma mark -
#pragma mark MVKCmdSetStencilTestEnable
VkResult MVKCmdSetStencilTestEnable::setContent(MVKCommandBuffer* cmdBuff,
VkBool32 stencilTestEnable) {
_stencilTestEnable = stencilTestEnable;
return VK_SUCCESS;
}
void MVKCmdSetStencilTestEnable::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_depthStencilState.setStencilTestEnable(_stencilTestEnable);
}
#pragma mark -
#pragma mark MVKCmdSetStencilOp
VkResult MVKCmdSetStencilOp::setContent(MVKCommandBuffer* cmdBuff,
VkStencilFaceFlags faceMask,
VkStencilOp failOp,
VkStencilOp passOp,
VkStencilOp depthFailOp,
VkCompareOp compareOp) {
_faceMask = faceMask;
_failOp = failOp;
_passOp = passOp;
_depthFailOp = depthFailOp;
_compareOp = compareOp;
return VK_SUCCESS;
}
void MVKCmdSetStencilOp::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_depthStencilState.setStencilOp(_faceMask, _failOp, _passOp, _depthFailOp, _compareOp);
}
#pragma mark -
@ -436,6 +459,95 @@ VkResult MVKCmdSetStencilReference::setContent(MVKCommandBuffer* cmdBuff,
}
void MVKCmdSetStencilReference::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_stencilReferenceValueState.setReferenceValues(_faceMask, _stencilReference);
cmdEncoder->_renderingState.setStencilReferenceValues(_faceMask, _stencilReference);
}
#pragma mark -
#pragma mark MVKCmdSetCullMode
VkResult MVKCmdSetCullMode::setContent(MVKCommandBuffer* cmdBuff,
VkCullModeFlags cullMode) {
_cullMode = cullMode;
return VK_SUCCESS;
}
void MVKCmdSetCullMode::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_renderingState.setCullMode(_cullMode, true);
}
#pragma mark -
#pragma mark MVKCmdSetFrontFace
VkResult MVKCmdSetFrontFace::setContent(MVKCommandBuffer* cmdBuff,
VkFrontFace frontFace) {
_frontFace = frontFace;
return VK_SUCCESS;
}
void MVKCmdSetFrontFace::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_renderingState.setFrontFace(_frontFace, true);
}
#pragma mark -
#pragma mark MVKCmdSetPatchControlPoints
VkResult MVKCmdSetPatchControlPoints::setContent(MVKCommandBuffer* cmdBuff,
uint32_t patchControlPoints) {
_patchControlPoints = patchControlPoints;
return VK_SUCCESS;
}
void MVKCmdSetPatchControlPoints::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_graphicsPipelineState.setPatchControlPoints(_patchControlPoints);
}
#pragma mark -
#pragma mark MVKCmdSetPrimitiveTopology
VkResult MVKCmdSetPrimitiveTopology::setContent(MVKCommandBuffer* cmdBuff,
VkPrimitiveTopology primitiveTopology) {
_primitiveTopology = primitiveTopology;
return VK_SUCCESS;
}
void MVKCmdSetPrimitiveTopology::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_renderingState.setPrimitiveTopology(_primitiveTopology, true);
}
#pragma mark -
#pragma mark MVKCmdSetPrimitiveRestartEnable
VkResult MVKCmdSetPrimitiveRestartEnable::setContent(MVKCommandBuffer* cmdBuff,
VkBool32 primitiveRestartEnable) {
// Validate
// In Metal, primitive restart cannot be disabled.
// Just issue warning here, as it is very likely the app is not actually expecting
// to use primitive restart at all, and is just setting this as a "just-in-case",
// and forcing an error here would be unexpected to the app (including CTS).
if ( !primitiveRestartEnable ) {
reportWarning(VK_ERROR_FEATURE_NOT_PRESENT, "Metal does not support disabling primitive restart.");
}
return VK_SUCCESS;
}
void MVKCmdSetPrimitiveRestartEnable::encode(MVKCommandEncoder* cmdEncoder) {}
#pragma mark -
#pragma mark MVKCmdSetRasterizerDiscardEnable
VkResult MVKCmdSetRasterizerDiscardEnable::setContent(MVKCommandBuffer* cmdBuff,
VkBool32 rasterizerDiscardEnable) {
_rasterizerDiscardEnable = rasterizerDiscardEnable;
return VK_SUCCESS;
}
void MVKCmdSetRasterizerDiscardEnable::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_renderingState.setRasterizerDiscardEnable(_rasterizerDiscardEnable, true);
}

View File

@ -1507,10 +1507,7 @@ void MVKCmdClearAttachments<N>::encode(MVKCommandEncoder* cmdEncoder) {
// Return to the previous rendering state on the next render activity
cmdEncoder->_graphicsPipelineState.markDirty();
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->_stencilReferenceValueState.markDirty();
cmdEncoder->_depthBiasState.markDirty();
cmdEncoder->_viewportState.markDirty();
cmdEncoder->_scissorState.markDirty();
cmdEncoder->_renderingState.markDirty();
}
template <size_t N>

View File

@ -300,14 +300,11 @@ public:
/** Encodes an operation to signal an event to a status. */
void signalEvent(MVKEvent* mvkEvent, bool status);
/**
* If a pipeline is currently bound, returns whether the current pipeline permits dynamic
* setting of the specified state. If no pipeline is currently bound, returns true.
*/
bool supportsDynamicState(VkDynamicState state);
/** Clips the rect to ensure it fits inside the render area. */
VkRect2D clipToRenderArea(VkRect2D rect);
/** Clips the scissor to ensure it fits inside the render area. */
VkRect2D clipToRenderArea(VkRect2D scissor);
MTLScissorRect clipToRenderArea(MTLScissorRect scissor);
/** Called by each graphics draw command to establish any outstanding state just prior to performing the draw. */
void finalizeDrawState(MVKGraphicsStage stage);
@ -361,6 +358,9 @@ public:
/** Returns the push constants associated with the specified shader stage. */
MVKPushConstantsCommandEncoderState* getPushConstants(VkShaderStageFlagBits shaderStage);
/** Encode the buffer binding as a vertex attribute buffer. */
void encodeVertexAttributeBuffer(MVKMTLBufferBinding& b, bool isDynamicStride);
/**
* Copy bytes into the Metal encoder at a Metal vertex buffer index, and optionally indicate
* that this binding might override a desriptor binding. If so, the descriptor binding will
@ -435,37 +435,22 @@ public:
id<MTLRenderCommandEncoder> _mtlRenderEncoder;
/** Tracks the current graphics pipeline bound to the encoder. */
MVKPipelineCommandEncoderState _graphicsPipelineState;
/** Tracks the current compute pipeline bound to the encoder. */
MVKPipelineCommandEncoderState _computePipelineState;
/** Tracks the current viewport state of the encoder. */
MVKViewportCommandEncoderState _viewportState;
/** Tracks the current scissor state of the encoder. */
MVKScissorCommandEncoderState _scissorState;
/** Tracks the current depth bias state of the encoder. */
MVKDepthBiasCommandEncoderState _depthBiasState;
/** Tracks the current blend color state of the encoder. */
MVKBlendColorCommandEncoderState _blendColorState;
/** Tracks the current depth stencil state of the encoder. */
MVKDepthStencilCommandEncoderState _depthStencilState;
/** Tracks the current stencil reference value state of the encoder. */
MVKStencilReferenceValueCommandEncoderState _stencilReferenceValueState;
MVKGraphicsPipelineCommandEncoderState _graphicsPipelineState;
/** Tracks the current graphics resources state of the encoder. */
MVKGraphicsResourcesCommandEncoderState _graphicsResourcesState;
/** Tracks the current compute pipeline bound to the encoder. */
MVKComputePipelineCommandEncoderState _computePipelineState;
/** Tracks the current compute resources state of the encoder. */
MVKComputeResourcesCommandEncoderState _computeResourcesState;
/** The type of primitive that will be rendered. */
MTLPrimitiveType _mtlPrimitiveType;
/** Tracks the current depth stencil state of the encoder. */
MVKDepthStencilCommandEncoderState _depthStencilState;
/** Tracks the current rendering states of the encoder. */
MVKRenderingCommandEncoderState _renderingState;
/** The size of the threadgroup for the compute shader. */
MTLSize _mtlThreadgroupSize;

View File

@ -25,7 +25,7 @@
#include "MVKFoundation.h"
#include "MTLRenderPassDescriptor+MoltenVK.h"
#include "MVKCmdDraw.h"
#include "MVKCmdRenderPass.h"
#include "MVKCmdRendering.h"
#include <sys/mman.h>
using namespace std;
@ -607,16 +607,12 @@ void MVKCommandEncoder::beginMetalRenderPass(MVKCommandUse cmdUse) {
_graphicsPipelineState.beginMetalRenderPass();
_graphicsResourcesState.beginMetalRenderPass();
_viewportState.beginMetalRenderPass();
_scissorState.beginMetalRenderPass();
_depthBiasState.beginMetalRenderPass();
_blendColorState.beginMetalRenderPass();
_depthStencilState.beginMetalRenderPass();
_renderingState.beginMetalRenderPass();
_vertexPushConstants.beginMetalRenderPass();
_tessCtlPushConstants.beginMetalRenderPass();
_tessEvalPushConstants.beginMetalRenderPass();
_fragmentPushConstants.beginMetalRenderPass();
_depthStencilState.beginMetalRenderPass();
_stencilReferenceValueState.beginMetalRenderPass();
_occlusionQueryState.beginMetalRenderPass();
}
@ -706,24 +702,23 @@ void MVKCommandEncoder::signalEvent(MVKEvent* mvkEvent, bool status) {
mvkEvent->encodeSignal(_mtlCmdBuffer, status);
}
bool MVKCommandEncoder::supportsDynamicState(VkDynamicState state) {
MVKGraphicsPipeline* gpl = (MVKGraphicsPipeline*)_graphicsPipelineState.getPipeline();
return !gpl || gpl->supportsDynamicState(state);
VkRect2D MVKCommandEncoder::clipToRenderArea(VkRect2D rect) {
uint32_t raLeft = max(_renderArea.offset.x, 0);
uint32_t raRight = raLeft + _renderArea.extent.width;
uint32_t raBottom = max(_renderArea.offset.y, 0);
uint32_t raTop = raBottom + _renderArea.extent.height;
rect.offset.x = mvkClamp<uint32_t>(rect.offset.x, raLeft, max(raRight - 1, raLeft));
rect.offset.y = mvkClamp<uint32_t>(rect.offset.y, raBottom, max(raTop - 1, raBottom));
rect.extent.width = min<uint32_t>(rect.extent.width, raRight - rect.offset.x);
rect.extent.height = min<uint32_t>(rect.extent.height, raTop - rect.offset.y);
return rect;
}
VkRect2D MVKCommandEncoder::clipToRenderArea(VkRect2D scissor) {
int32_t raLeft = _renderArea.offset.x;
int32_t raRight = raLeft + _renderArea.extent.width;
int32_t raBottom = _renderArea.offset.y;
int32_t raTop = raBottom + _renderArea.extent.height;
scissor.offset.x = mvkClamp(scissor.offset.x, raLeft, max(raRight - 1, raLeft));
scissor.offset.y = mvkClamp(scissor.offset.y, raBottom, max(raTop - 1, raBottom));
scissor.extent.width = min<int32_t>(scissor.extent.width, raRight - scissor.offset.x);
scissor.extent.height = min<int32_t>(scissor.extent.height, raTop - scissor.offset.y);
return scissor;
MTLScissorRect MVKCommandEncoder::clipToRenderArea(MTLScissorRect scissor) {
return mvkMTLScissorRectFromVkRect2D(clipToRenderArea(mvkVkRect2DFromMTLScissorRect(scissor)));
}
void MVKCommandEncoder::finalizeDrawState(MVKGraphicsStage stage) {
@ -733,16 +728,12 @@ void MVKCommandEncoder::finalizeDrawState(MVKGraphicsStage stage) {
}
_graphicsPipelineState.encode(stage); // Must do first..it sets others
_graphicsResourcesState.encode(stage); // Before push constants, to allow them to override.
_viewportState.encode(stage);
_scissorState.encode(stage);
_depthBiasState.encode(stage);
_blendColorState.encode(stage);
_depthStencilState.encode(stage);
_renderingState.encode(stage);
_vertexPushConstants.encode(stage);
_tessCtlPushConstants.encode(stage);
_tessEvalPushConstants.encode(stage);
_fragmentPushConstants.encode(stage);
_depthStencilState.encode(stage);
_stencilReferenceValueState.encode(stage);
_occlusionQueryState.encode(stage);
}
@ -831,16 +822,12 @@ void MVKCommandEncoder::endMetalRenderEncoding() {
_graphicsPipelineState.endMetalRenderPass();
_graphicsResourcesState.endMetalRenderPass();
_viewportState.endMetalRenderPass();
_scissorState.endMetalRenderPass();
_depthBiasState.endMetalRenderPass();
_blendColorState.endMetalRenderPass();
_depthStencilState.endMetalRenderPass();
_renderingState.endMetalRenderPass();
_vertexPushConstants.endMetalRenderPass();
_tessCtlPushConstants.endMetalRenderPass();
_tessEvalPushConstants.endMetalRenderPass();
_fragmentPushConstants.endMetalRenderPass();
_depthStencilState.endMetalRenderPass();
_stencilReferenceValueState.endMetalRenderPass();
_occlusionQueryState.endMetalRenderPass();
}
@ -932,6 +919,42 @@ void MVKCommandEncoder::setVertexBytes(id<MTLRenderCommandEncoder> mtlEncoder,
}
}
void MVKCommandEncoder::encodeVertexAttributeBuffer(MVKMTLBufferBinding& b, bool isDynamicStride) {
if (_device->_pMetalFeatures->dynamicVertexStride) {
#if MVK_XCODE_15
NSUInteger mtlStride = isDynamicStride ? b.stride : MTLAttributeStrideStatic;
if (b.isInline) {
[_mtlRenderEncoder setVertexBytes: b.mtlBytes
length: b.size
attributeStride: mtlStride
atIndex: b.index];
} else if (b.justOffset) {
[_mtlRenderEncoder setVertexBufferOffset: b.offset
attributeStride: mtlStride
atIndex: b.index];
} else {
[_mtlRenderEncoder setVertexBuffer: b.mtlBuffer
offset: b.offset
attributeStride: mtlStride
atIndex: b.index];
}
#endif
} else {
if (b.isInline) {
[_mtlRenderEncoder setVertexBytes: b.mtlBytes
length: b.size
atIndex: b.index];
} else if (b.justOffset) {
[_mtlRenderEncoder setVertexBufferOffset: b.offset
atIndex: b.index];
} else {
[_mtlRenderEncoder setVertexBuffer: b.mtlBuffer
offset: b.offset
atIndex: b.index];
}
}
}
void MVKCommandEncoder::setFragmentBytes(id<MTLRenderCommandEncoder> mtlEncoder,
const void* bytes,
NSUInteger length,
@ -1133,15 +1156,11 @@ MVKCommandEncoder::MVKCommandEncoder(MVKCommandBuffer* cmdBuffer,
MVKPrefillMetalCommandBuffersStyle prefillStyle) : MVKBaseDeviceObject(cmdBuffer->getDevice()),
_cmdBuffer(cmdBuffer),
_graphicsPipelineState(this),
_computePipelineState(this),
_viewportState(this),
_scissorState(this),
_depthBiasState(this),
_blendColorState(this),
_depthStencilState(this),
_stencilReferenceValueState(this),
_graphicsResourcesState(this),
_computePipelineState(this),
_computeResourcesState(this),
_depthStencilState(this),
_renderingState(this),
_vertexPushConstants(this, VK_SHADER_STAGE_VERTEX_BIT),
_tessCtlPushConstants(this, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
_tessEvalPushConstants(this, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),

View File

@ -21,6 +21,7 @@
#include "MVKMTLResourceBindings.h"
#include "MVKCommandResourceFactory.h"
#include "MVKDevice.h"
#include "MVKPipeline.h"
#include "MVKDescriptor.h"
#include "MVKSmallVector.h"
#include "MVKBitArray.h"
@ -81,7 +82,7 @@ public:
/**
* If the content of this instance is dirty, marks this instance as no longer dirty
* and calls the encodeImpl() function to encode the content onto the Metal encoder.
* Marking dirty is done in advance so that subclass encodeImpl() implementations
* Marking clean is done in advance so that subclass encodeImpl() implementations
* can override to leave this instance in a dirty state.
* Subclasses must override the encodeImpl() function to do the actual work.
*/
@ -96,8 +97,18 @@ public:
MVKCommandEncoderState(MVKCommandEncoder* cmdEncoder) : _cmdEncoder(cmdEncoder) {}
protected:
enum StateScope {
Static = 0,
Dynamic,
Count
};
virtual void encodeImpl(uint32_t stage) = 0;
MVKDevice* getDevice();
bool isDynamicState(MVKRenderStateType state);
template <typename T> T& getContent(T* iVarAry, MVKRenderStateType state) {
return iVarAry[isDynamicState(state) ? StateScope::Dynamic : StateScope::Static];
}
MVKCommandEncoder* _cmdEncoder;
bool _isDirty = false;
@ -108,20 +119,15 @@ protected:
#pragma mark -
#pragma mark MVKPipelineCommandEncoderState
/** Holds encoder state established by pipeline commands. */
/** Abstract class to hold encoder state established by pipeline commands. */
class MVKPipelineCommandEncoderState : public MVKCommandEncoderState {
public:
virtual void bindPipeline(MVKPipeline* pipeline);
/** Binds the pipeline. */
void bindPipeline(MVKPipeline* pipeline);
/** Returns the currently bound pipeline. */
MVKPipeline* getPipeline();
/** Constructs this instance for the specified command encoder. */
MVKPipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {}
MVKPipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder) : MVKCommandEncoderState(cmdEncoder) {}
protected:
void encodeImpl(uint32_t stage) override;
@ -131,58 +137,38 @@ protected:
#pragma mark -
#pragma mark MVKViewportCommandEncoderState
#pragma mark MVKGraphicsPipelineCommandEncoderState
/** Holds encoder state established by viewport commands. */
class MVKViewportCommandEncoderState : public MVKCommandEncoderState {
/** Holds encoder state established by graphics pipeline commands. */
class MVKGraphicsPipelineCommandEncoderState : public MVKPipelineCommandEncoderState {
public:
void bindPipeline(MVKPipeline* pipeline) override;
/**
* Sets one or more of the viewports, starting at the first index.
* The isSettingDynamically indicates that the scissor is being changed dynamically,
* which is only allowed if the pipeline was created as VK_DYNAMIC_STATE_SCISSOR.
*/
void setViewports(MVKArrayRef<const VkViewport> viewports,
uint32_t firstViewport,
bool isSettingDynamically);
MVKGraphicsPipeline* getGraphicsPipeline() { return (MVKGraphicsPipeline*)getPipeline(); }
/** Constructs this instance for the specified command encoder. */
MVKViewportCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {}
void setPatchControlPoints(uint32_t patchControlPoints);
uint32_t getPatchControlPoints();
MVKGraphicsPipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder) : MVKPipelineCommandEncoderState(cmdEncoder) {}
protected:
void encodeImpl(uint32_t stage) override;
MVKSmallVector<VkViewport, kMVKMaxViewportScissorCount> _viewports, _dynamicViewports;
uint32_t _patchControlPoints[StateScope::Count] = {};
};
#pragma mark -
#pragma mark MVKScissorCommandEncoderState
#pragma mark MVKComputePipelineCommandEncoderState
/** Holds encoder state established by viewport commands. */
class MVKScissorCommandEncoderState : public MVKCommandEncoderState {
/** Holds encoder state established by compute pipeline commands. */
class MVKComputePipelineCommandEncoderState : public MVKPipelineCommandEncoderState {
public:
MVKComputePipeline* getComputePipeline() { return (MVKComputePipeline*)getPipeline(); }
/**
* Sets one or more of the scissors, starting at the first index.
* The isSettingDynamically indicates that the scissor is being changed dynamically,
* which is only allowed if the pipeline was created as VK_DYNAMIC_STATE_SCISSOR.
*/
void setScissors(MVKArrayRef<const VkRect2D> scissors,
uint32_t firstScissor,
bool isSettingDynamically);
/** Constructs this instance for the specified command encoder. */
MVKScissorCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {}
MVKComputePipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder) : MVKPipelineCommandEncoderState(cmdEncoder) {}
protected:
void encodeImpl(uint32_t stage) override;
MVKSmallVector<VkRect2D, kMVKMaxViewportScissorCount> _scissors, _dynamicScissors;
};
@ -226,16 +212,29 @@ public:
/** Sets the depth stencil state during pipeline binding. */
void setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
/**
* Sets the stencil compare mask value of the indicated faces
* to the specified value, from explicit dynamic command.
*/
/** Enables or disables depth testing, from explicit dynamic command. */
void setDepthTestEnable(VkBool32 depthTestEnable);
/** Enables or disables depth writing, from explicit dynamic command. */
void setDepthWriteEnable(VkBool32 depthWriteEnable);
/** Sets the depth compare operation, from explicit dynamic command. */
void setDepthCompareOp(VkCompareOp depthCompareOp);
/** Enables or disables stencil testing, from explicit dynamic command. */
void setStencilTestEnable(VkBool32 stencilTestEnable);
/** Sets the stencil operations of the indicated faces from explicit dynamic command. */
void setStencilOp(VkStencilFaceFlags faceMask,
VkStencilOp failOp,
VkStencilOp passOp,
VkStencilOp depthFailOp,
VkCompareOp compareOp);
/** Sets the stencil compare mask value of the indicated faces from explicit dynamic command. */
void setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t stencilCompareMask);
/**
* Sets the stencil write mask value of the indicated faces
* to the specified value, from explicit dynamic command.
*/
/** Sets the stencil write mask value of the indicated faces from explicit dynamic command. */
void setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t stencilWriteMask);
void beginMetalRenderPass() override;
@ -246,96 +245,108 @@ public:
protected:
void encodeImpl(uint32_t stage) override;
void setStencilState(MVKMTLStencilDescriptorData& stencilInfo,
const VkStencilOpState& vkStencil,
bool enabled);
MVKMTLDepthStencilDescriptorData& getData(MVKRenderStateType state) { return getContent(_depthStencilData, state); }
template <typename T> void setContent(T& content, T value) {
if (content != value) {
content = value;
markDirty();
}
}
void setStencilState(MVKMTLStencilDescriptorData& sData, const VkStencilOpState& vkStencil);
void setStencilOp(MVKMTLStencilDescriptorData& sData, VkStencilOp failOp,
VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp);
MVKMTLDepthStencilDescriptorData _depthStencilData = kMVKMTLDepthStencilDescriptorDataDefault;
MVKMTLDepthStencilDescriptorData _depthStencilData[StateScope::Count];
bool _depthTestEnabled[StateScope::Count];
bool _hasDepthAttachment = false;
bool _hasStencilAttachment = false;
};
#pragma mark -
#pragma mark MVKStencilReferenceValueCommandEncoderState
#pragma mark MVKRenderingCommandEncoderState
/** Holds encoder state established by stencil reference values commands. */
class MVKStencilReferenceValueCommandEncoderState : public MVKCommandEncoderState {
public:
/** Sets the stencil references during pipeline binding. */
void setReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
/** Sets the stencil state from explicit dynamic command. */
void setReferenceValues(VkStencilFaceFlags faceMask, uint32_t stencilReference);
/** Constructs this instance for the specified command encoder. */
MVKStencilReferenceValueCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {}
protected:
void encodeImpl(uint32_t stage) override;
uint32_t _frontFaceValue = 0;
uint32_t _backFaceValue = 0;
struct MVKDepthBias {
float depthBiasConstantFactor;
float depthBiasSlopeFactor;
float depthBiasClamp;
};
struct MVKStencilReference {
uint32_t frontFaceValue;
uint32_t backFaceValue;
};
#pragma mark -
#pragma mark MVKDepthBiasCommandEncoderState
struct MVKMTLViewports {
MTLViewport viewports[kMVKMaxViewportScissorCount];
uint32_t viewportCount;
};
/** Holds encoder state established by depth bias commands. */
class MVKDepthBiasCommandEncoderState : public MVKCommandEncoderState {
struct MVKMTLScissors {
MTLScissorRect scissors[kMVKMaxViewportScissorCount];
uint32_t scissorCount;
};
/** Holds encoder state established by various rendering state commands. */
class MVKRenderingCommandEncoderState : public MVKCommandEncoderState {
public:
void setCullMode(VkCullModeFlags cullMode, bool isDynamic);
void setFrontFace(VkFrontFace frontFace, bool isDynamic);
void setPrimitiveTopology(VkPrimitiveTopology topology, bool isDynamic);
MTLPrimitiveType getPrimitiveType();
void setPolygonMode(VkPolygonMode polygonMode, bool isDynamic);
void setBlendConstants(float blendConstants[4], bool isDynamic);
/** Sets the depth bias during pipeline binding. */
void setDepthBias(const VkPipelineRasterizationStateCreateInfo& vkRasterInfo);
void setDepthBias(float depthBiasConstantFactor, float depthBiasSlopeFactor, float depthBiasClamp);
void setDepthBiasEnable(VkBool32 depthBiasEnable);
void setDepthClipEnable(bool depthClip, bool isDynamic);
/** Sets the depth bias dynamically. */
void setDepthBias(float depthBiasConstantFactor,
float depthBiasSlopeFactor,
float depthBiasClamp);
void setStencilReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
void setStencilReferenceValues(VkStencilFaceFlags faceMask, uint32_t stencilReference);
/** Constructs this instance for the specified command encoder. */
MVKDepthBiasCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {}
void setViewports(const MVKArrayRef<VkViewport> viewports, uint32_t firstViewport, bool isDynamic);
void setScissors(const MVKArrayRef<VkRect2D> scissors, uint32_t firstScissor, bool isDynamic);
void setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable, bool isDynamic);
void beginMetalRenderPass() override;
MVKRenderingCommandEncoderState(MVKCommandEncoder* cmdEncoder) : MVKCommandEncoderState(cmdEncoder) {}
protected:
void encodeImpl(uint32_t stage) override;
bool isDirty(MVKRenderStateType state);
bool isDrawingTriangles();
template <typename T> void setContent(T* iVarAry, T* pVal, MVKRenderStateType state, bool isDynamic) {
auto* pIVar = &iVarAry[isDynamic ? StateScope::Dynamic : StateScope::Static];
if( !mvkAreEqual(pVal, pIVar) ) {
*pIVar = *pVal;
_dirtyStates.enable(state);
_modifiedStates.enable(state);
markDirty();
}
}
float _depthBiasConstantFactor = 0;
float _depthBiasClamp = 0;
float _depthBiasSlopeFactor = 0;
bool _isEnabled = false;
};
#pragma mark -
#pragma mark MVKBlendColorCommandEncoderState
/** Holds encoder state established by blend color commands. */
class MVKBlendColorCommandEncoderState : public MVKCommandEncoderState {
public:
/** Sets the blend color, either as part of pipeline binding, or dynamically. */
void setBlendColor(float red, float green,
float blue, float alpha,
bool isDynamic);
/** Constructs this instance for the specified command encoder. */
MVKBlendColorCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {}
protected:
void encodeImpl(uint32_t stage) override;
float _red = 0;
float _green = 0;
float _blue = 0;
float _alpha = 0;
MVKMTLViewports _mtlViewports[StateScope::Count] = {};
MVKMTLScissors _mtlScissors[StateScope::Count] = {};
MVKColor32 _mtlBlendConstants[StateScope::Count] = {};
MVKDepthBias _mtlDepthBias[StateScope::Count] = {};
MVKStencilReference _mtlStencilReference[StateScope::Count] = {};
MTLCullMode _mtlCullMode[StateScope::Count] = { MTLCullModeNone, MTLCullModeNone };
MTLWinding _mtlFrontFace[StateScope::Count] = { MTLWindingClockwise, MTLWindingClockwise };
MTLPrimitiveType _mtlPrimitiveTopology[StateScope::Count] = { MTLPrimitiveTypePoint, MTLPrimitiveTypePoint };
MTLDepthClipMode _mtlDepthClipEnable[StateScope::Count] = { MTLDepthClipModeClip, MTLDepthClipModeClip };
MTLTriangleFillMode _mtlPolygonMode[StateScope::Count] = { MTLTriangleFillModeFill, MTLTriangleFillModeFill };
MVKRenderStateFlags _dirtyStates;
MVKRenderStateFlags _modifiedStates;
bool _mtlDepthBiasEnable[StateScope::Count] = {};
bool _mtlRasterizerDiscardEnable[StateScope::Count] = {};
bool _cullBothFaces[StateScope::Count] = {};
};

View File

@ -25,13 +25,21 @@
using namespace std;
#define shouldUpdateFace(face) mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_##face##_BIT)
#pragma mark -
#pragma mark MVKCommandEncoderState
MVKVulkanAPIObject* MVKCommandEncoderState::getVulkanAPIObject() { return _cmdEncoder->getVulkanAPIObject(); };
MVKDevice* MVKCommandEncoderState::getDevice() { return _cmdEncoder->getDevice(); }
bool MVKCommandEncoderState::isDynamicState(MVKRenderStateType state) {
auto* gpl = _cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
return !gpl || gpl->isDynamicState(state);
}
#pragma mark -
#pragma mark MVKPipelineCommandEncoderState
@ -52,108 +60,19 @@ void MVKPipelineCommandEncoderState::encodeImpl(uint32_t stage) {
#pragma mark -
#pragma mark MVKViewportCommandEncoderState
#pragma mark MVKGraphicsPipelineCommandEncoderState
void MVKViewportCommandEncoderState::setViewports(MVKArrayRef<const VkViewport> viewports,
uint32_t firstViewport,
bool isSettingDynamically) {
size_t vpCnt = viewports.size();
uint32_t maxViewports = getDevice()->_pProperties->limits.maxViewports;
if ((firstViewport + vpCnt > maxViewports) ||
(firstViewport >= maxViewports) ||
(isSettingDynamically && vpCnt == 0))
return;
auto& usingViewports = isSettingDynamically ? _dynamicViewports : _viewports;
if (firstViewport + vpCnt > usingViewports.size()) {
usingViewports.resize(firstViewport + vpCnt);
void MVKGraphicsPipelineCommandEncoderState::bindPipeline(MVKPipeline* pipeline) {
MVKPipelineCommandEncoderState::bindPipeline(pipeline);
_patchControlPoints[StateScope::Static] = getGraphicsPipeline()->_tessInfo.patchControlPoints;
}
bool dirty;
bool mustSetDynamically = _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
if (isSettingDynamically || (!mustSetDynamically && vpCnt > 0)) {
dirty = memcmp(&usingViewports[firstViewport], &viewports[0], vpCnt * sizeof(VkViewport)) != 0;
std::copy(viewports.begin(), viewports.end(), usingViewports.begin() + firstViewport);
} else {
dirty = !usingViewports.empty();
usingViewports.clear();
void MVKGraphicsPipelineCommandEncoderState::setPatchControlPoints(uint32_t patchControlPoints) {
_patchControlPoints[StateScope::Dynamic] = patchControlPoints;
}
if (dirty) markDirty();
}
void MVKViewportCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; }
auto& usingViewports = _viewports.size() > 0 ? _viewports : _dynamicViewports;
if (usingViewports.empty()) { return; }
if (_cmdEncoder->_pDeviceFeatures->multiViewport) {
size_t vpCnt = usingViewports.size();
MTLViewport mtlViewports[vpCnt];
for (uint32_t vpIdx = 0; vpIdx < vpCnt; vpIdx++) {
mtlViewports[vpIdx] = mvkMTLViewportFromVkViewport(usingViewports[vpIdx]);
}
#if MVK_MACOS_OR_IOS
[_cmdEncoder->_mtlRenderEncoder setViewports: mtlViewports count: vpCnt];
#endif
} else {
[_cmdEncoder->_mtlRenderEncoder setViewport: mvkMTLViewportFromVkViewport(usingViewports[0])];
}
}
#pragma mark -
#pragma mark MVKScissorCommandEncoderState
void MVKScissorCommandEncoderState::setScissors(MVKArrayRef<const VkRect2D> scissors,
uint32_t firstScissor,
bool isSettingDynamically) {
size_t sCnt = scissors.size();
uint32_t maxScissors = getDevice()->_pProperties->limits.maxViewports;
if ((firstScissor + sCnt > maxScissors) ||
(firstScissor >= maxScissors) ||
(isSettingDynamically && sCnt == 0))
return;
auto& usingScissors = isSettingDynamically ? _dynamicScissors : _scissors;
if (firstScissor + sCnt > usingScissors.size()) {
usingScissors.resize(firstScissor + sCnt);
}
bool dirty;
bool mustSetDynamically = _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_SCISSOR);
if (isSettingDynamically || (!mustSetDynamically && sCnt > 0)) {
dirty = memcmp(&usingScissors[firstScissor], &scissors[0], sCnt * sizeof(VkRect2D)) != 0;
std::copy(scissors.begin(), scissors.end(), usingScissors.begin() + firstScissor);
} else {
dirty = !usingScissors.empty();
usingScissors.clear();
}
if (dirty) markDirty();
}
void MVKScissorCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; }
auto& usingScissors = _scissors.size() > 0 ? _scissors : _dynamicScissors;
if (usingScissors.empty()) { return; }
if (_cmdEncoder->_pDeviceFeatures->multiViewport) {
size_t sCnt = usingScissors.size();
MTLScissorRect mtlScissors[sCnt];
for (uint32_t sIdx = 0; sIdx < sCnt; sIdx++) {
mtlScissors[sIdx] = mvkMTLScissorRectFromVkRect2D(_cmdEncoder->clipToRenderArea(usingScissors[sIdx]));
}
#if MVK_MACOS_OR_IOS
[_cmdEncoder->_mtlRenderEncoder setScissorRects: mtlScissors count: sCnt];
#endif
} else {
[_cmdEncoder->_mtlRenderEncoder setScissorRect: mvkMTLScissorRectFromVkRect2D(_cmdEncoder->clipToRenderArea(usingScissors[0]))];
}
uint32_t MVKGraphicsPipelineCommandEncoderState::getPatchControlPoints() {
return getContent(_patchControlPoints, PatchControlPoints);
}
@ -245,7 +164,7 @@ void MVKPushConstantsCommandEncoderState::encodeImpl(uint32_t stage) {
}
bool MVKPushConstantsCommandEncoderState::isTessellating() {
MVKGraphicsPipeline* gp = (MVKGraphicsPipeline*)_cmdEncoder->_graphicsPipelineState.getPipeline();
auto* gp = _cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
return gp ? gp->isTessellationPipeline() : false;
}
@ -254,74 +173,84 @@ bool MVKPushConstantsCommandEncoderState::isTessellating() {
#pragma mark MVKDepthStencilCommandEncoderState
void MVKDepthStencilCommandEncoderState:: setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
auto oldData = _depthStencilData;
auto& depthEnabled = _depthTestEnabled[StateScope::Static];
auto oldDepthEnabled = depthEnabled;
depthEnabled = static_cast<bool>(vkDepthStencilInfo.depthTestEnable);
if (vkDepthStencilInfo.depthTestEnable) {
_depthStencilData.depthCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(vkDepthStencilInfo.depthCompareOp);
_depthStencilData.depthWriteEnabled = vkDepthStencilInfo.depthWriteEnable;
} else {
_depthStencilData.depthCompareFunction = kMVKMTLDepthStencilDescriptorDataDefault.depthCompareFunction;
_depthStencilData.depthWriteEnabled = kMVKMTLDepthStencilDescriptorDataDefault.depthWriteEnabled;
auto& dsData = _depthStencilData[StateScope::Static];
auto oldData = dsData;
dsData.depthCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(vkDepthStencilInfo.depthCompareOp);
dsData.depthWriteEnabled = vkDepthStencilInfo.depthWriteEnable;
dsData.stencilTestEnabled = static_cast<bool>(vkDepthStencilInfo.stencilTestEnable);
setStencilState(dsData.frontFaceStencilData, vkDepthStencilInfo.front);
setStencilState(dsData.backFaceStencilData, vkDepthStencilInfo.back);
if (depthEnabled != oldDepthEnabled || dsData != oldData) { markDirty(); }
}
setStencilState(_depthStencilData.frontFaceStencilData, vkDepthStencilInfo.front, vkDepthStencilInfo.stencilTestEnable);
setStencilState(_depthStencilData.backFaceStencilData, vkDepthStencilInfo.back, vkDepthStencilInfo.stencilTestEnable);
if (!(oldData == _depthStencilData)) markDirty();
void MVKDepthStencilCommandEncoderState::setStencilState(MVKMTLStencilDescriptorData& sData,
const VkStencilOpState& vkStencil) {
sData.readMask = vkStencil.compareMask;
sData.writeMask = vkStencil.writeMask;
sData.stencilCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(vkStencil.compareOp);
sData.stencilFailureOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.failOp);
sData.depthFailureOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.depthFailOp);
sData.depthStencilPassOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.passOp);
}
void MVKDepthStencilCommandEncoderState::setStencilState(MVKMTLStencilDescriptorData& stencilInfo,
const VkStencilOpState& vkStencil,
bool enabled) {
if ( !enabled ) {
stencilInfo = kMVKMTLStencilDescriptorDataDefault;
return;
void MVKDepthStencilCommandEncoderState::setDepthTestEnable(VkBool32 depthTestEnable) {
setContent(_depthTestEnabled[StateScope::Dynamic], static_cast<bool>(depthTestEnable));
}
stencilInfo.enabled = true;
stencilInfo.stencilCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(vkStencil.compareOp);
stencilInfo.stencilFailureOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.failOp);
stencilInfo.depthFailureOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.depthFailOp);
stencilInfo.depthStencilPassOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.passOp);
if ( !_cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) ) {
stencilInfo.readMask = vkStencil.compareMask;
}
if ( !_cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK) ) {
stencilInfo.writeMask = vkStencil.writeMask;
}
void MVKDepthStencilCommandEncoderState::setDepthWriteEnable(VkBool32 depthWriteEnable) {
setContent(_depthStencilData[StateScope::Dynamic].depthWriteEnabled, static_cast<bool>(depthWriteEnable));
}
void MVKDepthStencilCommandEncoderState::setDepthCompareOp(VkCompareOp depthCompareOp) {
setContent(_depthStencilData[StateScope::Dynamic].depthCompareFunction,
(uint8_t)mvkMTLCompareFunctionFromVkCompareOp(depthCompareOp));
}
void MVKDepthStencilCommandEncoderState::setStencilTestEnable(VkBool32 stencilTestEnable) {
setContent(_depthStencilData[StateScope::Dynamic].stencilTestEnabled, static_cast<bool>(stencilTestEnable));
}
void MVKDepthStencilCommandEncoderState::setStencilOp(MVKMTLStencilDescriptorData& sData,
VkStencilOp failOp,
VkStencilOp passOp,
VkStencilOp depthFailOp,
VkCompareOp compareOp) {
auto oldData = sData;
sData.stencilCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(compareOp);
sData.stencilFailureOperation = mvkMTLStencilOperationFromVkStencilOp(failOp);
sData.depthFailureOperation = mvkMTLStencilOperationFromVkStencilOp(depthFailOp);
sData.depthStencilPassOperation = mvkMTLStencilOperationFromVkStencilOp(passOp);
if (sData != oldData) { markDirty(); }
}
void MVKDepthStencilCommandEncoderState::setStencilOp(VkStencilFaceFlags faceMask,
VkStencilOp failOp,
VkStencilOp passOp,
VkStencilOp depthFailOp,
VkCompareOp compareOp) {
auto& dsData = _depthStencilData[StateScope::Dynamic];
if (shouldUpdateFace(FRONT)) { setStencilOp(dsData.frontFaceStencilData, failOp, passOp, depthFailOp, compareOp); }
if (shouldUpdateFace(BACK)) { setStencilOp(dsData.backFaceStencilData, failOp, passOp, depthFailOp, compareOp); }
}
// We don't check for dynamic state here, because if this is called before pipeline is set,
// it may not be accurate, and if not dynamic, pipeline will override when it is encoded anyway.
void MVKDepthStencilCommandEncoderState::setStencilCompareMask(VkStencilFaceFlags faceMask,
uint32_t stencilCompareMask) {
auto oldData = _depthStencilData;
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_FRONT_BIT)) {
_depthStencilData.frontFaceStencilData.readMask = stencilCompareMask;
}
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_BACK_BIT)) {
_depthStencilData.backFaceStencilData.readMask = stencilCompareMask;
auto& dsData = _depthStencilData[StateScope::Dynamic];
if (shouldUpdateFace(FRONT)) { setContent(dsData.frontFaceStencilData.readMask, stencilCompareMask); }
if (shouldUpdateFace(BACK)) { setContent(dsData.backFaceStencilData.readMask, stencilCompareMask); }
}
if (!(oldData == _depthStencilData)) markDirty();
}
// We don't check for dynamic state here, because if this is called before pipeline is set,
// it may not be accurate, and if not dynamic, pipeline will override when it is encoded anyway.
void MVKDepthStencilCommandEncoderState::setStencilWriteMask(VkStencilFaceFlags faceMask,
uint32_t stencilWriteMask) {
auto oldData = _depthStencilData;
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_FRONT_BIT)) {
_depthStencilData.frontFaceStencilData.writeMask = stencilWriteMask;
}
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_BACK_BIT)) {
_depthStencilData.backFaceStencilData.writeMask = stencilWriteMask;
}
if (!(oldData == _depthStencilData)) markDirty();
auto& dsData = _depthStencilData[StateScope::Dynamic];
if (shouldUpdateFace(FRONT)) { setContent(dsData.frontFaceStencilData.writeMask, stencilWriteMask); }
if (shouldUpdateFace(BACK)) { setContent(dsData.backFaceStencilData.writeMask, stencilWriteMask); }
}
void MVKDepthStencilCommandEncoderState::beginMetalRenderPass() {
@ -337,130 +266,255 @@ void MVKDepthStencilCommandEncoderState::beginMetalRenderPass() {
if (_hasStencilAttachment != prevHasStencilAttachment) { markDirty(); }
}
// Combine static and dynamic depth/stencil data
void MVKDepthStencilCommandEncoderState::encodeImpl(uint32_t stage) {
auto cmdEncPool = _cmdEncoder->getCommandEncodingPool();
switch (stage) {
case kMVKGraphicsStageRasterization: {
// If renderpass does not have a depth or a stencil attachment, disable corresponding test
MVKMTLDepthStencilDescriptorData adjustedDSData = _depthStencilData;
adjustedDSData.disable(!_hasDepthAttachment, !_hasStencilAttachment);
[_cmdEncoder->_mtlRenderEncoder setDepthStencilState: cmdEncPool->getMTLDepthStencilState(adjustedDSData)];
break;
}
default: // Do nothing on other stages
break;
}
}
#pragma mark -
#pragma mark MVKStencilReferenceValueCommandEncoderState
void MVKStencilReferenceValueCommandEncoderState:: setReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
// If ref values are to be set dynamically, don't set them here.
if (_cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE)) { return; }
if (_frontFaceValue != vkDepthStencilInfo.front.reference || _backFaceValue != vkDepthStencilInfo.back.reference)
markDirty();
_frontFaceValue = vkDepthStencilInfo.front.reference;
_backFaceValue = vkDepthStencilInfo.back.reference;
}
// We don't check for dynamic state here, because if this is called before pipeline is set,
// it may not be accurate, and if not dynamic, pipeline will override when it is encoded anyway.
void MVKStencilReferenceValueCommandEncoderState::setReferenceValues(VkStencilFaceFlags faceMask,
uint32_t stencilReference) {
bool dirty = false;
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_FRONT_BIT)) {
dirty |= (_frontFaceValue != stencilReference);
_frontFaceValue = stencilReference;
}
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_BACK_BIT)) {
dirty |= (_backFaceValue != stencilReference);
_backFaceValue = stencilReference;
}
if (dirty) markDirty();
}
void MVKStencilReferenceValueCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; }
[_cmdEncoder->_mtlRenderEncoder setStencilFrontReferenceValue: _frontFaceValue
backReferenceValue: _backFaceValue];
MVKMTLDepthStencilDescriptorData dsData;
if (_hasDepthAttachment && getContent(_depthTestEnabled, DepthTestEnable)) {
dsData.depthCompareFunction = getData(DepthCompareOp).depthCompareFunction;
dsData.depthWriteEnabled = getData(DepthWriteEnable).depthWriteEnabled;
}
if (_hasStencilAttachment && getData(StencilTestEnable).stencilTestEnabled) {
dsData.stencilTestEnabled = true;
auto& frontFace = dsData.frontFaceStencilData;
auto& backFace = dsData.backFaceStencilData;
const auto& srcRM = getData(StencilCompareMask);
frontFace.readMask = srcRM.frontFaceStencilData.readMask;
backFace.readMask = srcRM.backFaceStencilData.readMask;
const auto& srcWM = getData(StencilWriteMask);
frontFace.writeMask = srcWM.frontFaceStencilData.writeMask;
backFace.writeMask = srcWM.backFaceStencilData.writeMask;
const auto& srcSOp = getData(StencilOp);
frontFace.stencilCompareFunction = srcSOp.frontFaceStencilData.stencilCompareFunction;
frontFace.stencilFailureOperation = srcSOp.frontFaceStencilData.stencilFailureOperation;
frontFace.depthFailureOperation = srcSOp.frontFaceStencilData.depthFailureOperation;
frontFace.depthStencilPassOperation = srcSOp.frontFaceStencilData.depthStencilPassOperation;
backFace.stencilCompareFunction = srcSOp.backFaceStencilData.stencilCompareFunction;
backFace.stencilFailureOperation = srcSOp.backFaceStencilData.stencilFailureOperation;
backFace.depthFailureOperation = srcSOp.backFaceStencilData.depthFailureOperation;
backFace.depthStencilPassOperation = srcSOp.backFaceStencilData.depthStencilPassOperation;
}
[_cmdEncoder->_mtlRenderEncoder setDepthStencilState: _cmdEncoder->getCommandEncodingPool()->getMTLDepthStencilState(dsData)];
}
#pragma mark -
#pragma mark MVKDepthBiasCommandEncoderState
#pragma mark MVKRenderingCommandEncoderState
void MVKDepthBiasCommandEncoderState::setDepthBias(const VkPipelineRasterizationStateCreateInfo& vkRasterInfo) {
#define getContent(state) getContent(_mtl##state, state)
#define setContent(state) setContent(_mtl##state, &mtl##state, state, isDynamic)
auto wasEnabled = _isEnabled;
_isEnabled = vkRasterInfo.depthBiasEnable;
void MVKRenderingCommandEncoderState::setCullMode(VkCullModeFlags cullMode, bool isDynamic) {
auto mtlCullMode = mvkMTLCullModeFromVkCullModeFlags(cullMode);
setContent(CullMode);
_cullBothFaces[isDynamic ? StateScope::Dynamic : StateScope::Static] = (cullMode == VK_CULL_MODE_FRONT_AND_BACK);
}
// If ref values are to be set dynamically, don't set them here.
if (_cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS)) { return; }
void MVKRenderingCommandEncoderState::setFrontFace(VkFrontFace frontFace, bool isDynamic) {
auto mtlFrontFace = mvkMTLWindingFromVkFrontFace(frontFace);
setContent(FrontFace);
}
if (_isEnabled != wasEnabled || _depthBiasConstantFactor != vkRasterInfo.depthBiasConstantFactor
|| _depthBiasSlopeFactor != vkRasterInfo.depthBiasSlopeFactor || _depthBiasClamp != vkRasterInfo.depthBiasClamp) {
void MVKRenderingCommandEncoderState::setPrimitiveTopology(VkPrimitiveTopology topology, bool isDynamic) {
auto mtlPrimitiveTopology = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(topology);
setContent(PrimitiveTopology);
}
markDirty();
_depthBiasConstantFactor = vkRasterInfo.depthBiasConstantFactor;
_depthBiasSlopeFactor = vkRasterInfo.depthBiasSlopeFactor;
_depthBiasClamp = vkRasterInfo.depthBiasClamp;
MTLPrimitiveType MVKRenderingCommandEncoderState::getPrimitiveType() {
return getContent(PrimitiveTopology);
}
bool MVKRenderingCommandEncoderState::isDrawingTriangles() {
switch (getPrimitiveType()) {
case MTLPrimitiveTypeTriangle: return true;
case MTLPrimitiveTypeTriangleStrip: return true;
default: return false;
}
}
// We don't check for dynamic state here, because if this is called before pipeline is set,
// it may not be accurate, and if not dynamic, pipeline will override when it is encoded anyway.
void MVKDepthBiasCommandEncoderState::setDepthBias(float depthBiasConstantFactor,
void MVKRenderingCommandEncoderState::setPolygonMode(VkPolygonMode polygonMode, bool isDynamic) {
auto mtlPolygonMode = mvkMTLTriangleFillModeFromVkPolygonMode(polygonMode);
setContent(PolygonMode);
}
void MVKRenderingCommandEncoderState::setBlendConstants(float blendConstants[4], bool isDynamic) {
MVKColor32 mtlBlendConstants;
mvkCopy(mtlBlendConstants.float32, blendConstants, 4);
setContent(BlendConstants);
}
void MVKRenderingCommandEncoderState::setDepthBias(const VkPipelineRasterizationStateCreateInfo& vkRasterInfo) {
bool isDynamic = false;
bool mtlDepthBiasEnable = static_cast<bool>(vkRasterInfo.depthBiasEnable);
setContent(DepthBiasEnable);
MVKDepthBias mtlDepthBias = {
.depthBiasConstantFactor = vkRasterInfo.depthBiasConstantFactor,
.depthBiasSlopeFactor = vkRasterInfo.depthBiasSlopeFactor,
.depthBiasClamp = vkRasterInfo.depthBiasClamp
};
setContent(DepthBias);
}
void MVKRenderingCommandEncoderState::setDepthBias(float depthBiasConstantFactor,
float depthBiasSlopeFactor,
float depthBiasClamp) {
if (_depthBiasConstantFactor != depthBiasConstantFactor || _depthBiasSlopeFactor != depthBiasSlopeFactor
|| _depthBiasClamp != depthBiasClamp) {
markDirty();
_depthBiasConstantFactor = depthBiasConstantFactor;
_depthBiasSlopeFactor = depthBiasSlopeFactor;
_depthBiasClamp = depthBiasClamp;
}
bool isDynamic = true;
MVKDepthBias mtlDepthBias = {
.depthBiasConstantFactor = depthBiasConstantFactor,
.depthBiasSlopeFactor = depthBiasSlopeFactor,
.depthBiasClamp = depthBiasClamp
};
setContent(DepthBias);
}
void MVKDepthBiasCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; }
if (_isEnabled) {
[_cmdEncoder->_mtlRenderEncoder setDepthBias: _depthBiasConstantFactor
slopeScale: _depthBiasSlopeFactor
clamp: _depthBiasClamp];
} else {
[_cmdEncoder->_mtlRenderEncoder setDepthBias: 0 slopeScale: 0 clamp: 0];
}
void MVKRenderingCommandEncoderState::setDepthBiasEnable(VkBool32 depthBiasEnable) {
bool isDynamic = true;
bool mtlDepthBiasEnable = static_cast<bool>(depthBiasEnable);
setContent(DepthBiasEnable);
}
void MVKRenderingCommandEncoderState::setDepthClipEnable(bool depthClip, bool isDynamic) {
auto mtlDepthClipEnable = depthClip ? MTLDepthClipModeClip : MTLDepthClipModeClamp;
setContent(DepthClipEnable);
}
#pragma mark -
#pragma mark MVKBlendColorCommandEncoderState
void MVKRenderingCommandEncoderState::setStencilReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
bool isDynamic = false;
MVKStencilReference mtlStencilReference = {
.frontFaceValue = vkDepthStencilInfo.front.reference,
.backFaceValue = vkDepthStencilInfo.back.reference
};
setContent(StencilReference);
}
void MVKBlendColorCommandEncoderState::setBlendColor(float red, float green,
float blue, float alpha,
void MVKRenderingCommandEncoderState::setStencilReferenceValues(VkStencilFaceFlags faceMask, uint32_t stencilReference) {
bool isDynamic = true;
MVKStencilReference mtlStencilReference = _mtlStencilReference[StateScope::Dynamic];
if (shouldUpdateFace(FRONT)) { mtlStencilReference.frontFaceValue = stencilReference; }
if (shouldUpdateFace(BACK)) { mtlStencilReference.backFaceValue = stencilReference; }
setContent(StencilReference);
}
void MVKRenderingCommandEncoderState::setViewports(const MVKArrayRef<VkViewport> viewports,
uint32_t firstViewport,
bool isDynamic) {
// Abort if we are using dynamic, but call is not dynamic.
if ( !isDynamic && _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS) ) { return; }
uint32_t maxViewports = getDevice()->_pProperties->limits.maxViewports;
if (firstViewport >= maxViewports) { return; }
if (_red != red || _green != green || _blue != blue || _alpha != alpha) {
markDirty();
_red = red;
_green = green;
_blue = blue;
_alpha = alpha;
MVKMTLViewports mtlViewports = isDynamic ? _mtlViewports[StateScope::Dynamic] : _mtlViewports[StateScope::Static];
size_t vpCnt = min((uint32_t)viewports.size(), maxViewports - firstViewport);
for (uint32_t vpIdx = 0; vpIdx < vpCnt; vpIdx++) {
mtlViewports.viewports[firstViewport + vpIdx] = mvkMTLViewportFromVkViewport(viewports[vpIdx]);
mtlViewports.viewportCount = max(mtlViewports.viewportCount, vpIdx + 1);
}
setContent(Viewports);
}
void MVKBlendColorCommandEncoderState::encodeImpl(uint32_t stage) {
void MVKRenderingCommandEncoderState::setScissors(const MVKArrayRef<VkRect2D> scissors,
uint32_t firstScissor,
bool isDynamic) {
uint32_t maxScissors = getDevice()->_pProperties->limits.maxViewports;
if (firstScissor >= maxScissors) { return; }
MVKMTLScissors mtlScissors = isDynamic ? _mtlScissors[StateScope::Dynamic] : _mtlScissors[StateScope::Static];
size_t sCnt = min((uint32_t)scissors.size(), maxScissors - firstScissor);
for (uint32_t sIdx = 0; sIdx < sCnt; sIdx++) {
mtlScissors.scissors[firstScissor + sIdx] = mvkMTLScissorRectFromVkRect2D(scissors[sIdx]);
mtlScissors.scissorCount = max(mtlScissors.scissorCount, sIdx + 1);
}
setContent(Scissors);
}
void MVKRenderingCommandEncoderState::setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable, bool isDynamic) {
bool mtlRasterizerDiscardEnable = static_cast<bool>(rasterizerDiscardEnable);
setContent(RasterizerDiscardEnable);
}
#pragma mark Encoding
void MVKRenderingCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; }
[_cmdEncoder->_mtlRenderEncoder setBlendColorRed: _red green: _green blue: _blue alpha: _alpha];
auto& rendEnc = _cmdEncoder->_mtlRenderEncoder;
if (isDirty(CullMode)) { [rendEnc setCullMode: getContent(CullMode)]; }
if (isDirty(FrontFace)) { [rendEnc setFrontFacingWinding: getContent(FrontFace)]; }
if (isDirty(BlendConstants)) {
auto& bcFlt = getContent(BlendConstants).float32;
[rendEnc setBlendColorRed: bcFlt[0] green: bcFlt[1] blue: bcFlt[2] alpha: bcFlt[3]];
}
if (isDirty(DepthBiasEnable) || isDirty(DepthBias)) {
if (getContent(DepthBiasEnable)) {
auto& db = getContent(DepthBias);
[rendEnc setDepthBias: db.depthBiasConstantFactor
slopeScale: db.depthBiasSlopeFactor
clamp: db.depthBiasClamp];
} else {
[rendEnc setDepthBias: 0 slopeScale: 0 clamp: 0];
}
}
if (isDirty(DepthClipEnable) && _cmdEncoder->_pDeviceFeatures->depthClamp) {
[rendEnc setDepthClipMode: getContent(DepthClipEnable)];
}
if (isDirty(StencilReference)) {
auto& sr = getContent(StencilReference);
[rendEnc setStencilFrontReferenceValue: sr.frontFaceValue backReferenceValue: sr.backFaceValue];
}
if (isDirty(Viewports)) {
auto& mtlViewports = getContent(Viewports);
if (_cmdEncoder->_pDeviceFeatures->multiViewport) {
#if MVK_MACOS_OR_IOS
[rendEnc setViewports: mtlViewports.viewports count: mtlViewports.viewportCount];
#endif
} else {
[rendEnc setViewport: mtlViewports.viewports[0]];
}
}
// If rasterizing discard has been dynamically enabled, or culling has been dynamically
// set to front-and-back, emulate this by using zeroed scissor rectangles.
if (isDirty(Scissors)) {
static MTLScissorRect zeroRect = {};
auto mtlScissors = getContent(Scissors);
bool shouldDiscard = ((_mtlRasterizerDiscardEnable[StateScope::Dynamic] && isDynamicState(RasterizerDiscardEnable)) ||
(isDrawingTriangles() && _cullBothFaces[StateScope::Dynamic] && isDynamicState(CullMode)));
for (uint32_t sIdx = 0; sIdx < mtlScissors.scissorCount; sIdx++) {
mtlScissors.scissors[sIdx] = shouldDiscard ? zeroRect : _cmdEncoder->clipToRenderArea(mtlScissors.scissors[sIdx]);
}
if (_cmdEncoder->_pDeviceFeatures->multiViewport) {
#if MVK_MACOS_OR_IOS
[rendEnc setScissorRects: mtlScissors.scissors count: mtlScissors.scissorCount];
#endif
} else {
[rendEnc setScissorRect: mtlScissors.scissors[0]];
}
}
}
// Return whether state is dirty, and mark it not dirty
bool MVKRenderingCommandEncoderState::isDirty(MVKRenderStateType state) {
bool rslt = _dirtyStates.isEnabled(state);
_dirtyStates.disable(state);
return rslt;
}
void MVKRenderingCommandEncoderState::beginMetalRenderPass() {
MVKCommandEncoderState::beginMetalRenderPass();
_dirtyStates = _modifiedStates;
}
@ -772,11 +826,16 @@ void MVKGraphicsResourcesCommandEncoderState::markDirty() {
}
}
#if !MVK_XCODE_15
static const NSUInteger MTLAttributeStrideStatic = NSUIntegerMax;
#endif
void MVKGraphicsResourcesCommandEncoderState::encodeImpl(uint32_t stage) {
MVKGraphicsPipeline* pipeline = (MVKGraphicsPipeline*)getPipeline();
auto* pipeline = _cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
bool fullImageViewSwizzle = pipeline->fullImageViewSwizzle() || getDevice()->_pMetalFeatures->nativeTextureSwizzle;
bool forTessellation = pipeline->isTessellationPipeline();
bool isDynamicVertexStride = pipeline->isDynamicState(VertexStride);
if (stage == kMVKGraphicsStageVertex) {
encodeBindings(kMVKShaderStageVertex, "vertex", fullImageViewSwizzle,
@ -812,33 +871,24 @@ void MVKGraphicsResourcesCommandEncoderState::encodeImpl(uint32_t stage) {
} else if (!forTessellation && stage == kMVKGraphicsStageRasterization) {
encodeBindings(kMVKShaderStageVertex, "vertex", fullImageViewSwizzle,
[pipeline](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
[pipeline, isDynamicVertexStride](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
// The app may have bound more vertex attribute buffers than used by the pipeline.
// We must not bind those extra buffers to the shader because they might overwrite
// any implicit buffers used by the pipeline.
if (pipeline->isValidVertexBufferIndex(kMVKShaderStageVertex, b.index)) {
if (b.isInline) {
cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder,
b.mtlBytes,
b.size,
b.index);
} else {
if (b.justOffset) {
[cmdEncoder->_mtlRenderEncoder setVertexBufferOffset: b.offset
atIndex: b.index];
} else {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer
offset: b.offset
atIndex: b.index];
}
cmdEncoder->encodeVertexAttributeBuffer(b, isDynamicVertexStride);
// Add any translated vertex bindings for this binding
if ( !b.isInline ) {
auto xltdVtxBindings = pipeline->getTranslatedVertexBindings();
for (auto& xltdBind : xltdVtxBindings) {
if (b.index == pipeline->getMetalBufferIndexForVertexAttributeBinding(xltdBind.binding)) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer
offset: b.offset + xltdBind.translationOffset
atIndex: pipeline->getMetalBufferIndexForVertexAttributeBinding(xltdBind.translationBinding)];
MVKMTLBufferBinding bx = {
.mtlBuffer = b.mtlBuffer,
.offset = b.offset + xltdBind.translationOffset,
.stride = b.stride,
.index = static_cast<uint16_t>(pipeline->getMetalBufferIndexForVertexAttributeBinding(xltdBind.translationBinding)) };
cmdEncoder->encodeVertexAttributeBuffer(bx, isDynamicVertexStride);
}
}
}
@ -898,19 +948,8 @@ void MVKGraphicsResourcesCommandEncoderState::encodeImpl(uint32_t stage) {
if (forTessellation && stage == kMVKGraphicsStageRasterization) {
encodeBindings(kMVKShaderStageTessEval, "tessellation evaluation", fullImageViewSwizzle,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
if (b.isInline)
cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder,
b.mtlBytes,
b.size,
b.index);
else if (b.justOffset)
[cmdEncoder->_mtlRenderEncoder setVertexBufferOffset: b.offset
atIndex: b.index];
else
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer
offset: b.offset
atIndex: b.index];
[isDynamicVertexStride](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
cmdEncoder->encodeVertexAttributeBuffer(b, isDynamicVertexStride);
},
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b, MVKArrayRef<const uint32_t> s)->void {
cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder,

View File

@ -23,7 +23,7 @@
#include "MVKCommandEncodingPool.h"
#include "MVKCommand.h"
#include "MVKCmdPipeline.h"
#include "MVKCmdRenderPass.h"
#include "MVKCmdRendering.h"
#include "MVKCmdDispatch.h"
#include "MVKCmdDraw.h"
#include "MVKCmdTransfer.h"

View File

@ -210,27 +210,24 @@ namespace std {
* change as early as possible.
*/
typedef struct MVKMTLStencilDescriptorData {
bool enabled; /**< Indicates whether stencil testing for this face is enabled. */
uint32_t readMask; /**< The bit-mask to apply when comparing the stencil buffer value to the reference value. */
uint32_t writeMask; /**< The bit-mask to apply when writing values to the stencil buffer. */
uint8_t stencilCompareFunction; /**< The stencil compare function (interpreted as MTLCompareFunction). */
uint8_t stencilFailureOperation; /**< The operation to take when the stencil test fails (interpreted as MTLStencilOperation). */
uint8_t depthFailureOperation; /**< The operation to take when the stencil test passes, but the depth test fails (interpreted as MTLStencilOperation). */
uint8_t depthStencilPassOperation; /**< The operation to take when both the stencil and depth tests pass (interpreted as MTLStencilOperation). */
uint32_t readMask; /**< The bit-mask to apply when comparing the stencil buffer value to the reference value. */
uint32_t writeMask; /**< The bit-mask to apply when writing values to the stencil buffer. */
bool operator==(const MVKMTLStencilDescriptorData& rhs) const { return mvkAreEqual(this, &rhs); }
bool operator!=(const MVKMTLStencilDescriptorData& rhs) const { return !(*this == rhs); }
MVKMTLStencilDescriptorData() {
// Start with all zeros to ensure memory comparisons will work,
// even if the structure contains alignment gaps.
mvkClear(this);
enabled = false;
mvkClear(this); // Clear all memory to ensure memory comparisons will work.
mvkEnableAllFlags(readMask);
mvkEnableAllFlags(writeMask);
stencilCompareFunction = MTLCompareFunctionAlways;
stencilFailureOperation = MTLStencilOperationKeep;
depthFailureOperation = MTLStencilOperationKeep;
depthStencilPassOperation = MTLStencilOperationKeep;
readMask = static_cast<uint32_t>(~0);
writeMask = static_cast<uint32_t>(~0);
}
} MVKMTLStencilDescriptorData;
@ -247,34 +244,32 @@ const MVKMTLStencilDescriptorData kMVKMTLStencilDescriptorDataDefault;
* change as early as possible.
*/
typedef struct MVKMTLDepthStencilDescriptorData {
uint8_t depthCompareFunction; /**< The depth compare function (interpreted as MTLCompareFunction). */
bool depthWriteEnabled; /**< Indicates whether depth writing is enabled. */
MVKMTLStencilDescriptorData frontFaceStencilData;
MVKMTLStencilDescriptorData backFaceStencilData;
uint8_t depthCompareFunction; /**< The depth compare function (interpreted as MTLCompareFunction). */
bool depthWriteEnabled; /**< Indicates whether depth writing is enabled. */
bool stencilTestEnabled; /**< Indicates whether stencil testing is enabled. */
bool operator==(const MVKMTLDepthStencilDescriptorData& rhs) const { return mvkAreEqual(this, &rhs); }
bool operator!=(const MVKMTLDepthStencilDescriptorData& rhs) const { return !(*this == rhs); }
std::size_t hash() const {
return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t));
}
/** Disable depth and/or stencil testing. */
void disable(bool disableDepth, bool disableStencil) {
if (disableDepth) {
void disableDepth() {
depthCompareFunction = MTLCompareFunctionAlways;
depthWriteEnabled = false;
}
if (disableStencil) {
void disableStencil() {
stencilTestEnabled = false;
frontFaceStencilData = kMVKMTLStencilDescriptorDataDefault;
backFaceStencilData = kMVKMTLStencilDescriptorDataDefault;
}
}
MVKMTLDepthStencilDescriptorData() {
// Start with all zeros to ensure memory comparisons will work,
// even if the structure contains alignment gaps.
mvkClear(this);
disable(true, true);
mvkClear(this); // Clear all memory to ensure memory comparisons will work.
disableDepth();
disableStencil();
}
} __attribute__((aligned(sizeof(uint64_t)))) MVKMTLDepthStencilDescriptorData;

View File

@ -433,9 +433,10 @@ id<MTLDepthStencilState> MVKCommandResourceFactory::newMTLDepthStencilState(bool
}
id<MTLDepthStencilState> MVKCommandResourceFactory::newMTLDepthStencilState(MVKMTLDepthStencilDescriptorData& dsData) {
MTLStencilDescriptor* fsDesc = newMTLStencilDescriptor(dsData.frontFaceStencilData); // temp retain
MTLStencilDescriptor* bsDesc = newMTLStencilDescriptor(dsData.backFaceStencilData); // temp retain
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new]; // temp retain
bool testStencil = dsData.stencilTestEnabled;
auto* fsDesc = testStencil ? newMTLStencilDescriptor(dsData.frontFaceStencilData) : nil; // temp retain
auto* bsDesc = testStencil ? newMTLStencilDescriptor(dsData.backFaceStencilData) : nil; // temp retain
auto* dsDesc = [MTLDepthStencilDescriptor new]; // temp retain
dsDesc.depthCompareFunction = (MTLCompareFunction)dsData.depthCompareFunction;
dsDesc.depthWriteEnabled = dsData.depthWriteEnabled;
dsDesc.frontFaceStencil = fsDesc;
@ -451,8 +452,6 @@ id<MTLDepthStencilState> MVKCommandResourceFactory::newMTLDepthStencilState(MVKM
}
MTLStencilDescriptor* MVKCommandResourceFactory::newMTLStencilDescriptor(MVKMTLStencilDescriptorData& sData) {
if ( !sData.enabled ) { return nil; }
MTLStencilDescriptor* sDesc = [MTLStencilDescriptor new]; // retained
sDesc.stencilCompareFunction = (MTLCompareFunction)sData.stencilCompareFunction;
sDesc.stencilFailureOperation = (MTLStencilOperation)sData.stencilFailureOperation;

View File

@ -86,13 +86,23 @@ MVK_CMD_TYPE_POOLS_FROM_2_THRESHOLDS(BindDescriptorSetsStatic, 1, 4)
MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(BindDescriptorSetsDynamic, 4)
MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetViewport, 1)
MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetScissor, 1)
MVK_CMD_TYPE_POOL(SetLineWidth)
MVK_CMD_TYPE_POOL(SetDepthBias)
MVK_CMD_TYPE_POOL(SetBlendConstants)
MVK_CMD_TYPE_POOL(SetDepthBounds)
MVK_CMD_TYPE_POOL(SetDepthBias)
MVK_CMD_TYPE_POOL(SetDepthBiasEnable)
MVK_CMD_TYPE_POOL(SetDepthTestEnable)
MVK_CMD_TYPE_POOL(SetDepthWriteEnable)
MVK_CMD_TYPE_POOL(SetDepthCompareOp)
MVK_CMD_TYPE_POOL(SetStencilTestEnable)
MVK_CMD_TYPE_POOL(SetStencilOp)
MVK_CMD_TYPE_POOL(SetStencilCompareMask)
MVK_CMD_TYPE_POOL(SetStencilWriteMask)
MVK_CMD_TYPE_POOL(SetStencilReference)
MVK_CMD_TYPE_POOL(SetCullMode)
MVK_CMD_TYPE_POOL(SetFrontFace)
MVK_CMD_TYPE_POOL(SetPrimitiveTopology)
MVK_CMD_TYPE_POOL(SetPatchControlPoints)
MVK_CMD_TYPE_POOL(SetPrimitiveRestartEnable)
MVK_CMD_TYPE_POOL(SetRasterizerDiscardEnable)
MVK_CMD_TYPE_POOLS_FROM_2_THRESHOLDS(BindVertexBuffers, 1, 2)
MVK_CMD_TYPE_POOL(BindIndexBuffer)
MVK_CMD_TYPE_POOL(Draw)

View File

@ -67,6 +67,7 @@ typedef struct MVKMTLBufferBinding {
union { id<MTLBuffer> mtlBuffer = nil; id<MTLBuffer> mtlResource; const void* mtlBytes; }; // aliases
VkDeviceSize offset = 0;
uint32_t size = 0;
uint32_t stride = 0;
uint16_t index = 0;
bool justOffset = false;
bool isDirty = true;
@ -78,14 +79,16 @@ typedef struct MVKMTLBufferBinding {
void update(const MVKMTLBufferBinding &other) {
if (mtlBuffer != other.mtlBuffer || size != other.size || other.isInline) {
mtlBuffer = other.mtlBuffer;
size = other.size;
isInline = other.isInline;
offset = other.offset;
size = other.size;
stride = other.stride;
isInline = other.isInline;
justOffset = false;
isOverridden = false;
isDirty = true;
} else if (offset != other.offset) {
} else if (offset != other.offset || stride != other.stride) {
offset = other.offset;
stride = other.stride;
justOffset = !isOverridden && (!isDirty || justOffset);
isOverridden = false;
isDirty = true;

View File

@ -387,6 +387,18 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
formatFeatures->formatA4B4G4R4 = canSupport4444;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: {
auto* extDynState = (VkPhysicalDeviceExtendedDynamicStateFeaturesEXT*)next;
extDynState->extendedDynamicState = true;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: {
auto* extDynState2 = (VkPhysicalDeviceExtendedDynamicState2FeaturesEXT*)next;
extDynState2->extendedDynamicState2 = true;
extDynState2->extendedDynamicState2LogicOp = false;
extDynState2->extendedDynamicState2PatchControlPoints = true;
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: {
auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next;
interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups;
@ -1696,10 +1708,11 @@ void MVKPhysicalDevice::initMetalFeatures() {
_metalFeatures.minSwapchainImageCount = kMVKMinSwapchainImageCount;
_metalFeatures.maxSwapchainImageCount = kMVKMaxSwapchainImageCount;
_metalFeatures.vertexStrideAlignment = 4;
_metalFeatures.maxPerStageStorageTextureCount = 8;
_metalFeatures.vertexStrideAlignment = supportsMTLGPUFamily(Apple5) ? 1 : 4;
_metalFeatures.dynamicVertexStride = mvkOSVersionIsAtLeast(14.0, 17.0, 1.0) && (supportsMTLGPUFamily(Apple4) || supportsMTLGPUFamily(Mac2));
// GPU-specific features
switch (_properties.vendorID) {
case kAMDVendorId:
@ -2411,7 +2424,7 @@ void MVKPhysicalDevice::initLimits() {
_properties.limits.maxVertexInputAttributes = 31;
_properties.limits.maxVertexInputBindings = 31;
_properties.limits.maxVertexInputBindingStride = (2 * KIBI);
_properties.limits.maxVertexInputBindingStride = supportsMTLGPUFamily(Apple2) ? kMVKUndefinedLargeUInt32 : (4 * KIBI);
_properties.limits.maxVertexInputAttributeOffset = _properties.limits.maxVertexInputBindingStride - 1;
_properties.limits.maxPerStageDescriptorSamplers = _metalFeatures.maxPerStageSamplerCount;

View File

@ -64,6 +64,8 @@ MVK_DEVICE_FEATURE(VulkanMemoryModel, VULKAN_MEMORY_MODEL,
MVK_DEVICE_FEATURE_EXTN(FragmentShaderBarycentric, FRAGMENT_SHADER_BARYCENTRIC, KHR, 1)
MVK_DEVICE_FEATURE_EXTN(PortabilitySubset, PORTABILITY_SUBSET, KHR, 15)
MVK_DEVICE_FEATURE_EXTN(4444Formats, 4444_FORMATS, EXT, 2)
MVK_DEVICE_FEATURE_EXTN(ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, EXT, 1)
MVK_DEVICE_FEATURE_EXTN(ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, EXT, 3)
MVK_DEVICE_FEATURE_EXTN(FragmentShaderInterlock, FRAGMENT_SHADER_INTERLOCK, EXT, 3)
MVK_DEVICE_FEATURE_EXTN(PipelineCreationCacheControl, PIPELINE_CREATION_CACHE_CONTROL, EXT, 1)
MVK_DEVICE_FEATURE_EXTN(Robustness2, ROBUSTNESS_2, EXT, 3)

View File

@ -635,16 +635,16 @@ void MVKInstance::initProcAddrs() {
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdResetEvent2, KHR, KHR_SYNCHRONIZATION_2);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdResolveImage2, KHR, KHR_COPY_COMMANDS_2);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetCullMode, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetDepthBiasEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetDepthBiasEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE_2);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetDepthBoundsTestEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetDepthCompareOp, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetDepthTestEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetDepthWriteEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetEvent2, KHR, KHR_SYNCHRONIZATION_2);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetFrontFace, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetPrimitiveRestartEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetPrimitiveRestartEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE_2);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetPrimitiveTopology, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetRasterizerDiscardEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetRasterizerDiscardEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE_2);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetScissorWithCount, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetStencilOp, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetStencilTestEnable, EXT, EXT_EXTENDED_DYNAMIC_STATE);
@ -698,6 +698,9 @@ void MVKInstance::initProcAddrs() {
ADD_DVC_EXT_ENTRY_POINT(vkReleaseSwapchainImagesEXT, EXT_SWAPCHAIN_MAINTENANCE_1);
ADD_DVC_EXT_ENTRY_POINT(vkGetRefreshCycleDurationGOOGLE, GOOGLE_DISPLAY_TIMING);
ADD_DVC_EXT_ENTRY_POINT(vkGetPastPresentationTimingGOOGLE, GOOGLE_DISPLAY_TIMING);
ADD_DVC_EXT_ENTRY_POINT(vkCmdSetLogicOpEXT, EXT_EXTENDED_DYNAMIC_STATE_2);
ADD_DVC_EXT_ENTRY_POINT(vkCmdSetPatchControlPointsEXT, EXT_EXTENDED_DYNAMIC_STATE_2);
ADD_DVC_EXT_ENTRY_POINT(vkCmdSetLogicOpEnableEXT, EXT_EXTENDED_DYNAMIC_STATE_3);
}
void MVKInstance::logVersions() {

View File

@ -218,6 +218,49 @@ struct MVKStagedDescriptorBindingUse {
MVKBitArray stages[4] = {};
};
/** Enumeration identifying different state content types. */
enum MVKRenderStateType {
Unknown = 0,
BlendConstants,
CullMode,
DepthBias,
DepthBiasEnable,
DepthBounds,
DepthBoundsTestEnable,
DepthClipEnable,
DepthCompareOp,
DepthTestEnable,
DepthWriteEnable,
FrontFace,
LogicOp,
LogicOpEnable,
PatchControlPoints,
PolygonMode,
PrimitiveRestartEnable,
PrimitiveTopology,
RasterizerDiscardEnable,
SampleLocations,
Scissors,
StencilCompareMask,
StencilOp,
StencilReference,
StencilTestEnable,
StencilWriteMask,
VertexStride,
Viewports,
};
/** Boolean tracking of rendering state. */
struct MVKRenderStateFlags {
void enable(MVKRenderStateType rs) { if (rs) { mvkEnableFlags(_stateFlags, getFlagMask(rs)); } }
void disable(MVKRenderStateType rs) { if (rs) { mvkDisableFlags(_stateFlags, getFlagMask(rs)); } }
bool isEnabled(MVKRenderStateType rs) { return mvkIsAnyFlagEnabled(_stateFlags, getFlagMask(rs)); }
protected:
uint32_t getFlagMask(MVKRenderStateType rs) { return rs ? (1u << (rs - 1u)) : 0; } // Ignore Unknown type
uint32_t _stateFlags = 0;
};
/** Represents an Vulkan graphics pipeline. */
class MVKGraphicsPipeline : public MVKPipeline {
@ -229,15 +272,12 @@ public:
/** Binds this pipeline to the specified command encoder. */
void encode(MVKCommandEncoder* cmdEncoder, uint32_t stage = 0) override;
/** Returns whether this pipeline permits dynamic setting of the specifie state. */
bool supportsDynamicState(VkDynamicState state);
/** Returns whether this pipeline permits dynamic setting of the state. */
bool isDynamicState(MVKRenderStateType state) { return _dynamicState.isEnabled(state); }
/** Returns whether this pipeline has tessellation shaders. */
bool isTessellationPipeline() { return _tessInfo.patchControlPoints > 0; }
/** Returns the number of input tessellation patch control points. */
uint32_t getInputControlPointCount() { return _tessInfo.patchControlPoints; }
/** Returns the number of output tessellation patch control points. */
uint32_t getOutputControlPointCount() { return _outputControlPointCount; }
@ -313,6 +353,8 @@ public:
~MVKGraphicsPipeline() override;
protected:
friend class MVKGraphicsPipelineCommandEncoderState;
typedef MVKSmallVector<SPIRVShaderInterfaceVariable, 32> SPIRVShaderOutputs;
typedef MVKSmallVector<SPIRVShaderInterfaceVariable, 32> SPIRVShaderInputs;
@ -320,6 +362,7 @@ protected:
id<MTLComputePipelineState> getOrCompilePipeline(MTLComputePipelineDescriptor* plDesc, id<MTLComputePipelineState>& plState, const char* compilerType);
bool compileTessVertexStageState(MTLComputePipelineDescriptor* vtxPLDesc, MVKMTLFunction* pVtxFunctions, VkPipelineCreationFeedback* pVertexFB);
bool compileTessControlStageState(MTLComputePipelineDescriptor* tcPLDesc, VkPipelineCreationFeedback* pTessCtlFB);
void initDynamicState(const VkGraphicsPipelineCreateInfo* pCreateInfo);
void initCustomSamplePositions(const VkGraphicsPipelineCreateInfo* pCreateInfo);
void initMTLRenderPipelineState(const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData, VkPipelineCreationFeedback* pPipelineFB, const VkPipelineShaderStageCreateInfo* pVertexSS, VkPipelineCreationFeedback* pVertexFB, const VkPipelineShaderStageCreateInfo* pTessCtlSS, VkPipelineCreationFeedback* pTessCtlFB, const VkPipelineShaderStageCreateInfo* pTessEvalSS, VkPipelineCreationFeedback* pTessEvalFB, const VkPipelineShaderStageCreateInfo* pFragmentSS, VkPipelineCreationFeedback* pFragmentFB);
void initShaderConversionConfig(SPIRVToMSLConversionConfiguration& shaderConfig, const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData);
@ -356,10 +399,10 @@ protected:
VkPipelineTessellationStateCreateInfo _tessInfo;
VkPipelineRasterizationStateCreateInfo _rasterInfo;
VkPipelineDepthStencilStateCreateInfo _depthStencilInfo;
MVKRenderStateFlags _dynamicState;
MVKSmallVector<VkViewport, kMVKMaxViewportScissorCount> _viewports;
MVKSmallVector<VkRect2D, kMVKMaxViewportScissorCount> _scissors;
MVKSmallVector<VkDynamicState> _dynamicState;
MVKSmallVector<MTLSamplePosition> _customSamplePositions;
MVKSmallVector<MVKTranslatedVertexBinding> _translatedVertexBindings;
MVKSmallVector<MVKZeroDivisorVertexBinding> _zeroDivisorVertexBindings;
@ -374,11 +417,7 @@ protected:
id<MTLComputePipelineState> _mtlTessControlStageState = nil;
id<MTLRenderPipelineState> _mtlPipelineState = nil;
float _blendConstants[4] = { 0.0, 0.0, 0.0, 1.0 };
MTLCullMode _mtlCullMode;
MTLWinding _mtlFrontWinding;
MTLTriangleFillMode _mtlFillMode;
MTLDepthClipMode _mtlDepthClipMode;
float _blendConstants[4] = {};
MVKShaderImplicitRezBinding _reservedVertexAttributeBufferCount;
MVKShaderImplicitRezBinding _viewRangeBufferIndex;
MVKShaderImplicitRezBinding _outputBufferIndex;
@ -387,6 +426,7 @@ protected:
uint32_t _tessCtlPatchOutputBufferIndex = 0;
uint32_t _tessCtlLevelBufferIndex = 0;
bool _hasRasterInfo = false;
bool _needsVertexSwizzleBuffer = false;
bool _needsVertexBufferSizeBuffer = false;
bool _needsVertexDynamicOffsetBuffer = false;

View File

@ -292,24 +292,20 @@ void MVKGraphicsPipeline::encode(MVKCommandEncoder* cmdEncoder, uint32_t stage)
// Depth stencil state - Cleared _depthStencilInfo values will disable depth testing
cmdEncoder->_depthStencilState.setDepthStencilState(_depthStencilInfo);
cmdEncoder->_stencilReferenceValueState.setReferenceValues(_depthStencilInfo);
// Rasterization
cmdEncoder->_blendColorState.setBlendColor(_blendConstants[0], _blendConstants[1],
_blendConstants[2], _blendConstants[3], false);
cmdEncoder->_depthBiasState.setDepthBias(_rasterInfo);
cmdEncoder->_viewportState.setViewports(_viewports.contents(), 0, false);
cmdEncoder->_scissorState.setScissors(_scissors.contents(), 0, false);
cmdEncoder->_mtlPrimitiveType = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(_vkPrimitiveTopology);
[mtlCmdEnc setCullMode: _mtlCullMode];
[mtlCmdEnc setFrontFacingWinding: _mtlFrontWinding];
[mtlCmdEnc setTriangleFillMode: _mtlFillMode];
if (_device->_enabledFeatures.depthClamp) {
[mtlCmdEnc setDepthClipMode: _mtlDepthClipMode];
cmdEncoder->_renderingState.setPrimitiveTopology(_vkPrimitiveTopology, false);
cmdEncoder->_renderingState.setBlendConstants(_blendConstants, false);
cmdEncoder->_renderingState.setStencilReferenceValues(_depthStencilInfo);
cmdEncoder->_renderingState.setViewports(_viewports.contents(), 0, false);
cmdEncoder->_renderingState.setScissors(_scissors.contents(), 0, false);
if (_hasRasterInfo) {
cmdEncoder->_renderingState.setCullMode(_rasterInfo.cullMode, false);
cmdEncoder->_renderingState.setFrontFace(_rasterInfo.frontFace, false);
cmdEncoder->_renderingState.setPolygonMode(_rasterInfo.polygonMode, false);
cmdEncoder->_renderingState.setDepthBias(_rasterInfo);
cmdEncoder->_renderingState.setDepthClipEnable( !_rasterInfo.depthClampEnable, false );
}
break;
}
@ -320,21 +316,6 @@ void MVKGraphicsPipeline::encode(MVKCommandEncoder* cmdEncoder, uint32_t stage)
cmdEncoder->_graphicsResourcesState.bindViewRangeBuffer(_viewRangeBufferIndex, _needsVertexViewRangeBuffer, _needsFragmentViewRangeBuffer);
}
bool MVKGraphicsPipeline::supportsDynamicState(VkDynamicState state) {
for (auto& ds : _dynamicState) {
if (state == ds) {
// Some dynamic states have other restrictions
switch (state) {
case VK_DYNAMIC_STATE_DEPTH_BIAS:
return _rasterInfo.depthBiasEnable;
default:
return true;
}
}
}
return false;
}
static const char vtxCompilerType[] = "Vertex stage pipeline for tessellation";
bool MVKGraphicsPipeline::compileTessVertexStageState(MTLComputePipelineDescriptor* vtxPLDesc,
@ -414,6 +395,10 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
const VkGraphicsPipelineCreateInfo* pCreateInfo) :
MVKPipeline(device, pipelineCache, (MVKPipelineLayout*)pCreateInfo->layout, pCreateInfo->flags, parent) {
// Extract dynamic state first, as it can affect many configurations.
initDynamicState(pCreateInfo);
// Determine rasterization early, as various other structs are validated and interpreted in this context.
const VkPipelineRenderingCreateInfo* pRendInfo = getRenderingCreateInfo(pCreateInfo);
_isRasterizing = !isRasterizationDisabled(pCreateInfo);
@ -509,17 +494,12 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
initMTLRenderPipelineState(pCreateInfo, reflectData, pPipelineFB, pVertexSS, pVertexFB, pTessCtlSS, pTessCtlFB, pTessEvalSS, pTessEvalFB, pFragmentSS, pFragmentFB);
if ( !_hasValidMTLPipelineStates ) { return; }
// Track dynamic state
const VkPipelineDynamicStateCreateInfo* pDS = pCreateInfo->pDynamicState;
if (pDS) {
for (uint32_t i = 0; i < pDS->dynamicStateCount; i++) {
_dynamicState.push_back(pDS->pDynamicStates[i]);
}
}
// Blending - must ignore allowed bad pColorBlendState pointer if rasterization disabled or no color attachments
if (_isRasterizingColor && pCreateInfo->pColorBlendState) {
memcpy(&_blendConstants, &pCreateInfo->pColorBlendState->blendConstants, sizeof(_blendConstants));
mvkCopy(_blendConstants, pCreateInfo->pColorBlendState->blendConstants, 4);
} else {
static float defaultBlendConstants[4] = { 0, 0.0, 0.0, 1.0 };
mvkCopy(_blendConstants, defaultBlendConstants, 4);
}
// Topology
@ -527,24 +507,16 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
? pCreateInfo->pInputAssemblyState->topology
: VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
// In Metal, primitive restart cannot be disabled.
// Just issue warning here, as it is very likely the app is not actually expecting
// to use primitive restart at all, and is just setting this as a "just-in-case",
// and forcing an error here would be unexpected to the app (including CTS).
if (pCreateInfo->pInputAssemblyState && !pCreateInfo->pInputAssemblyState->primitiveRestartEnable) {
reportWarning(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateGraphicsPipeline(): Metal does not support disabling primitive restart.");
}
// Rasterization
_mtlCullMode = MTLCullModeNone;
_mtlFrontWinding = MTLWindingCounterClockwise;
_mtlFillMode = MTLTriangleFillModeFill;
_mtlDepthClipMode = MTLDepthClipModeClip;
bool hasRasterInfo = mvkSetOrClear(&_rasterInfo, pCreateInfo->pRasterizationState);
if (hasRasterInfo) {
_mtlCullMode = mvkMTLCullModeFromVkCullModeFlags(_rasterInfo.cullMode);
_mtlFrontWinding = mvkMTLWindingFromVkFrontFace(_rasterInfo.frontFace);
_mtlFillMode = mvkMTLTriangleFillModeFromVkPolygonMode(_rasterInfo.polygonMode);
if (_rasterInfo.depthClampEnable) {
if (_device->_enabledFeatures.depthClamp) {
_mtlDepthClipMode = MTLDepthClipModeClamp;
} else {
setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "This device does not support depth clamping."));
}
}
}
_hasRasterInfo = mvkSetOrClear(&_rasterInfo, pCreateInfo->pRasterizationState);
// Must run after _isRasterizing and _dynamicState are populated
initCustomSamplePositions(pCreateInfo);
@ -557,26 +529,81 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
// Viewports and scissors - must ignore allowed bad pViewportState pointer if rasterization is disabled
auto pVPState = _isRasterizing ? pCreateInfo->pViewportState : nullptr;
if (pVPState) {
uint32_t vpCnt = pVPState->viewportCount;
// If viewports are dynamic, ignore them here.
uint32_t vpCnt = (pVPState->pViewports && !isDynamicState(Viewports)) ? pVPState->viewportCount : 0;
_viewports.reserve(vpCnt);
for (uint32_t vpIdx = 0; vpIdx < vpCnt; vpIdx++) {
// If viewport is dyanamic, we still add a dummy so that the count will be tracked.
VkViewport vp;
if ( !supportsDynamicState(VK_DYNAMIC_STATE_VIEWPORT) ) { vp = pVPState->pViewports[vpIdx]; }
_viewports.push_back(vp);
_viewports.push_back(pVPState->pViewports[vpIdx]);
}
uint32_t sCnt = pVPState->scissorCount;
// If scissors are dynamic, ignore them here.
uint32_t sCnt = (pVPState->pScissors && !isDynamicState(Scissors)) ? pVPState->scissorCount : 0;
_scissors.reserve(sCnt);
for (uint32_t sIdx = 0; sIdx < sCnt; sIdx++) {
// If scissor is dyanamic, we still add a dummy so that the count will be tracked.
VkRect2D sc;
if ( !supportsDynamicState(VK_DYNAMIC_STATE_SCISSOR) ) { sc = pVPState->pScissors[sIdx]; }
_scissors.push_back(sc);
_scissors.push_back(pVPState->pScissors[sIdx]);
}
}
}
static MVKRenderStateType getRenderStateType(VkDynamicState vkDynamicState) {
switch (vkDynamicState) {
case VK_DYNAMIC_STATE_BLEND_CONSTANTS: return BlendConstants;
case VK_DYNAMIC_STATE_CULL_MODE: return CullMode;
case VK_DYNAMIC_STATE_DEPTH_BIAS: return DepthBias;
case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE: return DepthBiasEnable;
case VK_DYNAMIC_STATE_DEPTH_BOUNDS: return DepthBounds;
case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE: return DepthBoundsTestEnable;
case VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT: return DepthClipEnable;
case VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT: return DepthClipEnable;
case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP: return DepthCompareOp;
case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE: return DepthTestEnable;
case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE: return DepthWriteEnable;
case VK_DYNAMIC_STATE_FRONT_FACE: return FrontFace;
case VK_DYNAMIC_STATE_LOGIC_OP_EXT: return LogicOp;
case VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT: return LogicOpEnable;
case VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT: return PatchControlPoints;
case VK_DYNAMIC_STATE_POLYGON_MODE_EXT: return PolygonMode;
case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE: return PrimitiveRestartEnable;
case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY: return PrimitiveTopology;
case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE: return RasterizerDiscardEnable;
case VK_DYNAMIC_STATE_SCISSOR: return Scissors;
case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT: return Scissors;
case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK: return StencilCompareMask;
case VK_DYNAMIC_STATE_STENCIL_OP: return StencilOp;
case VK_DYNAMIC_STATE_STENCIL_REFERENCE: return StencilReference;
case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE: return StencilTestEnable;
case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK: return StencilWriteMask;
case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE: return VertexStride;
case VK_DYNAMIC_STATE_VIEWPORT: return Viewports;
case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT: return Viewports;
default: return Unknown;
}
}
// This is executed first during pipeline creation. Do not depend on any internal state here.
void MVKGraphicsPipeline::initDynamicState(const VkGraphicsPipelineCreateInfo* pCreateInfo) {
const auto* pDS = pCreateInfo->pDynamicState;
if ( !pDS ) { return; }
for (uint32_t i = 0; i < pDS->dynamicStateCount; i++) {
auto dynStateType = getRenderStateType(pDS->pDynamicStates[i]);
bool isDynamic = true;
// Some dynamic states have other restrictions
switch (dynStateType) {
case VertexStride:
isDynamic = _device->_pMetalFeatures->dynamicVertexStride;
if ( !isDynamic ) { setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "This device and platform does not support VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE (macOS 14.0 or iOS/tvOS 17.0, plus either Apple4 or Mac2 GPU).")); }
break;
default:
break;
}
if (isDynamic) { _dynamicState.enable(dynStateType); }
}
}
// Either returns an existing pipeline state or compiles a new one.
id<MTLRenderPipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLRenderPipelineDescriptor* plDesc,
id<MTLRenderPipelineState>& plState) {
@ -613,7 +640,7 @@ void MVKGraphicsPipeline::initCustomSamplePositions(const VkGraphicsPipelineCrea
case VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT: {
auto* pSampLocnsCreateInfo = (VkPipelineSampleLocationsStateCreateInfoEXT*)next;
_isUsingCustomSamplePositions = pSampLocnsCreateInfo->sampleLocationsEnable;
if (_isUsingCustomSamplePositions && !supportsDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT)) {
if (_isUsingCustomSamplePositions && !isDynamicState(SampleLocations)) {
for (uint32_t slIdx = 0; slIdx < pSampLocnsCreateInfo->sampleLocationsInfo.sampleLocationsCount; slIdx++) {
auto& sl = pSampLocnsCreateInfo->sampleLocationsInfo.pSampleLocations[slIdx];
_customSamplePositions.push_back(MTLSamplePositionMake(sl.x, sl.y));
@ -1311,6 +1338,10 @@ bool MVKGraphicsPipeline::addFragmentShaderToPipeline(MTLRenderPipelineDescripto
return true;
}
#if !MVK_XCODE_15
static const NSUInteger MTLBufferLayoutStrideDynamic = NSUIntegerMax;
#endif
template<class T>
bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
const VkPipelineVertexInputStateCreateInfo* pVI,
@ -1328,8 +1359,9 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
}
// Vertex buffer bindings
uint32_t vbCnt = pVI->vertexBindingDescriptionCount;
bool isVtxStrideStatic = !isDynamicState(VertexStride);
uint32_t maxBinding = 0;
uint32_t vbCnt = pVI->vertexBindingDescriptionCount;
for (uint32_t i = 0; i < vbCnt; i++) {
const VkVertexInputBindingDescription* pVKVB = &pVI->pVertexBindingDescriptions[i];
if (shaderConfig.isVertexBufferUsed(pVKVB->binding)) {
@ -1352,7 +1384,7 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
vbDesc.stepFunction = (decltype(vbDesc.stepFunction))MTLStepFunctionConstant;
vbDesc.stepRate = 0;
} else {
vbDesc.stride = pVKVB->stride;
vbDesc.stride = isVtxStrideStatic ? pVKVB->stride : MTLBufferLayoutStrideDynamic;
vbDesc.stepFunction = (decltype(vbDesc.stepFunction))mvkMTLStepFunctionFromVkVertexInputRate(pVKVB->inputRate, isTessellationPipeline());
vbDesc.stepRate = 1;
}
@ -1903,11 +1935,12 @@ bool MVKGraphicsPipeline::isRenderingPoints(const VkGraphicsPipelineCreateInfo*
(pCreateInfo->pRasterizationState && (pCreateInfo->pRasterizationState->polygonMode == VK_POLYGON_MODE_POINT)));
}
// We disable rasterization if either rasterizerDiscard is enabled or the cull mode dictates it.
// We disable rasterization if either static rasterizerDiscard is enabled or the static cull mode dictates it.
bool MVKGraphicsPipeline::isRasterizationDisabled(const VkGraphicsPipelineCreateInfo* pCreateInfo) {
return (pCreateInfo->pRasterizationState &&
(pCreateInfo->pRasterizationState->rasterizerDiscardEnable ||
((pCreateInfo->pRasterizationState->cullMode == VK_CULL_MODE_FRONT_AND_BACK) && pCreateInfo->pInputAssemblyState &&
((pCreateInfo->pRasterizationState->rasterizerDiscardEnable && !isDynamicState(RasterizerDiscardEnable)) ||
((pCreateInfo->pRasterizationState->cullMode == VK_CULL_MODE_FRONT_AND_BACK) && !isDynamicState(CullMode) &&
pCreateInfo->pInputAssemblyState &&
(mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology) == MTLPrimitiveTopologyClassTriangle))));
}

View File

@ -103,6 +103,8 @@ MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER,
MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, INSTANCE, 10.11, 8.0, 1.0)
MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, INSTANCE, 10.11, 8.0, 1.0)
MVK_EXTENSION(EXT_descriptor_indexing, EXT_DESCRIPTOR_INDEXING, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(EXT_extended_dynamic_state, EXT_EXTENDED_DYNAMIC_STATE, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(EXT_extended_dynamic_state2, EXT_EXTENDED_DYNAMIC_STATE_2, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(EXT_external_memory_host, EXT_EXTERNAL_MEMORY_HOST, DEVICE, 10.11, 8.0, 1.0)
MVK_EXTENSION(EXT_fragment_shader_interlock, EXT_FRAGMENT_SHADER_INTERLOCK, DEVICE, 10.13, 11.0, 1.0)
MVK_EXTENSION(EXT_hdr_metadata, EXT_HDR_METADATA, DEVICE, 10.15, MVK_NA, MVK_NA)

View File

@ -60,6 +60,9 @@ typedef struct {
#pragma mark -
#pragma mark Vulkan support
/** A generic 32-bit color permitting float, int32, or uint32 values. */
typedef VkClearColorValue MVKColor32;
/** Tracks the Vulkan command currently being used. */
typedef enum : uint8_t {
kMVKCommandUseNone = 0, /**< No use defined. */
@ -142,7 +145,7 @@ static inline std::string mvkGetMoltenVKVersionString(uint32_t mvkVersion) {
/** Returns whether the specified positive value is a power-of-two. */
template<typename T>
static constexpr bool mvkIsPowerOfTwo(T value) {
return value && ((value & (value - 1)) == 0);
return value > 0 && ((value & (value - 1)) == 0);
}
/**
@ -278,21 +281,21 @@ void mvkFlipVertically(void* rowMajorData, uint32_t rowCount, size_t bytesPerRow
* They are ridiculously large numbers, but low enough to be safely used as both
* uint and int values without risking overflowing between positive and negative values.
*/
static int32_t kMVKUndefinedLargePositiveInt32 = mvkEnsurePowerOfTwo(std::numeric_limits<int32_t>::max() / 2);
static int32_t kMVKUndefinedLargeNegativeInt32 = -kMVKUndefinedLargePositiveInt32;
static uint32_t kMVKUndefinedLargeUInt32 = kMVKUndefinedLargePositiveInt32;
static int64_t kMVKUndefinedLargePositiveInt64 = mvkEnsurePowerOfTwo(std::numeric_limits<int64_t>::max() / 2);
static int64_t kMVKUndefinedLargeNegativeInt64 = -kMVKUndefinedLargePositiveInt64;
static uint64_t kMVKUndefinedLargeUInt64 = kMVKUndefinedLargePositiveInt64;
static constexpr int32_t kMVKUndefinedLargePositiveInt32 = mvkEnsurePowerOfTwo(std::numeric_limits<int32_t>::max() / 2);
static constexpr int32_t kMVKUndefinedLargeNegativeInt32 = -kMVKUndefinedLargePositiveInt32;
static constexpr uint32_t kMVKUndefinedLargeUInt32 = kMVKUndefinedLargePositiveInt32;
static constexpr int64_t kMVKUndefinedLargePositiveInt64 = mvkEnsurePowerOfTwo(std::numeric_limits<int64_t>::max() / 2);
static constexpr int64_t kMVKUndefinedLargeNegativeInt64 = -kMVKUndefinedLargePositiveInt64;
static constexpr uint64_t kMVKUndefinedLargeUInt64 = kMVKUndefinedLargePositiveInt64;
#pragma mark Vulkan structure support functions
/** Returns a VkExtent2D created from the width and height of a VkExtent3D. */
static inline VkExtent2D mvkVkExtent2DFromVkExtent3D(VkExtent3D e) { return {e.width, e.height }; }
static constexpr VkExtent2D mvkVkExtent2DFromVkExtent3D(VkExtent3D e) { return {e.width, e.height }; }
/** Returns a VkExtent3D, created from a VkExtent2D, and with depth of 1. */
static inline VkExtent3D mvkVkExtent3DFromVkExtent2D(VkExtent2D e) { return {e.width, e.height, 1U }; }
static constexpr VkExtent3D mvkVkExtent3DFromVkExtent2D(VkExtent2D e) { return {e.width, e.height, 1U }; }
/** Returns whether the two Vulkan extents are equal by comparing their respective components. */
static constexpr bool mvkVkExtent2DsAreEqual(VkExtent2D e1, VkExtent2D e2) {
@ -333,13 +336,13 @@ static constexpr uint32_t mvkPackSwizzle(VkComponentMapping components) {
}
/** Unpacks a single 32-bit word containing four swizzle components. */
static inline VkComponentMapping mvkUnpackSwizzle(uint32_t packed) {
VkComponentMapping components;
components.r = (VkComponentSwizzle)((packed >> 0) & 0xFF);
components.g = (VkComponentSwizzle)((packed >> 8) & 0xFF);
components.b = (VkComponentSwizzle)((packed >> 16) & 0xFF);
components.a = (VkComponentSwizzle)((packed >> 24) & 0xFF);
return components;
static constexpr VkComponentMapping mvkUnpackSwizzle(uint32_t packed) {
return {
.r = (VkComponentSwizzle)((packed >> 0) & 0xFF),
.g = (VkComponentSwizzle)((packed >> 8) & 0xFF),
.b = (VkComponentSwizzle)((packed >> 16) & 0xFF),
.a = (VkComponentSwizzle)((packed >> 24) & 0xFF),
};
}
/**
@ -384,24 +387,24 @@ static constexpr bool mvkVkComponentMappingsMatch(VkComponentMapping cm1, VkComp
/** Rounds the value to nearest integer using half-to-even rounding. */
static inline double mvkRoundHalfToEven(const double val) {
return val - std::remainder(val, 1.0); // remainder() uses half-to-even rounding, and unfortunately isn't constexpr until C++23.
return val - std::remainder(val, 1.0); // remainder() uses half-to-even rounding, but unfortunately isn't constexpr until C++23.
}
/** Returns whether the value will fit inside the numeric type. */
template<typename T, typename Tval>
const bool mvkFits(const Tval& val) {
static constexpr bool mvkFits(const Tval& val) {
return val <= std::numeric_limits<T>::max();
}
/** Clamps the value between the lower and upper bounds, inclusive. */
template<typename T>
const T& mvkClamp(const T& val, const T& lower, const T& upper) {
static constexpr const T& mvkClamp(const T& val, const T& lower, const T& upper) {
return std::min(std::max(val, lower), upper);
}
/** Returns the result of a division, rounded up. */
template<typename T, typename U>
constexpr typename std::common_type<T, U>::type mvkCeilingDivide(T numerator, U denominator) {
static constexpr typename std::common_type<T, U>::type mvkCeilingDivide(T numerator, U denominator) {
typedef typename std::common_type<T, U>::type R;
// Short circuit very common usecase of dividing by one.
return (denominator == 1) ? numerator : (R(numerator) + denominator - 1) / denominator;
@ -427,18 +430,18 @@ struct MVKAbs<R, T, false> {
/** Returns the absolute value of the difference of two numbers. */
template<typename T, typename U>
constexpr typename std::common_type<T, U>::type mvkAbsDiff(T x, U y) {
static constexpr typename std::common_type<T, U>::type mvkAbsDiff(T x, U y) {
return x >= y ? x - y : y - x;
}
/** Returns the greatest common divisor of two numbers. */
template<typename T>
constexpr T mvkGreatestCommonDivisorImpl(T a, T b) {
static constexpr T mvkGreatestCommonDivisorImpl(T a, T b) {
return b == 0 ? a : mvkGreatestCommonDivisorImpl(b, a % b);
}
template<typename T, typename U>
constexpr typename std::common_type<T, U>::type mvkGreatestCommonDivisor(T a, U b) {
static constexpr typename std::common_type<T, U>::type mvkGreatestCommonDivisor(T a, U b) {
typedef typename std::common_type<T, U>::type R;
typedef typename std::make_unsigned<R>::type UI;
return static_cast<R>(mvkGreatestCommonDivisorImpl(static_cast<UI>(MVKAbs<R, T>::eval(a)), static_cast<UI>(MVKAbs<R, U>::eval(b))));
@ -446,7 +449,7 @@ constexpr typename std::common_type<T, U>::type mvkGreatestCommonDivisor(T a, U
/** Returns the least common multiple of two numbers. */
template<typename T, typename U>
constexpr typename std::common_type<T, U>::type mvkLeastCommonMultiple(T a, U b) {
static constexpr typename std::common_type<T, U>::type mvkLeastCommonMultiple(T a, U b) {
typedef typename std::common_type<T, U>::type R;
return (a == 0 && b == 0) ? 0 : MVKAbs<R, T>::eval(a) / mvkGreatestCommonDivisor(a, b) * MVKAbs<R, U>::eval(b);
}
@ -463,7 +466,7 @@ constexpr typename std::common_type<T, U>::type mvkLeastCommonMultiple(T a, U b)
* value returned by previous calls as the seed in subsequent calls.
*/
template<class N>
std::size_t mvkHash(const N* pVals, std::size_t count = 1, std::size_t seed = 5381) {
static constexpr std::size_t mvkHash(const N* pVals, std::size_t count = 1, std::size_t seed = 5381) {
std::size_t hash = seed;
for (std::size_t i = 0; i < count; i++) { hash = ((hash << 5) + hash) ^ pVals[i]; }
return hash;
@ -497,7 +500,7 @@ protected:
/** Ensures the size of the specified container is at least the specified size. */
template<typename C, typename S>
void mvkEnsureSize(C& container, S size) {
static void mvkEnsureSize(C& container, S size) {
if (size > container.size()) { container.resize(size); }
}
@ -506,7 +509,7 @@ void mvkEnsureSize(C& container, S size) {
* each object, including freeing the object memory, and clearing the container.
*/
template<typename C>
void mvkDestroyContainerContents(C& container) {
static void mvkDestroyContainerContents(C& container) {
for (auto elem : container) { elem->destroy(); }
container.clear();
}
@ -517,7 +520,7 @@ void mvkDestroyContainerContents(C& container) {
*/
#ifdef __OBJC__
template<typename C>
void mvkReleaseContainerContents(C& container) {
static void mvkReleaseContainerContents(C& container) {
for (auto elem : container) { [elem release]; }
container.clear();
}
@ -525,14 +528,14 @@ void mvkReleaseContainerContents(C& container) {
/** Returns whether the container contains an item equal to the value. */
template<class C, class T>
bool mvkContains(C& container, const T& val) {
static constexpr bool mvkContains(C& container, const T& val) {
for (const T& cVal : container) { if (cVal == val) { return true; } }
return false;
}
/** Removes the first occurance of the specified value from the specified container. */
template<class C, class T>
void mvkRemoveFirstOccurance(C& container, T val) {
static void mvkRemoveFirstOccurance(C& container, T val) {
for (auto iter = container.begin(), end = container.end(); iter != end; iter++) {
if( *iter == val ) {
container.erase(iter);
@ -543,7 +546,7 @@ void mvkRemoveFirstOccurance(C& container, T val) {
/** Removes all occurances of the specified value from the specified container. */
template<class C, class T>
void mvkRemoveAllOccurances(C& container, T val) {
static void mvkRemoveAllOccurances(C& container, T val) {
container.erase(std::remove(container.begin(), container.end(), val), container.end());
}
@ -552,7 +555,7 @@ void mvkRemoveAllOccurances(C& container, T val) {
/** Selects and returns one of the values, based on the platform OS. */
template<typename T>
const T& mvkSelectPlatformValue(const T& macOSVal, const T& iOSVal) {
static constexpr const T& mvkSelectPlatformValue(const T& macOSVal, const T& iOSVal) {
#if MVK_IOS_OR_TVOS
return iOSVal;
#endif
@ -566,22 +569,29 @@ const T& mvkSelectPlatformValue(const T& macOSVal, const T& iOSVal) {
* The optional count allows clearing multiple elements in an array.
*/
template<typename T>
void mvkClear(T* pVal, size_t count = 1) { if (pVal) { memset(pVal, 0, sizeof(T) * count); } }
static void mvkClear(T* pDst, size_t count = 1) {
if ( !pDst ) { return; } // Bad pointer
if constexpr(std::is_arithmetic_v<T>) { if (count == 1) { *pDst = static_cast<T>(0); } } // Fast clear of a single primitive
memset(pDst, 0, sizeof(T) * count); // Memory clear of complex content or array
}
/**
* If pVal is not null, overrides the const declaration, and clears the memory occupied by *pVal
* by writing zeros to all bytes. The optional count allows clearing multiple elements in an array.
*/
template<typename T>
void mvkClear(const T* pVal, size_t count = 1) { mvkClear((T*)pVal, count); }
static void mvkClear(const T* pVal, size_t count = 1) { mvkClear((T*)pVal, count); }
/**
* If pSrc and pDst are both not null, copies the contents of the source value to the
* destination value. The optional count allows copying of multiple elements in an array.
*/
template<typename T>
void mvkCopy(T* pDst, const T* pSrc, size_t count = 1) {
if (pSrc && pDst) { memcpy(pDst, pSrc, sizeof(T) * count); }
static void mvkCopy(T* pDst, const T* pSrc, size_t count = 1) {
if ( !pDst || !pSrc ) { return; } // Bad pointers
if (pDst == pSrc) { return; } // Same object
if constexpr(std::is_arithmetic_v<T>) { if (count == 1) { *pDst = *pSrc; } } // Fast copy of a single primitive
memcpy(pDst, pSrc, sizeof(T) * count); // Memory copy of complex content or array
}
/**
@ -589,8 +599,11 @@ void mvkCopy(T* pDst, const T* pSrc, size_t count = 1) {
* otherwise returns false. The optional count allows comparing multiple elements in an array.
*/
template<typename T>
bool mvkAreEqual(const T* pV1, const T* pV2, size_t count = 1) {
return (pV1 && pV2) ? (memcmp(pV1, pV2, sizeof(T) * count) == 0) : false;
static constexpr bool mvkAreEqual(const T* pV1, const T* pV2, size_t count = 1) {
if ( !pV2 || !pV2 ) { return false; } // Bad pointers
if (pV1 == pV2) { return true; } // Same object
if constexpr(std::is_arithmetic_v<T>) { if (count == 1) { return *pV1 == *pV2; } } // Fast compare of a single primitive
return memcmp(pV1, pV2, sizeof(T) * count) == 0; // Memory compare of complex content or array
}
/**
@ -632,10 +645,18 @@ static constexpr bool mvkSetOrClear(T* pDest, const T* pSrc) {
template<typename Tv, typename Tm>
void mvkEnableFlags(Tv& value, const Tm bitMask) { value = (Tv)(value | bitMask); }
/** Enables all the flags (sets bits to 1) within the value parameter. */
template<typename Tv>
void mvkEnableAllFlags(Tv& value) { value = ~static_cast<Tv>(0); }
/** Disables the flags (sets bits to 0) within the value parameter specified by the bitMask parameter. */
template<typename Tv, typename Tm>
void mvkDisableFlags(Tv& value, const Tm bitMask) { value = (Tv)(value & ~(Tv)bitMask); }
/** Enables all the flags (sets bits to 1) within the value parameter. */
template<typename Tv>
void mvkDisableAllFlags(Tv& value) { value = static_cast<Tv>(0); }
/** Returns whether the specified value has ANY of the flags specified in bitMask enabled (set to 1). */
template<typename Tv, typename Tm>
static constexpr bool mvkIsAnyFlagEnabled(Tv value, const Tm bitMask) { return ((value & bitMask) != 0); }

View File

@ -584,23 +584,32 @@ MTLMultisampleStencilResolveFilter mvkMTLMultisampleStencilResolveFilterFromVkRe
#endif
MVK_PUBLIC_SYMBOL MTLViewport mvkMTLViewportFromVkViewport(VkViewport vkViewport) {
MTLViewport mtlViewport;
mtlViewport.originX = vkViewport.x;
mtlViewport.originY = vkViewport.y;
mtlViewport.width = vkViewport.width;
mtlViewport.height = vkViewport.height;
mtlViewport.znear = vkViewport.minDepth;
mtlViewport.zfar = vkViewport.maxDepth;
return mtlViewport;
return {
.originX = vkViewport.x,
.originY = vkViewport.y,
.width = vkViewport.width,
.height = vkViewport.height,
.znear = vkViewport.minDepth,
.zfar = vkViewport.maxDepth
};
}
MVK_PUBLIC_SYMBOL MTLScissorRect mvkMTLScissorRectFromVkRect2D(VkRect2D vkRect) {
MTLScissorRect mtlScissor;
mtlScissor.x = vkRect.offset.x;
mtlScissor.y = vkRect.offset.y;
mtlScissor.width = vkRect.extent.width;
mtlScissor.height = vkRect.extent.height;
return mtlScissor;
return {
.x = (NSUInteger)max(vkRect.offset.x, 0),
.y = (NSUInteger)max(vkRect.offset.y, 0),
.width = vkRect.extent.width,
.height = vkRect.extent.height
};
}
MVK_PUBLIC_SYMBOL VkRect2D mvkVkRect2DFromMTLScissorRect(MTLScissorRect mtlScissorRect) {
return {
.offset = { .x = (int32_t)mtlScissorRect.x,
.y = (int32_t)mtlScissorRect.y },
.extent = { .width = (uint32_t)mtlScissorRect.width,
.height = (uint32_t)mtlScissorRect.height }
};
}
MVK_PUBLIC_SYMBOL MTLCompareFunction mvkMTLCompareFunctionFromVkCompareOp(VkCompareOp vkOp) {

View File

@ -1466,7 +1466,6 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetLineWidth(
float lineWidth) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetLineWidth, commandBuffer, lineWidth);
MVKTraceVulkanCallEnd();
}
@ -1496,7 +1495,6 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthBounds(
float maxDepthBounds) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetDepthBounds, commandBuffer, minDepthBounds, maxDepthBounds);
MVKTraceVulkanCallEnd();
}
@ -1564,13 +1562,14 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBindIndexBuffer(
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBindVertexBuffers(
VkCommandBuffer commandBuffer,
uint32_t startBinding,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets) {
MVKTraceVulkanCallStart();
MVKAddCmdFrom2Thresholds(BindVertexBuffers, bindingCount, 1, 2, commandBuffer, startBinding, bindingCount, pBuffers, pOffsets);
MVKAddCmdFrom2Thresholds(BindVertexBuffers, bindingCount, 1, 2, commandBuffer,
firstBinding, bindingCount, pBuffers, pOffsets, nullptr, nullptr);
MVKTraceVulkanCallEnd();
}
@ -2526,16 +2525,21 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBeginRendering(
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdEndRendering(
VkCommandBuffer commandBuffer) {
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBindVertexBuffers2(
VkCommandBuffer commandBuffer,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets,
const VkDeviceSize* pSizes,
const VkDeviceSize* pStrides) {
MVKTraceVulkanCallStart();
MVKAddCmd(EndRendering, commandBuffer);
MVKAddCmdFrom2Thresholds(BindVertexBuffers, bindingCount, 1, 2, commandBuffer,
firstBinding, bindingCount, pBuffers, pOffsets, pSizes, pStrides);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_STUB(vkCmdBindVertexBuffers2, void, VkCommandBuffer, uint32_t, uint32_t, const VkBuffer*, const VkDeviceSize*, const VkDeviceSize*, const VkDeviceSize*)
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBlitImage2(
VkCommandBuffer commandBuffer,
const VkBlitImageInfo2* pBlitImageInfo) {
@ -2585,6 +2589,14 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdCopyImageToBuffer2(
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdEndRendering(
VkCommandBuffer commandBuffer) {
MVKTraceVulkanCallStart();
MVKAddCmd(EndRendering, commandBuffer);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdPipelineBarrier2(
VkCommandBuffer commandBuffer,
const VkDependencyInfo* pDependencyInfo) {
@ -2615,12 +2627,58 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdResolveImage2(
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_STUB(vkCmdSetCullMode, void, VkCommandBuffer, VkCullModeFlags)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthBiasEnable, void, VkCommandBuffer, VkBool32)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthBoundsTestEnable, void, VkCommandBuffer, VkBool32)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthCompareOp, void, VkCommandBuffer, VkCompareOp)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthTestEnable, void, VkCommandBuffer, VkBool32)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthWriteEnable, void, VkCommandBuffer, VkBool32)
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetCullMode(
VkCommandBuffer commandBuffer,
VkCullModeFlags cullMode) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetCullMode, commandBuffer, cullMode);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthBiasEnable(
VkCommandBuffer commandBuffer,
VkBool32 depthBiasEnable) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetDepthBiasEnable, commandBuffer, depthBiasEnable);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthBoundsTestEnable(
VkCommandBuffer commandBuffer,
VkBool32 depthBoundsTestEnable) {
MVKTraceVulkanCallStart();
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthCompareOp(
VkCommandBuffer commandBuffer,
VkCompareOp depthCompareOp) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetDepthCompareOp, commandBuffer, depthCompareOp);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthTestEnable(
VkCommandBuffer commandBuffer,
VkBool32 depthTestEnable) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetDepthTestEnable, commandBuffer, depthTestEnable);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthWriteEnable(
VkCommandBuffer commandBuffer,
VkBool32 depthWriteEnable) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetDepthWriteEnable, commandBuffer, depthWriteEnable);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetEvent2(
VkCommandBuffer commandBuffer,
@ -2632,14 +2690,83 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetEvent2(
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_STUB(vkCmdSetFrontFace, void, VkCommandBuffer, VkFrontFace)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetPrimitiveRestartEnable, void, VkCommandBuffer, VkBool32)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetPrimitiveTopology, void, VkCommandBuffer, VkPrimitiveTopology)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetRasterizerDiscardEnable, void, VkCommandBuffer, VkBool32)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetScissorWithCount, void, VkCommandBuffer, uint32_t, const VkRect2D*)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetStencilOp, void, VkCommandBuffer, VkStencilFaceFlags, VkStencilOp, VkStencilOp, VkStencilOp, VkCompareOp)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetStencilTestEnable, void, VkCommandBuffer, VkBool32)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetViewportWithCount, void, VkCommandBuffer, uint32_t, const VkViewport*)
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetFrontFace(
VkCommandBuffer commandBuffer,
VkFrontFace frontFace) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetFrontFace, commandBuffer, frontFace);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetPrimitiveRestartEnable(
VkCommandBuffer commandBuffer,
VkBool32 primitiveRestartEnable) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetPrimitiveRestartEnable, commandBuffer, primitiveRestartEnable);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetPrimitiveTopology(
VkCommandBuffer commandBuffer,
VkPrimitiveTopology primitiveTopology) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetPrimitiveTopology, commandBuffer, primitiveTopology);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetRasterizerDiscardEnable(
VkCommandBuffer commandBuffer,
VkBool32 rasterizerDiscardEnable) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetRasterizerDiscardEnable, commandBuffer, rasterizerDiscardEnable);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetScissorWithCount(
VkCommandBuffer commandBuffer,
uint32_t scissorCount,
const VkRect2D* pScissors) {
MVKTraceVulkanCallStart();
MVKAddCmdFromThreshold(SetScissor, scissorCount, 1, commandBuffer, 0, scissorCount, pScissors);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetStencilOp(
VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
VkStencilOp failOp,
VkStencilOp passOp,
VkStencilOp depthFailOp,
VkCompareOp compareOp) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetStencilOp, commandBuffer, faceMask, failOp, passOp, depthFailOp, compareOp);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetStencilTestEnable(
VkCommandBuffer commandBuffer,
VkBool32 stencilTestEnable) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetStencilTestEnable, commandBuffer, stencilTestEnable);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetViewportWithCount(
VkCommandBuffer commandBuffer,
uint32_t viewportCount,
const VkViewport* pViewports) {
MVKTraceVulkanCallStart();
MVKAddCmdFromThreshold(SetViewport, viewportCount, 1, commandBuffer, 0, viewportCount, pViewports);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdWaitEvents2(
VkCommandBuffer commandBuffer,
@ -2733,7 +2860,6 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkSetPrivateData(
}
#pragma mark -
#pragma mark VK_KHR_bind_memory2 extension
@ -3481,6 +3607,60 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkSubmitDebugUtilsMessageEXT(
}
#pragma mark -
#pragma mark VK_EXT_extended_dynamic_state
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdBindVertexBuffers2, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetCullMode, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetDepthBoundsTestEnable, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetDepthCompareOp, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetDepthTestEnable, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetDepthWriteEnable, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetFrontFace, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetPrimitiveTopology, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetScissorWithCount, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetStencilOp, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetStencilTestEnable, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetViewportWithCount, EXT);
#pragma mark -
#pragma mark VK_EXT_extended_dynamic_state2
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetDepthBiasEnable, EXT);
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetLogicOpEXT(
VkCommandBuffer commandBuffer,
VkLogicOp logicOp) {
MVKTraceVulkanCallStart();
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetPatchControlPointsEXT(
VkCommandBuffer commandBuffer,
uint32_t patchControlPoints) {
MVKTraceVulkanCallStart();
MVKAddCmd(SetPatchControlPoints, commandBuffer, patchControlPoints);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetPrimitiveRestartEnable, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdSetRasterizerDiscardEnable, EXT);
#pragma mark -
#pragma mark VK_EXT_extended_dynamic_state3
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetLogicOpEnableEXT(
VkCommandBuffer commandBuffer,
VkBool32 logicOpEnable) {
MVKTraceVulkanCallStart();
MVKTraceVulkanCallEnd();
}
#pragma mark -
#pragma mark VK_EXT_external_memory_host extension
@ -3565,6 +3745,7 @@ MVK_PUBLIC_VULKAN_CORE_ALIAS(vkGetPrivateData, EXT);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkSetPrivateData, EXT);
#pragma mark -
#pragma mark VK_EXT_sample_locations extension
@ -3588,6 +3769,7 @@ void vkCmdSetSampleLocationsEXT(
MVKTraceVulkanCallEnd();
}
#pragma mark -
#pragma mark VK_GOOGLE_display_timing extension
@ -3616,12 +3798,14 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPastPresentationTimingGOOGLE(
return rslt;
}
#pragma mark -
#pragma mark VK_AMD_draw_indirect_count
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdDrawIndexedIndirectCount, AMD);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdDrawIndirectCount, AMD);
#pragma mark -
#pragma mark iOS & macOS surface extensions