update ctx->ov_option.layout to the explict value which will be
used in function init_model_ov.
also move the code before input_resizable which uses the layout
Host map'd bufs skipped flushes unconditionally, always forcing the coherent flag
regardless of the memory type actually chosen for the import.
All known implementations import host memory as coherent, in which case nothing changes.
Dependencies were only released when a context was about to be reused, so
all buffers and deps got held up and piled up in the queue.
Release them as soon as they're done instead. Cuts RAM usage down by a ton.
Execution contexts track at most a few dozen dependencies so dynamically
growing the arrays was just stupid, and ARR_REALLOC required the field
name to also exist as a local variable.
Pool depth sets how far the CPU records ahead of the GPU, and has no relation
to the number of queues in a family.
Scaling it by the queue count only multiplied command pools, fences and context state.
Use a small fixed depth everywhere, and one context per thread only for threadsafe hwaccels,
which submit from every frame thread concurrently.
armasm64 warns "A4228: Alignment value exceeds AREA alignment; alignment
not guaranteed" on the .Lcoeffs literal pool. gas-preprocessor.pl emits
the text section as "AREA |.text|, CODE, READONLY, ALIGN=4", i.e. a
16-byte section alignment, so a 32-byte ALIGN inside it cannot be
guaranteed by the assembler.
16 is enough here: the pool holds .quad values that are read with
"ldr d0, .Lcoeffs" literal loads, which only require 8-byte alignment.
It also matches the rest of the aarch64 asm, where the function and
const macros both default to .align 4.
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
Cisco's ISVCDecoder retains DPB and reference state across
avcodec_flush_buffers(), causing the next IDR to be accepted but
subsequent P-frames to fail decode after a seek or loop. Cisco's
API does not expose a non-destructive reset; tear down and rebuild
the decoder via the existing close/init callbacks.
The .flush callback is void and cannot report a re-init failure, so
svc_decode_frame() guards against a NULL decoder left behind by a
failed re-init. svc_decode_init() now also tears the decoder back
down on an Initialize() failure so that path leaves the same clean
NULL state the guard expects and does not leak the ISVCDecoder.
Signed-off-by: Scott Kidder <scott@kidder.io>
checkasm:
- CPU: AMD Ryzen 9 9950X3D 16-Core Processor (00B40F40)
- Timing source: x86 (rdtsc)
- Bench duration: 100000 µs per function (448667793 cycles)
- Random seed: 3773883393
Benchmark results:
name cycles (vs ref)
f32_lut_3d_xyz_dynamic_c: 125193.9
f32_lut_3d_xyz_static_c: 25792.1
f32_lut_3d_xyzw_dynamic_c: 123807.1
f32_lut_3d_xyzw_static_c: 25739.0
This is roughly ~50% faster than the existing code in lut3d.c, from a quick
test.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
These may differ from the regular op lists in nontrivial ways, due to e.g.
different optimization steps being taken.
In practice, it seems this just adds the extra LUT_3D uops, but we don't
know that for sure, so better to brute force the list. That said, I do
think we can safely skip the extra backend flags in this case, at least.
Even in the worst case scenario, that would just force a fallback to the
C reference backend.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
The value range normalization and input range clamp will normally be
optimized away.
This commit also moves the legacy 3dlut pass to be legacy-exclusive, as the
ops code now uses the new logic. This ordering ensures that the conversion
works on every commit in isolation.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
Instead of generating the 3DLUT and applying it right away, init_passes()
now just generates it and passes it as a parameter to add_convert_pass(),
which will forward it to the underlying implementation.
I pre-emptively moved the function to the legacy section, in anticipation
of the following commit which will make this legacy-only.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
Since this depends on the overall picture parameters anyways, updating it
directly from the private setup() function was always a bit hacky. More
importantly, this needed for the ops-based 3DLUT implementation, which is
already using the pass priv pointer to store the compiled function.
Overall, simpler to just lift it to the top level and update it directly as
needed.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
The structure for the tetrahedral interpolation deviates slightly from the
naive formulation in lut3d.c; instead of branching into every separate case,
we sort the weights and offsets using a series of conditional swaps. This
actually performs identically on my end, but results in code that is much
closer to what SIMD will be doing. That should hopefully serve as a better
reference for future SIMD implementors. (Myself included)
I also reordered the dynamic tone-mapping code a bit to better indicate the
sources of live register pressure that will manifest in the real SIMD kernel.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
After extensive testing, prototyping and benchmarking across a range of
systems, I determined that the optimal data layout for the SIMD 3DLUT is
essentially exactly the one we have. 16-bit integers are near optimal for
quality vs compactness, and crucially, x86 lets us load the entire packed
3DLUT entry with a single `vpgatherdq` instruction.
This dwarfs the loss from needing to cast the resulting 16-bit integers
back to f32 and renormalize.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
av_round16f() was incorrectly scaling to 65534, which would correspond to
a neutral PT offset of 32767 = (1 << 15) - 1, but the code was assuming a
value of (1 << 15). To fix it, and make the PT channel correctly symmetric
around the intended neutral value, we have to map PT = +0.5 to 65536, an
unrepresentable value. This is not an issue because the PT channel values are
strictly inside some subset of [-0.5, 0.5] in practice, for real in-gamut
color values - it's already an envelope that includes quite a bit of safety
margin.
Similarly, av_round16f() is also the wrong tool for the I/RGB channels,
because it incorrectly scaled those to 65534, an off by one of the intended
unorm16 full range peak of 65535. This silently resulted in e.g. RGBA64
true white (65535) not round-tripping through the 3DLUT.
Fix both by splitting this helper into two separate helpers, each of them
fixed to the correct, intended value range.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
The ops-based 3DLUT approach will take care of appropriately normalizing
the input to the expected domain; so the format choice no longer matters here
except for the lut3d_apply() function, which will only be used by the legacy
reference code path. So we can just continue hard-coding the format there.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
Instead of clamping in the application function. Trivial simplicity gain
for the SIMD code.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
This was originally introduced to make matching linear ops against
implementations faster. However, since this is now handled on the uops
level, there is no more reason to carry this metadata on the ops level.
Simplifies a lot of places in the code. It will simplify even more, once
the linear optimizations are moved to the uops level.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
Introduce a unified FORWARD() helper macro that can be used for any type of
op, whether it is independent per component or more complex. By initializing
every op to the same IDENTITY state, we can leverage the monoid property to
make this work for naive propagations as well.
As an aside, we also properly zero out the unrelated fields when discarding
a component (i.e. marking it as GARBAGE).
This will make a couple of up-coming refactors a bit easier.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
This violates the documentation (monoid property).
It's a bit arbitrary whether to consider this an OR-type or AND-type flag,
since mixing swapped and non-swapped components is almost surely a bug, but
keeping it as an OR-type makes sure such cases at least show up in the
result.
Sponsored-by: Sovereign Tech Fund
Signed-off-by: Niklas Haas <git@haasn.dev>
Since the switch to libcheckasm, checkasm no longer uses
FFmpeg's emms_c, timers, AVLFG or string handling functions,
so remove these headers.
This necessitated adding some missing headers (mostly string.h)
to some files.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This has been done in order to use the same parameters
that influence the number of elements to be processed
sets to make benchmarks between different instruction
sets comparable. Yet it has a downside: Only one parameter
combination would ever be executed when using --repeat,
hiding potential bugs.
Luckily libcheckasm makes it easy to fix this:
At the start of every test function, the internal state
of rnd() is reset, so that it produces the same sequence
of random values. So just initialize these parameters
every time (and before actually testing any function).
This also would make this test trivially parallelizable with --repeat.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This has been done in order to use the same height
for each function for benchmarks of different
instruction sets to make the benchmarks comparable.
Yet it has a downside: Only one number would ever be
executed when using --repeat, hiding potential bugs.
Luckily libcheckasm makes it easy to fix this:
At the start of every test function, the internal state
of rnd() is reset, so that it produces the same sequence
of random values. So just initialize the heights every time
(and before actually testing any function).
This also would make this test trivially parallelizable with --repeat.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
llviddsp functions typically operate on whole lines,
i.e. the pointers are aligned to STRIDE_ALIGN. They
can therefore avoid tail handling by just clobbering
the padding (if any).
The test gets a random width via 16 * av_clip(rnd(), 16, 128);
in practice, it is very unlikely for rnd() to return
a value between 16 and 128, so width is typically 16*16 or
16*128. Buffers of this size are allocated later.
When rnd() returns an odd number in the allowed range
(this happens for the seed 4161216273), the buffers used
in the test don't contain the padding that exists in actual
usage, leading to invalid stores and also to segmentation faults
(usage of aligned load instructions on unaligned addresses).
Fix this by adding the necessary alignment to the buffers.
Also don't use a static variable to store width (it is unnecessary,
because since the switch to libcheckasm, rnd() always returns
the same sequence of random numbers for test runs with different
instruction sets) and use a really random width, not something
that is mostly just one of two values and always mod 16.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This has been done in order to use the same number of blocks
for benchmarks of different instruction sets to
make the benchmarks comparable. Yet it has a downside:
Only one number would ever be executed when using --repeat.
Luckily libcheckasm makes it easy to fix this:
At the start of every test function, the internal state
of rnd() is reset, so that it produces the same sequence
of random values. So just removing the static variable works.
This would also makes this test trivially parallelizable.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This has been done in order to use the same width
for benchmarks of different instruction sets to
make the benchmarks comparable. Yet it has a downside:
Only one width would ever be executed when using --repeat.
Luckily libcheckasm makes it easy to fix this:
At the start of every test function, the internal state
of rnd() is reset, so that it produces the same sequence
of random values. So just removing the static variable works.
This would also make this test trivially parallelizable.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
The fence was reset when a context began recording, so an error
between recording start and submission (observed in the wild as
intermittent VK_ERROR_MEMORY_MAP_FAILED from vkEndCommandBuffer on
ANV under threaded load) left it permanently unsignalled, deadlocking
the next user of the context.
Reset the fence only once a fully recorded submission is about to be
handed to the queue: abandoned recordings then leave the fence
signalled from the previous submission, and the context self-heals on
reuse. Should the queue submission itself fail, signal the fence with
an empty submission.
These shaders reduce across the subgroup after divergent control flow
and implicitly rely on invocations reconverging as written, the
MaximallyReconvergesKHR execution mode turns that assumption into a
guarantee.
A capture device could previously be selected only by index or by name.
Both are unreliable when multiple audio/video devices share a name or
across reboots. AVFoundation reorders the device indices, and the USB
video uniqueID embeds the macOS locationID, which can be reassigned on
reboot or replug and can then resolve to a different physical device.
Add -video_device_id and -audio_device_id, which take a prefixed
identifier: uid:<unique ID> or serial:<USB serial number>.
The USB serial number is the only identifier that stays pegged to a
given physical unit. For video it is resolved to the device's current
locationID via IOKit. For audio it is matched against the uniqueID,
which already embeds it. The unique ID covers devices that have no
serial, such as virtual camera/audio devices.
-list_devices additionally prints each device's uniqueID and USB serial
so the values can be discovered. IOKit is detected in configure and used
only when available.
Signed-off-by: Gabriel Balaich <ffmpeg@ninbura.com>