<div dir="ltr"><div>TMZ is more complicated. If there is a TMZ buffer used by a command buffer, then all other used buffers must also be TMZ or read only. If no TMZ buffers are used by a command buffer, then TMZ is disabled. If a context is not secure, TMZ is also disabled. A context can switch between secure and non-secure based on the buffers being used.<br></div><div><br></div><div>So mixing secure and non-secure memory writes in one command buffer won't work. This is not fixable in the driver - apps must be aware of this.<br></div><div><br></div><div>Marek<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jun 3, 2020 at 5:50 AM Daniel Stone <<a href="mailto:daniel@fooishbar.org" target="_blank">daniel@fooishbar.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Alex,<br>
<br>
On Mon, 1 Jun 2020 at 15:25, Alex Deucher <<a href="mailto:alexdeucher@gmail.com" target="_blank">alexdeucher@gmail.com</a>> wrote:<br>
> On Fri, May 29, 2020 at 11:03 AM Daniel Stone <<a href="mailto:daniel@fooishbar.org" target="_blank">daniel@fooishbar.org</a>> wrote:<br>
> > What Weston _does_ know, however, is that display controller can work<br>
> > with modifier set A, and the GPU can work with modifier set B, and if<br>
> > the client can pick something from modifier set A, then there is a<br>
> > much greater probability that Weston can leave the GPU alone so it can<br>
> > be entirely used by the client. It also knows that if the surface<br>
> > can't be directly scanned out for whatever reason, then there's no<br>
> > point in the client optimising for direct scanout, and it can tell the<br>
> > client to select based on optimality purely for the GPU.<br>
><br>
> Just so I understand this correctly, the main reason for this is to<br>
> deal with display hardware and render hardware from different vendors<br>
> which may or may not support any common formats other than linear.<br>
<br>
It handles pretty much everything other than a single-context,<br>
single-GPU, single-device, tunnel.<br>
<br>
When sharing between subsystems and device categories, it lets us talk<br>
about capabilities in a more global way. For example, GBM lets you<br>
talk about 'scanout' and 'texture' and 'render', but what about media<br>
codecs? We could add the concept of decode/encode to something like<br>
GBM, and all the protocols like Wayland/X11 as well, then hope it<br>
actually works, but ...<br>
<br>
When sharing between heterogeneous vendors, it lets us talk about<br>
capabilities in a neutral way. For example, if you look at most modern<br>
Arm SoCs, your GPU, display controller, and media codec, will very<br>
likely all be from three totally different vendors. A GPU like<br>
Mali-T8xx can be shipped in tens of different vendor SoCs in several<br>
different revisions each. Just saying 'scanout' is totally meaningless<br>
for the Panfrost driver. Putting awareness for every different KMS<br>
platform and every different codec down into the Mesa driver is a<br>
synchronisation nightmare, and all those drivers would also need<br>
specific awareness about the Mesa driver. So modifiers allow us to<br>
explicitly describe that we want a particular revision of Arm<br>
Framebuffer Compression, and all the components can understand that<br>
without having to be specifically aware of 15 different KMS drivers.<br>
But even if you have the same vendor ...<br>
<br>
When sharing between multiple devices of the same class from the same<br>
vendor, it lets us surface and transit that information in a generic<br>
way, without AMD having to figure out ways to tunnel back-channel<br>
information between different instances of drivers potentially<br>
targeting different revisions. The alternatives seem to be deeply<br>
pessimal hacks, and we think we can do better. And when we get<br>
pessimal ...<br>
<br>
In every case, modifiers are about surfacing and sharing information.<br>
One of the reasons Collabora have been putting so much time and energy<br>
into this work is exactly _because_ solving those problems on a<br>
case-by-case basis was a pretty lucrative source of revenue for us.<br>
Debugging these kinds of issues before has usually involved specific<br>
driver knowledge, hacking into the driver to insert your own tracing,<br>
etc.<br>
<br>
If you (as someone who's trying to use a device optimally) are<br>
fortunate enough that you can get the attention of a vendor and have<br>
them solve the problem for you, then that's lucky for everyone apart<br>
from the AMD engineers who have to go solve it. If you're not, and you<br>
can't figure it out yourself, then you have to go pay a consultancy.<br>
On the face of it, that's good for us, except that we don't want to be<br>
doing that kind of repetitive boring work. But it's bad for the<br>
ecosystem that this knowledge is hidden away and that you have to pay<br>
specialists to extract it. So we're really keen to surface as much<br>
mechanism and information as possible, to give people the tools to<br>
either solve their own problems or at least make well-informed<br>
reports, burn down a toxic source of revenue, waste less engineering<br>
time extracting hidden information, and empower users as much as<br>
possible.<br>
<br>
> It<br>
> provides a way to tunnel device capabilities between the different<br>
> drivers. In the case of a device with display and rendering on the<br>
> same device or multiple devices from the same vendor, it not really<br>
> that useful.<br>
<br>
Oh no, it's still super useful. There are a ton of corner cases where<br>
'if you're on same same-vendor same-gen same-silicon hardware' falls<br>
apart - in addition to the world just not being very much<br>
same-vendor/same-gen/same-silicon anymore. For some concrete examples:<br>
<br>
On NVIDIA Tegra hardware, planes within the display controller have<br>
heterogeneous capability. Some can decompress and detile, others<br>
can't.<br>
<br>
On Rockchip hardware, AFBC (DCC equivalent) is available for scanout<br>
on any plane, and can be produced by the GPU. Great! Except that 'any<br>
plane' isn't 'every plane' - there's a global decompression unit.<br>
<br>
On Intel hardware, they appear to have forked the media codec IP,<br>
shipping two different versions of the codec, one as 'low-power' and<br>
one as 'normal', obviously with varying capability.<br>
<br>
Even handwaving those away as vendor errors - that performance on<br>
those gens will always be pessimal and they should do better next time<br>
- I don't think same-vendor/same-gen/same-silicon is a good design<br>
point anymore. Between heterogeneous cut-and-paste SoCs, multi-GPU and<br>
eGPU usecases, virtualisation and tunneling, etc, the usecases are<br>
starting to demand that we do better. Vulkan's memory-allocation<br>
design also really pushes against the model that memory allocations<br>
themselves are blessed with side-channel descriptor tags.<br>
<br>
'Those aren't my usecases and we've made Vulkan work so we don't need<br>
it' is an entirely reasonable position, but then you're just<br>
exchanging the problem of describing your tiling & compression layouts<br>
in a 56-bit enum to make modifiers work, for the problem of<br>
maintaining a surprisingly wide chunk of the display stack. For all<br>
the reasons above, over the past few years, the entire rest of the<br>
ecosystem has settled on using modifiers to describe and negotiate<br>
buffer exchange across context/process/protocol/subsystem/device<br>
boundaries. All the effort of making this work in KMS, GBM, EGL,<br>
Vulkan, Wayland, X11, V4L2, VA-API, GStreamer, etc, is going there.<br>
<br>
Realistically, the non-modifier path is probably going to bitrot, and<br>
people are certainly resistant to putting more smarts into it, because<br>
it just adds complexity to a now-single-vendor path - even NVIDIA are<br>
pushing this forward, and their display path is much more of an<br>
encapsulated magic tunnel than AMD's. In that sense, it's pretty much<br>
accumulating technical debt; the longer you avoid dealing with the<br>
display stack by implementing modifiers, the more work you have to put<br>
into maintaining the display stack by fixing the non-modifier path.<br>
<br>
> It doesn't seem to provide much over the current EGL<br>
> hints (SCANOUT, SECURE, etc.).<br>
<br>
Well yeah, if those single bits of information are enough to perfectly<br>
encapsulate everything you need to know, then sure. But it hasn't been<br>
for others, which is why we've all migrated away from them.<br>
<br>
> I still don't understand how it solves<br>
> the DCC problem though. Compression and encryption seem kind like<br>
> meta modifiers. There is an under laying high level layout, linear,<br>
> tiled, etc. but it could also be compressed and/or encrypted. Is the<br>
> idea that those are separate modifiers? E.g.,<br>
> 0: linear<br>
> 1: linear | encrypted<br>
> 2. linear | compressed<br>
> 3: linear | encrypted | compressed<br>
> 4: tiled1<br>
> 5: tiled1 | encrypted<br>
> 6: tiled1 | compressed<br>
> 7: tiled1 | encrypted | compressed<br>
> etc.<br>
> Or that the modifiers only expose the high level layout, and it's then<br>
> up the the driver(s) to enable compression, etc. if both sides have a<br>
> compatible layout?<br>
<br>
Do you remember the old wfb from xserver? Think of modifiers as pretty<br>
much that. The format (e.g. A8R8G8B8) describes what you will read<br>
when you load a particular pixel/texel, and what will get stored when<br>
you write. The modifier describes how to get there: that includes both<br>
tiling (since you need to know the particular tiling layout in order<br>
to know the byte location to access), and compression (since you need<br>
to know the particular compression mechanism in order to access the<br>
pixel, e.g. for RLE-type compression that you need to access the first<br>
pixel of the tile if the 'all pixels are the identical' bit is set).<br>
<br>
The idea is that these tokens fully describe the mechanisms in use,<br>
without the drivers needing to do magic heuristics. For instance, if<br>
your modifier is just 'tiled', then that's not a full description. A<br>
full description would tell you about supertiling structures, tile<br>
sizes and ordering, etc. The definitions already in<br>
include/uapi/drm/drm_fourcc.h are a bit of a mixed bag - we've<br>
definitely learnt more as we've gone on - but the NVIDIA definitions<br>
are pretty exemplary for something deeply parameterised along a lot<br>
of variable axes.<br>
<br>
Basically, if you have to have sets of heuristics which you keep in<br>
sync in order to translate from modifier -> hardware layout params,<br>
then your modifiers aren't expressive enough. From a very quick look<br>
at DC, that would be your tile-split, tile-mode, array-mode, and<br>
swizzle-mode parameters, plus whatever from dc_tiling_mode isn't<br>
completely static and deterministic. 'DCCRate' always appears to be<br>
hardcoded to 1 (and 'DCCRateChroma' never set), but that might be one<br>
to parameterise as well.<br>
<br>
With that expression, you don't have to determine the tiling layout<br>
from dimensions/usage/etc, because the modifier _is_ the tiling<br>
layout, ditto compression.<br>
<br>
Encryption I'm minded to consider as something different. Modifiers<br>
don't cover buffer placement at all. That includes whether or not the<br>
memory is physically contiguous, whether it's in<br>
hidden-VRAM/BAR/sysmem, which device it lives on, etc. As far as I can<br>
tell from TMZ, encryption is essentially a side effect of placement?<br>
The memory is encrypted, the encryption is an immutable property of<br>
the allocation, and if the device is configured to access encrypted<br>
memory (by being 'secure'), then the encryption is transparent, no?<br>
<br>
That being said, there is a reasonable argument to consume a single<br>
bit in modifiers for TMZ on/off (assuming TMZ is not parameterised),<br>
which would make its availability and use much more transparent.<br>
<br>
Cheers,<br>
Daniel<br>
</blockquote></div>