Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSL: Add an option to insert texture swizzles into generated shaders. #706

Merged
merged 9 commits into from
Sep 25, 2018

Conversation

cdavis5e
Copy link
Contributor

It's intended to be used with MoltenVK to support arbitrary
VkComponentMapping settings. The idea is that MoltenVK will pass a
buffer (which it set to some buffer index that isn't being used)
containing packed versions of the VkComponentMapping struct, one for
each sampled image.

Yes, this is horribly ugly. It is unfortunately necessary. Much of the
ugliness is to support swizzling gather operations, where we need to
alter the component that the gather operates on--something complicated
by the gather() method requiring the passed-in component to be a
constant expression. It doesn't even support swizzling gathers on depth
textures, though I could add that if it turns out we need it.

It's intended to be used with MoltenVK to support arbitrary
`VkComponentMapping` settings. The idea is that MoltenVK will pass a
buffer (which it set to some buffer index that isn't being used)
containing packed versions of the `VkComponentMapping` struct, one for
each sampled image.

Yes, this is horribly ugly. It is unfortunately necessary. Much of the
ugliness is to support swizzling gather operations, where we need to
alter the component that the gather operates on--something complicated
by the `gather()` method requiring the passed-in component to be a
constant expression. It doesn't even support swizzling gathers on depth
textures, though I could add that if it turns out we need it.
@HansKristian-Work
Copy link
Contributor

Oh ... dear. ... ._____.

Is the idea here to have two shader variants? One "clean", and one to deal with swizzling if there is at least one non-identity VkComponentMapping? Did you evaluate the possibility of having one shader variant per combination of VkComponentMapping so you could statically swizzle the texture? (I suppose that would be rather insane too).

@cdavis5e
Copy link
Contributor Author

I did. It would require us to recompile the shader every time a descriptor for an image with a non-identity swizzle were bound or pushed. And the code wouldn't look much better, since we have to contend with ZERO and ONE swizzles as well.

...I wonder if it would be best to discuss this with @billhollings.

@HansKristian-Work
Copy link
Contributor

HansKristian-Work commented Sep 20, 2018

I'm fine with either approach from the aspect of SPIRV-Cross if this is truly needed, although as you say, it's extremely ugly.

I was under the impression though that the portability layers would not attempt to go to this length of emulation. Is there some important case that has changed this stance? (This might affect how we deal with odd-ball cases like textureQueryLod ...)

When I think about it, static swizzle will not work in the case of arrays of textures. Each texture could have its own swizzle potentially, don't think we have a choice in the edgiest of cases.

@cdavis5e
Copy link
Contributor Author

There is. We at CodeWeavers need stencil data from depth/stencil textures to always be in green for our D3D emulation--something which cannot be done without swizzling. There are also games that need swizzling--DOOM and Wolfenstein come to mind (no surprise there, since id Software promulgated the original GL_ARB_texture_swizzle extension in the first place). And then it turns out that D3D12 also added support for component swizzling.

@HansKristian-Work
Copy link
Contributor

Do you know of any significant performance implication of doing dynamic swizzling like this (DOOM / Wolf)? Hopefully it's just limited to a few not very important passes.

I'll review tomorrow.

@cdavis5e
Copy link
Contributor Author

Well... In the case where a non-identity swizzle is given, it'll now take 24 compares+4 branches (6 compares+one branch per component), which I guess could add up over time for large meshes and/or high resolutions. The gather case should be less affected, since it only operates on a single component at a time (6 compares+one branch).

I admit that static swizzling would give faster shaders (no compares or branches)--it might actually be preferable. Whether it's worth the tradeoff of having to recompile shaders on every bind or push of a swizzled image descriptor, I don't know.

@HansKristian-Work
Copy link
Contributor

HansKristian-Work commented Sep 20, 2018

And even if we went with static swizzle, we would need this fallback path for arrays of textures, so it'd get even more complicated. :( Have you filed this bug to Apple? Lack of texture swizzle is quite glaring.

Static swizzle would probably add a fair amount of CPU overhead as well compared to just checking "do we have any swizzled texture?".

@cdavis5e
Copy link
Contributor Author

I filed rdar://44287804, which turns out to be a dupe of rdar://39856026--so this is a known issue to Apple.

spirv_msl.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@HansKristian-Work HansKristian-Work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing swizzling in leaf functions is not covered here ... Then again, I'm not sure if we should subject ourselves to that level of insanity unless we absolutely have to. If we don't for now, we need to check for this error and error out.

@@ -1237,6 +1237,7 @@ struct Meta
Decoration decoration;
std::vector<Decoration> members;
uint32_t sampler = 0;
uint32_t image = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'll need to refactor this to SPIRCombinedSampler that HLSL uses eventually ...

It'll be useful to have an "auxiliary buffer" for other builtins--e.g.
`DrawIndex` (which should be easier to implement now), or `ViewIndex`
when someone gets around to implementing multiview.

Pass this buffer to leaf functions as well.

Test that we handle this for integer textures as well.
spirv_msl.cpp Outdated Show resolved Hide resolved
spirv_msl.cpp Outdated Show resolved Hide resolved
spirv_msl.hpp Outdated Show resolved Hide resolved
spirv_msl.hpp Outdated Show resolved Hide resolved
spirv_msl.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@HansKristian-Work HansKristian-Work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments. Should be okay to merge after fixes, although I wish we didn't have to do this ... ;)

Just add our own separate function for analyzing sampled image usage.
While I'm at it, don't use a bitwise op with a `bool` variable.
Apparently, MSVC doesn't like that.
This needs extra work to map them back to the original resource.
@HansKristian-Work HansKristian-Work merged commit 69b034f into KhronosGroup:master Sep 25, 2018
@HansKristian-Work
Copy link
Contributor

Thanks for all the work and changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants