Both the API user and the driver may attempt to map a BO, possibly
only partially and using different ranges. This is a problem because
we only have a single map per BO. Fix this by making sure that when
a BO is mapped, we always map its entire range. This way if a BO
has been mapped before, we know that map is still valid no matter the
region we need to access now.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
The blit shader path for buffer to image copies is pretty bad,
since it needs to produce a tiled image from the linear buffer
prior to emitting the blit copy.
This patch adds a new preferential path where we implement the
copy using the CPU, similar to what the GL driver does for
texture uploads. This makes vkQuake2 at least 4x faster when
dynamic lights are enabled (which triggers dynamic texture
updates).
We also tested a GPU path where we use a shader that takes the
linear buffer as a UBO and copies directly from it. This also
shows a clear performance gain, but still worse than the CPU
implementation.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
We had done all the plumbing for this but EZ can be disabled in 3 places
and we were never setting the enable bit in the configuration bits packet.
Also, configuration bits must not enable EZ if this has been disabled in
the RCL for the whole frame, which we do if we don't have a depth
attachment at all.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
Otherwise cloned BO lists point to the original list objects and not
the cloned ones, and that will confuse anything that tries to iterate over
them, such as list_length(), leading to infinite loops.
Fixes (in debug mode):
dEQP-VK.api.command_buffers.render_pass_continue
In that test we clone a full CL job from a secondary, and without this,
the BO lists in its CL lists will point to the bo_list field in the
original job, leading to an infinite loop as we assert the expected size
of these lists at queue submit time in handle_cl_job.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
Asserting on them makes it easier to identify applications and tests that
try to use unimplemented features.
Also, there are some APIs that relate to optional features we don't
(or can't) support, such as sparse, so for these we just provide
the trivial implementation.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This allows us to remove some individual bos for the image and
sampler, used to store the SAMPLER_STATE and TEXTURE_SHADER_STATE. Now
they are prepacked on static memory as part of the vulkan object
struct.
This commit introduces small descriptor structs, used to define what
the bo subregion would contain. It is used mostly to compute offsets
to that specific data, and define the size needed. Having said so, it
would be possible to replace them with some kind of flag (like anv) or
just compute the offset based on the context.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
So far we were saving all the descriptor info on the host memory. With
this commit we do the equivalent that other mesa vulkan drivers (Anvil
and Turnip) and create a bo on the descriptor pool that would be
suballocated for each descriptor.
This would allow to clean up individual bos from some vulkan objects,
reducing device memory fragmentation, and allowing to avoid to alloc
bos for that info. After all, pre-allocating needed memory is one of
the purposes of the descriptor pool.
This commit introduces all the infrastructure, but doesn't use it for
any descriptor yet, as if no descriptor needed data uploaded to a bo.
The idea to decide which info goes to the descriptor pool bo is info
that we would need to upload to a bo in any case, as it is referenced
as an address by any packet.
We could be more aggressive with that general rule, but that would be
enough for now. If in the future we support
VK_EXT_descriptor_indexing, we probably would need to store more info,
as under that extension, descriptors can be updated after being bound.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
We were assuming that if the command buffer state doesn't have any
attachments (as per the attachment count) the attachment state array
should not be allocated, however, during meta operations it is
possible that the attachment state grows (since meta operations can
emit render passes of their own). In that case, we would grow the
state for the meta operation but then pop the previous attachment
count and we would leak the state.
An example of that is a secondary command buffer which has no
attachment state by default since it doesn't execute a render pass
begin, but that executes one in a meta operation (for
vkCmdClearAttachments for example).
Fix this by making the attachment count an allocation count instead
and not popping it once we finish a meta operation. Also, always free
the state so long as there is a valid pointer, and assert that the
allocated count is not zero in that case.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
The main change we are introducing here is that now we allow secondary
command buffers that execute in a render pass to have a job list with
more than one job.
The main issue with vkCmdClearAttachments is that we currently need
this to spawn multiple jobs to clear multilayered framebuffers, as we
need to setup a different 2D framebuffer for each layer to clear and
therefore emit a different RCL for each. We could avoid this
completely by used layered rendering with the "clear rect" path to
redirect the clear rects to appropriate layers of the primary
framebuffer, however, our hardware only supports layered rendering
with geometry shaders, which we don't support at present.
Because vkCmdClearAttachments relies on having framebuffer state
available (something we would not need if we used the geometry shader
implementation), if this is not available in the secondary we need to
postpone emission of the command until the secondary is executed
inside a primary. We do this by using a new CPU job
V3DV_JOB_TYPE_CPU_CLEAR_ATTACHMENTS that is processed during
vkCmdExecuteCommands by calling vkCmdClearAttachments directly in the
primary.
As a consequence of these changes, it is now possible that a secondary
command buffer that runs inside a render pass have any kind of job in
its job list, including partial CLs that need to be branched to and
full CLs that need to be submitted to the GPU as is, so we introduced
a new GPU job type V3DV_JOB_TYPE_GPU_CL_SECONDARY to identify partial
CLs.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
Event waits can be safely moved before a render pass start, since
event setting and resetting commands cannot happen inside one. We
don't need to go that far, but we can use this to record the wait
in its own separate job and then execute this job before the
binning commands recorded in the secondary command buffer when
we execute the secondary into a primary.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
There are basically two types of scenarios to consider:
- Secondary command buffers that run inside a render pass.
- Secondary command buffers that run outside a render pass.
For the former we want to record their commands into a binning command
list that we can branch to when executed into a primary command
buffer. This means this kind of command buffers don't spawn new jobs,
just the default one where they record the binning commands which
won't include the frame setup, which will be provided by the primary
they will be executed in.
For the latter we don't require anything special, we just record as
many jobs as we need as usual and link that job list from the primary
job list when executed.
This handles most scenarios except:
- vkCmdWaitForEvents
- VkCmdClearAttachments
Both of these can spawn new jobs inside a render pass, which is not
what we want for secondary command buffers. We will address this is
follow-up patches.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
We should always do this. So far we have been getting away with this
because we overallocate at v3dv_job_start_frame, but that won't do
for secondary command buffers for example, it is also unreliable
if CLs grow past that initial allocation.
In the future, we might want to fix our emit macros so they do the
allocation check implicitly, which would simplify the code and would
make this process a lot less error prone.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
We are currently able to clear any supported format using the TLB, but
this is more consistent with other parts of the code and is what we want
should we add any formats in the future where we can't get away with
TLB clears.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
During a command buffer reset we call cmd_buffer_init(), which will
add the command buffer to the pool, so make sure we remove it first
and that we use a safe iterator when resetting a pool.
Fixes:
dEQP-VK.api.command_buffers.pool_reset_reuse
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
That it is justconvert VkSpecializationInfo to
nir_spirv_specialization and pass it to spirv_to_nir.
The code is also basically the same used by anv, tu, and radv
Eventually it would make sense to move it to a common place.
Note that we are using calloc there to allocate the temporary
spec_entries. Trying to use vk_alloc2 causes some problems with the
nir_validate.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
In order to properly check (and possibly compile) shader variants we
need a pipeline and a compatible descriptor set. So far we were trying
to do that check as early as possible, so we were trying to do it at
CmdBindPipeline or CmdBindDescriptorSets, and a combination of dirty
flags. This showed to not cover all the corners cases, and made the
code complex, as needed to handle cases where the descriptors were not
yet available, and return early. The latter also meant that we were
running several checks that failed in the middle.
This commit moves the variant check to CmdDraw, when we should have a
pipeline and compatible descriptor sets, and simplifies and makes more
strict the existing code.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This reverts a previous half-attempt at an implementation of events
using a BO to hold the event state, and provides a full
implementation. V3D doesn't have any built-in GPU functionality to
wait on any kind of events, so we need to implement this in the driver
an therefore we no longer need to use a BO for the event state.
Instead, we implement GPU waits by using a CPU job for the wait
operation that spawns a wait thread if the wait operation doesn't have
all its events signaled by the time it is processed. To implement the
semantics of the wait correctly, any jobs in the same command buffer
that come after the wait will not be emitted until the wait thread
completes.
If a submit spawns any wait threads for a command buffer we can't
signal any semaphores for it until all the wait threads complete and
we know that all the jobs for those command buffers have been
submitted. The same applies to the submit fence, if present.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This is generally very difficult to handle properly everywhere, but
at least this is good enough to make the few CTS tests for this happy.
Fixes (on Rpi4):
dEQP-VK.wsi.xlib.swapchain.simulate_oom.*
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
There is a hw bug by which the only way to clear the depth/stencil
tile buffers is to emit a clear of all tile buffers, so if we have
to do any such clears, we just emit a single clear of all tile
buffers and skip doing any per-buffer clears, even for color buffers,
since they would be redundant.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
We were declaring the destroy callback function as taking a pointer for the
vulkan object handle and relying on an implicit conversion to the Vulkan
handle type, however that would be incorrect on 32-bit platforms, where
non-dispatchable Vulkan objects (the kind that we may allocate privately during
command buffer recording), are defined as uint64_t, so the signature of the
destry callback type doesn't match the signature of the actual Vulkan
function, leading to bogus results. Fix that by using uint64_t instead.
This fixes compilation warnings and also crashes in some tests when
compiling and executing natively in Rpi4.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
We were pre-packing the constants from the pipeline state and then
always emitting that at draw time, ignoring dynamic state. This makes
it so we don't prepack at pipeline creation time and we always emit
the correct constants directly the command buffer dynamic state.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
We can now implement all depth/stencil blits as compatible color blits,
so let's just have the blit shader interface simply convert any blit with
a depth/stencil format to a compatible color blit (like we were already
doing for s8d24) and get rid of the depth blitting path. This also allows
us to ignore the blit aspect in the blit pipeline cache key.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
Now that our blit shader interface supports color writemasks and swizzles,
users can specify depth/stencil blits as color blits properly when needed,
so let's just do instead, which is more straight forward and less error prone.
Because s8d24 to s8d24 blits always require the same conversion to color blit,
the blit shader will handle these automatically, including blits of just one
aspect, however, for scenarios where there are additional semantics to consider
(particularly, copies from/to buffer), it is still up to the blit shader caller
to specify a proper color blit matching the required semantics.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
We implement this by blitting the requested region to a linear image
setup to use the buffer memory store at the requested offset.
Because we can't store linear depth/stencil images, we implement
copies of depth/stencil aspects by using a compatible color blit.
To do this, we also need to account for the fact that when we are
copying depth from a d24 format we need to copy them from the MSB
24-bits of each word as provided by the hardware and store them
in the LSB 24-bit of the buffer (as per Vulkan requirements). This
is achieved by expanding our blit interface to also accept a swizzle
to apply to the source texture.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
The page alignment requirement is for UIF images only, and for linear
images it is actually useful to use a 4-byte alignment so we can
use them to write images to linear buffers at arbitrary positions, which
we will need when copying subrects of an image to a buffer.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
An image can be suballocated from a larger memory allocation, in which
case we get a memory offset for the start of the bound region at
vkBindImageMemory. Take that offset into account when doing image
addressing calculations.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
With compressed formats we compute the final height/width dividing by
the block sizes. On some cases the block sizes are bigger that the
original values, or it is not a exact division, so we need to round up
the division.
Fixes tests like:
dEQP-VK.texture.compressed.*
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
As opposed to returning true only if it can handle the case and it
also successfully processes it.
This is because we expect handled cases to be successfully processed
except in abnormal situations such as out-of-memory errors. If an OOM
is the reason a fallback path fails, we don't want to try another path
(which will likely hit an OOM too): we have already recorded the OOM
error in the command buffer and we just want to stop executing the
command, so just flag the case as handled and move on.
Also, if we don't do this, in an OOM scenario we'll likely end up running
out of fallback paths and end up asserting (on debug builds), which makes
some CTS tests unhappy because they expect OOM to be handled more
gracefully, so this allows us to make CTS happy also in debug builds,
which is convenient.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
In "v3dv: implement stencil aspect blits for combined depth/stencil format"
we only implemented the support we needed to implement partial copies.
Copies only allow to copy a single aspect, so we really only supported blitting
either the depth aspect or the stencil aspect, but not both, however,
actual blits (as per vkCmdBlitImage) allow to blit both stencil and depth
aspects at the same time, so this adds support for that.
Finally, this also fixes the fact that we were not really masking color writes
effectively for stencil-only blits, since create_blit_pipeline() would check
the requested aspect to see if it would need to mask writes, but by the time
we called this, we had already switched the aspect to color. The reason this
was not caught before is that for copies this would only mean that when we
copied stencil we would also copy depth, and the image copy CTS tests are
probably copying both aspects anyway.
Fixes:
dEQP-VK.api.copy_and_blit.core.blit_image.all_formats.depth_stencil.*d24_unorm_s8_uint*
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
The idea is that we also want to use the blit mechanism to implement
the copy, like we do for partial image copies. Unfortunately, we can't
sample from a linear image, so we first need to upload the buffer
contents to a tiled image, and then blit from that image to the
destination, which is not great for performance or memory usage.
In the future, we mihgt be able to do better by using a specialized
shader for these copies that takes a UBO as input instead of a texture.
The shader would then be able to access the linea buffer through the
UBO directly without having to copy the buffer contents to a tiled
image first.
This only supports color images for now, we will add support for
depth/stencil images separately.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
Since we don't support rendering to compressed formats, we implement this
by using a compatible format with the same bpp as the compressed format.
However, we need to take into account that the underlying compressed image
bpp is computed for a full block, so when we specify regions on the
compressed image, we need to divide offsets and dimensions by the block
size.
This works well for anything that copies to a compressed format using
the TLB, but it doesn't specifically address copies from compressed
formats to other compatible images. These go through the blit path
and require to copy by blitting (texturing) from the compressed format
to another format. In this case, we choose a comptible format with
the per-texel bpp (not the block bpp) of the compressed format so it
matches the setup for the blit operation.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>