diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index ba65238d..bf05a93f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -77,7 +77,7 @@ public: void getFeatures(VkPhysicalDeviceFeatures* features); /** Populates the specified structure with the features of this device. */ - void getFeatures(VkPhysicalDeviceFeatures2KHR* features); + void getFeatures(VkPhysicalDeviceFeatures2* features); /** Populates the specified structure with the Metal-specific features of this device. */ void getMetalFeatures(MVKPhysicalDeviceMetalFeatures* mtlFeatures); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index 4d003101..1d08714a 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -58,10 +58,25 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures* features) { if (features) { *features = _features; } } -void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2KHR* features) { +void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) { if (features) { - features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; + features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; features->features = _features; + auto* next = (VkStructureType*)features->pNext; + while (next) { + switch (*next) { + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: { + auto* divisorFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next; + divisorFeatures->vertexAttributeInstanceRateDivisor = true; + divisorFeatures->vertexAttributeInstanceRateZeroDivisor = true; + next = (VkStructureType*)divisorFeatures->pNext; + break; + } + default: + next = (VkStructureType*)((VkPhysicalDeviceFeatures2*)next)->pNext; + break; + } + } } } @@ -92,6 +107,12 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) { next = (VkStructureType*)pointClipProps->pNext; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: { + auto* divisorProps = (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*)next; + divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32; + next = (VkStructureType*)divisorProps->pNext; + break; + } default: next = (VkStructureType*)((VkPhysicalDeviceProperties2*)next)->pNext; break; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm index 77581465..0f8f9f90 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm @@ -278,6 +278,21 @@ void MVKGraphicsPipeline::initMTLRenderPipelineState(const VkGraphicsPipelineCre // Returns a MTLRenderPipelineDescriptor constructed from this instance, or nil if an error occurs. MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor(const VkGraphicsPipelineCreateInfo* pCreateInfo) { + // Collect extension structures + VkPipelineVertexInputDivisorStateCreateInfoEXT* pVertexInputDivisorState = nullptr; + VkStructureType* next = (VkStructureType*)pCreateInfo->pNext; + while (next) { + switch (*next) { + case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT: + pVertexInputDivisorState = (VkPipelineVertexInputDivisorStateCreateInfoEXT*)next; + next = (VkStructureType*)pVertexInputDivisorState->pNext; + break; + default: + next = (VkStructureType*)((VkGraphicsPipelineCreateInfo*)next)->pNext; + break; + } + } + SPIRVToMSLConverterContext shaderContext; initMVKShaderConverterContext(shaderContext, pCreateInfo); @@ -342,6 +357,24 @@ MTLRenderPipelineDescriptor* MVKGraphicsPipeline::getMTLRenderPipelineDescriptor } } + // Vertex buffer divisors (step rates) + if (pVertexInputDivisorState) { + vbCnt = pVertexInputDivisorState->vertexBindingDivisorCount; + for (uint32_t i = 0; i < vbCnt; i++) { + const VkVertexInputBindingDivisorDescriptionEXT* pVKVB = &pVertexInputDivisorState->pVertexBindingDivisors[i]; + uint32_t vbIdx = _device->getMetalBufferIndexForVertexAttributeBinding(pVKVB->binding); + if (shaderContext.isVertexBufferUsed(vbIdx)) { + MTLVertexBufferLayoutDescriptor* vbDesc = plDesc.vertexDescriptor.layouts[vbIdx]; + if (vbDesc.stepFunction == MTLVertexStepFunctionPerInstance) { + if (pVKVB->divisor == 0) + vbDesc.stepFunction = MTLVertexStepFunctionConstant; + else + vbDesc.stepRate = pVKVB->divisor; + } + } + } + } + // Color attachments if (pCreateInfo->pColorBlendState) { for (uint32_t caIdx = 0; caIdx < pCreateInfo->pColorBlendState->attachmentCount; caIdx++) { diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index 0cde5dbc..db3c6db5 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -43,6 +43,7 @@ MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS) MVK_EXTENSION(KHR_surface, KHR_SURFACE) MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN) MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER) +MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR) MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE) MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE) MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK)