KhronosGroup / MoltenVK

MoltenVK is a Vulkan Portability implementation. It layers a subset of the high-performance, industry-standard Vulkan graphics and compute API over Apple's Metal graphics framework, enabling Vulkan applications to run on macOS, iOS and tvOS.
Apache License 2.0
4.74k stars 414 forks source link

Add support for Metal shader framebuffer fetch #1374

Open billhollings opened 3 years ago

billhollings commented 3 years ago

VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT descriptors should use shader framebuffer fetch, when it is available on the platform, using color(m) within the shader, instead of setFragmentTexture:, because doing so is more performant, and allows memoryless textures to be used for the input attachments.

jpd002 commented 3 years ago

Hey there! I'm working on a PlayStation2 emulator (https://github.com/jpd002/Play-) and I'm using MoltenVK to enable Vulkan on macOS/iOS platforms. The PS2 has lots of weird pixel blending/testing/pixel format scenarios that are not directly supported by standard APIs and I've been using fragment shader interlock to implement these on desktop platforms.

I've been looking at enabling Vulkan on mobile platforms a few weeks ago and I figured I could add support for the PS2 graphical features using subpasses and framebuffer fetch. I did a bit of research in MoltenVK's code and saw the few bits and pieces mentioning that framebuffer fetch was not supported and I then stumbled on this issue.

I would love to add support for this inside MoltenVK, but I'm not totally sure what would be the requirements. I did a quick & dirty PoC on my side to see how framebuffer fetch could be enabled (https://github.com/jpd002/MoltenVK/commit/898553af81e3ee24e82d5c654c15776c3c1b4b78), but the real challenge is to make it work properly in all scenarios 😃.

The Vulkan spec is not super clear about how and when framebuffer fetch should be used, but I guess in the case of MoltenVK, that we would only enable it if the image used for the input attachment has the VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT and is using the VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT memory type. I guess only tiled GPUs have the VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT memory type, so I guess we wouldn't need to do a throughout check on the device type.

Are there other things that we should worry about to add support for framebuffer fetch on MoltenVK?

Thanks!

Jhonnyg commented 11 months ago

I'm facing this exact issue right now. We (Defold: https://defold.com/) are integrating third-party code that uses shader code that is reliant on subpassInput variables getting transpiled into [[color]] inputs. Currently I'm using the workaround that @jpd002 posted above, but I'd rather not have to maintain a fork of MoltenVK for this purpose alone 🤔 @billhollings have you guys planned to look at this at some point or is this the way forward for the foreseeable future? Thanks!

aitor-lunarg commented 6 months ago

Due to change #1373, input attachment usage images with transient usage return different memory types compared to non input attachment usage images with transient usage. This goes against the Vulkan spec, section VkMemoryRequirements: For images created with a color format, the memoryTypeBits member is identical for all VkImage objects created with the same combination of values for the tiling member, the VK_IMAGE_CREATE_SPARSE_BINDING_BIT bit of the flags member, the VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT bit of the flags member, the VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT bit of the usage member if the VkPhysicalDeviceHostImageCopyPropertiesEXT::identicalMemoryTypeRequirements property is VK_FALSE, handleTypes member of VkExternalMemoryImageCreateInfo, and the VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT of the usage member in the VkImageCreateInfo structure passed to vkCreateImage.

Makes the following Vulkan 1.0 CTS tests fail:

dEQP-VK.memory.requirements.core.image.transient_tiling_linear
dEQP-VK.memory.requirements.core.image.transient_tiling_optimal

Having this implemented will help us reach support for the following Vulkan extensions (none are core in any Vulkan version):

VK_EXT_rasterization_order_attachment_access
VK_KHR_dynamic_rendering_local_read