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_16bit_storage`
- `VK_KHR_8bit_storage` - `VK_KHR_8bit_storage`
- `VK_KHR_bind_memory2` - `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_copy_commands2`
- `VK_KHR_create_renderpass2` - `VK_KHR_create_renderpass2`
- `VK_KHR_dedicated_allocation` - `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_device_group_creation`
- `VK_KHR_driver_properties` - `VK_KHR_driver_properties`
- `VK_KHR_dynamic_rendering` - `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_memory_requirements2`
- `VK_KHR_get_physical_device_properties2` - `VK_KHR_get_physical_device_properties2`
- `VK_KHR_get_surface_capabilities2` - `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_portability_subset`
- `VK_KHR_push_descriptor` - `VK_KHR_push_descriptor`
- `VK_KHR_relaxed_block_layout` - `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_sampler_ycbcr_conversion`
- `VK_KHR_separate_depth_stencil_layouts` - `VK_KHR_separate_depth_stencil_layouts`
- `VK_KHR_shader_draw_parameters` - `VK_KHR_shader_draw_parameters`
- `VK_KHR_shader_float_controls` - `VK_KHR_shader_float_controls`
- `VK_KHR_shader_float16_int8` - `VK_KHR_shader_float16_int8`
- `VK_KHR_shader_non_semantic_info` - `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_spirv_1_4`
- `VK_KHR_storage_buffer_storage_class` - `VK_KHR_storage_buffer_storage_class`
- `VK_KHR_surface` - `VK_KHR_surface`
@ -354,53 +358,78 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll
- `VK_KHR_timeline_semaphore` - `VK_KHR_timeline_semaphore`
- `VK_KHR_uniform_buffer_standard_layout` - `VK_KHR_uniform_buffer_standard_layout`
- `VK_KHR_variable_pointers` - `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_4444_formats`
- `VK_EXT_buffer_device_address` *(requires GPU Tier 2 argument buffers support)* - *Requires 16-bit formats and either native texture swizzling or manual swizzling to be enabled.*
- `VK_EXT_calibrated_timestamps` *(requires Metal 2.2)* - `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_marker`
- `VK_EXT_debug_report` - `VK_EXT_debug_report`
- `VK_EXT_debug_utils` - `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 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_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_host_query_reset`
- `VK_EXT_image_robustness` - `VK_EXT_image_robustness`
- `VK_EXT_inline_uniform_block` - `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_objects`
- `VK_EXT_metal_surface` - `VK_EXT_metal_surface`
- `VK_EXT_pipeline_creation_cache_control` - `VK_EXT_pipeline_creation_cache_control`
- `VK_EXT_pipeline_creation_feedback` - `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_private_data `
- `VK_EXT_robustness2` - `VK_EXT_robustness2`
- `VK_EXT_sample_locations` - `VK_EXT_sample_locations`
- `VK_EXT_scalar_block_layout` - `VK_EXT_scalar_block_layout`
- `VK_EXT_separate_stencil_usage` - `VK_EXT_separate_stencil_usage`
- `VK_EXT_shader_atomic_float` *(requires Metal 3.0)* - `VK_EXT_shader_atomic_float`
- `VK_EXT_shader_demote_to_helper_invocation` *(requires Metal Shading Language 2.3)* - *Requires Metal 3.0.*
- `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)* - `VK_EXT_shader_demote_to_helper_invocation`
- `VK_EXT_shader_subgroup_ballot` *(requires Mac GPU family 2 or Apple GPU family 4)* - *Requires Metal Shading Language 2.3.*
- `VK_EXT_shader_subgroup_vote` *(requires Mac GPU family 2 or Apple GPU family 4)* - `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_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_surface_maintenance1`
- `VK_EXT_swapchain_colorspace` - `VK_EXT_swapchain_colorspace`
- `VK_EXT_swapchain_maintenance1` - `VK_EXT_swapchain_maintenance1`
- `VK_EXT_vertex_attribute_divisor` - `VK_EXT_vertex_attribute_divisor`
- `VK_EXT_texel_buffer_alignment` *(requires Metal 2.0)* - `VK_EXT_texel_buffer_alignment`
- `VK_EXT_texture_compression_astc_hdr` *(iOS and macOS, requires family 6 (A13) or better Apple GPU)* - *Requires Metal 2.0.*
- `VK_MVK_ios_surface` *(iOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)* - `VK_EXT_texture_compression_astc_hdr`
- `VK_MVK_macos_surface` *(macOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)* - *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_gpu_shader_half_float`
- `VK_AMD_negative_viewport_height` - `VK_AMD_negative_viewport_height`
- `VK_AMD_shader_image_load_store_lod` *(requires Apple GPU)* - `VK_AMD_shader_image_load_store_lod`
- `VK_AMD_shader_trinary_minmax` *(requires Metal 2.1)* - *Requires Apple GPU.*
- `VK_IMG_format_pvrtc` *(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_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` - `VK_NV_glsl_shader`
In order to visibly display your content on *macOS*, *iOS*, or *tvOS*, you must enable the 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**. 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. - 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 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 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)*. 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)* Refer to the *Vulkan SDK [Getting Started](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html)*
document for more info. document for more info.

View File

@ -20,6 +20,8 @@ Released TBD
- Add support for extensions: - Add support for extensions:
- `VK_KHR_synchronization2` - `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 - Fix rare case where vertex attribute buffers are not bound to Metal
when no other bindings change between pipelines. when no other bindings change between pipelines.
- Ensure objects retained for life of `MTLCommandBuffer` during `vkCmdBlitImage()` & `vkQueuePresentKHR()`. - 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 */; }; 2FEA0A6724902F9F00EEF3AD /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F0429D1FB4CF82009FCCB8 /* MVKCommonEnvironment.h */; };
2FEA0A6824902F9F00EEF3AD /* MVKWatermark.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149491FB6A3F7005F00B4 /* MVKWatermark.h */; }; 2FEA0A6824902F9F00EEF3AD /* MVKWatermark.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149491FB6A3F7005F00B4 /* MVKWatermark.h */; };
2FEA0A6924902F9F00EEF3AD /* MVKOSExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.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 */; }; 2FEA0A6B24902F9F00EEF3AD /* MVKCmdPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB76E1C7DFB4800632CA3 /* MVKCmdPipeline.h */; };
2FEA0A6C24902F9F00EEF3AD /* MVKSmallVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */; }; 2FEA0A6C24902F9F00EEF3AD /* MVKSmallVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */; };
2FEA0A6D24902F9F00EEF3AD /* MVKPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB78D1C7DFB4800632CA3 /* MVKPipeline.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 */; }; 2FEA0A9424902F9F00EEF3AD /* MVKCommandPool.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB77B1C7DFB4800632CA3 /* MVKCommandPool.mm */; };
2FEA0A9524902F9F00EEF3AD /* MVKCmdDraw.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */; }; 2FEA0A9524902F9F00EEF3AD /* MVKCmdDraw.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */; };
2FEA0A9624902F9F00EEF3AD /* MVKCommandBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7791C7DFB4800632CA3 /* MVKCommandBuffer.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 */; }; 2FEA0A9824902F9F00EEF3AD /* MVKBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7801C7DFB4800632CA3 /* MVKBuffer.mm */; };
2FEA0A9924902F9F00EEF3AD /* mvk_datatypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.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 */; }; 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 */; }; A94FB7C11C7DFB4800632CA3 /* MVKCmdQueries.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7701C7DFB4800632CA3 /* MVKCmdQueries.h */; };
A94FB7C21C7DFB4800632CA3 /* MVKCmdQueries.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */; }; A94FB7C21C7DFB4800632CA3 /* MVKCmdQueries.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */; };
A94FB7C31C7DFB4800632CA3 /* 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 */; }; A94FB7C41C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */; };
A94FB7C51C7DFB4800632CA3 /* MVKCmdRenderPass.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */; }; A94FB7C51C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */; };
A94FB7C61C7DFB4800632CA3 /* MVKCmdRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */; }; A94FB7C61C7DFB4800632CA3 /* MVKCmdRendering.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */; };
A94FB7C71C7DFB4800632CA3 /* MVKCmdRenderPass.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */; }; A94FB7C71C7DFB4800632CA3 /* MVKCmdRendering.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */; };
A94FB7C81C7DFB4800632CA3 /* MVKCmdDraw.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7741C7DFB4800632CA3 /* MVKCmdDraw.h */; }; A94FB7C81C7DFB4800632CA3 /* MVKCmdDraw.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB7741C7DFB4800632CA3 /* MVKCmdDraw.h */; };
A94FB7C91C7DFB4800632CA3 /* 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 */; }; 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 */; }; DCFD7F0B2A45BC6E007BBBF7 /* MVKCommonEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F0429D1FB4CF82009FCCB8 /* MVKCommonEnvironment.h */; };
DCFD7F0C2A45BC6E007BBBF7 /* MVKWatermark.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149491FB6A3F7005F00B4 /* MVKWatermark.h */; }; DCFD7F0C2A45BC6E007BBBF7 /* MVKWatermark.h in Headers */ = {isa = PBXBuildFile; fileRef = A98149491FB6A3F7005F00B4 /* MVKWatermark.h */; };
DCFD7F0D2A45BC6E007BBBF7 /* MVKOSExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B51BD6225E986A00AC74D2 /* MVKOSExtensions.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 */; }; DCFD7F0F2A45BC6E007BBBF7 /* MVKCmdPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB76E1C7DFB4800632CA3 /* MVKCmdPipeline.h */; };
DCFD7F102A45BC6E007BBBF7 /* MVKSmallVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */; }; DCFD7F102A45BC6E007BBBF7 /* MVKSmallVectorAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A9F3D9D924732A4C00745190 /* MVKSmallVectorAllocator.h */; };
DCFD7F112A45BC6E007BBBF7 /* MVKPipeline.h in Headers */ = {isa = PBXBuildFile; fileRef = A94FB78D1C7DFB4800632CA3 /* MVKPipeline.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 */; }; DCFD7F3A2A45BC6E007BBBF7 /* MVKCommandPool.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB77B1C7DFB4800632CA3 /* MVKCommandPool.mm */; };
DCFD7F3B2A45BC6E007BBBF7 /* MVKCmdDraw.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */; }; DCFD7F3B2A45BC6E007BBBF7 /* MVKCmdDraw.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7751C7DFB4800632CA3 /* MVKCmdDraw.mm */; };
DCFD7F3C2A45BC6E007BBBF7 /* MVKCommandBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7791C7DFB4800632CA3 /* MVKCommandBuffer.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 */; }; DCFD7F3E2A45BC6E007BBBF7 /* MVKBuffer.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7801C7DFB4800632CA3 /* MVKBuffer.mm */; };
DCFD7F3F2A45BC6E007BBBF7 /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; }; DCFD7F3F2A45BC6E007BBBF7 /* MVKEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9A5E9C525C0822700E9085E /* MVKEnvironment.cpp */; };
DCFD7F402A45BC6E007BBBF7 /* mvk_datatypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = A94FB7A91C7DFB4800632CA3 /* mvk_datatypes.mm */; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCmdRendering.h; sourceTree = "<group>"; };
A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MVKCmdRenderPass.mm; 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>"; }; 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>"; }; 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>"; }; A94FB7761C7DFB4800632CA3 /* MVKCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MVKCommand.h; sourceTree = "<group>"; };
@ -744,8 +744,8 @@
A94FB76F1C7DFB4800632CA3 /* MVKCmdPipeline.mm */, A94FB76F1C7DFB4800632CA3 /* MVKCmdPipeline.mm */,
A94FB7701C7DFB4800632CA3 /* MVKCmdQueries.h */, A94FB7701C7DFB4800632CA3 /* MVKCmdQueries.h */,
A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */, A94FB7711C7DFB4800632CA3 /* MVKCmdQueries.mm */,
A94FB7721C7DFB4800632CA3 /* MVKCmdRenderPass.h */, A94FB7721C7DFB4800632CA3 /* MVKCmdRendering.h */,
A94FB7731C7DFB4800632CA3 /* MVKCmdRenderPass.mm */, A94FB7731C7DFB4800632CA3 /* MVKCmdRendering.mm */,
A94FB76C1C7DFB4800632CA3 /* MVKCmdTransfer.h */, A94FB76C1C7DFB4800632CA3 /* MVKCmdTransfer.h */,
A94FB76D1C7DFB4800632CA3 /* MVKCmdTransfer.mm */, A94FB76D1C7DFB4800632CA3 /* MVKCmdTransfer.mm */,
A94FB7761C7DFB4800632CA3 /* MVKCommand.h */, A94FB7761C7DFB4800632CA3 /* MVKCommand.h */,
@ -995,7 +995,7 @@
2FEA0A6724902F9F00EEF3AD /* MVKCommonEnvironment.h in Headers */, 2FEA0A6724902F9F00EEF3AD /* MVKCommonEnvironment.h in Headers */,
2FEA0A6824902F9F00EEF3AD /* MVKWatermark.h in Headers */, 2FEA0A6824902F9F00EEF3AD /* MVKWatermark.h in Headers */,
2FEA0A6924902F9F00EEF3AD /* MVKOSExtensions.h in Headers */, 2FEA0A6924902F9F00EEF3AD /* MVKOSExtensions.h in Headers */,
2FEA0A6A24902F9F00EEF3AD /* MVKCmdRenderPass.h in Headers */, 2FEA0A6A24902F9F00EEF3AD /* MVKCmdRendering.h in Headers */,
2FEA0A6B24902F9F00EEF3AD /* MVKCmdPipeline.h in Headers */, 2FEA0A6B24902F9F00EEF3AD /* MVKCmdPipeline.h in Headers */,
2FEA0A6C24902F9F00EEF3AD /* MVKSmallVectorAllocator.h in Headers */, 2FEA0A6C24902F9F00EEF3AD /* MVKSmallVectorAllocator.h in Headers */,
2FEA0A6D24902F9F00EEF3AD /* MVKPipeline.h in Headers */, 2FEA0A6D24902F9F00EEF3AD /* MVKPipeline.h in Headers */,
@ -1074,7 +1074,7 @@
A9F042A41FB4CF83009FCCB8 /* MVKCommonEnvironment.h in Headers */, A9F042A41FB4CF83009FCCB8 /* MVKCommonEnvironment.h in Headers */,
A981495D1FB6A3F7005F00B4 /* MVKWatermark.h in Headers */, A981495D1FB6A3F7005F00B4 /* MVKWatermark.h in Headers */,
A9B51BD9225E986A00AC74D2 /* MVKOSExtensions.h in Headers */, A9B51BD9225E986A00AC74D2 /* MVKOSExtensions.h in Headers */,
A94FB7C41C7DFB4800632CA3 /* MVKCmdRenderPass.h in Headers */, A94FB7C41C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */,
A94FB7BC1C7DFB4800632CA3 /* MVKCmdPipeline.h in Headers */, A94FB7BC1C7DFB4800632CA3 /* MVKCmdPipeline.h in Headers */,
A9F3D9DC24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */, A9F3D9DC24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */,
A9C327562AAFBD390025EE79 /* MVKConfigMembers.def in Headers */, A9C327562AAFBD390025EE79 /* MVKConfigMembers.def in Headers */,
@ -1151,7 +1151,7 @@
A9F042A51FB4CF83009FCCB8 /* MVKCommonEnvironment.h in Headers */, A9F042A51FB4CF83009FCCB8 /* MVKCommonEnvironment.h in Headers */,
A981495E1FB6A3F7005F00B4 /* MVKWatermark.h in Headers */, A981495E1FB6A3F7005F00B4 /* MVKWatermark.h in Headers */,
A9B51BDA225E986A00AC74D2 /* MVKOSExtensions.h in Headers */, A9B51BDA225E986A00AC74D2 /* MVKOSExtensions.h in Headers */,
A94FB7C51C7DFB4800632CA3 /* MVKCmdRenderPass.h in Headers */, A94FB7C51C7DFB4800632CA3 /* MVKCmdRendering.h in Headers */,
A94FB7BD1C7DFB4800632CA3 /* MVKCmdPipeline.h in Headers */, A94FB7BD1C7DFB4800632CA3 /* MVKCmdPipeline.h in Headers */,
A9F3D9DD24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */, A9F3D9DD24732A4D00745190 /* MVKSmallVectorAllocator.h in Headers */,
A94FB7F91C7DFB4800632CA3 /* MVKPipeline.h in Headers */, A94FB7F91C7DFB4800632CA3 /* MVKPipeline.h in Headers */,
@ -1228,7 +1228,7 @@
DCFD7F0B2A45BC6E007BBBF7 /* MVKCommonEnvironment.h in Headers */, DCFD7F0B2A45BC6E007BBBF7 /* MVKCommonEnvironment.h in Headers */,
DCFD7F0C2A45BC6E007BBBF7 /* MVKWatermark.h in Headers */, DCFD7F0C2A45BC6E007BBBF7 /* MVKWatermark.h in Headers */,
DCFD7F0D2A45BC6E007BBBF7 /* MVKOSExtensions.h in Headers */, DCFD7F0D2A45BC6E007BBBF7 /* MVKOSExtensions.h in Headers */,
DCFD7F0E2A45BC6E007BBBF7 /* MVKCmdRenderPass.h in Headers */, DCFD7F0E2A45BC6E007BBBF7 /* MVKCmdRendering.h in Headers */,
DCFD7F0F2A45BC6E007BBBF7 /* MVKCmdPipeline.h in Headers */, DCFD7F0F2A45BC6E007BBBF7 /* MVKCmdPipeline.h in Headers */,
DCFD7F102A45BC6E007BBBF7 /* MVKSmallVectorAllocator.h in Headers */, DCFD7F102A45BC6E007BBBF7 /* MVKSmallVectorAllocator.h in Headers */,
DCFD7F112A45BC6E007BBBF7 /* MVKPipeline.h in Headers */, DCFD7F112A45BC6E007BBBF7 /* MVKPipeline.h in Headers */,
@ -1674,7 +1674,7 @@
2FEA0A9424902F9F00EEF3AD /* MVKCommandPool.mm in Sources */, 2FEA0A9424902F9F00EEF3AD /* MVKCommandPool.mm in Sources */,
2FEA0A9524902F9F00EEF3AD /* MVKCmdDraw.mm in Sources */, 2FEA0A9524902F9F00EEF3AD /* MVKCmdDraw.mm in Sources */,
2FEA0A9624902F9F00EEF3AD /* MVKCommandBuffer.mm in Sources */, 2FEA0A9624902F9F00EEF3AD /* MVKCommandBuffer.mm in Sources */,
2FEA0A9724902F9F00EEF3AD /* MVKCmdRenderPass.mm in Sources */, 2FEA0A9724902F9F00EEF3AD /* MVKCmdRendering.mm in Sources */,
2FEA0A9824902F9F00EEF3AD /* MVKBuffer.mm in Sources */, 2FEA0A9824902F9F00EEF3AD /* MVKBuffer.mm in Sources */,
2FEA0A9924902F9F00EEF3AD /* mvk_datatypes.mm in Sources */, 2FEA0A9924902F9F00EEF3AD /* mvk_datatypes.mm in Sources */,
2FEA0A9A24902F9F00EEF3AD /* MVKExtensions.mm in Sources */, 2FEA0A9A24902F9F00EEF3AD /* MVKExtensions.mm in Sources */,
@ -1734,7 +1734,7 @@
A94FB7D61C7DFB4800632CA3 /* MVKCommandPool.mm in Sources */, A94FB7D61C7DFB4800632CA3 /* MVKCommandPool.mm in Sources */,
A94FB7CA1C7DFB4800632CA3 /* MVKCmdDraw.mm in Sources */, A94FB7CA1C7DFB4800632CA3 /* MVKCmdDraw.mm in Sources */,
A94FB7D21C7DFB4800632CA3 /* MVKCommandBuffer.mm in Sources */, A94FB7D21C7DFB4800632CA3 /* MVKCommandBuffer.mm in Sources */,
A94FB7C61C7DFB4800632CA3 /* MVKCmdRenderPass.mm in Sources */, A94FB7C61C7DFB4800632CA3 /* MVKCmdRendering.mm in Sources */,
A94FB7DE1C7DFB4800632CA3 /* MVKBuffer.mm in Sources */, A94FB7DE1C7DFB4800632CA3 /* MVKBuffer.mm in Sources */,
A9A5E9C725C0822700E9085E /* MVKEnvironment.cpp in Sources */, A9A5E9C725C0822700E9085E /* MVKEnvironment.cpp in Sources */,
A94FB82A1C7DFB4800632CA3 /* mvk_datatypes.mm in Sources */, A94FB82A1C7DFB4800632CA3 /* mvk_datatypes.mm in Sources */,
@ -1794,7 +1794,7 @@
A94FB7D71C7DFB4800632CA3 /* MVKCommandPool.mm in Sources */, A94FB7D71C7DFB4800632CA3 /* MVKCommandPool.mm in Sources */,
A94FB7CB1C7DFB4800632CA3 /* MVKCmdDraw.mm in Sources */, A94FB7CB1C7DFB4800632CA3 /* MVKCmdDraw.mm in Sources */,
A94FB7D31C7DFB4800632CA3 /* MVKCommandBuffer.mm in Sources */, A94FB7D31C7DFB4800632CA3 /* MVKCommandBuffer.mm in Sources */,
A94FB7C71C7DFB4800632CA3 /* MVKCmdRenderPass.mm in Sources */, A94FB7C71C7DFB4800632CA3 /* MVKCmdRendering.mm in Sources */,
A94FB7DF1C7DFB4800632CA3 /* MVKBuffer.mm in Sources */, A94FB7DF1C7DFB4800632CA3 /* MVKBuffer.mm in Sources */,
A9A5E9C925C0822700E9085E /* MVKEnvironment.cpp in Sources */, A9A5E9C925C0822700E9085E /* MVKEnvironment.cpp in Sources */,
A94FB82B1C7DFB4800632CA3 /* mvk_datatypes.mm in Sources */, A94FB82B1C7DFB4800632CA3 /* mvk_datatypes.mm in Sources */,
@ -1854,7 +1854,7 @@
DCFD7F3A2A45BC6E007BBBF7 /* MVKCommandPool.mm in Sources */, DCFD7F3A2A45BC6E007BBBF7 /* MVKCommandPool.mm in Sources */,
DCFD7F3B2A45BC6E007BBBF7 /* MVKCmdDraw.mm in Sources */, DCFD7F3B2A45BC6E007BBBF7 /* MVKCmdDraw.mm in Sources */,
DCFD7F3C2A45BC6E007BBBF7 /* MVKCommandBuffer.mm in Sources */, DCFD7F3C2A45BC6E007BBBF7 /* MVKCommandBuffer.mm in Sources */,
DCFD7F3D2A45BC6E007BBBF7 /* MVKCmdRenderPass.mm in Sources */, DCFD7F3D2A45BC6E007BBBF7 /* MVKCmdRendering.mm in Sources */,
DCFD7F3E2A45BC6E007BBBF7 /* MVKBuffer.mm in Sources */, DCFD7F3E2A45BC6E007BBBF7 /* MVKBuffer.mm in Sources */,
DCFD7F3F2A45BC6E007BBBF7 /* MVKEnvironment.cpp in Sources */, DCFD7F3F2A45BC6E007BBBF7 /* MVKEnvironment.cpp in Sources */,
DCFD7F402A45BC6E007BBBF7 /* mvk_datatypes.mm 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. */ /** Returns the Metal MTLScissorRect corresponding to the specified Vulkan VkRect2D. */
MTLScissorRect mvkMTLScissorRectFromVkRect2D(VkRect2D vkRect); 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, */ /** Returns the Metal MTLCompareFunction corresponding to the specified Vulkan VkCompareOp, */
MTLCompareFunction mvkMTLCompareFunctionFromVkCompareOp(VkCompareOp vkOp); 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. */ 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. */ 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. */ 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; } MVKPhysicalDeviceMetalFeatures;
/** /**

View File

@ -46,7 +46,7 @@ void MVKCmdDispatch::encode(MVKCommandEncoder* cmdEncoder) {
MTLRegion mtlThreadgroupCount = MTLRegionMake3D(_baseGroupX, _baseGroupY, _baseGroupZ, _groupCountX, _groupCountY, _groupCountZ); MTLRegion mtlThreadgroupCount = MTLRegionMake3D(_baseGroupX, _baseGroupY, _baseGroupZ, _groupCountX, _groupCountY, _groupCountZ);
cmdEncoder->finalizeDispatchState(); // Ensure all updated state has been submitted to Metal cmdEncoder->finalizeDispatchState(); // Ensure all updated state has been submitted to Metal
id<MTLComputeCommandEncoder> mtlEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch); id<MTLComputeCommandEncoder> mtlEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseDispatch);
auto* pipeline = (MVKComputePipeline*)cmdEncoder->_computePipelineState.getPipeline(); auto* pipeline = cmdEncoder->_computePipelineState.getComputePipeline();
if (pipeline->allowsDispatchBase()) { if (pipeline->allowsDispatchBase()) {
if ([mtlEncoder respondsToSelector: @selector(setStageInRegion:)]) { if ([mtlEncoder respondsToSelector: @selector(setStageInRegion:)]) {
// We'll use the stage-input region to pass the base along to the shader. // 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: public:
VkResult setContent(MVKCommandBuffer* cmdBuff, VkResult setContent(MVKCommandBuffer* cmdBuff,
uint32_t startBinding, uint32_t firstBinding,
uint32_t bindingCount, uint32_t bindingCount,
const VkBuffer* pBuffers, const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets); const VkDeviceSize* pOffsets,
const VkDeviceSize* pSizes,
const VkDeviceSize* pStrides);
void encode(MVKCommandEncoder* cmdEncoder) override; void encode(MVKCommandEncoder* cmdEncoder) override;

View File

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

View File

@ -30,6 +30,34 @@ class MVKDescriptorSet;
class MVKDescriptorUpdateTemplate; 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 -
#pragma mark MVKCmdPipelineBarrier #pragma mark MVKCmdPipelineBarrier

View File

@ -26,6 +26,33 @@
#include "mvk_datatypes.hpp" #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 -
#pragma mark MVKCmdPipelineBarrier #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) * 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 -
#pragma mark MVKCmdSetViewport #pragma mark MVKCmdSetViewport
@ -295,25 +267,6 @@ typedef MVKCmdSetScissor<1> MVKCmdSetScissor1;
typedef MVKCmdSetScissor<kMVKMaxViewportScissorCount> MVKCmdSetScissorMulti; 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 -
#pragma mark MVKCmdSetDepthBias #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 -
#pragma mark MVKCmdSetBlendConstants #pragma mark MVKCmdSetBlendConstants
@ -352,31 +324,110 @@ public:
protected: protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override; MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
float _red; float _blendConstants[4] = {};
float _green;
float _blue;
float _alpha;
}; };
#pragma mark - #pragma mark -
#pragma mark MVKCmdSetDepthBounds #pragma mark MVKCmdSetDepthTestEnable
/** Vulkan command to set depth bounds. */ /** Vulkan command to dynamically enable depth testing. */
class MVKCmdSetDepthBounds : public MVKCommand { class MVKCmdSetDepthTestEnable : public MVKCommand {
public: public:
VkResult setContent(MVKCommandBuffer* cmdBuff, VkResult setContent(MVKCommandBuffer* cmdBuff,
float minDepthBounds, VkBool32 depthTestEnable);
float maxDepthBounds);
void encode(MVKCommandEncoder* cmdEncoder) override; void encode(MVKCommandEncoder* cmdEncoder) override;
protected: protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override; MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
float _minDepthBounds; VkBool32 _depthTestEnable;
float _maxDepthBounds; };
#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; 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) * Copyright (c) 2015-2023 The Brenwill Workshop Ltd. (http://www.brenwill.com)
* *
@ -16,7 +16,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include "MVKCmdRenderPass.h" #include "MVKCmdRendering.h"
#include "MVKCommandBuffer.h" #include "MVKCommandBuffer.h"
#include "MVKCommandPool.h" #include "MVKCommandPool.h"
#include "MVKFramebuffer.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 -
#pragma mark MVKCmdSetViewport #pragma mark MVKCmdSetViewport
@ -278,7 +251,7 @@ VkResult MVKCmdSetViewport<N>::setContent(MVKCommandBuffer* cmdBuff,
template <size_t N> template <size_t N>
void MVKCmdSetViewport<N>::encode(MVKCommandEncoder* cmdEncoder) { void MVKCmdSetViewport<N>::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_viewportState.setViewports(_viewports.contents(), _firstViewport, true); cmdEncoder->_renderingState.setViewports(_viewports.contents(), _firstViewport, true);
} }
template class MVKCmdSetViewport<1>; template class MVKCmdSetViewport<1>;
@ -305,31 +278,13 @@ VkResult MVKCmdSetScissor<N>::setContent(MVKCommandBuffer* cmdBuff,
template <size_t N> template <size_t N>
void MVKCmdSetScissor<N>::encode(MVKCommandEncoder* cmdEncoder) { 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<1>;
template class MVKCmdSetScissor<kMVKMaxViewportScissorCount>; 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 -
#pragma mark MVKCmdSetDepthBias #pragma mark MVKCmdSetDepthBias
@ -345,48 +300,116 @@ VkResult MVKCmdSetDepthBias::setContent(MVKCommandBuffer* cmdBuff,
} }
void MVKCmdSetDepthBias::encode(MVKCommandEncoder* cmdEncoder) { void MVKCmdSetDepthBias::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_depthBiasState.setDepthBias(_depthBiasConstantFactor, cmdEncoder->_renderingState.setDepthBias(_depthBiasConstantFactor,
_depthBiasSlopeFactor, _depthBiasSlopeFactor,
_depthBiasClamp); _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 -
#pragma mark MVKCmdSetBlendConstants #pragma mark MVKCmdSetBlendConstants
VkResult MVKCmdSetBlendConstants::setContent(MVKCommandBuffer* cmdBuff, VkResult MVKCmdSetBlendConstants::setContent(MVKCommandBuffer* cmdBuff,
const float blendConst[4]) { const float blendConst[4]) {
_red = blendConst[0]; mvkCopy(_blendConstants, blendConst, 4);
_green = blendConst[1];
_blue = blendConst[2];
_alpha = blendConst[3];
return VK_SUCCESS; return VK_SUCCESS;
} }
void MVKCmdSetBlendConstants::encode(MVKCommandEncoder* cmdEncoder) { void MVKCmdSetBlendConstants::encode(MVKCommandEncoder* cmdEncoder) {
cmdEncoder->_blendColorState.setBlendColor(_red, _green, _blue, _alpha, true); cmdEncoder->_renderingState.setBlendConstants(_blendConstants, true);
} }
#pragma mark - #pragma mark -
#pragma mark MVKCmdSetDepthBounds #pragma mark MVKCmdSetDepthTestEnable
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.");
}
VkResult MVKCmdSetDepthTestEnable::setContent(MVKCommandBuffer* cmdBuff,
VkBool32 depthTestEnable) {
_depthTestEnable = depthTestEnable;
return VK_SUCCESS; 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 - #pragma mark -
@ -436,6 +459,95 @@ VkResult MVKCmdSetStencilReference::setContent(MVKCommandBuffer* cmdBuff,
} }
void MVKCmdSetStencilReference::encode(MVKCommandEncoder* cmdEncoder) { 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 // Return to the previous rendering state on the next render activity
cmdEncoder->_graphicsPipelineState.markDirty(); cmdEncoder->_graphicsPipelineState.markDirty();
cmdEncoder->_depthStencilState.markDirty(); cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->_stencilReferenceValueState.markDirty(); cmdEncoder->_renderingState.markDirty();
cmdEncoder->_depthBiasState.markDirty();
cmdEncoder->_viewportState.markDirty();
cmdEncoder->_scissorState.markDirty();
} }
template <size_t N> template <size_t N>

View File

@ -300,14 +300,11 @@ public:
/** Encodes an operation to signal an event to a status. */ /** Encodes an operation to signal an event to a status. */
void signalEvent(MVKEvent* mvkEvent, bool status); void signalEvent(MVKEvent* mvkEvent, bool status);
/** /** Clips the rect to ensure it fits inside the render area. */
* If a pipeline is currently bound, returns whether the current pipeline permits dynamic VkRect2D clipToRenderArea(VkRect2D rect);
* setting of the specified state. If no pipeline is currently bound, returns true.
*/
bool supportsDynamicState(VkDynamicState state);
/** Clips the scissor to ensure it fits inside the render area. */ /** 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. */ /** Called by each graphics draw command to establish any outstanding state just prior to performing the draw. */
void finalizeDrawState(MVKGraphicsStage stage); void finalizeDrawState(MVKGraphicsStage stage);
@ -361,6 +358,9 @@ public:
/** Returns the push constants associated with the specified shader stage. */ /** Returns the push constants associated with the specified shader stage. */
MVKPushConstantsCommandEncoderState* getPushConstants(VkShaderStageFlagBits shaderStage); 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 * 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 * that this binding might override a desriptor binding. If so, the descriptor binding will
@ -435,37 +435,22 @@ public:
id<MTLRenderCommandEncoder> _mtlRenderEncoder; id<MTLRenderCommandEncoder> _mtlRenderEncoder;
/** Tracks the current graphics pipeline bound to the encoder. */ /** Tracks the current graphics pipeline bound to the encoder. */
MVKPipelineCommandEncoderState _graphicsPipelineState; MVKGraphicsPipelineCommandEncoderState _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;
/** Tracks the current graphics resources state of the encoder. */ /** Tracks the current graphics resources state of the encoder. */
MVKGraphicsResourcesCommandEncoderState _graphicsResourcesState; MVKGraphicsResourcesCommandEncoderState _graphicsResourcesState;
/** Tracks the current compute pipeline bound to the encoder. */
MVKComputePipelineCommandEncoderState _computePipelineState;
/** Tracks the current compute resources state of the encoder. */ /** Tracks the current compute resources state of the encoder. */
MVKComputeResourcesCommandEncoderState _computeResourcesState; MVKComputeResourcesCommandEncoderState _computeResourcesState;
/** The type of primitive that will be rendered. */ /** Tracks the current depth stencil state of the encoder. */
MTLPrimitiveType _mtlPrimitiveType; MVKDepthStencilCommandEncoderState _depthStencilState;
/** Tracks the current rendering states of the encoder. */
MVKRenderingCommandEncoderState _renderingState;
/** The size of the threadgroup for the compute shader. */ /** The size of the threadgroup for the compute shader. */
MTLSize _mtlThreadgroupSize; MTLSize _mtlThreadgroupSize;

View File

@ -25,7 +25,7 @@
#include "MVKFoundation.h" #include "MVKFoundation.h"
#include "MTLRenderPassDescriptor+MoltenVK.h" #include "MTLRenderPassDescriptor+MoltenVK.h"
#include "MVKCmdDraw.h" #include "MVKCmdDraw.h"
#include "MVKCmdRenderPass.h" #include "MVKCmdRendering.h"
#include <sys/mman.h> #include <sys/mman.h>
using namespace std; using namespace std;
@ -607,16 +607,12 @@ void MVKCommandEncoder::beginMetalRenderPass(MVKCommandUse cmdUse) {
_graphicsPipelineState.beginMetalRenderPass(); _graphicsPipelineState.beginMetalRenderPass();
_graphicsResourcesState.beginMetalRenderPass(); _graphicsResourcesState.beginMetalRenderPass();
_viewportState.beginMetalRenderPass(); _depthStencilState.beginMetalRenderPass();
_scissorState.beginMetalRenderPass(); _renderingState.beginMetalRenderPass();
_depthBiasState.beginMetalRenderPass();
_blendColorState.beginMetalRenderPass();
_vertexPushConstants.beginMetalRenderPass(); _vertexPushConstants.beginMetalRenderPass();
_tessCtlPushConstants.beginMetalRenderPass(); _tessCtlPushConstants.beginMetalRenderPass();
_tessEvalPushConstants.beginMetalRenderPass(); _tessEvalPushConstants.beginMetalRenderPass();
_fragmentPushConstants.beginMetalRenderPass(); _fragmentPushConstants.beginMetalRenderPass();
_depthStencilState.beginMetalRenderPass();
_stencilReferenceValueState.beginMetalRenderPass();
_occlusionQueryState.beginMetalRenderPass(); _occlusionQueryState.beginMetalRenderPass();
} }
@ -706,24 +702,23 @@ void MVKCommandEncoder::signalEvent(MVKEvent* mvkEvent, bool status) {
mvkEvent->encodeSignal(_mtlCmdBuffer, status); mvkEvent->encodeSignal(_mtlCmdBuffer, status);
} }
bool MVKCommandEncoder::supportsDynamicState(VkDynamicState state) { VkRect2D MVKCommandEncoder::clipToRenderArea(VkRect2D rect) {
MVKGraphicsPipeline* gpl = (MVKGraphicsPipeline*)_graphicsPipelineState.getPipeline();
return !gpl || gpl->supportsDynamicState(state); 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) { MTLScissorRect MVKCommandEncoder::clipToRenderArea(MTLScissorRect scissor) {
return mvkMTLScissorRectFromVkRect2D(clipToRenderArea(mvkVkRect2DFromMTLScissorRect(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;
} }
void MVKCommandEncoder::finalizeDrawState(MVKGraphicsStage stage) { void MVKCommandEncoder::finalizeDrawState(MVKGraphicsStage stage) {
@ -733,16 +728,12 @@ void MVKCommandEncoder::finalizeDrawState(MVKGraphicsStage stage) {
} }
_graphicsPipelineState.encode(stage); // Must do first..it sets others _graphicsPipelineState.encode(stage); // Must do first..it sets others
_graphicsResourcesState.encode(stage); // Before push constants, to allow them to override. _graphicsResourcesState.encode(stage); // Before push constants, to allow them to override.
_viewportState.encode(stage); _depthStencilState.encode(stage);
_scissorState.encode(stage); _renderingState.encode(stage);
_depthBiasState.encode(stage);
_blendColorState.encode(stage);
_vertexPushConstants.encode(stage); _vertexPushConstants.encode(stage);
_tessCtlPushConstants.encode(stage); _tessCtlPushConstants.encode(stage);
_tessEvalPushConstants.encode(stage); _tessEvalPushConstants.encode(stage);
_fragmentPushConstants.encode(stage); _fragmentPushConstants.encode(stage);
_depthStencilState.encode(stage);
_stencilReferenceValueState.encode(stage);
_occlusionQueryState.encode(stage); _occlusionQueryState.encode(stage);
} }
@ -831,16 +822,12 @@ void MVKCommandEncoder::endMetalRenderEncoding() {
_graphicsPipelineState.endMetalRenderPass(); _graphicsPipelineState.endMetalRenderPass();
_graphicsResourcesState.endMetalRenderPass(); _graphicsResourcesState.endMetalRenderPass();
_viewportState.endMetalRenderPass(); _depthStencilState.endMetalRenderPass();
_scissorState.endMetalRenderPass(); _renderingState.endMetalRenderPass();
_depthBiasState.endMetalRenderPass();
_blendColorState.endMetalRenderPass();
_vertexPushConstants.endMetalRenderPass(); _vertexPushConstants.endMetalRenderPass();
_tessCtlPushConstants.endMetalRenderPass(); _tessCtlPushConstants.endMetalRenderPass();
_tessEvalPushConstants.endMetalRenderPass(); _tessEvalPushConstants.endMetalRenderPass();
_fragmentPushConstants.endMetalRenderPass(); _fragmentPushConstants.endMetalRenderPass();
_depthStencilState.endMetalRenderPass();
_stencilReferenceValueState.endMetalRenderPass();
_occlusionQueryState.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, void MVKCommandEncoder::setFragmentBytes(id<MTLRenderCommandEncoder> mtlEncoder,
const void* bytes, const void* bytes,
NSUInteger length, NSUInteger length,
@ -1133,15 +1156,11 @@ MVKCommandEncoder::MVKCommandEncoder(MVKCommandBuffer* cmdBuffer,
MVKPrefillMetalCommandBuffersStyle prefillStyle) : MVKBaseDeviceObject(cmdBuffer->getDevice()), MVKPrefillMetalCommandBuffersStyle prefillStyle) : MVKBaseDeviceObject(cmdBuffer->getDevice()),
_cmdBuffer(cmdBuffer), _cmdBuffer(cmdBuffer),
_graphicsPipelineState(this), _graphicsPipelineState(this),
_computePipelineState(this),
_viewportState(this),
_scissorState(this),
_depthBiasState(this),
_blendColorState(this),
_depthStencilState(this),
_stencilReferenceValueState(this),
_graphicsResourcesState(this), _graphicsResourcesState(this),
_computePipelineState(this),
_computeResourcesState(this), _computeResourcesState(this),
_depthStencilState(this),
_renderingState(this),
_vertexPushConstants(this, VK_SHADER_STAGE_VERTEX_BIT), _vertexPushConstants(this, VK_SHADER_STAGE_VERTEX_BIT),
_tessCtlPushConstants(this, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT), _tessCtlPushConstants(this, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
_tessEvalPushConstants(this, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT), _tessEvalPushConstants(this, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),

View File

@ -21,6 +21,7 @@
#include "MVKMTLResourceBindings.h" #include "MVKMTLResourceBindings.h"
#include "MVKCommandResourceFactory.h" #include "MVKCommandResourceFactory.h"
#include "MVKDevice.h" #include "MVKDevice.h"
#include "MVKPipeline.h"
#include "MVKDescriptor.h" #include "MVKDescriptor.h"
#include "MVKSmallVector.h" #include "MVKSmallVector.h"
#include "MVKBitArray.h" #include "MVKBitArray.h"
@ -81,7 +82,7 @@ public:
/** /**
* If the content of this instance is dirty, marks this instance as no longer dirty * 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. * 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. * can override to leave this instance in a dirty state.
* Subclasses must override the encodeImpl() function to do the actual work. * Subclasses must override the encodeImpl() function to do the actual work.
*/ */
@ -96,8 +97,18 @@ public:
MVKCommandEncoderState(MVKCommandEncoder* cmdEncoder) : _cmdEncoder(cmdEncoder) {} MVKCommandEncoderState(MVKCommandEncoder* cmdEncoder) : _cmdEncoder(cmdEncoder) {}
protected: protected:
enum StateScope {
Static = 0,
Dynamic,
Count
};
virtual void encodeImpl(uint32_t stage) = 0; virtual void encodeImpl(uint32_t stage) = 0;
MVKDevice* getDevice(); 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; MVKCommandEncoder* _cmdEncoder;
bool _isDirty = false; bool _isDirty = false;
@ -108,20 +119,15 @@ protected:
#pragma mark - #pragma mark -
#pragma mark MVKPipelineCommandEncoderState #pragma mark MVKPipelineCommandEncoderState
/** Holds encoder state established by pipeline commands. */ /** Abstract class to hold encoder state established by pipeline commands. */
class MVKPipelineCommandEncoderState : public MVKCommandEncoderState { class MVKPipelineCommandEncoderState : public MVKCommandEncoderState {
public: public:
virtual void bindPipeline(MVKPipeline* pipeline);
/** Binds the pipeline. */
void bindPipeline(MVKPipeline* pipeline);
/** Returns the currently bound pipeline. */
MVKPipeline* getPipeline(); MVKPipeline* getPipeline();
/** Constructs this instance for the specified command encoder. */ MVKPipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder) : MVKCommandEncoderState(cmdEncoder) {}
MVKPipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder)
: MVKCommandEncoderState(cmdEncoder) {}
protected: protected:
void encodeImpl(uint32_t stage) override; void encodeImpl(uint32_t stage) override;
@ -131,58 +137,38 @@ protected:
#pragma mark - #pragma mark -
#pragma mark MVKViewportCommandEncoderState #pragma mark MVKGraphicsPipelineCommandEncoderState
/** Holds encoder state established by viewport commands. */ /** Holds encoder state established by graphics pipeline commands. */
class MVKViewportCommandEncoderState : public MVKCommandEncoderState { class MVKGraphicsPipelineCommandEncoderState : public MVKPipelineCommandEncoderState {
public: public:
void bindPipeline(MVKPipeline* pipeline) override;
/** MVKGraphicsPipeline* getGraphicsPipeline() { return (MVKGraphicsPipeline*)getPipeline(); }
* 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);
/** Constructs this instance for the specified command encoder. */ void setPatchControlPoints(uint32_t patchControlPoints);
MVKViewportCommandEncoderState(MVKCommandEncoder* cmdEncoder) uint32_t getPatchControlPoints();
: MVKCommandEncoderState(cmdEncoder) {}
MVKGraphicsPipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder) : MVKPipelineCommandEncoderState(cmdEncoder) {}
protected: protected:
void encodeImpl(uint32_t stage) override; uint32_t _patchControlPoints[StateScope::Count] = {};
MVKSmallVector<VkViewport, kMVKMaxViewportScissorCount> _viewports, _dynamicViewports;
}; };
#pragma mark - #pragma mark -
#pragma mark MVKScissorCommandEncoderState #pragma mark MVKComputePipelineCommandEncoderState
/** Holds encoder state established by viewport commands. */ /** Holds encoder state established by compute pipeline commands. */
class MVKScissorCommandEncoderState : public MVKCommandEncoderState { class MVKComputePipelineCommandEncoderState : public MVKPipelineCommandEncoderState {
public: public:
MVKComputePipeline* getComputePipeline() { return (MVKComputePipeline*)getPipeline(); }
/** MVKComputePipelineCommandEncoderState(MVKCommandEncoder* cmdEncoder) : MVKPipelineCommandEncoderState(cmdEncoder) {}
* 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) {}
protected: 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. */ /** Sets the depth stencil state during pipeline binding. */
void setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo); void setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
/** /** Enables or disables depth testing, from explicit dynamic command. */
* Sets the stencil compare mask value of the indicated faces void setDepthTestEnable(VkBool32 depthTestEnable);
* to the specified value, from explicit dynamic command.
*/ /** 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); void setStencilCompareMask(VkStencilFaceFlags faceMask, uint32_t stencilCompareMask);
/** /** Sets the stencil write mask value of the indicated faces from explicit dynamic command. */
* Sets the stencil write mask value of the indicated faces
* to the specified value, from explicit dynamic command.
*/
void setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t stencilWriteMask); void setStencilWriteMask(VkStencilFaceFlags faceMask, uint32_t stencilWriteMask);
void beginMetalRenderPass() override; void beginMetalRenderPass() override;
@ -246,96 +245,108 @@ public:
protected: protected:
void encodeImpl(uint32_t stage) override; void encodeImpl(uint32_t stage) override;
void setStencilState(MVKMTLStencilDescriptorData& stencilInfo, MVKMTLDepthStencilDescriptorData& getData(MVKRenderStateType state) { return getContent(_depthStencilData, state); }
const VkStencilOpState& vkStencil, template <typename T> void setContent(T& content, T value) {
bool enabled); 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 _hasDepthAttachment = false;
bool _hasStencilAttachment = false; bool _hasStencilAttachment = false;
}; };
#pragma mark - #pragma mark -
#pragma mark MVKStencilReferenceValueCommandEncoderState #pragma mark MVKRenderingCommandEncoderState
/** Holds encoder state established by stencil reference values commands. */ struct MVKDepthBias {
class MVKStencilReferenceValueCommandEncoderState : public MVKCommandEncoderState { float depthBiasConstantFactor;
float depthBiasSlopeFactor;
public: float depthBiasClamp;
/** 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 MVKStencilReference {
uint32_t frontFaceValue;
uint32_t backFaceValue;
};
#pragma mark - struct MVKMTLViewports {
#pragma mark MVKDepthBiasCommandEncoderState MTLViewport viewports[kMVKMaxViewportScissorCount];
uint32_t viewportCount;
};
/** Holds encoder state established by depth bias commands. */ struct MVKMTLScissors {
class MVKDepthBiasCommandEncoderState : public MVKCommandEncoderState { MTLScissorRect scissors[kMVKMaxViewportScissorCount];
uint32_t scissorCount;
};
/** Holds encoder state established by various rendering state commands. */
class MVKRenderingCommandEncoderState : public MVKCommandEncoderState {
public: 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(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 setStencilReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo);
void setDepthBias(float depthBiasConstantFactor, void setStencilReferenceValues(VkStencilFaceFlags faceMask, uint32_t stencilReference);
float depthBiasSlopeFactor,
float depthBiasClamp);
/** Constructs this instance for the specified command encoder. */ void setViewports(const MVKArrayRef<VkViewport> viewports, uint32_t firstViewport, bool isDynamic);
MVKDepthBiasCommandEncoderState(MVKCommandEncoder* cmdEncoder) void setScissors(const MVKArrayRef<VkRect2D> scissors, uint32_t firstScissor, bool isDynamic);
: MVKCommandEncoderState(cmdEncoder) {}
void setRasterizerDiscardEnable(VkBool32 rasterizerDiscardEnable, bool isDynamic);
void beginMetalRenderPass() override;
MVKRenderingCommandEncoderState(MVKCommandEncoder* cmdEncoder) : MVKCommandEncoderState(cmdEncoder) {}
protected: protected:
void encodeImpl(uint32_t stage) override; 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; MVKMTLViewports _mtlViewports[StateScope::Count] = {};
float _depthBiasClamp = 0; MVKMTLScissors _mtlScissors[StateScope::Count] = {};
float _depthBiasSlopeFactor = 0; MVKColor32 _mtlBlendConstants[StateScope::Count] = {};
bool _isEnabled = false; MVKDepthBias _mtlDepthBias[StateScope::Count] = {};
}; MVKStencilReference _mtlStencilReference[StateScope::Count] = {};
MTLCullMode _mtlCullMode[StateScope::Count] = { MTLCullModeNone, MTLCullModeNone };
MTLWinding _mtlFrontFace[StateScope::Count] = { MTLWindingClockwise, MTLWindingClockwise };
#pragma mark - MTLPrimitiveType _mtlPrimitiveTopology[StateScope::Count] = { MTLPrimitiveTypePoint, MTLPrimitiveTypePoint };
#pragma mark MVKBlendColorCommandEncoderState MTLDepthClipMode _mtlDepthClipEnable[StateScope::Count] = { MTLDepthClipModeClip, MTLDepthClipModeClip };
MTLTriangleFillMode _mtlPolygonMode[StateScope::Count] = { MTLTriangleFillModeFill, MTLTriangleFillModeFill };
/** Holds encoder state established by blend color commands. */ MVKRenderStateFlags _dirtyStates;
class MVKBlendColorCommandEncoderState : public MVKCommandEncoderState { MVKRenderStateFlags _modifiedStates;
bool _mtlDepthBiasEnable[StateScope::Count] = {};
public: bool _mtlRasterizerDiscardEnable[StateScope::Count] = {};
bool _cullBothFaces[StateScope::Count] = {};
/** 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;
}; };

View File

@ -25,13 +25,21 @@
using namespace std; using namespace std;
#define shouldUpdateFace(face) mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_##face##_BIT)
#pragma mark - #pragma mark -
#pragma mark MVKCommandEncoderState #pragma mark MVKCommandEncoderState
MVKVulkanAPIObject* MVKCommandEncoderState::getVulkanAPIObject() { return _cmdEncoder->getVulkanAPIObject(); }; MVKVulkanAPIObject* MVKCommandEncoderState::getVulkanAPIObject() { return _cmdEncoder->getVulkanAPIObject(); };
MVKDevice* MVKCommandEncoderState::getDevice() { return _cmdEncoder->getDevice(); } 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 -
#pragma mark MVKPipelineCommandEncoderState #pragma mark MVKPipelineCommandEncoderState
@ -52,108 +60,19 @@ void MVKPipelineCommandEncoderState::encodeImpl(uint32_t stage) {
#pragma mark - #pragma mark -
#pragma mark MVKViewportCommandEncoderState #pragma mark MVKGraphicsPipelineCommandEncoderState
void MVKViewportCommandEncoderState::setViewports(MVKArrayRef<const VkViewport> viewports, void MVKGraphicsPipelineCommandEncoderState::bindPipeline(MVKPipeline* pipeline) {
uint32_t firstViewport, MVKPipelineCommandEncoderState::bindPipeline(pipeline);
bool isSettingDynamically) { _patchControlPoints[StateScope::Static] = getGraphicsPipeline()->_tessInfo.patchControlPoints;
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);
} }
bool dirty; void MVKGraphicsPipelineCommandEncoderState::setPatchControlPoints(uint32_t patchControlPoints) {
bool mustSetDynamically = _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_VIEWPORT); _patchControlPoints[StateScope::Dynamic] = patchControlPoints;
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();
} }
if (dirty) markDirty(); uint32_t MVKGraphicsPipelineCommandEncoderState::getPatchControlPoints() {
} return getContent(_patchControlPoints, PatchControlPoints);
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]))];
}
} }
@ -245,7 +164,7 @@ void MVKPushConstantsCommandEncoderState::encodeImpl(uint32_t stage) {
} }
bool MVKPushConstantsCommandEncoderState::isTessellating() { bool MVKPushConstantsCommandEncoderState::isTessellating() {
MVKGraphicsPipeline* gp = (MVKGraphicsPipeline*)_cmdEncoder->_graphicsPipelineState.getPipeline(); auto* gp = _cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
return gp ? gp->isTessellationPipeline() : false; return gp ? gp->isTessellationPipeline() : false;
} }
@ -254,74 +173,84 @@ bool MVKPushConstantsCommandEncoderState::isTessellating() {
#pragma mark MVKDepthStencilCommandEncoderState #pragma mark MVKDepthStencilCommandEncoderState
void MVKDepthStencilCommandEncoderState:: setDepthStencilState(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) { 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) { auto& dsData = _depthStencilData[StateScope::Static];
_depthStencilData.depthCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(vkDepthStencilInfo.depthCompareOp); auto oldData = dsData;
_depthStencilData.depthWriteEnabled = vkDepthStencilInfo.depthWriteEnable; dsData.depthCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(vkDepthStencilInfo.depthCompareOp);
} else { dsData.depthWriteEnabled = vkDepthStencilInfo.depthWriteEnable;
_depthStencilData.depthCompareFunction = kMVKMTLDepthStencilDescriptorDataDefault.depthCompareFunction;
_depthStencilData.depthWriteEnabled = kMVKMTLDepthStencilDescriptorDataDefault.depthWriteEnabled; 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); void MVKDepthStencilCommandEncoderState::setStencilState(MVKMTLStencilDescriptorData& sData,
setStencilState(_depthStencilData.backFaceStencilData, vkDepthStencilInfo.back, vkDepthStencilInfo.stencilTestEnable); const VkStencilOpState& vkStencil) {
sData.readMask = vkStencil.compareMask;
if (!(oldData == _depthStencilData)) markDirty(); 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, void MVKDepthStencilCommandEncoderState::setDepthTestEnable(VkBool32 depthTestEnable) {
const VkStencilOpState& vkStencil, setContent(_depthTestEnabled[StateScope::Dynamic], static_cast<bool>(depthTestEnable));
bool enabled) {
if ( !enabled ) {
stencilInfo = kMVKMTLStencilDescriptorDataDefault;
return;
} }
stencilInfo.enabled = true; void MVKDepthStencilCommandEncoderState::setDepthWriteEnable(VkBool32 depthWriteEnable) {
stencilInfo.stencilCompareFunction = mvkMTLCompareFunctionFromVkCompareOp(vkStencil.compareOp); setContent(_depthStencilData[StateScope::Dynamic].depthWriteEnabled, static_cast<bool>(depthWriteEnable));
stencilInfo.stencilFailureOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.failOp); }
stencilInfo.depthFailureOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.depthFailOp);
stencilInfo.depthStencilPassOperation = mvkMTLStencilOperationFromVkStencilOp(vkStencil.passOp); void MVKDepthStencilCommandEncoderState::setDepthCompareOp(VkCompareOp depthCompareOp) {
setContent(_depthStencilData[StateScope::Dynamic].depthCompareFunction,
if ( !_cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) ) { (uint8_t)mvkMTLCompareFunctionFromVkCompareOp(depthCompareOp));
stencilInfo.readMask = vkStencil.compareMask; }
}
if ( !_cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK) ) { void MVKDepthStencilCommandEncoderState::setStencilTestEnable(VkBool32 stencilTestEnable) {
stencilInfo.writeMask = vkStencil.writeMask; 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, void MVKDepthStencilCommandEncoderState::setStencilCompareMask(VkStencilFaceFlags faceMask,
uint32_t stencilCompareMask) { uint32_t stencilCompareMask) {
auto oldData = _depthStencilData; auto& dsData = _depthStencilData[StateScope::Dynamic];
if (shouldUpdateFace(FRONT)) { setContent(dsData.frontFaceStencilData.readMask, stencilCompareMask); }
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_FRONT_BIT)) { if (shouldUpdateFace(BACK)) { setContent(dsData.backFaceStencilData.readMask, stencilCompareMask); }
_depthStencilData.frontFaceStencilData.readMask = stencilCompareMask;
}
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_BACK_BIT)) {
_depthStencilData.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, void MVKDepthStencilCommandEncoderState::setStencilWriteMask(VkStencilFaceFlags faceMask,
uint32_t stencilWriteMask) { uint32_t stencilWriteMask) {
auto oldData = _depthStencilData; auto& dsData = _depthStencilData[StateScope::Dynamic];
if (shouldUpdateFace(FRONT)) { setContent(dsData.frontFaceStencilData.writeMask, stencilWriteMask); }
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_FRONT_BIT)) { if (shouldUpdateFace(BACK)) { setContent(dsData.backFaceStencilData.writeMask, stencilWriteMask); }
_depthStencilData.frontFaceStencilData.writeMask = stencilWriteMask;
}
if (mvkAreAllFlagsEnabled(faceMask, VK_STENCIL_FACE_BACK_BIT)) {
_depthStencilData.backFaceStencilData.writeMask = stencilWriteMask;
}
if (!(oldData == _depthStencilData)) markDirty();
} }
void MVKDepthStencilCommandEncoderState::beginMetalRenderPass() { void MVKDepthStencilCommandEncoderState::beginMetalRenderPass() {
@ -337,130 +266,255 @@ void MVKDepthStencilCommandEncoderState::beginMetalRenderPass() {
if (_hasStencilAttachment != prevHasStencilAttachment) { markDirty(); } if (_hasStencilAttachment != prevHasStencilAttachment) { markDirty(); }
} }
// Combine static and dynamic depth/stencil data
void MVKDepthStencilCommandEncoderState::encodeImpl(uint32_t stage) { 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; } 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 -
#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; void MVKRenderingCommandEncoderState::setCullMode(VkCullModeFlags cullMode, bool isDynamic) {
_isEnabled = vkRasterInfo.depthBiasEnable; 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. void MVKRenderingCommandEncoderState::setFrontFace(VkFrontFace frontFace, bool isDynamic) {
if (_cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS)) { return; } auto mtlFrontFace = mvkMTLWindingFromVkFrontFace(frontFace);
setContent(FrontFace);
}
if (_isEnabled != wasEnabled || _depthBiasConstantFactor != vkRasterInfo.depthBiasConstantFactor void MVKRenderingCommandEncoderState::setPrimitiveTopology(VkPrimitiveTopology topology, bool isDynamic) {
|| _depthBiasSlopeFactor != vkRasterInfo.depthBiasSlopeFactor || _depthBiasClamp != vkRasterInfo.depthBiasClamp) { auto mtlPrimitiveTopology = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(topology);
setContent(PrimitiveTopology);
}
markDirty(); MTLPrimitiveType MVKRenderingCommandEncoderState::getPrimitiveType() {
_depthBiasConstantFactor = vkRasterInfo.depthBiasConstantFactor; return getContent(PrimitiveTopology);
_depthBiasSlopeFactor = vkRasterInfo.depthBiasSlopeFactor; }
_depthBiasClamp = vkRasterInfo.depthBiasClamp;
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, void MVKRenderingCommandEncoderState::setPolygonMode(VkPolygonMode polygonMode, bool isDynamic) {
// it may not be accurate, and if not dynamic, pipeline will override when it is encoded anyway. auto mtlPolygonMode = mvkMTLTriangleFillModeFromVkPolygonMode(polygonMode);
void MVKDepthBiasCommandEncoderState::setDepthBias(float depthBiasConstantFactor, 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 depthBiasSlopeFactor,
float depthBiasClamp) { float depthBiasClamp) {
bool isDynamic = true;
if (_depthBiasConstantFactor != depthBiasConstantFactor || _depthBiasSlopeFactor != depthBiasSlopeFactor MVKDepthBias mtlDepthBias = {
|| _depthBiasClamp != depthBiasClamp) { .depthBiasConstantFactor = depthBiasConstantFactor,
.depthBiasSlopeFactor = depthBiasSlopeFactor,
markDirty(); .depthBiasClamp = depthBiasClamp
_depthBiasConstantFactor = depthBiasConstantFactor; };
_depthBiasSlopeFactor = depthBiasSlopeFactor; setContent(DepthBias);
_depthBiasClamp = depthBiasClamp;
}
} }
void MVKDepthBiasCommandEncoderState::encodeImpl(uint32_t stage) { void MVKRenderingCommandEncoderState::setDepthBiasEnable(VkBool32 depthBiasEnable) {
if (stage != kMVKGraphicsStageRasterization) { return; } bool isDynamic = true;
if (_isEnabled) { bool mtlDepthBiasEnable = static_cast<bool>(depthBiasEnable);
[_cmdEncoder->_mtlRenderEncoder setDepthBias: _depthBiasConstantFactor setContent(DepthBiasEnable);
slopeScale: _depthBiasSlopeFactor
clamp: _depthBiasClamp];
} else {
[_cmdEncoder->_mtlRenderEncoder setDepthBias: 0 slopeScale: 0 clamp: 0];
}
} }
void MVKRenderingCommandEncoderState::setDepthClipEnable(bool depthClip, bool isDynamic) {
auto mtlDepthClipEnable = depthClip ? MTLDepthClipModeClip : MTLDepthClipModeClamp;
setContent(DepthClipEnable);
}
#pragma mark - void MVKRenderingCommandEncoderState::setStencilReferenceValues(const VkPipelineDepthStencilStateCreateInfo& vkDepthStencilInfo) {
#pragma mark MVKBlendColorCommandEncoderState bool isDynamic = false;
MVKStencilReference mtlStencilReference = {
.frontFaceValue = vkDepthStencilInfo.front.reference,
.backFaceValue = vkDepthStencilInfo.back.reference
};
setContent(StencilReference);
}
void MVKBlendColorCommandEncoderState::setBlendColor(float red, float green, void MVKRenderingCommandEncoderState::setStencilReferenceValues(VkStencilFaceFlags faceMask, uint32_t stencilReference) {
float blue, float alpha, 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) { bool isDynamic) {
// Abort if we are using dynamic, but call is not dynamic. uint32_t maxViewports = getDevice()->_pProperties->limits.maxViewports;
if ( !isDynamic && _cmdEncoder->supportsDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS) ) { return; } if (firstViewport >= maxViewports) { return; }
if (_red != red || _green != green || _blue != blue || _alpha != alpha) { MVKMTLViewports mtlViewports = isDynamic ? _mtlViewports[StateScope::Dynamic] : _mtlViewports[StateScope::Static];
markDirty(); size_t vpCnt = min((uint32_t)viewports.size(), maxViewports - firstViewport);
_red = red; for (uint32_t vpIdx = 0; vpIdx < vpCnt; vpIdx++) {
_green = green; mtlViewports.viewports[firstViewport + vpIdx] = mvkMTLViewportFromVkViewport(viewports[vpIdx]);
_blue = blue; mtlViewports.viewportCount = max(mtlViewports.viewportCount, vpIdx + 1);
_alpha = alpha;
} }
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; } 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) { void MVKGraphicsResourcesCommandEncoderState::encodeImpl(uint32_t stage) {
MVKGraphicsPipeline* pipeline = (MVKGraphicsPipeline*)getPipeline(); auto* pipeline = _cmdEncoder->_graphicsPipelineState.getGraphicsPipeline();
bool fullImageViewSwizzle = pipeline->fullImageViewSwizzle() || getDevice()->_pMetalFeatures->nativeTextureSwizzle; bool fullImageViewSwizzle = pipeline->fullImageViewSwizzle() || getDevice()->_pMetalFeatures->nativeTextureSwizzle;
bool forTessellation = pipeline->isTessellationPipeline(); bool forTessellation = pipeline->isTessellationPipeline();
bool isDynamicVertexStride = pipeline->isDynamicState(VertexStride);
if (stage == kMVKGraphicsStageVertex) { if (stage == kMVKGraphicsStageVertex) {
encodeBindings(kMVKShaderStageVertex, "vertex", fullImageViewSwizzle, encodeBindings(kMVKShaderStageVertex, "vertex", fullImageViewSwizzle,
@ -812,33 +871,24 @@ void MVKGraphicsResourcesCommandEncoderState::encodeImpl(uint32_t stage) {
} else if (!forTessellation && stage == kMVKGraphicsStageRasterization) { } else if (!forTessellation && stage == kMVKGraphicsStageRasterization) {
encodeBindings(kMVKShaderStageVertex, "vertex", fullImageViewSwizzle, 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. // 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 // We must not bind those extra buffers to the shader because they might overwrite
// any implicit buffers used by the pipeline. // any implicit buffers used by the pipeline.
if (pipeline->isValidVertexBufferIndex(kMVKShaderStageVertex, b.index)) { if (pipeline->isValidVertexBufferIndex(kMVKShaderStageVertex, b.index)) {
if (b.isInline) { cmdEncoder->encodeVertexAttributeBuffer(b, isDynamicVertexStride);
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];
}
// Add any translated vertex bindings for this binding // Add any translated vertex bindings for this binding
if ( !b.isInline ) {
auto xltdVtxBindings = pipeline->getTranslatedVertexBindings(); auto xltdVtxBindings = pipeline->getTranslatedVertexBindings();
for (auto& xltdBind : xltdVtxBindings) { for (auto& xltdBind : xltdVtxBindings) {
if (b.index == pipeline->getMetalBufferIndexForVertexAttributeBinding(xltdBind.binding)) { if (b.index == pipeline->getMetalBufferIndexForVertexAttributeBinding(xltdBind.binding)) {
[cmdEncoder->_mtlRenderEncoder setVertexBuffer: b.mtlBuffer MVKMTLBufferBinding bx = {
offset: b.offset + xltdBind.translationOffset .mtlBuffer = b.mtlBuffer,
atIndex: pipeline->getMetalBufferIndexForVertexAttributeBinding(xltdBind.translationBinding)]; .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) { if (forTessellation && stage == kMVKGraphicsStageRasterization) {
encodeBindings(kMVKShaderStageTessEval, "tessellation evaluation", fullImageViewSwizzle, encodeBindings(kMVKShaderStageTessEval, "tessellation evaluation", fullImageViewSwizzle,
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void { [isDynamicVertexStride](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b)->void {
if (b.isInline) cmdEncoder->encodeVertexAttributeBuffer(b, isDynamicVertexStride);
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];
}, },
[](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b, MVKArrayRef<const uint32_t> s)->void { [](MVKCommandEncoder* cmdEncoder, MVKMTLBufferBinding& b, MVKArrayRef<const uint32_t> s)->void {
cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder, cmdEncoder->setVertexBytes(cmdEncoder->_mtlRenderEncoder,

View File

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

View File

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

View File

@ -433,9 +433,10 @@ id<MTLDepthStencilState> MVKCommandResourceFactory::newMTLDepthStencilState(bool
} }
id<MTLDepthStencilState> MVKCommandResourceFactory::newMTLDepthStencilState(MVKMTLDepthStencilDescriptorData& dsData) { id<MTLDepthStencilState> MVKCommandResourceFactory::newMTLDepthStencilState(MVKMTLDepthStencilDescriptorData& dsData) {
MTLStencilDescriptor* fsDesc = newMTLStencilDescriptor(dsData.frontFaceStencilData); // temp retain bool testStencil = dsData.stencilTestEnabled;
MTLStencilDescriptor* bsDesc = newMTLStencilDescriptor(dsData.backFaceStencilData); // temp retain auto* fsDesc = testStencil ? newMTLStencilDescriptor(dsData.frontFaceStencilData) : nil; // temp retain
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new]; // temp retain auto* bsDesc = testStencil ? newMTLStencilDescriptor(dsData.backFaceStencilData) : nil; // temp retain
auto* dsDesc = [MTLDepthStencilDescriptor new]; // temp retain
dsDesc.depthCompareFunction = (MTLCompareFunction)dsData.depthCompareFunction; dsDesc.depthCompareFunction = (MTLCompareFunction)dsData.depthCompareFunction;
dsDesc.depthWriteEnabled = dsData.depthWriteEnabled; dsDesc.depthWriteEnabled = dsData.depthWriteEnabled;
dsDesc.frontFaceStencil = fsDesc; dsDesc.frontFaceStencil = fsDesc;
@ -451,8 +452,6 @@ id<MTLDepthStencilState> MVKCommandResourceFactory::newMTLDepthStencilState(MVKM
} }
MTLStencilDescriptor* MVKCommandResourceFactory::newMTLStencilDescriptor(MVKMTLStencilDescriptorData& sData) { MTLStencilDescriptor* MVKCommandResourceFactory::newMTLStencilDescriptor(MVKMTLStencilDescriptorData& sData) {
if ( !sData.enabled ) { return nil; }
MTLStencilDescriptor* sDesc = [MTLStencilDescriptor new]; // retained MTLStencilDescriptor* sDesc = [MTLStencilDescriptor new]; // retained
sDesc.stencilCompareFunction = (MTLCompareFunction)sData.stencilCompareFunction; sDesc.stencilCompareFunction = (MTLCompareFunction)sData.stencilCompareFunction;
sDesc.stencilFailureOperation = (MTLStencilOperation)sData.stencilFailureOperation; 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(BindDescriptorSetsDynamic, 4)
MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetViewport, 1) MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetViewport, 1)
MVK_CMD_TYPE_POOLS_FROM_THRESHOLD(SetScissor, 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(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(SetStencilCompareMask)
MVK_CMD_TYPE_POOL(SetStencilWriteMask) MVK_CMD_TYPE_POOL(SetStencilWriteMask)
MVK_CMD_TYPE_POOL(SetStencilReference) 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_POOLS_FROM_2_THRESHOLDS(BindVertexBuffers, 1, 2)
MVK_CMD_TYPE_POOL(BindIndexBuffer) MVK_CMD_TYPE_POOL(BindIndexBuffer)
MVK_CMD_TYPE_POOL(Draw) 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 union { id<MTLBuffer> mtlBuffer = nil; id<MTLBuffer> mtlResource; const void* mtlBytes; }; // aliases
VkDeviceSize offset = 0; VkDeviceSize offset = 0;
uint32_t size = 0; uint32_t size = 0;
uint32_t stride = 0;
uint16_t index = 0; uint16_t index = 0;
bool justOffset = false; bool justOffset = false;
bool isDirty = true; bool isDirty = true;
@ -78,14 +79,16 @@ typedef struct MVKMTLBufferBinding {
void update(const MVKMTLBufferBinding &other) { void update(const MVKMTLBufferBinding &other) {
if (mtlBuffer != other.mtlBuffer || size != other.size || other.isInline) { if (mtlBuffer != other.mtlBuffer || size != other.size || other.isInline) {
mtlBuffer = other.mtlBuffer; mtlBuffer = other.mtlBuffer;
size = other.size;
isInline = other.isInline;
offset = other.offset; offset = other.offset;
size = other.size;
stride = other.stride;
isInline = other.isInline;
justOffset = false; justOffset = false;
isOverridden = false; isOverridden = false;
isDirty = true; isDirty = true;
} else if (offset != other.offset) { } else if (offset != other.offset || stride != other.stride) {
offset = other.offset; offset = other.offset;
stride = other.stride;
justOffset = !isOverridden && (!isDirty || justOffset); justOffset = !isOverridden && (!isDirty || justOffset);
isOverridden = false; isOverridden = false;
isDirty = true; isDirty = true;

View File

@ -387,6 +387,18 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
formatFeatures->formatA4B4G4R4 = canSupport4444; formatFeatures->formatA4B4G4R4 = canSupport4444;
break; 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: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: {
auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next; auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next;
interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups; interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups;
@ -1696,10 +1708,11 @@ void MVKPhysicalDevice::initMetalFeatures() {
_metalFeatures.minSwapchainImageCount = kMVKMinSwapchainImageCount; _metalFeatures.minSwapchainImageCount = kMVKMinSwapchainImageCount;
_metalFeatures.maxSwapchainImageCount = kMVKMaxSwapchainImageCount; _metalFeatures.maxSwapchainImageCount = kMVKMaxSwapchainImageCount;
_metalFeatures.vertexStrideAlignment = 4;
_metalFeatures.maxPerStageStorageTextureCount = 8; _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 // GPU-specific features
switch (_properties.vendorID) { switch (_properties.vendorID) {
case kAMDVendorId: case kAMDVendorId:
@ -2411,7 +2424,7 @@ void MVKPhysicalDevice::initLimits() {
_properties.limits.maxVertexInputAttributes = 31; _properties.limits.maxVertexInputAttributes = 31;
_properties.limits.maxVertexInputBindings = 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.maxVertexInputAttributeOffset = _properties.limits.maxVertexInputBindingStride - 1;
_properties.limits.maxPerStageDescriptorSamplers = _metalFeatures.maxPerStageSamplerCount; _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(FragmentShaderBarycentric, FRAGMENT_SHADER_BARYCENTRIC, KHR, 1)
MVK_DEVICE_FEATURE_EXTN(PortabilitySubset, PORTABILITY_SUBSET, KHR, 15) MVK_DEVICE_FEATURE_EXTN(PortabilitySubset, PORTABILITY_SUBSET, KHR, 15)
MVK_DEVICE_FEATURE_EXTN(4444Formats, 4444_FORMATS, EXT, 2) 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(FragmentShaderInterlock, FRAGMENT_SHADER_INTERLOCK, EXT, 3)
MVK_DEVICE_FEATURE_EXTN(PipelineCreationCacheControl, PIPELINE_CREATION_CACHE_CONTROL, EXT, 1) MVK_DEVICE_FEATURE_EXTN(PipelineCreationCacheControl, PIPELINE_CREATION_CACHE_CONTROL, EXT, 1)
MVK_DEVICE_FEATURE_EXTN(Robustness2, ROBUSTNESS_2, EXT, 3) 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(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(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(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(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(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(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(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(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(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(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(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(vkCmdSetStencilOp, EXT, EXT_EXTENDED_DYNAMIC_STATE);
ADD_DVC_1_3_PROMOTED_ENTRY_POINT(vkCmdSetStencilTestEnable, 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(vkReleaseSwapchainImagesEXT, EXT_SWAPCHAIN_MAINTENANCE_1);
ADD_DVC_EXT_ENTRY_POINT(vkGetRefreshCycleDurationGOOGLE, GOOGLE_DISPLAY_TIMING); ADD_DVC_EXT_ENTRY_POINT(vkGetRefreshCycleDurationGOOGLE, GOOGLE_DISPLAY_TIMING);
ADD_DVC_EXT_ENTRY_POINT(vkGetPastPresentationTimingGOOGLE, 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() { void MVKInstance::logVersions() {

View File

@ -218,6 +218,49 @@ struct MVKStagedDescriptorBindingUse {
MVKBitArray stages[4] = {}; 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. */ /** Represents an Vulkan graphics pipeline. */
class MVKGraphicsPipeline : public MVKPipeline { class MVKGraphicsPipeline : public MVKPipeline {
@ -229,15 +272,12 @@ public:
/** Binds this pipeline to the specified command encoder. */ /** Binds this pipeline to the specified command encoder. */
void encode(MVKCommandEncoder* cmdEncoder, uint32_t stage = 0) override; void encode(MVKCommandEncoder* cmdEncoder, uint32_t stage = 0) override;
/** Returns whether this pipeline permits dynamic setting of the specifie state. */ /** Returns whether this pipeline permits dynamic setting of the state. */
bool supportsDynamicState(VkDynamicState state); bool isDynamicState(MVKRenderStateType state) { return _dynamicState.isEnabled(state); }
/** Returns whether this pipeline has tessellation shaders. */ /** Returns whether this pipeline has tessellation shaders. */
bool isTessellationPipeline() { return _tessInfo.patchControlPoints > 0; } 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. */ /** Returns the number of output tessellation patch control points. */
uint32_t getOutputControlPointCount() { return _outputControlPointCount; } uint32_t getOutputControlPointCount() { return _outputControlPointCount; }
@ -313,6 +353,8 @@ public:
~MVKGraphicsPipeline() override; ~MVKGraphicsPipeline() override;
protected: protected:
friend class MVKGraphicsPipelineCommandEncoderState;
typedef MVKSmallVector<SPIRVShaderInterfaceVariable, 32> SPIRVShaderOutputs; typedef MVKSmallVector<SPIRVShaderInterfaceVariable, 32> SPIRVShaderOutputs;
typedef MVKSmallVector<SPIRVShaderInterfaceVariable, 32> SPIRVShaderInputs; typedef MVKSmallVector<SPIRVShaderInterfaceVariable, 32> SPIRVShaderInputs;
@ -320,6 +362,7 @@ protected:
id<MTLComputePipelineState> getOrCompilePipeline(MTLComputePipelineDescriptor* plDesc, id<MTLComputePipelineState>& plState, const char* compilerType); id<MTLComputePipelineState> getOrCompilePipeline(MTLComputePipelineDescriptor* plDesc, id<MTLComputePipelineState>& plState, const char* compilerType);
bool compileTessVertexStageState(MTLComputePipelineDescriptor* vtxPLDesc, MVKMTLFunction* pVtxFunctions, VkPipelineCreationFeedback* pVertexFB); bool compileTessVertexStageState(MTLComputePipelineDescriptor* vtxPLDesc, MVKMTLFunction* pVtxFunctions, VkPipelineCreationFeedback* pVertexFB);
bool compileTessControlStageState(MTLComputePipelineDescriptor* tcPLDesc, VkPipelineCreationFeedback* pTessCtlFB); bool compileTessControlStageState(MTLComputePipelineDescriptor* tcPLDesc, VkPipelineCreationFeedback* pTessCtlFB);
void initDynamicState(const VkGraphicsPipelineCreateInfo* pCreateInfo);
void initCustomSamplePositions(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 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); void initShaderConversionConfig(SPIRVToMSLConversionConfiguration& shaderConfig, const VkGraphicsPipelineCreateInfo* pCreateInfo, const SPIRVTessReflectionData& reflectData);
@ -356,10 +399,10 @@ protected:
VkPipelineTessellationStateCreateInfo _tessInfo; VkPipelineTessellationStateCreateInfo _tessInfo;
VkPipelineRasterizationStateCreateInfo _rasterInfo; VkPipelineRasterizationStateCreateInfo _rasterInfo;
VkPipelineDepthStencilStateCreateInfo _depthStencilInfo; VkPipelineDepthStencilStateCreateInfo _depthStencilInfo;
MVKRenderStateFlags _dynamicState;
MVKSmallVector<VkViewport, kMVKMaxViewportScissorCount> _viewports; MVKSmallVector<VkViewport, kMVKMaxViewportScissorCount> _viewports;
MVKSmallVector<VkRect2D, kMVKMaxViewportScissorCount> _scissors; MVKSmallVector<VkRect2D, kMVKMaxViewportScissorCount> _scissors;
MVKSmallVector<VkDynamicState> _dynamicState;
MVKSmallVector<MTLSamplePosition> _customSamplePositions; MVKSmallVector<MTLSamplePosition> _customSamplePositions;
MVKSmallVector<MVKTranslatedVertexBinding> _translatedVertexBindings; MVKSmallVector<MVKTranslatedVertexBinding> _translatedVertexBindings;
MVKSmallVector<MVKZeroDivisorVertexBinding> _zeroDivisorVertexBindings; MVKSmallVector<MVKZeroDivisorVertexBinding> _zeroDivisorVertexBindings;
@ -374,11 +417,7 @@ protected:
id<MTLComputePipelineState> _mtlTessControlStageState = nil; id<MTLComputePipelineState> _mtlTessControlStageState = nil;
id<MTLRenderPipelineState> _mtlPipelineState = nil; id<MTLRenderPipelineState> _mtlPipelineState = nil;
float _blendConstants[4] = { 0.0, 0.0, 0.0, 1.0 }; float _blendConstants[4] = {};
MTLCullMode _mtlCullMode;
MTLWinding _mtlFrontWinding;
MTLTriangleFillMode _mtlFillMode;
MTLDepthClipMode _mtlDepthClipMode;
MVKShaderImplicitRezBinding _reservedVertexAttributeBufferCount; MVKShaderImplicitRezBinding _reservedVertexAttributeBufferCount;
MVKShaderImplicitRezBinding _viewRangeBufferIndex; MVKShaderImplicitRezBinding _viewRangeBufferIndex;
MVKShaderImplicitRezBinding _outputBufferIndex; MVKShaderImplicitRezBinding _outputBufferIndex;
@ -387,6 +426,7 @@ protected:
uint32_t _tessCtlPatchOutputBufferIndex = 0; uint32_t _tessCtlPatchOutputBufferIndex = 0;
uint32_t _tessCtlLevelBufferIndex = 0; uint32_t _tessCtlLevelBufferIndex = 0;
bool _hasRasterInfo = false;
bool _needsVertexSwizzleBuffer = false; bool _needsVertexSwizzleBuffer = false;
bool _needsVertexBufferSizeBuffer = false; bool _needsVertexBufferSizeBuffer = false;
bool _needsVertexDynamicOffsetBuffer = 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 // Depth stencil state - Cleared _depthStencilInfo values will disable depth testing
cmdEncoder->_depthStencilState.setDepthStencilState(_depthStencilInfo); cmdEncoder->_depthStencilState.setDepthStencilState(_depthStencilInfo);
cmdEncoder->_stencilReferenceValueState.setReferenceValues(_depthStencilInfo);
// Rasterization // Rasterization
cmdEncoder->_blendColorState.setBlendColor(_blendConstants[0], _blendConstants[1], cmdEncoder->_renderingState.setPrimitiveTopology(_vkPrimitiveTopology, false);
_blendConstants[2], _blendConstants[3], false); cmdEncoder->_renderingState.setBlendConstants(_blendConstants, false);
cmdEncoder->_depthBiasState.setDepthBias(_rasterInfo); cmdEncoder->_renderingState.setStencilReferenceValues(_depthStencilInfo);
cmdEncoder->_viewportState.setViewports(_viewports.contents(), 0, false); cmdEncoder->_renderingState.setViewports(_viewports.contents(), 0, false);
cmdEncoder->_scissorState.setScissors(_scissors.contents(), 0, false); cmdEncoder->_renderingState.setScissors(_scissors.contents(), 0, false);
cmdEncoder->_mtlPrimitiveType = mvkMTLPrimitiveTypeFromVkPrimitiveTopology(_vkPrimitiveTopology); if (_hasRasterInfo) {
cmdEncoder->_renderingState.setCullMode(_rasterInfo.cullMode, false);
[mtlCmdEnc setCullMode: _mtlCullMode]; cmdEncoder->_renderingState.setFrontFace(_rasterInfo.frontFace, false);
[mtlCmdEnc setFrontFacingWinding: _mtlFrontWinding]; cmdEncoder->_renderingState.setPolygonMode(_rasterInfo.polygonMode, false);
[mtlCmdEnc setTriangleFillMode: _mtlFillMode]; cmdEncoder->_renderingState.setDepthBias(_rasterInfo);
cmdEncoder->_renderingState.setDepthClipEnable( !_rasterInfo.depthClampEnable, false );
if (_device->_enabledFeatures.depthClamp) {
[mtlCmdEnc setDepthClipMode: _mtlDepthClipMode];
} }
break; break;
} }
@ -320,21 +316,6 @@ void MVKGraphicsPipeline::encode(MVKCommandEncoder* cmdEncoder, uint32_t stage)
cmdEncoder->_graphicsResourcesState.bindViewRangeBuffer(_viewRangeBufferIndex, _needsVertexViewRangeBuffer, _needsFragmentViewRangeBuffer); 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"; static const char vtxCompilerType[] = "Vertex stage pipeline for tessellation";
bool MVKGraphicsPipeline::compileTessVertexStageState(MTLComputePipelineDescriptor* vtxPLDesc, bool MVKGraphicsPipeline::compileTessVertexStageState(MTLComputePipelineDescriptor* vtxPLDesc,
@ -414,6 +395,10 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
const VkGraphicsPipelineCreateInfo* pCreateInfo) : const VkGraphicsPipelineCreateInfo* pCreateInfo) :
MVKPipeline(device, pipelineCache, (MVKPipelineLayout*)pCreateInfo->layout, pCreateInfo->flags, parent) { 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. // Determine rasterization early, as various other structs are validated and interpreted in this context.
const VkPipelineRenderingCreateInfo* pRendInfo = getRenderingCreateInfo(pCreateInfo); const VkPipelineRenderingCreateInfo* pRendInfo = getRenderingCreateInfo(pCreateInfo);
_isRasterizing = !isRasterizationDisabled(pCreateInfo); _isRasterizing = !isRasterizationDisabled(pCreateInfo);
@ -509,17 +494,12 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
initMTLRenderPipelineState(pCreateInfo, reflectData, pPipelineFB, pVertexSS, pVertexFB, pTessCtlSS, pTessCtlFB, pTessEvalSS, pTessEvalFB, pFragmentSS, pFragmentFB); initMTLRenderPipelineState(pCreateInfo, reflectData, pPipelineFB, pVertexSS, pVertexFB, pTessCtlSS, pTessCtlFB, pTessEvalSS, pTessEvalFB, pFragmentSS, pFragmentFB);
if ( !_hasValidMTLPipelineStates ) { return; } 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 // Blending - must ignore allowed bad pColorBlendState pointer if rasterization disabled or no color attachments
if (_isRasterizingColor && pCreateInfo->pColorBlendState) { 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 // Topology
@ -527,24 +507,16 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
? pCreateInfo->pInputAssemblyState->topology ? pCreateInfo->pInputAssemblyState->topology
: VK_PRIMITIVE_TOPOLOGY_POINT_LIST); : 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 // Rasterization
_mtlCullMode = MTLCullModeNone; _hasRasterInfo = mvkSetOrClear(&_rasterInfo, pCreateInfo->pRasterizationState);
_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."));
}
}
}
// Must run after _isRasterizing and _dynamicState are populated // Must run after _isRasterizing and _dynamicState are populated
initCustomSamplePositions(pCreateInfo); initCustomSamplePositions(pCreateInfo);
@ -557,26 +529,81 @@ MVKGraphicsPipeline::MVKGraphicsPipeline(MVKDevice* device,
// Viewports and scissors - must ignore allowed bad pViewportState pointer if rasterization is disabled // Viewports and scissors - must ignore allowed bad pViewportState pointer if rasterization is disabled
auto pVPState = _isRasterizing ? pCreateInfo->pViewportState : nullptr; auto pVPState = _isRasterizing ? pCreateInfo->pViewportState : nullptr;
if (pVPState) { 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); _viewports.reserve(vpCnt);
for (uint32_t vpIdx = 0; vpIdx < vpCnt; vpIdx++) { for (uint32_t vpIdx = 0; vpIdx < vpCnt; vpIdx++) {
// If viewport is dyanamic, we still add a dummy so that the count will be tracked. _viewports.push_back(pVPState->pViewports[vpIdx]);
VkViewport vp;
if ( !supportsDynamicState(VK_DYNAMIC_STATE_VIEWPORT) ) { vp = pVPState->pViewports[vpIdx]; }
_viewports.push_back(vp);
} }
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); _scissors.reserve(sCnt);
for (uint32_t sIdx = 0; sIdx < sCnt; sIdx++) { for (uint32_t sIdx = 0; sIdx < sCnt; sIdx++) {
// If scissor is dyanamic, we still add a dummy so that the count will be tracked. _scissors.push_back(pVPState->pScissors[sIdx]);
VkRect2D sc;
if ( !supportsDynamicState(VK_DYNAMIC_STATE_SCISSOR) ) { sc = pVPState->pScissors[sIdx]; }
_scissors.push_back(sc);
} }
} }
} }
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. // Either returns an existing pipeline state or compiles a new one.
id<MTLRenderPipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLRenderPipelineDescriptor* plDesc, id<MTLRenderPipelineState> MVKGraphicsPipeline::getOrCompilePipeline(MTLRenderPipelineDescriptor* plDesc,
id<MTLRenderPipelineState>& plState) { id<MTLRenderPipelineState>& plState) {
@ -613,7 +640,7 @@ void MVKGraphicsPipeline::initCustomSamplePositions(const VkGraphicsPipelineCrea
case VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT: { case VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT: {
auto* pSampLocnsCreateInfo = (VkPipelineSampleLocationsStateCreateInfoEXT*)next; auto* pSampLocnsCreateInfo = (VkPipelineSampleLocationsStateCreateInfoEXT*)next;
_isUsingCustomSamplePositions = pSampLocnsCreateInfo->sampleLocationsEnable; _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++) { for (uint32_t slIdx = 0; slIdx < pSampLocnsCreateInfo->sampleLocationsInfo.sampleLocationsCount; slIdx++) {
auto& sl = pSampLocnsCreateInfo->sampleLocationsInfo.pSampleLocations[slIdx]; auto& sl = pSampLocnsCreateInfo->sampleLocationsInfo.pSampleLocations[slIdx];
_customSamplePositions.push_back(MTLSamplePositionMake(sl.x, sl.y)); _customSamplePositions.push_back(MTLSamplePositionMake(sl.x, sl.y));
@ -1311,6 +1338,10 @@ bool MVKGraphicsPipeline::addFragmentShaderToPipeline(MTLRenderPipelineDescripto
return true; return true;
} }
#if !MVK_XCODE_15
static const NSUInteger MTLBufferLayoutStrideDynamic = NSUIntegerMax;
#endif
template<class T> template<class T>
bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc, bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
const VkPipelineVertexInputStateCreateInfo* pVI, const VkPipelineVertexInputStateCreateInfo* pVI,
@ -1328,8 +1359,9 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
} }
// Vertex buffer bindings // Vertex buffer bindings
uint32_t vbCnt = pVI->vertexBindingDescriptionCount; bool isVtxStrideStatic = !isDynamicState(VertexStride);
uint32_t maxBinding = 0; uint32_t maxBinding = 0;
uint32_t vbCnt = pVI->vertexBindingDescriptionCount;
for (uint32_t i = 0; i < vbCnt; i++) { for (uint32_t i = 0; i < vbCnt; i++) {
const VkVertexInputBindingDescription* pVKVB = &pVI->pVertexBindingDescriptions[i]; const VkVertexInputBindingDescription* pVKVB = &pVI->pVertexBindingDescriptions[i];
if (shaderConfig.isVertexBufferUsed(pVKVB->binding)) { if (shaderConfig.isVertexBufferUsed(pVKVB->binding)) {
@ -1352,7 +1384,7 @@ bool MVKGraphicsPipeline::addVertexInputToPipeline(T* inputDesc,
vbDesc.stepFunction = (decltype(vbDesc.stepFunction))MTLStepFunctionConstant; vbDesc.stepFunction = (decltype(vbDesc.stepFunction))MTLStepFunctionConstant;
vbDesc.stepRate = 0; vbDesc.stepRate = 0;
} else { } else {
vbDesc.stride = pVKVB->stride; vbDesc.stride = isVtxStrideStatic ? pVKVB->stride : MTLBufferLayoutStrideDynamic;
vbDesc.stepFunction = (decltype(vbDesc.stepFunction))mvkMTLStepFunctionFromVkVertexInputRate(pVKVB->inputRate, isTessellationPipeline()); vbDesc.stepFunction = (decltype(vbDesc.stepFunction))mvkMTLStepFunctionFromVkVertexInputRate(pVKVB->inputRate, isTessellationPipeline());
vbDesc.stepRate = 1; vbDesc.stepRate = 1;
} }
@ -1903,11 +1935,12 @@ bool MVKGraphicsPipeline::isRenderingPoints(const VkGraphicsPipelineCreateInfo*
(pCreateInfo->pRasterizationState && (pCreateInfo->pRasterizationState->polygonMode == VK_POLYGON_MODE_POINT))); (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) { bool MVKGraphicsPipeline::isRasterizationDisabled(const VkGraphicsPipelineCreateInfo* pCreateInfo) {
return (pCreateInfo->pRasterizationState && return (pCreateInfo->pRasterizationState &&
(pCreateInfo->pRasterizationState->rasterizerDiscardEnable || ((pCreateInfo->pRasterizationState->rasterizerDiscardEnable && !isDynamicState(RasterizerDiscardEnable)) ||
((pCreateInfo->pRasterizationState->cullMode == VK_CULL_MODE_FRONT_AND_BACK) && pCreateInfo->pInputAssemblyState && ((pCreateInfo->pRasterizationState->cullMode == VK_CULL_MODE_FRONT_AND_BACK) && !isDynamicState(CullMode) &&
pCreateInfo->pInputAssemblyState &&
(mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(pCreateInfo->pInputAssemblyState->topology) == MTLPrimitiveTopologyClassTriangle)))); (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_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_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_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_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_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) 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 -
#pragma mark Vulkan support #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. */ /** Tracks the Vulkan command currently being used. */
typedef enum : uint8_t { typedef enum : uint8_t {
kMVKCommandUseNone = 0, /**< No use defined. */ 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. */ /** Returns whether the specified positive value is a power-of-two. */
template<typename T> template<typename T>
static constexpr bool mvkIsPowerOfTwo(T value) { 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 * 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. * 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 constexpr int32_t kMVKUndefinedLargePositiveInt32 = mvkEnsurePowerOfTwo(std::numeric_limits<int32_t>::max() / 2);
static int32_t kMVKUndefinedLargeNegativeInt32 = -kMVKUndefinedLargePositiveInt32; static constexpr int32_t kMVKUndefinedLargeNegativeInt32 = -kMVKUndefinedLargePositiveInt32;
static uint32_t kMVKUndefinedLargeUInt32 = kMVKUndefinedLargePositiveInt32; static constexpr uint32_t kMVKUndefinedLargeUInt32 = kMVKUndefinedLargePositiveInt32;
static int64_t kMVKUndefinedLargePositiveInt64 = mvkEnsurePowerOfTwo(std::numeric_limits<int64_t>::max() / 2); static constexpr int64_t kMVKUndefinedLargePositiveInt64 = mvkEnsurePowerOfTwo(std::numeric_limits<int64_t>::max() / 2);
static int64_t kMVKUndefinedLargeNegativeInt64 = -kMVKUndefinedLargePositiveInt64; static constexpr int64_t kMVKUndefinedLargeNegativeInt64 = -kMVKUndefinedLargePositiveInt64;
static uint64_t kMVKUndefinedLargeUInt64 = kMVKUndefinedLargePositiveInt64; static constexpr uint64_t kMVKUndefinedLargeUInt64 = kMVKUndefinedLargePositiveInt64;
#pragma mark Vulkan structure support functions #pragma mark Vulkan structure support functions
/** Returns a VkExtent2D created from the width and height of a VkExtent3D. */ /** 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. */ /** 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. */ /** Returns whether the two Vulkan extents are equal by comparing their respective components. */
static constexpr bool mvkVkExtent2DsAreEqual(VkExtent2D e1, VkExtent2D e2) { 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. */ /** Unpacks a single 32-bit word containing four swizzle components. */
static inline VkComponentMapping mvkUnpackSwizzle(uint32_t packed) { static constexpr VkComponentMapping mvkUnpackSwizzle(uint32_t packed) {
VkComponentMapping components; return {
components.r = (VkComponentSwizzle)((packed >> 0) & 0xFF); .r = (VkComponentSwizzle)((packed >> 0) & 0xFF),
components.g = (VkComponentSwizzle)((packed >> 8) & 0xFF); .g = (VkComponentSwizzle)((packed >> 8) & 0xFF),
components.b = (VkComponentSwizzle)((packed >> 16) & 0xFF); .b = (VkComponentSwizzle)((packed >> 16) & 0xFF),
components.a = (VkComponentSwizzle)((packed >> 24) & 0xFF); .a = (VkComponentSwizzle)((packed >> 24) & 0xFF),
return components; };
} }
/** /**
@ -384,24 +387,24 @@ static constexpr bool mvkVkComponentMappingsMatch(VkComponentMapping cm1, VkComp
/** Rounds the value to nearest integer using half-to-even rounding. */ /** Rounds the value to nearest integer using half-to-even rounding. */
static inline double mvkRoundHalfToEven(const double val) { 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. */ /** Returns whether the value will fit inside the numeric type. */
template<typename T, typename Tval> 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(); return val <= std::numeric_limits<T>::max();
} }
/** Clamps the value between the lower and upper bounds, inclusive. */ /** Clamps the value between the lower and upper bounds, inclusive. */
template<typename T> 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); return std::min(std::max(val, lower), upper);
} }
/** Returns the result of a division, rounded up. */ /** Returns the result of a division, rounded up. */
template<typename T, typename U> 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; typedef typename std::common_type<T, U>::type R;
// Short circuit very common usecase of dividing by one. // Short circuit very common usecase of dividing by one.
return (denominator == 1) ? numerator : (R(numerator) + denominator - 1) / denominator; 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. */ /** Returns the absolute value of the difference of two numbers. */
template<typename T, typename U> 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; return x >= y ? x - y : y - x;
} }
/** Returns the greatest common divisor of two numbers. */ /** Returns the greatest common divisor of two numbers. */
template<typename T> 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); return b == 0 ? a : mvkGreatestCommonDivisorImpl(b, a % b);
} }
template<typename T, typename U> 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::common_type<T, U>::type R;
typedef typename std::make_unsigned<R>::type UI; 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)))); 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. */ /** Returns the least common multiple of two numbers. */
template<typename T, typename U> 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; 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); 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. * value returned by previous calls as the seed in subsequent calls.
*/ */
template<class N> 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; std::size_t hash = seed;
for (std::size_t i = 0; i < count; i++) { hash = ((hash << 5) + hash) ^ pVals[i]; } for (std::size_t i = 0; i < count; i++) { hash = ((hash << 5) + hash) ^ pVals[i]; }
return hash; return hash;
@ -497,7 +500,7 @@ protected:
/** Ensures the size of the specified container is at least the specified size. */ /** Ensures the size of the specified container is at least the specified size. */
template<typename C, typename S> 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); } 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. * each object, including freeing the object memory, and clearing the container.
*/ */
template<typename C> template<typename C>
void mvkDestroyContainerContents(C& container) { static void mvkDestroyContainerContents(C& container) {
for (auto elem : container) { elem->destroy(); } for (auto elem : container) { elem->destroy(); }
container.clear(); container.clear();
} }
@ -517,7 +520,7 @@ void mvkDestroyContainerContents(C& container) {
*/ */
#ifdef __OBJC__ #ifdef __OBJC__
template<typename C> template<typename C>
void mvkReleaseContainerContents(C& container) { static void mvkReleaseContainerContents(C& container) {
for (auto elem : container) { [elem release]; } for (auto elem : container) { [elem release]; }
container.clear(); container.clear();
} }
@ -525,14 +528,14 @@ void mvkReleaseContainerContents(C& container) {
/** Returns whether the container contains an item equal to the value. */ /** Returns whether the container contains an item equal to the value. */
template<class C, class T> 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; } } for (const T& cVal : container) { if (cVal == val) { return true; } }
return false; return false;
} }
/** Removes the first occurance of the specified value from the specified container. */ /** Removes the first occurance of the specified value from the specified container. */
template<class C, class T> 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++) { for (auto iter = container.begin(), end = container.end(); iter != end; iter++) {
if( *iter == val ) { if( *iter == val ) {
container.erase(iter); container.erase(iter);
@ -543,7 +546,7 @@ void mvkRemoveFirstOccurance(C& container, T val) {
/** Removes all occurances of the specified value from the specified container. */ /** Removes all occurances of the specified value from the specified container. */
template<class C, class T> 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()); 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. */ /** Selects and returns one of the values, based on the platform OS. */
template<typename T> 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 #if MVK_IOS_OR_TVOS
return iOSVal; return iOSVal;
#endif #endif
@ -566,22 +569,29 @@ const T& mvkSelectPlatformValue(const T& macOSVal, const T& iOSVal) {
* The optional count allows clearing multiple elements in an array. * The optional count allows clearing multiple elements in an array.
*/ */
template<typename T> 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 * 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. * by writing zeros to all bytes. The optional count allows clearing multiple elements in an array.
*/ */
template<typename T> 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 * 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. * destination value. The optional count allows copying of multiple elements in an array.
*/ */
template<typename T> template<typename T>
void mvkCopy(T* pDst, const T* pSrc, size_t count = 1) { static void mvkCopy(T* pDst, const T* pSrc, size_t count = 1) {
if (pSrc && pDst) { memcpy(pDst, pSrc, sizeof(T) * count); } 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. * otherwise returns false. The optional count allows comparing multiple elements in an array.
*/ */
template<typename T> template<typename T>
bool mvkAreEqual(const T* pV1, const T* pV2, size_t count = 1) { static constexpr bool mvkAreEqual(const T* pV1, const T* pV2, size_t count = 1) {
return (pV1 && pV2) ? (memcmp(pV1, pV2, sizeof(T) * count) == 0) : false; 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> template<typename Tv, typename Tm>
void mvkEnableFlags(Tv& value, const Tm bitMask) { value = (Tv)(value | bitMask); } 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. */ /** Disables the flags (sets bits to 0) within the value parameter specified by the bitMask parameter. */
template<typename Tv, typename Tm> template<typename Tv, typename Tm>
void mvkDisableFlags(Tv& value, const Tm bitMask) { value = (Tv)(value & ~(Tv)bitMask); } 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). */ /** Returns whether the specified value has ANY of the flags specified in bitMask enabled (set to 1). */
template<typename Tv, typename Tm> template<typename Tv, typename Tm>
static constexpr bool mvkIsAnyFlagEnabled(Tv value, const Tm bitMask) { return ((value & bitMask) != 0); } static constexpr bool mvkIsAnyFlagEnabled(Tv value, const Tm bitMask) { return ((value & bitMask) != 0); }

View File

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

View File

@ -1466,7 +1466,6 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetLineWidth(
float lineWidth) { float lineWidth) {
MVKTraceVulkanCallStart(); MVKTraceVulkanCallStart();
MVKAddCmd(SetLineWidth, commandBuffer, lineWidth);
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
@ -1496,7 +1495,6 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetDepthBounds(
float maxDepthBounds) { float maxDepthBounds) {
MVKTraceVulkanCallStart(); MVKTraceVulkanCallStart();
MVKAddCmd(SetDepthBounds, commandBuffer, minDepthBounds, maxDepthBounds);
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
@ -1564,13 +1562,14 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBindIndexBuffer(
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBindVertexBuffers( MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBindVertexBuffers(
VkCommandBuffer commandBuffer, VkCommandBuffer commandBuffer,
uint32_t startBinding, uint32_t firstBinding,
uint32_t bindingCount, uint32_t bindingCount,
const VkBuffer* pBuffers, const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets) { const VkDeviceSize* pOffsets) {
MVKTraceVulkanCallStart(); MVKTraceVulkanCallStart();
MVKAddCmdFrom2Thresholds(BindVertexBuffers, bindingCount, 1, 2, commandBuffer, startBinding, bindingCount, pBuffers, pOffsets); MVKAddCmdFrom2Thresholds(BindVertexBuffers, bindingCount, 1, 2, commandBuffer,
firstBinding, bindingCount, pBuffers, pOffsets, nullptr, nullptr);
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
@ -2526,16 +2525,21 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBeginRendering(
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdEndRendering( MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBindVertexBuffers2(
VkCommandBuffer commandBuffer) { VkCommandBuffer commandBuffer,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets,
const VkDeviceSize* pSizes,
const VkDeviceSize* pStrides) {
MVKTraceVulkanCallStart(); MVKTraceVulkanCallStart();
MVKAddCmd(EndRendering, commandBuffer); MVKAddCmdFrom2Thresholds(BindVertexBuffers, bindingCount, 1, 2, commandBuffer,
firstBinding, bindingCount, pBuffers, pOffsets, pSizes, pStrides);
MVKTraceVulkanCallEnd(); 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( MVK_PUBLIC_VULKAN_SYMBOL void vkCmdBlitImage2(
VkCommandBuffer commandBuffer, VkCommandBuffer commandBuffer,
const VkBlitImageInfo2* pBlitImageInfo) { const VkBlitImageInfo2* pBlitImageInfo) {
@ -2585,6 +2589,14 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdCopyImageToBuffer2(
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdEndRendering(
VkCommandBuffer commandBuffer) {
MVKTraceVulkanCallStart();
MVKAddCmd(EndRendering, commandBuffer);
MVKTraceVulkanCallEnd();
}
MVK_PUBLIC_VULKAN_SYMBOL void vkCmdPipelineBarrier2( MVK_PUBLIC_VULKAN_SYMBOL void vkCmdPipelineBarrier2(
VkCommandBuffer commandBuffer, VkCommandBuffer commandBuffer,
const VkDependencyInfo* pDependencyInfo) { const VkDependencyInfo* pDependencyInfo) {
@ -2615,12 +2627,58 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdResolveImage2(
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
MVK_PUBLIC_VULKAN_STUB(vkCmdSetCullMode, void, VkCommandBuffer, VkCullModeFlags) MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetCullMode(
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthBiasEnable, void, VkCommandBuffer, VkBool32) VkCommandBuffer commandBuffer,
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthBoundsTestEnable, void, VkCommandBuffer, VkBool32) VkCullModeFlags cullMode) {
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthCompareOp, void, VkCommandBuffer, VkCompareOp)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthTestEnable, void, VkCommandBuffer, VkBool32) MVKTraceVulkanCallStart();
MVK_PUBLIC_VULKAN_STUB(vkCmdSetDepthWriteEnable, void, VkCommandBuffer, VkBool32) 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( MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetEvent2(
VkCommandBuffer commandBuffer, VkCommandBuffer commandBuffer,
@ -2632,14 +2690,83 @@ MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetEvent2(
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
MVK_PUBLIC_VULKAN_STUB(vkCmdSetFrontFace, void, VkCommandBuffer, VkFrontFace) MVK_PUBLIC_VULKAN_SYMBOL void vkCmdSetFrontFace(
MVK_PUBLIC_VULKAN_STUB(vkCmdSetPrimitiveRestartEnable, void, VkCommandBuffer, VkBool32) VkCommandBuffer commandBuffer,
MVK_PUBLIC_VULKAN_STUB(vkCmdSetPrimitiveTopology, void, VkCommandBuffer, VkPrimitiveTopology) VkFrontFace frontFace) {
MVK_PUBLIC_VULKAN_STUB(vkCmdSetRasterizerDiscardEnable, void, VkCommandBuffer, VkBool32)
MVK_PUBLIC_VULKAN_STUB(vkCmdSetScissorWithCount, void, VkCommandBuffer, uint32_t, const VkRect2D*) MVKTraceVulkanCallStart();
MVK_PUBLIC_VULKAN_STUB(vkCmdSetStencilOp, void, VkCommandBuffer, VkStencilFaceFlags, VkStencilOp, VkStencilOp, VkStencilOp, VkCompareOp) MVKAddCmd(SetFrontFace, commandBuffer, frontFace);
MVK_PUBLIC_VULKAN_STUB(vkCmdSetStencilTestEnable, void, VkCommandBuffer, VkBool32) MVKTraceVulkanCallEnd();
MVK_PUBLIC_VULKAN_STUB(vkCmdSetViewportWithCount, void, VkCommandBuffer, uint32_t, const VkViewport*) }
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( MVK_PUBLIC_VULKAN_SYMBOL void vkCmdWaitEvents2(
VkCommandBuffer commandBuffer, VkCommandBuffer commandBuffer,
@ -2733,7 +2860,6 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkSetPrivateData(
} }
#pragma mark - #pragma mark -
#pragma mark VK_KHR_bind_memory2 extension #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 -
#pragma mark VK_EXT_external_memory_host extension #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); MVK_PUBLIC_VULKAN_CORE_ALIAS(vkSetPrivateData, EXT);
#pragma mark - #pragma mark -
#pragma mark VK_EXT_sample_locations extension #pragma mark VK_EXT_sample_locations extension
@ -3588,6 +3769,7 @@ void vkCmdSetSampleLocationsEXT(
MVKTraceVulkanCallEnd(); MVKTraceVulkanCallEnd();
} }
#pragma mark - #pragma mark -
#pragma mark VK_GOOGLE_display_timing extension #pragma mark VK_GOOGLE_display_timing extension
@ -3616,12 +3798,14 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkGetPastPresentationTimingGOOGLE(
return rslt; return rslt;
} }
#pragma mark - #pragma mark -
#pragma mark VK_AMD_draw_indirect_count #pragma mark VK_AMD_draw_indirect_count
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdDrawIndexedIndirectCount, AMD); MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdDrawIndexedIndirectCount, AMD);
MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdDrawIndirectCount, AMD); MVK_PUBLIC_VULKAN_CORE_ALIAS(vkCmdDrawIndirectCount, AMD);
#pragma mark - #pragma mark -
#pragma mark iOS & macOS surface extensions #pragma mark iOS & macOS surface extensions