Compare commits

...

909 Commits

Author SHA1 Message Date
Jason Ekstrand
e9dff5bb99 vk: Add an ICD declaration file 2015-09-24 14:45:58 -07:00
Jason Ekstrand
39cd3783a4 anv: Add support for the ICD loader 2015-09-24 14:45:58 -07:00
Jason Ekstrand
a95f51c1d7 anv: Add a global dispatch table for use in meta operations 2015-09-24 14:45:58 -07:00
Jason Ekstrand
00d18a661f anv/entrypoints: Expose the anv_resolve_entrypoint function 2015-09-24 14:45:58 -07:00
Jason Ekstrand
f5e72695e0 anv/entrypoints: Rename anv_layer to anv_dispatch_table 2015-09-24 14:45:58 -07:00
Jason Ekstrand
913a9b76f7 anv/batch_chain: Remove the current_surface_bo helper
It's no longer used outside anv_batch_chain so we certainly don't need to
be exporting.  Inside anv_batch_chain, it's only used twice and it can be
replaced by a single line so there's really no point.
2015-09-24 08:46:41 -07:00
Jason Ekstrand
bc17f9c9d7 anv/cmd_buffer: Add a helper for getting the surface state base address 2015-09-24 08:42:38 -07:00
Jason Ekstrand
e1a7c721d3 anv/allocator: Don't ever call mremap
This has always been a bit sketchy and neither Kristian nor I have ever
really liked it.
2015-09-24 08:42:14 -07:00
Jason Ekstrand
99e62f5ce8 anv/allocator: Delete the unused center_fd_offset from anv_block_pool 2015-09-24 08:41:56 -07:00
Jason Ekstrand
429665823d anv/allocator: Do a better job of centering bi-directional block pools 2015-09-24 08:41:47 -07:00
Jason Ekstrand
76be58efce anv/batch_chain: Clean up the reloc list swapping code 2015-09-24 08:41:38 -07:00
Jason Ekstrand
041f5ea089 anv/meta: Add location specifiers to meta shaders 2015-09-21 16:21:56 -07:00
Jason Ekstrand
f406b708a5 Merge branch 'nir-spirv' into vulkan 2015-09-17 20:03:40 -07:00
Jason Ekstrand
616db92b01 nir/spirv: Add better location handling
Previously, our location handling was focussed on either no location
(usually implicit 0) or a builting.  Unfortunately, if you gave it a
location, it would blow it away and just not care.  This worked fine with
crucible and our meta shaders but didn't work with the CTS.  The new code
uses the "data.explicit_location" field to denote that it has a "final"
location (usually from a builtin) and, otherwise, the location is
considered to be relative to the base for that shader stage.
2015-09-17 20:02:46 -07:00
Jason Ekstrand
a788e7c659 anv/device: Move mutex initialization to befor block pools 2015-09-17 18:23:21 -07:00
Jason Ekstrand
595e6cacf1 meta: Initial support for packing parameters
Probably incomplete but it should do for now
2015-09-17 18:21:05 -07:00
Jason Ekstrand
d616493953 anv/meta: Pass the depth through the clear vertex shader
It shouldn't matter since we shut off the VS but it's at least clearer.
2015-09-17 18:09:21 -07:00
Jason Ekstrand
3b8aa26b8e anv/formats: Properly report depth-stencil formats 2015-09-17 17:44:20 -07:00
Jason Ekstrand
b5f6889648 vk/device: Don't allow device or instance creation with invalid extensions 2015-09-17 17:44:20 -07:00
Jason Ekstrand
dcf424c98c anv/tests: Add some asserts for data integrity in block_pool_no_free 2015-09-17 17:44:20 -07:00
Jason Ekstrand
5f57ff7e18 anv/allocator: Make the block pool double-ended
This allows us to allocate from either side of the block pool in a
consistent way.  If you use the previous block_pool_alloc function, you
will get offsets from the start of the pool as normal.  If you use the new
block_pool_alloc_back function, you will get a negative index that
corresponds to something in the "back" of the pool.
2015-09-17 17:44:20 -07:00
Jason Ekstrand
15624fcf55 anv/tests: Refactor the block_pool_no_free test
This simply breaks the monotonicity check out into its own function
2015-09-17 17:44:20 -07:00
Jason Ekstrand
55daed947d vk/allocator: Split block_pool_alloc into two functions 2015-09-17 17:44:20 -07:00
Jason Ekstrand
c55fa89251 anv/allocator: Use a signed 32-bit offset for the free list
This has the unfortunate side-effect of making it so that we can't have a
block pool bigger than 1GB.  However, that's unlikely to happen and, for
the sake of bi-directional block pools, we need to negative offsets.
2015-09-17 17:44:20 -07:00
Jason Ekstrand
8c6bc1e85d anv/allocator: Create 2GB memfd up-front for the block pool 2015-09-17 17:44:20 -07:00
Jason Ekstrand
74bf7aa07c anv/allocator: Take the device mutex when growing a block pool
We don't have any locking issues yet because we use the pool size itself as
a mutex in block_pool_alloc to guarantee that only one thread is resizing
at a time.  However, we are about to add support for growing the block pool
at both ends.  This introduces two potential races:

 1) You could have two block_pool_alloc() calls that both try to grow the
    block pool, one from each end.

 2) The relocation handling code will now have to think about not only the
    bo that we use for the block pool but also the offset from the start of
    that bo to the center of the block pool.  It's possible that the block
    pool growing code could race with the relocation handling code and get
    a bo and offset out of sync.

Grabbing the device mutex solves both of these problems.  Thanks to (2), we
can't really do anything more granular.
2015-09-17 17:44:20 -07:00
Jason Ekstrand
222ddac810 anv: Document the index and offset parameters of anv_bo 2015-09-17 17:44:20 -07:00
Chad Versace
85520aa070 vk/image: Remove stale FINISHME for non-2D image views
gen8_image_view_init() now supports 1D, 2D, and 3D image views.
2015-09-14 15:16:57 -07:00
Chad Versace
622a317e4c vk/image: Teach vkCreateImage about layout of 1D surfaces
Calling vkCreateImage() with VK_IMAGE_TYPE_1D now succeeds and computes
the surface layout correctly.
2015-09-14 15:15:12 -07:00
Chad Versace
6221593ff8 vk/meta: Partially implement vkCmdCopy*, vkCmdBlit* for 3D images
Partially implement the below functions for 3D images:
    vkCmdCopyBufferToImage
    vkCmdCopyImageToBuffer
    vkCmdCopyImage
    vkCmdBlitImage

Not all features work, and there is much for performance improvement.
Beware that vkCmdCopyImage and vkCmdBlitImage are untested.  Crucible
proves that vkCmdCopyBufferToImage and vkCmdCopyImageToBuffer works,
though.

Supported:
    - copy regions with z offset

Unsupported:
    - copy regions with extent.depth > 1

Crucible test results on master@d452d2b are:
    pass: func.miptree.r8g8b8a8-unorm.*.view-3d.*
    pass: func.miptree.d32-sfloat.*.view-3d.*
    fail: func.miptree.s8-uint.*.view-3d.*
2015-09-14 14:27:34 -07:00
Chad Versace
0ecafe0285 vk/meta: Rename meta_emit_blit() params
Rename src -> src_view and dest -> dest_view. This reduces noise in the next
patch's diff, which adds new params to the function.
2015-09-14 12:29:51 -07:00
Chad Versace
b659a066e9 vk/gen8: Set RENDER_SURFACE_STATE::RenderTargetViewExtent 2015-09-14 12:29:49 -07:00
Chad Versace
ffa61e1572 vk/gen8: Refactor setting of SURFACE_STATE::Depth
The field's meaning depends on SURFACE_STATE::SurfaceType.
Make that correlation explicit by switching on VkImageType.
For good measure, add some PRM quotes too.
2015-09-14 12:27:05 -07:00
Chad Versace
eed74e3a02 vk: Teach vkCreateImage about layout of 3D surfaces
Calling vkCreateImage() with VK_IMAGE_TYPE_3D now succeeds and computes
the surface layout correctly. However, 3D images do not yet work for
many other Vulkan entrypoints.
2015-09-14 11:04:08 -07:00
Chad Versace
e01d5a0471 vk: Refactor anv_image_make_surface()
Move the code that calculates the layout of 2D surfaces into a switch case.
2015-09-14 11:00:18 -07:00
Jason Ekstrand
8c8ad6dddf vk: Use push constants for dynamic buffers 2015-09-11 15:56:19 -07:00
Jason Ekstrand
2b4a2eb592 vk/compiler: Rework create_params_array 2015-09-11 15:55:54 -07:00
Jason Ekstrand
c3086c54a8 vk/compiler: Add a NIR pass for pushing dynamic buffer offset
This commit just adds the NIR pass but does none of the uniform setup
2015-09-11 15:53:56 -07:00
Jason Ekstrand
7487371056 vk/pipeline_layout: Add dynamic_offset_start and has_dynamic_offsets fields 2015-09-11 15:52:43 -07:00
Jason Ekstrand
de5220c7ce vk/pipeline_layout: Move surface/sampler start from SoA to AoS
This makes more sense to me and it's more consistent with
anv_descriptor_set_layout.
2015-09-11 10:43:55 -07:00
Jason Ekstrand
b908c67816 vk: Rework the push constants data structure
Previously, we simply had a big blob of stuff for "driver constants".  Now,
we have a very specific data structure that contains the driver constants
that we care about.
2015-09-11 10:25:23 -07:00
Jason Ekstrand
fd21f0681a Add the wayland protocol files to .gitignire 2015-09-11 09:29:40 -07:00
Jason Ekstrand
8040dc4ca5 vk/error: Handle ERROR_OUT_OF_DATE_WSI 2015-09-08 12:13:07 -07:00
Jason Ekstrand
060720f0c9 vk/wsi/x11: Actually block on X so we don't re-use busy buffers 2015-09-08 11:51:47 -07:00
Jason Ekstrand
1bee19e023 vk: Add the WSI header files 2015-09-08 10:33:46 -07:00
Jason Ekstrand
2f3de6260d Merge branch 'nir-spirv' into vulkan 2015-09-05 14:12:59 -07:00
Jason Ekstrand
4d73ca3c58 nir/spirv.h: Remove some cruft missed while merging
There were merge conflicts in spirv.h that got missed because they were in
a comment and so it still compiled.  This gets rid of them and we should be
on-par with upstream spirv->nir.
2015-09-05 14:11:40 -07:00
Jason Ekstrand
612b13aeae nir/spirv: Add support for most of the rest of texturing
Assuming this all works, about the only thing left should be some
corner-cases for tg4
2015-09-05 14:10:05 -07:00
Jason Ekstrand
fe786ff67d Merge branch 'nir-spirv' into vulkan 2015-09-05 13:17:53 -07:00
Jason Ekstrand
35fcd37fcf nir/spirv: Handle decorations after assigning variable locations 2015-09-05 13:17:21 -07:00
Jason Ekstrand
87d02f515b Merge branch 'nir-spirv' into vulkan 2015-09-05 09:48:33 -07:00
Jason Ekstrand
9be43ef99c nir/spirv: Handle the MatrixStride member decoration 2015-09-05 09:47:45 -07:00
Jason Ekstrand
01924a03d4 vk: Actually link in wayland libraries
Turns out this was why I had accidentally broken the universe.  Oops...
2015-09-04 20:02:38 -07:00
Jason Ekstrand
2c4ae00db6 vk: Conditionally compile Wayland support
Pulling in libwayland causes undefined symbols in applications that are
linked against vulkan alone.  Ideally, we would like to dlopen a platform
support library or something like that.  For now, this works and should get
crucible running again.
2015-09-04 19:18:52 -07:00
Jason Ekstrand
b3c037f329 vk: Fix size return value handling in a couple plces 2015-09-04 19:05:51 -07:00
Jason Ekstrand
9a95d08ed6 Merge branch 'nir-spirv' into vulkan 2015-09-04 18:54:15 -07:00
Jason Ekstrand
6d5dafd779 nir/spirv/glsl450: Use the correct write mask 2015-09-04 18:50:14 -07:00
Jason Ekstrand
7174d155e9 nir: Add a lower_fdiv option and use it in i965 2015-09-04 18:50:14 -07:00
Jason Ekstrand
f32d16a9f0 nir/spirv: Use the actual GLSL 450 extension header from Khronos 2015-09-04 18:50:14 -07:00
Jason Ekstrand
9e2c13350e nir/spirv: Add support for SpvDecorationColMajor 2015-09-04 18:50:14 -07:00
Jason Ekstrand
f3bdb93a8e nir/types: Allow single-column matrices
This can sometimes be a convenient way to build vectors.
2015-09-04 18:50:14 -07:00
Jason Ekstrand
48e87c0163 vk/wsi: Add Wayland WSI support 2015-09-04 17:55:42 -07:00
Jason Ekstrand
348cb29a20 vk/wsi: Move to a clallback system for the entire WSI implementation
We do this for two reasons: First, because it allows us to simplify WSI and
compiling in/out support for a particular platform is as simple as calling
or not calling the platform-specific init function.  Second, the
implementation gives us a place for a given chunk of the WSI to stash
stuff in the instance.
2015-09-04 17:55:42 -07:00
Jason Ekstrand
06d8fd5881 vk/instance: Expose anv_instance_alloc/free 2015-09-04 17:55:42 -07:00
Jason Ekstrand
c0b97577e8 vk/WSI: Use a callback mechanism instead of explicit switching 2015-09-04 17:55:42 -07:00
Jason Ekstrand
ca3cfbf6f1 vk: Add an initial implementation of the actual Khronos WSI extension
Unfortunately, this is a very large commit and removes the old LunarG WSI
extension.  This is because there are a couple of entrypoints that have the
same name between the two extensions so implementing them both is
impractiacl.

Support is still incomplete, but this is enough to get vkcube up and going
again.
2015-09-04 17:55:42 -07:00
Jason Ekstrand
3d9fbb6575 vk: Add initial support for VK_WSI_swapchain 2015-09-04 17:55:42 -07:00
Jason Ekstrand
beb466ff5b vk: Move anv_x11.c to anv_wsi_x11.c 2015-09-04 17:55:42 -07:00
Jason Ekstrand
9a7600c9b5 vk/device: Use an array for device extensions 2015-09-04 17:55:42 -07:00
Kristian Høgsberg Kristensen
8af3624651 vk: Further reduce diff to master
Now that we don't compile GLSL, we can roll back a few more hacks and
unexport some things from the backend compiler.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-04 16:17:01 -07:00
Kristian Høgsberg Kristensen
7c1d20dc48 vk: Drop GLSL code from anv_compiler.cpp
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 14:02:11 -07:00
Kristian Høgsberg Kristensen
316c8ac53b vk: Assert that the SPIR-V module has the magic number
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 12:27:28 -07:00
Kristian Høgsberg Kristensen
6e35a1f166 vk: Remove various hacks/scaffolding code
Since we switched away from calling brwCreateContext() there's a bit of
hacky support we can now delete.  This reduces our diff to upstream master.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 12:17:13 -07:00
Kristian Høgsberg Kristensen
1d787781ff vk: Fall back to previous gens in entry point resolver
We used to always just do a one-level fallback from genX_* to anv_*
entry points. That worked for gen7 and gen8 where all entry points were
either different or could be made anv_* entry points (eg
anv_CreateDynamicViewportState). We're about to add gen9 and now need to
be able to fall back to gen8 entry points for most things.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 11:53:09 -07:00
Kristian Høgsberg Kristensen
c4dbff58d8 vk: Drop redundant gen7_CreateGraphicsPipelines
This is handled by anv_CreateGraphicsPipelines().

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 11:53:09 -07:00
Kristian Høgsberg Kristensen
b5e90f3f48 vk: Use vk* entrypoints in meta, not driver_layer pointers
We'll change the dispatch mechanism again in a later commit. Stop using
the driver_layer function pointers and just use the public entry points.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 11:53:09 -07:00
Kristian Høgsberg Kristensen
82396a5514 vk: Drop check for I915_PARAM_HAS_EXEC_CONSTANTS
We don't use this kernel feature.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 11:53:08 -07:00
Kristian Høgsberg Kristensen
c4b30e7885 vk: Add new vk_errorf that takes a format string
This allows us to annotate error cases in debug builds.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 11:53:08 -07:00
Kristian Høgsberg Kristensen
2e346c882d vk: Make vk_error a little more helpful
Print out file and line number and translate the error code to the
symbolic name.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-09-03 11:53:08 -07:00
Chad Versace
0cb26523d3 vk/image: Add PRM reference for QPitch equation
Suggested-by: Nanley Chery <nanley.g.chery@intel.com>
2015-09-03 11:04:38 -07:00
Chad Versace
28503191f1 vk/meta: Partially fix vkCmdCopyBufferToImage for S8_UINT
Create R8_UINT VkAttachmentView and VkImageView for the stencil data.

This fixes a crash, but the pixels in the destination image are still
incorrect. They are not properly tiled.

Fixes crashes in Crucible tests func.miptree.s8-uint.aspect-stencil.* as
of crucible-7471449. Test results improve 'lost' -> 'fail'.
2015-09-02 11:08:36 -07:00
Jason Ekstrand
be0a4da6a5 vk/meta: Use SPIR-V for shaders
We are also now using glslc for compiling the Vulkan driver like we do in
curcible.
2015-09-01 15:16:06 -07:00
Jason Ekstrand
362ab2d788 vk/compiler: Handle interpolation qualifiers for SPIR-V shaders 2015-09-01 15:15:04 -07:00
Jason Ekstrand
126ade0023 vk/extensions: count needs to be <= number of extensions 2015-09-01 12:28:50 -07:00
Jason Ekstrand
0c2d476935 vk/compiler: Properly reference/delete programs when using SPIR-V 2015-09-01 12:28:50 -07:00
Jason Ekstrand
16ebe883a4 vk/meta: Add a helper for making an image from a buffer 2015-08-31 21:54:38 -07:00
Jason Ekstrand
86c3476668 nir/spirv: Use VERTEX_ID_ZERO_BASE for VertexId
In Vulkan, VertexId and InstanceId will be zero-based and new intrinsics,
VertexIndex and InstanceIndex, will be added for non-zer-based.  See also,
Khronos bug #14255
2015-08-31 17:16:49 -07:00
Jason Ekstrand
6350c97412 Merge remote-tracking branch 'fdo-personal/nir-spirv' into vulkan
From now on, the majority of SPIR-V improvements should happen on the spirv
branch which will also be public.  It will be frequently merged into the
vulkan driver.
2015-08-31 17:14:47 -07:00
Jason Ekstrand
22fdb2f855 nir/spirv: Update to the latest revision 2015-08-31 17:05:23 -07:00
Jason Ekstrand
ce70cae756 nir/builder: Use nir_after_instr to advance the cursor
This *should* ensure that the cursor gets properly advanced in all cases.
We had a problem before where, if the cursor was created using
nir_after_cf_node on a non-block cf_node, that would call nir_before_block
on the block following the cf node.  Instructions would then get inserted
in backwards order at the top of the block which is not at all what you
would expect from nir_after_cf_node.  By just resetting to after_instr, we
avoid all these problems.
2015-08-31 17:05:23 -07:00
Jason Ekstrand
24b0c53231 nir/intrinsics: Move to a two-dimensional binding model for UBO's 2015-08-31 17:05:23 -07:00
Jason Ekstrand
f4608bc530 nir/nir_variable: Add a descriptor set field
We need this for SPIR-V
2015-08-31 17:05:23 -07:00
Jason Ekstrand
85cf2385c5 mesa: Move gl_vert_attrib from mtypes.h to shader_enums.h
It is a shader enum after all...
2015-08-31 17:05:23 -07:00
Jason Ekstrand
de4f379a70 nir/cursor: Add a helper for getting the current block 2015-08-31 17:05:23 -07:00
Connor Abbott
024c49e95e nir/builder: add a nir_fdot() convenience function 2015-08-31 17:05:23 -07:00
Jason Ekstrand
f6a0eff1ba nir: Add a pass to lower outputs to temporary variables
This pass can be used as a helper for NIR producers so they don't have to
worry about creating the temporaries themselves.
2015-08-31 17:05:23 -07:00
Jason Ekstrand
4956bbaa33 nir/cursor: Add a constructor for the end of a block but before the jump 2015-08-31 16:58:20 -07:00
Connor Abbott
c62be38286 nir/types: add more nir_type_is_xxx() wrappers 2015-08-31 16:58:20 -07:00
Connor Abbott
a1e136711b nir/types: add a helper to transpose a matrix type 2015-08-31 16:58:20 -07:00
Jason Ekstrand
756b00389c nir/spirv: Don't assert that the current block is empty
It's possible that someone will give us SPIR-V code in which someone
needlessly branches to new blocks.  We should handle that ok now.
2015-08-31 16:58:20 -07:00
Jason Ekstrand
fe220ebd37 nir/spirv: Add initial support for samplers 2015-08-31 16:58:20 -07:00
Jason Ekstrand
a992909aae nir/spirv: Move Exp and Log to the list of currently unhandled ALU ops
NIR doesn't have the native opcodes for them anymore
2015-08-31 16:58:20 -07:00
Jason Ekstrand
45963c9c64 nir/types: Add support for sampler types 2015-08-31 16:58:20 -07:00
Jason Ekstrand
2887e68f36 nir/spirv: Make the global constants in spirv.h static
I've been promissed in a bug that this will be fixed in a future version of
the header.  However, in the interest of my branch building, I'm adding
these changes in myself for the moment.
2015-08-31 16:58:20 -07:00
Jason Ekstrand
62b094a81c nir/spirv: Handle jump-to-loop in a more general way 2015-08-31 16:58:20 -07:00
Jason Ekstrand
ca51d926fd nir/spirv: Handle boolean uniforms correctly 2015-08-31 16:58:20 -07:00
Jason Ekstrand
b6562bbc30 nir/spirv: Handle control-flow with loops 2015-08-31 16:58:20 -07:00
Jason Ekstrand
4a63761e1d nir/spirv: Set a name on temporary variables 2015-08-31 16:58:20 -07:00
Jason Ekstrand
6fc7911d15 nir/spirv: Use the correct length for copying string literals 2015-08-31 16:58:20 -07:00
Jason Ekstrand
9da6d808be nir/spirv: Make vtn_ssa_value handle constants as well as ssa values 2015-08-31 16:58:20 -07:00
Jason Ekstrand
1feeee9cf4 nir/spirv: Add initial support for GLSL 4.50 builtins 2015-08-31 16:58:20 -07:00
Jason Ekstrand
577c09fdad nir/spirv: Split the core datastructures into a header file 2015-08-31 16:58:20 -07:00
Jason Ekstrand
66fc7f252f nir/spirv: Use the builder for all instructions
We don't actually use it to create all the instructions but we do use it
for insertion always.  This should make things far more consistent for
implementing extended instructions.
2015-08-31 16:58:20 -07:00
Jason Ekstrand
9e03b6724c nir/spirv: Add support for a bunch of ALU operations 2015-08-31 16:58:20 -07:00
Jason Ekstrand
91b3b46d8b nir/spirv: Add support for indirect array accesses 2015-08-31 16:58:20 -07:00
Jason Ekstrand
9197e3b9fc nir/spirv: Explicitly type constants and SSA values 2015-08-31 16:58:20 -07:00
Jason Ekstrand
b7904b8281 nir/spirv: Handle OpBranchConditional
We do control-flow handling as a two-step process.  The first step is to
walk the instructions list and record various information about blocks and
functions.  This is where the acutal nir_function_overload objects get
created.  We also record the start/stop instruction for each block.  Then
a second pass walks over each of the functions and over the blocks in each
function in a way that's NIR-friendly and actually parses the instructions.
2015-08-31 16:58:20 -07:00
Jason Ekstrand
d216dcee94 nir/spirv: Add a helper for getting a value as an SSA value 2015-08-31 16:58:20 -07:00
Jason Ekstrand
f36fabb736 nir/spirv: Split instruction handling into preamble and body sections 2015-08-31 16:58:20 -07:00
Jason Ekstrand
7bf4b53f1c nir/spirv: Implement load/store instructiosn 2015-08-31 16:58:20 -07:00
Jason Ekstrand
7d64741a5e nir: Add a helper for getting the tail of a deref chain 2015-08-31 16:58:20 -07:00
Jason Ekstrand
112c607216 nir/spirv: Actaully add variables to the funciton or shader 2015-08-31 16:58:20 -07:00
Jason Ekstrand
4fa1366392 nir/spirv: Add a vtn_untyped_value helper 2015-08-31 16:58:20 -07:00
Jason Ekstrand
e709a4ebb8 nir/spirv: Use vtn_value in the types code and fix a off-by-one error 2015-08-31 16:58:20 -07:00
Jason Ekstrand
67af6c59f2 nir/types: Add an is_vector_or_scalar helper 2015-08-31 16:58:20 -07:00
Jason Ekstrand
5e6c5e3c8e nir/spirv: Add support for deref chains 2015-08-31 16:58:20 -07:00
Jason Ekstrand
366366c7f7 nir/types: Add a scalar type constructor 2015-08-31 16:58:20 -07:00
Jason Ekstrand
befecb3c55 nir/spirv: Add support for OpLabel 2015-08-31 16:58:20 -07:00
Jason Ekstrand
399e962d25 nir/spirv: Add support for declaring functions 2015-08-31 16:58:20 -07:00
Jason Ekstrand
ac4d459aa2 nir/types: Add accessors for function parameter/return types 2015-08-31 16:58:20 -07:00
Jason Ekstrand
3a266a18ae nir/spirv: Add support for declaring variables
Deref chains and variable load/store operations are still missing.
2015-08-31 16:58:20 -07:00
Jason Ekstrand
2494055631 nir/spirv: Add support for constants 2015-08-31 16:58:20 -07:00
Jason Ekstrand
2a023f30a6 nir/spirv: Add basic support for types 2015-08-31 16:58:20 -07:00
Jason Ekstrand
5bb94c9b12 nir/types: Add more helpers for creating types 2015-08-31 16:58:20 -07:00
Jason Ekstrand
53bff3e445 glsl/types: Expose the function_param and struct_field structs to C
Previously, they were hidden behind a #ifdef __cplusplus so C wouldn't find
them.  This commit simpliy moves the #ifdef and adds #ifdef's around
constructors.
2015-08-31 16:58:20 -07:00
Jason Ekstrand
0db3e4dd72 glsl/types: Add support for function types 2015-08-31 16:58:20 -07:00
Jason Ekstrand
1169fcdb05 glsl: Add GLSL_TYPE_FUNCTION to the base types enums 2015-08-31 16:58:20 -07:00
Jason Ekstrand
b79916dacc nir/spirv: Rework the way values are added
Instead of having functions to add values and set various things, we just
have a function that does a few asserts and then returns the value.  The
caller is then responsible for setting the various fields.
2015-08-31 16:58:20 -07:00
Jason Ekstrand
ac60aba351 nir/spirv: Add stub support for extension instructions 2015-08-31 16:58:20 -07:00
Jason Ekstrand
78eabc6153 REVERT: Add a simple helper program for testing SPIR-V -> NIR translation 2015-08-31 16:58:20 -07:00
Jason Ekstrand
2c585a722d glsl/compiler: Move the error_no_memory stub to standalone_scaffolding.cpp 2015-08-31 16:58:20 -07:00
Jason Ekstrand
b20d9f5643 nir: Add the start of a SPIR-V to NIR translator
At the moment, it can handle the very basics of strings and can ignore
debug instructions.  It also has basic support for decorations.
2015-08-31 16:58:20 -07:00
Jason Ekstrand
9d92b4fd0e nir: Import the revision 30 SPIR-V header from Khronos 2015-08-31 16:58:20 -07:00
Jason Ekstrand
0af4bf4d4b Merge remote-tracking branch 'mesa-public/master' into vulkan 2015-08-31 16:30:07 -07:00
Jason Ekstrand
9f9628e9dd vk/SPIR-V: Pull num_uniform_components out of the NIR shader 2015-08-28 22:31:03 -07:00
Jason Ekstrand
44e6ea74b0 spirv: lower outputs to temporaries 2015-08-28 17:38:41 -07:00
Jason Ekstrand
9cebdd78d8 nir: Add a pass to lower outputs to temporary variables
This pass can be used as a helper for NIR producers so they don't have to
worry about creating the temporaries themselves.
2015-08-28 17:38:41 -07:00
Jason Ekstrand
5e7c7b2a4e spirv: Only do a block load if you're actually loading a uniform 2015-08-28 16:17:45 -07:00
Jason Ekstrand
98abed2441 spirv: Use VERTEX_ID_ZERO_BASE for vertex id 2015-08-28 16:08:29 -07:00
Jason Ekstrand
dbc3eb5bb4 vk/compiler: Pass the correct is_scalar value to brw_process_nir 2015-08-28 12:13:17 -07:00
Jason Ekstrand
ea56d0cb1d glsl/types: Fix up function type hash table insertion 2015-08-28 12:00:25 -07:00
Chad Versace
a2d15ee698 vk/meta: Support stencil in vkCmdCopyImageToBuffer
At Crucible commit 12e64a4, fixes the
func.depthstencil.stencil-triangles.* tests on Broadwell.
2015-08-28 08:41:21 -07:00
Chad Versace
84cfc08c10 vk/pipeline: Fix crash when the pipeline has no attributes
If there are no attributes, don't emit 3DSTATE_VERTEX_ELEMENTS.
That packet does not allow 0 attributes.
2015-08-28 08:07:15 -07:00
Chad Versace
053d32d2a5 vk/image: Linear stencil buffers are illegal
The hardware requires that stencil buffer memory be W-tiled.

From the Sandybridge PRM:
   This buffer is supported only in Tile W memory.
2015-08-28 08:04:59 -07:00
Chad Versace
14e1d58fb7 vk: Fix stride of stencil buffers
Stencil buffers have strange pitch. The PRM says:

  The pitch must be set to 2x the value computed based on width,
  as the stencil buffer is stored with two rows interleaved.
2015-08-28 08:03:46 -07:00
Chad Versace
31af126229 vk: Program stencil ops in 3DSTATE_WM_DEPTH_STENCIL
The driver ignored the Vulkan stencil, always programming the hardware
stencil op to 0 (STENCILOP_KEEP).
2015-08-28 08:00:56 -07:00
Chad Versace
bff2879abe vk/image: Don't abort when creating stencil image views
When creating a stencil image view, log a FINISHME but don't abort.
We're sooooo close to having this working.
2015-08-28 07:59:59 -07:00
Chad Versace
4f852c76dc vk/meta: Save/restore VkDynamicDepthStencilState 2015-08-28 07:59:29 -07:00
Chad Versace
104c4e5ddf vk/meta: Don't skip clearing when clearing only depth attachment
anv_cmd_buffer_clear_attachments() skipped the clear renderpass if no
color attachments needed to be cleared, even if a depth attachment
needed to be cleared.
2015-08-28 07:58:51 -07:00
Chad Versace
aacb7bb9b6 vk: Add func anv_cmd_buffer_get_depth_stencil_view()
This function removes some duplicated code from
genN_cmd_buffer_emit_depth_stencil().
2015-08-28 07:57:34 -07:00
Chad Versace
641c25dd55 vk: Declare some local variables as const
In anv_cmd_buffer_emit_depth_stencil(), declare 'subpass' and 'fb' as
const.
2015-08-28 07:53:24 -07:00
Chad Versace
c6f19b4248 vk: Don't duplicate anv_depth_stencil_view's surface data
In anv_depth_stencil_view, replace the members
    bo
    depth_offset
    depth_stride
    depth_format
    depth_qpitch
    stencil_offset
    stencil_stride
    stencil_qpitch
with the single member
    const struct anv_image *image

The removed members duplicated data in anv_image::depth_surface and
anv_image::stencil_surface.
2015-08-28 07:52:19 -07:00
Chad Versace
35b0262a2d vk/gen7: Add func gen7_cmd_buffer_emit_depth_stencil()
This patch moves all the GEN7_3DSTATE_DEPTH_BUFFER code from
gen7_cmd_buffer_begin_subpass() into a new function
gen7_cmd_buffer_emit_depth_stencil().
2015-08-28 07:46:16 -07:00
Chad Versace
b2ee317e24 vk: Fix format of anv_depth_stencil_view
The format of the view itself and of the view's image may differ.
Moreover, if the view's format has no depth aspect but the image's
format does, we must not program the depth buffer. Ditto for stencil.
2015-08-28 07:44:32 -07:00
Chad Versace
798acb2464 vk/gen7: Fix gen of emitted packet in gen7_batch_lri()
Emit GEN7_MI_LOAD_REGISTER_IMM, not the GEN8 version.
2015-08-28 07:36:35 -07:00
Chad Versace
4461392343 vk: Remove dummy anv_depth_stencil_view 2015-08-28 07:35:39 -07:00
Chad Versace
941b48e992 vk/image: Let anv_image have one anv_surface per aspect
Split anv_image::primary_surface into two: anv_image::color_surface and
depth_surface.
2015-08-28 07:17:54 -07:00
Jason Ekstrand
c313a989b4 spirv: Bump to the public revision 31 2015-08-27 15:24:04 -07:00
Jason Ekstrand
2a8d1ac958 vk: Update to API version 0.138.2 2015-08-27 11:41:04 -07:00
Jason Ekstrand
4e3ee043c0 vk/gen8: Add support for push constants 2015-08-27 10:25:58 -07:00
Jason Ekstrand
375a65d5de vk/private.h: Handle a NULL bo but valid offset in __gen_combine_address 2015-08-27 10:25:58 -07:00
Jason Ekstrand
c8365c55f5 vk/cmd_buffer: Set the CONSTANTS_REL_GENERAL flag on execbuf
This tells the kernel that the push constant buffers are relative to the
dynamic state base address.
2015-08-27 10:25:58 -07:00
Jason Ekstrand
efc2cce01f HACK: Don't call nir_setup_uniforms
We're doing our own uniform setup and we don't need to call into the entire
GL stack to mess with things.
2015-08-27 10:25:58 -07:00
Jason Ekstrand
33cabeab01 vk/compiler: Add a helper for setting up prog_data->param
This new helper sets it up the way we'll want for handling push constants.
2015-08-27 10:25:16 -07:00
Jason Ekstrand
5446bf352e vk: Add initial API support for setting push constants
This doesn't add support for actually uploading them, it just ensures that
we have and update the shadow copy.
2015-08-26 17:59:15 -07:00
Jason Ekstrand
36134e1050 Merge remote-tracking branch 'mesa-public/master' into vulkan 2015-08-26 11:04:30 -07:00
Jason Ekstrand
74e076bba8 vk/meta: Destroy vertex shaders when setting up clearing 2015-08-25 18:51:26 -07:00
Jason Ekstrand
4bb9915755 vk/gen8: Don't duplicate generic pipeline setup
gen8_graphics_pipeline_create had a bunch of stuff in it that's already set
up by anv_pipeline_init.  The duplication was causing double-initialization
of a state stream and made valgrind very angry.
2015-08-25 18:41:25 -07:00
Jason Ekstrand
9b387b5d3f Merge remote-tracking branch 'mesa-public/master' into vulkan 2015-08-25 18:41:21 -07:00
Kristian Høgsberg Kristensen
5360edcb30 vk/vec4: Use the right constant for offset into a UBO
We were using constant 0, which is the set.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-25 16:14:59 -07:00
Kristian Høgsberg Kristensen
647a60226d vk: Use true/false for RenderCacheReadWriteMode
This field in surface state is a bool, WriteOnlyCache is an enum from
GEN8.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-25 15:58:21 -07:00
Kristian Høgsberg Kristensen
7e5afa75b5 vk: Support descriptor sets and bindings in vec4 ubo loads
Still incomplete, but at least we get the simplest case working.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-25 15:57:12 -07:00
Kristian Høgsberg Kristensen
00e7799c69 vk/gen7: Enable L3 caching for GEN7 MOCS
Do what GL does here.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-25 15:55:56 -07:00
Kristian Høgsberg Kristensen
6a1098b2c2 vk/gen7: Use TILEWALK_XMAJOR for linear surfaces
You wouldn't think the TileWalk mode matters when TiledSurface is
false. However, it has to be TILEWALK_XMAJOR. Make it so.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-25 10:54:13 -07:00
Kristian Høgsberg Kristensen
f1455ffac7 vk: Add gen7 support
With all the previous commits in place, we can now drop in support for
multiple platforms. First up is gen7 (Ivybridge).

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:41 -07:00
Kristian Høgsberg Kristensen
891995e55b vk: Move 3DSTATE_SBE setup to just before 3DSTATE_PS
This is a more logical place for it, between geometry front end state
and pixel backend state.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:41 -07:00
Kristian Høgsberg Kristensen
9c752b5b38 vk: Move generic pipeline init to anv_pipeline.c
This logic will be shared between multiple gens.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:41 -07:00
Kristian Høgsberg Kristensen
3800573fb5 vk: Move gen8 specific state into gen8 sub-structs
This commit moves all occurances of gen8 specific state into a gen8
substruct. This clearly identifies the state as gen8 specific and
prepares for adding gen7 state structs. In the process we also rename
the field names to exactly match the command or state packet name,
without the 3DSTATE prefix, eg:

  3DSTATE_VF -> gen8.vf
  3DSTATE_WM_DEPTH_STENCIL -> gen8.wm_depth_stencil

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:41 -07:00
Kristian Høgsberg Kristensen
615da3795a vk: Always use a placeholder vertex shader in meta
The clear pipeline didn't have a vertex shader and relied on the clear
shader being hardcoded by the compiler to accept one attribute. This
necessitated a few special cases in the 3DSTATE_VS setup. Instead,
always provide a vertex shader, even if we disable VS dispatch.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:41 -07:00
Kristian Høgsberg Kristensen
ac738ada7a vk: Trim out irrelevant 0-initialized surface state fields
Many of of these fields aren't used for buffer surfaces, so leave them
out for brevity.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:41 -07:00
Kristian Høgsberg Kristensen
963a1e35e7 vk: Update generated headers
This adds VALIGN_2 and VALIGN_4 defines for IVB and HSW
RENDER_SURFACE_STATE.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:41 -07:00
Kristian Høgsberg Kristensen
f5275f7eb3 vk: Move anv_color_attachment_view_init() to gen8_state.c
I'd prefer to move anv_CreateAttachmentView() as well, but it's a little
too much generic code to just duplicate for each gen.  For now, we'll
add a anv_color_attachment_view_init() to dispatch to the gen specific
implementation, which we then call from anv_CreateAttachmentView().

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
988341a73c vk: Move anv_CreateImageView to gen8_state.c
We'll probably want to move some code back into a shared init function,
but this gets one GEN8 surface state initialization out of anv_image.c.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
bc568ee992 vk: Make anv_cmd_buffer_begin_subpass() switch on gen
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
8fe74ec45c vk: Add generic wrapper for filling out buffer surface state
We need this for generating surface state on the fly for dynamic buffer
views.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
a2b822185e vk: Add helper for adding surface state reloc
We're going to have to do this differently for earlier gens, so lets do
it in place only.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
e43fc871be vk: Make batch chain code gen-agnostic
Since the extra dword in MI_BATCH_BUFFER_START added in gen8 is at the
end of the struct, we can emit the gen8 packet on all gens as long as we
set the instruction length correctly.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
25ab43ee8c vk: Move vkCmdPipelineBarrier to gen8_cmd_buffer.c
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
b4ef2302a9 vk: Use helper function for emitting MI_BATCH_BUFFER_START
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
97360ffc6c vk: Use anv_batch_emit() for chaining back to primary batch
We used to use a manual GEN8_MI_BATCH_BUFFER_START_pack() call, but this
refactors the code to use anv_batch_emit();

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
cff717c649 vk: Downgrade state packet to gen7 where they're common
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
64045eebfb vk: Reorder gen8 specific code into three new files
We'll organize gen specific code in three files per gen: pipeline,
cmd_buffer and state, eg:

    gen8_cmd_buffer.c
    gen8_pipeline.c
    gen8_state.c

where gen8_cmd_buffer.c holds all vkCmd* entry points, gne8_pipeline.c
all gen specific code related to pipeline building and remaining state
code (sampler, surface state, dynamic state) in gen8_state.c.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
9f0bb5977b vk: Move gen8_CmdBindIndexBuffer() to anv_gen8.c
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
a7649b2869 vk: Move gen8_cmd_buffer_emit_state_base_address() to anv_gen8.c
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
130db30771 vk: Move gen8 specific parts of queries to anv_gen8.c
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
98126c021f vk: Move dynamic depth stenctil to anv_gen8.c 2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
0bcf85d79f vk: Move pipeline creation to anv_gen8.c 2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
ef0ab62486 vk: Move anv_CreateSampler to anv_gen8.c
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
fb428727e0 vk: Move anv_CreateBufferView to anv_gen8.c
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
74556b076a vk: Add new anv_gen8.c and move CreateDynamicRasterState there
Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-24 13:45:40 -07:00
Kristian Høgsberg Kristensen
ee9788973f vk: Implement multi-gen dispatch mechanism 2015-08-24 13:45:39 -07:00
Chad Versace
c4e7ed9163 vk/meta: Implement depth clears
Fixes Crucible test
func.depthstencil.basic-depth.clear-1.0.op-greater.
2015-08-20 10:25:05 -07:00
Chad Versace
0db3d67a14 vk: Cache each render pass's number of clear ops
During vkCreateRenderPass, count the number of clear ops and store them
in new members of anv_render_pass:

    uint32_t num_color_clear_attachments
    bool has_depth_clear_attachment
    bool has_stencil_clear_attachment

Cacheing these 8 bytes (including padding) reduces the number of times
that anv_cmd_buffer_clear_attachments needs to loop over the pass's
attachments.
2015-08-20 10:25:04 -07:00
Chad Versace
2387219101 vk: Use temp var in vkCreateRenderPass's attachment loop
Store the attachment in a temporary variable and
s/pass->attachments[i]/att/ .
2015-08-20 10:25:04 -07:00
Chad Versace
1c24a191cd vk: Improve memory locality of anv_render_pass
Allocate the pass's array of attachments, anv_render_pass::attachments,
in the same allocation as the pass itself.
2015-08-20 09:31:58 -07:00
Chad Versace
4eaf90effb vk: Unharcode an argument to sizeof
s/struct anv_subpass/pass->subpasses[0])/
2015-08-20 09:31:58 -07:00
Chad Versace
44ef4484c8 vk/meta: Add Z coord to clear vertices
For now, the Z coordinate is always 0.0. Will later be used for depth
clears.
2015-08-20 09:31:12 -07:00
Chad Versace
4aef5c62cd vk/meta: Restore all saved state in anv_cmd_buffer_restore()
anv_cmd_buffer_restore() did not restore the old
VkDynamicColorBlendState.
2015-08-20 09:30:34 -07:00
Chad Versace
9f908fcbde vk/meta: Use consistent names and types in anv_saved_state
In struct anv_saved_state, each member's type was a pointer to an Anvil
struct and each member's name was prefixed with "old" except cb_state,
which was a Vulkan handle whose name lacked "old".
2015-08-20 09:29:41 -07:00
Neil Roberts
49d9e89d00 Add mesa.icd to the .gitignore
Since 4d7e0fa8c7 this file is generated by the configure script.
Reviewed-by: Tapani Palli <tapani.palli@intel.com>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>

(cherry picked from commit 885762e182)
2015-08-19 14:12:31 -07:00
Chad Versace
bd0aab9a58 vk/meta: Fix dest format of vkCmdCopyImage
The source image's format was incorrectly used for both the source view
and destination view. For vkCmdCopyImage to correctly translate formats,
the destination view's format must be that of the destination image's.
2015-08-18 12:44:06 -07:00
Chad Versace
b0875aa911 vk: Assert that swap chain format is a color format 2015-08-18 12:43:57 -07:00
Chad Versace
d52822541e vk/image: Don't set anv_surface_view::offset twice
It was set twice a few lines apart, and the second setting always
overrode the first.
2015-08-18 11:48:50 -07:00
Chad Versace
e7d3a5df5a vk/meta: Use anv_format_is_color()
That is, replace !anv_format_is_depth_or_stencil() with
anv_format_is_color(). That conveys the meaning better.
2015-08-18 11:48:48 -07:00
Chad Versace
50f7bf70da vk: Add anv_format_is_color() 2015-08-18 11:48:46 -07:00
Chad Versace
6ff95bba8a vk: Add anv_format reference to anv_render_pass_attachment
Change type of anv_render_pass_attachment::format from VkFormat to const
struct anv_format*.  This elimiates the repetitive lookups into the
VkFormat -> anv_format table when looping over attachments during
anv_cmd_buffer_clear_attachments().
2015-08-17 14:08:55 -07:00
Chad Versace
5a6b2e6df0 vk/image: Simplify stencil case for anv_image_create()
Stop creating a temporary VkImageCreateInfo with overriden
format=VK_FORMAT_S8_UINT. Instead, just pass the format override
directly to anv_image_make_surface().
2015-08-17 14:08:55 -07:00
Chad Versace
a9c36daa83 vk/formats: Add global pointer to anv_format for S8_UINT
Stencil formats are often a special case. To reduce the number of lookups
into the VkFormat-to-anv_format translation table when working with
stencil, expose the table's entry for VK_FORMAT_S8_UINT as global
variable anv_format_s8_uint.
2015-08-17 14:08:55 -07:00
Chad Versace
60c4ac57f2 vk: Add anv_format reference t anv_surface_view
Change type of anv_surface_view::format from VkFormat to const struct
anv_format*. This reduces the number of lookups in the VkFormat ->
anv_format table.
2015-08-17 14:08:55 -07:00
Chad Versace
c11094ec9a vk: Pass anv_format to anv_fill_buffer_surface_state()
This moves the translation of VkFormat to anv_format from
anv_fill_buffer_surface_state() to its caller.

A prep commit to reduce more VkFormat -> anv_format translations.
2015-08-17 14:08:55 -07:00
Chad Versace
ded736f16a vk: Add anv_format reference to anv_image
Change type of anv_image::format from VkFormat to const struct
anv_format*. This reduces the number of lookups in the VkFormat ->
anv_format table.
2015-08-17 14:08:55 -07:00
Chad Versace
4ae42c83ec vk: Store the original VkFormat in anv_format
Store the original VkFormat as anv_format::vk_format. This will be used
to reduce format indirection, such as lookups into the VkFormat ->
anv_format translation table.
2015-08-17 14:07:44 -07:00
Jason Ekstrand
e39e1f4d24 vk: Update .gitignore for the autogenerated spirv changes 2015-08-17 11:47:25 -07:00
Kristian Høgsberg Kristensen
aac6f7c3bb vk: Drop aub dumper and PCI ID override feature
These are now available in intel_aubdump from intel-gpu-tools.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-17 11:41:19 -07:00
Kristian Høgsberg Kristensen
6d09d0644b vk: Use anv_image_create() for creating dmabuf VkImage
We need to make sure we use the VkImage infrastructure for creating
dmabuf images.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-17 11:41:19 -07:00
Jason Ekstrand
0deae66eb1 vk: Add an _autogen suffix autogenerated spirv file names
This prevents make from stomping on nir_spirv.h
2015-08-17 11:40:16 -07:00
Jason Ekstrand
6a7ca4ef2c Merge remote-tracking branch 'mesa-public/master' into vulkan 2015-08-17 11:25:03 -07:00
Jason Ekstrand
b4c02253c4 vk: Add four unit tests for our lock-free data-structures 2015-08-14 17:04:39 -07:00
Jason Ekstrand
16c5b9f4ed vk: Build a version of the driver for linking into unit tests 2015-08-14 17:04:39 -07:00
Kristian Høgsberg Kristensen
30d82136bb vk: Update generated headers
This update brings usable IVB/HSW RENDER_SURFACE_STATE structs
and adds more float fields that we previously failed to
recognize.
2015-08-12 21:05:32 -07:00
Kristian Høgsberg Kristensen
9564dd37a0 vk: Query aperture size up front in anv_physical_device_init()
We already query the device in various ways here and we can just also
get the aperture size.  This avoids keeping an extra drm fd open
during the life time of the driver.

Also, we need to use explicit 64 bit types for the aperture size, not
size_t.
2015-08-10 17:18:55 -07:00
Kristian Høgsberg Kristensen
8605ee60e0 vk: Share upload logic and add size assert
This lets us hit an assert if we exceed the block pool size instead of
GPU hanging.

Signed-off-by: Kristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
2015-08-10 17:17:45 -07:00
Jason Ekstrand
6757e2f75c vk/cmd_buffer: Allow for null VkCmdPool's 2015-08-04 14:01:08 -07:00
Kristian Høgsberg Kristensen
4b097d73e6 vk: Call anv_batch_emit_dwords() up front in anv_batch_emit()
This avoids putting a memory barrier between the template struct and
the pack function, which generates much better code.
2015-08-03 15:38:14 -07:00
Kristian Høgsberg Kristensen
fbb119061e vk: Update generated headers
This adds zeroing of reserved blocks of dwords and removes an
instruction definition.
2015-08-03 15:21:27 -07:00
Jason Ekstrand
facf587dea vk/allocator: Solve a data race in anv_block_pool
The anv_block_pool data structure suffered from the exact same race as the
state pool.  Namely, that the uniqueness of the blocks handed out depends
on the next_block value increasing monotonically.  However, this invariant
did not hold thanks to our block "return" concept.
2015-08-03 01:19:34 -07:00
Jason Ekstrand
5e5a783530 vk: Add and use an anv_block_pool_size() helper 2015-08-03 01:18:09 -07:00
Jason Ekstrand
56ce219493 vk/allocator: Make block_pool_grow take and return a size
It takes the old size as an argument and returns the new size as the return
value.  On error, it returns a size of 0.
2015-08-03 01:06:45 -07:00
Jason Ekstrand
fd64598462 vk/allocator: Fix a data race in the state pool
The previous algorithm had a race because of the way we were using
__sync_fetch_and_add for everything.  In particular, the concept of
"returning" over-allocated states in the "next > end" case was completely
bogus.  If too many threads were hitting the state pool at the same time,
it was possible to have the following sequence:

A: Get an offset (next == end)
B: Get an offset (next > end)
A: Resize the pool (now next < end by a lot)
C: Get an offset (next < end)
B: Return the over-allocated offset
D: Get an offset

in which case D will get the same offset as C.  The solution to this race
is to get rid of the concept of "returning" over-allocated states.
Instead, the thread that gets a new block simply sets the next and end
offsets directly and threads that over-allocate don't return anything and
just futex-wait.  Since you can only ever hit the over-allocate case if
someone else hit the "next == end" case and hasn't resized yet, you're
guaranteed that the end value will get updated and the futex won't block
forever.
2015-08-03 00:38:48 -07:00
Jason Ekstrand
481122f4ac vk/allocator: Make a few things more consistant 2015-08-03 00:35:19 -07:00
Jason Ekstrand
e65953146c vk/allocator: Use memory pools rather than (MALLOC|FREE)LIKE
We have pools, so we should be using them.  Also, I think this will help
keep valgrind from getting confused when we have to end up fighting with
system allocations such as those from malloc/free and mmap/munmap.
2015-07-31 10:38:28 -07:00
Jason Ekstrand
1920ef9675 vk/allocator: Add an anv_state_pool_finish function
Currently this is a no-op but it gives us a place to put finalization
things in the future.
2015-07-31 10:38:28 -07:00
Jason Ekstrand
930598ad56 vk/instance: valgrind-guard client-provided allocations 2015-07-31 10:38:23 -07:00
Jason Ekstrand
e40bdcef1f vk/device: Add anv_instance_alloc/free helpers
This way we can more consistently alloc/free the device and it will provide
us a better place to put valgrind hooks in the next patch
2015-07-31 10:14:17 -07:00
Jason Ekstrand
0f050aaa15 vk/device: Mark newly allocated memory as undefined for valgrind
This way valgrind still works even if the client gives us memory that has
been initialized or re-uses memory for some reason.
2015-07-31 09:44:42 -07:00
Jason Ekstrand
1f49a7d9fc vk/batch_chain: Decrement num_relocs instead of incrementing it 2015-07-31 09:11:47 -07:00
Jason Ekstrand
220a01d525 vk/batch_chain: Compute secondary exec mode after finishing the bo
Figuring out whether or not to do a copy requires knowing the length of the
final batch_bo.  This gets set by anv_batch_bo_finish so we have to do it
afterwards.  Not sure how this was even working before.
2015-07-31 08:52:30 -07:00
Jason Ekstrand
26ba0ad54d vk: Re-name command buffer implementation files
Previously, the command buffer implementation was split between
anv_cmd_buffer.c and anv_cmd_emit.c.  However, this naming convention was
confusing because none of the Vulkan entrypoints for anv_cmd_buffer were
actually in anv_cmd_buffer.c.  This changes it so that anv_cmd_buffer.c is
what you think it is and the internals are in anv_batch_chain.c.
2015-07-30 15:00:42 -07:00
Jason Ekstrand
e379cd9a0e vk/cmd_buffer: Add a simple command pool implementation 2015-07-30 14:55:49 -07:00
Jason Ekstrand
4c2a182a36 vk/cmd_buffer: Add support for zero-copy batch chaining 2015-07-30 14:22:17 -07:00
Jason Ekstrand
21004f23bf vk: Add initial support for secondary command buffers 2015-07-30 11:36:48 -07:00
Jason Ekstrand
5aee803b97 vk/cmd_buffer: Split batch chaining into a helper function 2015-07-30 11:34:58 -07:00
Jason Ekstrand
0c4a2dab7e vk/device: Make BATCH_SIZE a global #define 2015-07-30 11:34:09 -07:00
Jason Ekstrand
ace093031d vk/cmd_buffer: Add functions for cloning a list of anv_batch_bo's
We'll need this to implement secondary command buffers.
2015-07-30 11:32:27 -07:00
Jason Ekstrand
7af67e085f vk/reloc_list: Actually set the new length in reloc_list_grow 2015-07-30 11:29:55 -07:00
Jason Ekstrand
f15be18c92 util/list: Add list splicing functions
This adds functions for splicing one list into another.  These have
more-or-less the same API as the kernel list splicing functions.
2015-07-30 11:28:22 -07:00
Jason Ekstrand
e39d0b635c CLONE 2015-07-30 08:24:02 -07:00
Jason Ekstrand
82548a3aca vk/cmd_buffer: Invalidate texture cache in emit_state_base_address
Previously, the caller of emit_state_base_address was doing this.  However,
putting it directly in emit_state_base_address means that we'll never
forget the flush at the cost of one PIPE_CONTROL at the top every batch
(that should do nothing since the kernel just flushed for us).
2015-07-30 08:24:02 -07:00
Jason Ekstrand
56ce896d73 vk/cmd_buffer: Rename emit_batch_buffer_end to end_batch_buffer
This is more generic and doesn't imply that it emits MI_BATCH_BUFFER_END.
While we're at it, we'll move NOOP adding from bo_finish to
end_batch_buffer.
2015-07-30 08:24:02 -07:00
Jason Ekstrand
3ed9cea84d vk/cmd_buffer: Use an array to track all know anv_batch_bo objects
Instead of walking the list of batch and surface buffers, we simply keep
track of all known batch and surface buffers as we build the command
buffer.  Then we use this new list to construct the validate list.
2015-07-29 15:30:15 -07:00
Jason Ekstrand
0f31c580bf vk/cmd_buffer: Rework validate list creation
The algorighm we used previously required us to call add_bo in a particular
order in order to guarantee that we get the initial batch buffer as the
last element in the validate list.  The new algorighm does a recursive walk
over the buffers and then re-orders the list.  This should be much more
robust as we start to add circular dependancies in the relocations.
2015-07-29 15:16:54 -07:00
Jason Ekstrand
4fc7510a7c vk/cmd_buffer: Move emit_batch_buffer_end higher in the file 2015-07-29 12:01:08 -07:00
Jason Ekstrand
8208f01a35 vk/cmd_buffer: Store the relocation list in the anv_batch_bo struct
Before, we were doing this thing where we had one big relocation list for
the whole command buffer and each subbuffer took a chunk out of it.  Now,
we store the actual relocation list in the anv_batch_bo.  This comes at the
cost of more small allocations but makes a lot of things simpler.
2015-07-29 12:01:08 -07:00
Jason Ekstrand
7d50734240 vk/batch: Make relocs a pointer to a relocation list
Previously anv_batch.relocs was an actual relocation list.  However, this
is limiting if the implementation of the batch wants to change the
relocation list as the batch progresses.
2015-07-29 12:01:08 -07:00
Kristian Høgsberg Kristensen
fcea3e2d23 vk/headers: Update to new generated gen headers
This update fixes cases where a 48-bit address field was split into
two parts:

    __gen_address_type                           MemoryAddress;
    uint32_t                                     MemoryAddressHigh;

which cases this pack code to be generated:

   dw[1] =
       __gen_combine_address(data, &dw[1], values->MemoryAddress, dw1);

   dw[2] =
      __gen_field(values->MemoryAddressHigh, 0, 15) |
      0;

which breaks for addresses above 4G.

This update also fixes arrays of structs in commands and structs, for
example, we now have:

   struct GEN8_BLEND_STATE_ENTRY                Entry[8];

and the pack functions now write all dwords in the packet, making
valgrind happy.

Finally, we would try to pack 64 bits of blend state into a uint32_t -
that's also fixed now.
2015-07-29 11:02:33 -07:00
Jason Ekstrand
65f3d00cd6 vk/cmd_buffer: Update a comment 2015-07-29 08:33:56 -07:00
Jason Ekstrand
86a53d2880 vk/cmd_buffer: Use a doubly-linked list for batch and surface buffers
This is probably better than hand-rolling the list of buffers.
2015-07-28 17:47:59 -07:00
Jason Ekstrand
6aba52381a vk/aub: Use the data directly from the execbuf2
Previously, we were crawling through the anv_cmd_buffer datastructure to
pull out batch buffers and things.  This meant that every time something in
anv_cmd_buffer changed, we broke aub dumping.  However, aub dumping should
just dump the stuff the kernel knows about so we really don't need to be
crawling driver internals.
2015-07-28 16:53:45 -07:00
Jason Ekstrand
3c2743dcd1 vk/cmd_buffer: Pull the execbuf stuff into a substruct 2015-07-27 16:37:09 -07:00
Jason Ekstrand
4ced8650d4 vk/cmd_buffer: Move the remaining entrypoints into cmd_emit.c 2015-07-27 15:14:31 -07:00
Jason Ekstrand
d4c249364d vk/cmd_buffer: Move the re-emission of STATE_BASE_ADDRESS to the flushing code
This used to happen magically in cmd_buffer_new_surface_state_bo.  However,
according to Ken, STATE_BASE_ADDRESS is very gen-specific so we really
shouldn't have it in the generic data-structure code.
2015-07-27 15:05:06 -07:00
Jason Ekstrand
117d74b4e2 vk/cmd_buffer: Factor the guts of CmdBufferEnd into two helpers 2015-07-27 14:52:16 -07:00
Jason Ekstrand
8fb6405718 vk/cmd_buffer: Factor the guts of (Create|Reset|Destroy)CmdBuffer into helpers 2015-07-27 14:23:56 -07:00
Jason Ekstrand
80ad578c4e vk/private.h: Re-arrange and better comment anv_cmd_buffer 2015-07-27 12:40:43 -07:00
Jason Ekstrand
50e86b5777 vk: Actually advertise 0.138.1 at runtime 2015-07-23 10:44:27 -07:00
Jason Ekstrand
f884b500d0 vk/vulkan.h: Bump to the version 0.138.1 header
This doesn't actually require any implementation changes but it does change
an enum so it is ABI-incompatable with 0.138.0.
2015-07-23 10:38:22 -07:00
Jason Ekstrand
e99773badd vk: Add two more valgrind checks 2015-07-23 08:57:54 -07:00
Jason Ekstrand
b1fcc30ff0 vk/meta: Destroy shader modules 2015-07-22 17:51:26 -07:00
Jason Ekstrand
3460e6cb2f vk/device: Finish the scratch block pool on device destruction 2015-07-22 17:51:14 -07:00
Jason Ekstrand
867f6cb90c vk: Add a FreeDescriptorSets function 2015-07-22 17:33:09 -07:00
Jason Ekstrand
c9dc1f4098 vk/pipeline: Be more sloppy about shader entrypoint names
The CTS passes in NULL names right now.  It's not too hard to support that
as just "main".  With this, and a patch to vulkancts, we now pass all 6
tests.
2015-07-22 15:26:56 -07:00
Chad Versace
2c2233e328 vk: Prefix most filenames with anv
Jason started the task by creating anv_cmd_buffer.c and anv_cmd_emit.c.
This patch finishes the task by renaming all other files except
gen*_pack.h and glsl_scraper.py.
2015-07-17 20:25:38 -07:00
Chad Versace
f70d079854 vk/image: Remove unneeded data from anv_buffer_view
This completes the FINISHME to trim unneeded data from anv_buffer_view.

A VkExtent3D doesn't make sense for a VkBufferView.
So remove the member anv_surface_view::extent, and push it up to the two
objects that actually need it, anv_image_view and anv_attachment_view.
2015-07-17 14:48:23 -07:00
Chad Versace
194b77d426 vk: Document members of anv_surface_view 2015-07-17 14:39:05 -07:00
Chad Versace
169251bff0 vk: Remove more raw casts
This removes nearly all the remaining raw Anvil<->Vulkan casts from the
C source files.  (File compiler.cpp still contains many raw casts, and
I plan on ignoring that).

As far as I can tell, the only remaining raw casts are:
    anv_attachment_view -> anv_depth_stencil_view
    anv_attachment_view -> anv_color_attachment_view
2015-07-17 14:32:22 -07:00
Chad Versace
fc3838376b vk/image: Add braces around multi-line ifs 2015-07-17 13:38:09 -07:00
Connor Abbott
b2cfd85060 nir/spirv: don't declare builtin blocks
They aren't used, and the backend was barfing on them. Also, remove a
hack in in compiler.cpp now that they're gone.
2015-07-16 11:04:22 -07:00
Connor Abbott
b599735be4 nir/spirv: add support for loading UBO's
We directly emit ubo load intrinsics based off of the offset information
handed to us from SPIR-V.
2015-07-16 10:54:09 -07:00
Connor Abbott
513ee7fa48 nir/types: add more nir_type_is_xxx() wrappers 2015-07-15 21:58:32 -07:00
Connor Abbott
9fa0989ff2 nir: move to two-level binding model for UBO's
The GLSL layer above is still hacky, so we're really just moving the
hack into GLSL-to-NIR. I'd rather not go all the way and make GLSL
support the Vulkan binding model too, since presumably we'll be
switching to SPIR-V exclusively, and so working on proper GLSL support
will be a waste of time. For now, doing this keeps it working as we add
SPIR-V->NIR support though.
2015-07-15 17:18:48 -07:00
Chad Versace
5520221118 vk: Remove unneeded vulkan-138.h 2015-07-15 17:16:07 -07:00
Chad Versace
73a8f9543a vk: Bump vulkan.h version to 0.138 2015-07-15 17:16:07 -07:00
Chad Versace
55781f8d02 vk/0.138: Update VkResult values 2015-07-15 17:16:07 -07:00
Chad Versace
756d8064c1 vk/0.132: Do type-safety 2015-07-15 17:16:07 -07:00
Jason Ekstrand
927f54de68 vk/cmd_buffer: Move batch buffer padding to anv_batch_bo_finish() 2015-07-15 17:11:04 -07:00
Jason Ekstrand
9c0db9d349 vk/cmd_buffer: Rename bo_count to exec2_bo_count 2015-07-15 16:56:29 -07:00
Jason Ekstrand
6037b5d610 vk/cmd_buffer: Add a helper for allocating dynamic state
This matches what we do for surface state and makes the dynamic state pool
more opaque to things that need to get dynamic state.
2015-07-15 16:56:29 -07:00
Jason Ekstrand
7ccc8dd24a vk/private.h: Move cmd_buffer functions to near the cmd_buffer struct 2015-07-15 16:56:29 -07:00
Jason Ekstrand
d22d5f25fc vk: Split command buffer state into its own structure
Everything else in anv_cmd_buffer is the actual guts of the datastructure.
2015-07-15 16:56:29 -07:00
Jason Ekstrand
da4d9f6c7c vk: Move most of the anv_Cmd related stuff to its own file 2015-07-15 16:56:28 -07:00
Jason Ekstrand
d862099198 vk: Pull the guts of anv_cmd_buffer into its own file 2015-07-15 16:56:28 -07:00
Chad Versace
498ae009d3 vk/glsl: Replace raw casts
Needed for upcoming type-safety changes.
2015-07-15 15:51:37 -07:00
Chad Versace
6f140e8af1 vk/meta: Remove raw casts
Needed for upcoming type-safety changes.
2015-07-15 15:51:37 -07:00
Chad Versace
badbf0c94a vk/x11: Remove raw casts
The raw casts in the WSI functions will break the build when the
type-safety changes arrive.
2015-07-15 15:49:10 -07:00
Chad Versace
61a4bfe253 vk: Delete vkDbgSetObjectTag()
Because VkObject is going away.
2015-07-15 15:34:20 -07:00
Jason Ekstrand
e1c78ebe53 vk/device: Remove unneeded checks for NULL 2015-07-15 15:22:32 -07:00
Jason Ekstrand
f4748bff59 vk/device: Provide proper NULL handling in anv_device_free
The Vulkan spec does not specify that the free function provided to
CreateInstance must handle NULL properly so we do it in the wrapper.  If
this ever changes in the spec, we can delete the extra 2 lines.
2015-07-15 15:22:32 -07:00
Chad Versace
4c8e1e5888 vk: Stop internally calling anv_DestroyObject()
Replace each anv_DestroyObject() with anv_DestroyFoo().

Let vkDestroyObject() live for a while longer for Crucible's sake.
2015-07-15 15:11:16 -07:00
Chad Versace
f5ad06eb78 vk: Fix vkDestroyObject dispatch for VkRenderPass
It called anv_device_free() instead of anv_DestroyRenderPass().
2015-07-15 15:07:41 -07:00
Chad Versace
188f2328de vk: Fix vkCreate/DestroyRenderPass
While updating vkDestroyObject, I discovered that vkDestroyPass reliably
crashes. That hasn't been an issue yet, though, because it is never
called.

In vkCreateRenderPass:
    - Don't allocate empty attachment arrays.
    - Ensure that pointers to empty attachment arrays are NULL.
    - Store VkRenderPassCreateInfo::subpassCount as
      anv_render_pass::subpass_count.

In vkDestroyRenderPass:
    - Fix loop bounds: s/attachment_count/subpass_count/
    - Don't call anv_device_free on null pointers.
2015-07-15 15:07:41 -07:00
Chad Versace
c6270e8044 vk: Refactor create/destroy code for anv_descriptor_set
Define two new functions:
    anv_descriptor_set_create
    anv_descriptor_set_destroy
2015-07-15 14:31:22 -07:00
Chad Versace
365d80a91e vk: Replace some raw casts with safe casts
That is, replace some instances of
    (VkFoo) foo
with
    anv_foo_to_handle(foo)
2015-07-15 14:00:21 -07:00
Chad Versace
7529e7ce86 vk: Correct anv_CreateShaderModule's prototype
s/VkShader/VkShaderModule/

:sigh: I look forward to type-safety.
2015-07-15 13:59:47 -07:00
Chad Versace
8213be790e vk: Define struct anv_image_view, anv_buffer_view
Follow the pattern of anv_attachment_view. We need these structs to
implement the type-safety that arrived in the 0.132 header.
2015-07-15 12:19:29 -07:00
Chad Versace
43241a24bc vk/meta: Fix declared type of a shader module
s/VkShader/VkShaderModule/

I'm looking forward to a type-safe vulkan.h ;)
2015-07-15 11:49:37 -07:00
Chad Versace
94e473c993 vk: Remove struct anv_object
Trivial removal because vkDestroyObject() no longer uses it.
2015-07-15 11:29:43 -07:00
Jason Ekstrand
e375f722a6 vk/device: More documentation on surface state flushing 2015-07-15 11:09:02 -07:00
Connor Abbott
9aabe69028 vk/device: explain why a flush is necessary
Jason found this from experimenting, but the docs give a reasonable
explanation of why it's necessary.
2015-07-14 23:03:19 -07:00
Chad Versace
5f46c4608f vk: Fix indentation of anv_dynamic_cb_state 2015-07-14 18:19:10 -07:00
Chad Versace
0eeba6b80c vk: Add finishmes for VkDescriptorPool
VkDescriptorPool is a stub object. As a consequence, it's impossible to
free descriptor set memory.
2015-07-14 18:19:00 -07:00
Jason Ekstrand
2b5a4dc5f3 vk: Add vulkan-138 and remove vulkan-0.132
Now, 138 is the target and not 132.  Once object destruction is finished,
we can delete 138 as it will be identical to vulkan.h
2015-07-14 17:54:13 -07:00
Jason Ekstrand
1f658bed70 vk/device: Add stub support for command pools
Real support isn't really that far away.  We just need a data structure
with a linked list and a few tests.
2015-07-14 17:40:00 -07:00
Jason Ekstrand
ca7243b54e vk/vulkan.h: Add the stuff for cross-queue resource sharing
We only have one queue, so this is currently a no-op on our implementation.
2015-07-14 17:20:50 -07:00
Jason Ekstrand
553b4434ca vk/vulkan.h: Add a couple of size fields for specialization constants 2015-07-14 17:12:39 -07:00
Jason Ekstrand
e5db209d54 vk/vulkan.h: Move around buffer image granularities 2015-07-14 17:10:37 -07:00
Jason Ekstrand
c7fcfebd5b vk: Add stubs for all the sparse resource stuff 2015-07-14 17:06:11 -07:00
Jason Ekstrand
2a9136feb4 vk/image: Add a stub for the new ImageFormatProperties function
This lets the client query about things like multisample.  We don't do
multisample right now, so I'll let Chad deal with that when he gets to it.
2015-07-14 17:05:30 -07:00
Jason Ekstrand
2c4dc92f40 vk/vulkan.h: Rename FormatInfo to FormatProperties 2015-07-14 17:04:46 -07:00
Jason Ekstrand
d7f44852be vk/vulkan.h: Re-order some #define's 2015-07-14 16:41:39 -07:00
Jason Ekstrand
1fd3bc818a vk/vulkan.h: Rename a function parameter 2015-07-14 16:39:01 -07:00
Jason Ekstrand
2e2f48f840 vk: Remove abreviations 2015-07-14 16:34:31 -07:00
Jason Ekstrand
02db21ae11 vk: Add the new extension/layer enumeration entrypoints 2015-07-14 16:11:21 -07:00
Jason Ekstrand
a463eacb8f vk/vulkan.h: Change maxAnisotropy to a float 2015-07-14 15:04:11 -07:00
Jason Ekstrand
98957b18d2 vk/vulkan.h: Add the VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT flag 2015-07-14 15:03:39 -07:00
Jason Ekstrand
a35811d086 vk/vulkan.h: Rename a couple of function parameters
No functional change.
2015-07-14 15:03:01 -07:00
Jason Ekstrand
55723e97f1 vk: Split the memory requirements/binding functions 2015-07-14 14:59:39 -07:00
Jason Ekstrand
ccb2e5cd62 vk: Make barriers more precise (rev. 133) 2015-07-14 14:50:35 -07:00
Jason Ekstrand
30445f8f7a vk: Split the dynamic state binding function into one per state 2015-07-14 14:26:10 -07:00
Jason Ekstrand
d2c0870ff3 vk/vulkan.h: Rename a function parameter to match 132 2015-07-14 14:11:04 -07:00
Jason Ekstrand
8478350992 vk: Implement Multipass 2015-07-14 11:37:14 -07:00
Jason Ekstrand
68768c40be vk/vulkan.h: Re-arrange some enums and definitions in preparation for 131 2015-07-14 11:32:15 -07:00
Chad Versace
66cbb7f76d vk/0.132: Add vkDestroyRenderPass() 2015-07-14 11:21:31 -07:00
Chad Versace
6d0ed38db5 vk/0.132: Add vkDestroy*View()
vkDestroyColorAttachmentView
vkDestroyDepthStencilView

These functions are not in the 0.132 header, but adding them will help
us attain the type-safety API updates more quickly.
2015-07-14 11:19:22 -07:00
Chad Versace
1ca611cbad vk/0.132: Add vkDestroyCommandBuffer() 2015-07-14 11:11:41 -07:00
Chad Versace
6eec0b186c vk/0.132: Add vkDestroyImageView()
Just declare it in vulkan.h. Jason defined the function earlier
in image.c.
2015-07-14 11:09:14 -07:00
Chad Versace
4b2c5a98f0 vk/0.132: Add vkDestroyBufferView()
Just declare it in vulkan.h. Jason already defined the function
earlier in vulkan.c.
2015-07-14 11:06:57 -07:00
Chad Versace
08f7731f67 vk/0.132: Add vkDestroyFramebuffer() 2015-07-14 10:59:30 -07:00
Chad Versace
0c8456ef1e vk/0.132: Add vkDestroyDynamicDepthStencilState() 2015-07-14 10:54:51 -07:00
Chad Versace
b29c929e8e vk/0.132: Add vkDestroyDynamicColorBlendState() 2015-07-14 10:52:45 -07:00
Chad Versace
5e1737c42f vk/0.132: Add vkDestroyDynamicRasterState() 2015-07-14 10:51:08 -07:00
Chad Versace
d80fea1af6 vk/0.132: Add vkDestroyDynamicViewportState() 2015-07-14 10:42:45 -07:00
Chad Versace
9250e1e9e5 vk/0.132: Add vkDestroyDescriptorPool() 2015-07-14 10:38:22 -07:00
Chad Versace
f925ea31e7 vk/0.132: Add vkDestroyDescriptorSetLayout() 2015-07-14 10:36:49 -07:00
Chad Versace
ec5e2f4992 vk/0.132: Add vkDestroySampler() 2015-07-14 10:34:00 -07:00
Chad Versace
a684198935 vk/0.132: Add vkDestroyPipelineLayout() 2015-07-14 10:29:47 -07:00
Chad Versace
6e5ab5cf1b vk/0.132: Add vkDestroyPipeline() 2015-07-14 10:26:17 -07:00
Chad Versace
114015321e vk/0.132: Add vkDestroyPipelineCache() 2015-07-14 10:19:27 -07:00
Chad Versace
cb57bff36c vk/0.132: Add vkDestroyShader() 2015-07-14 10:16:22 -07:00
Chad Versace
8ae8e14ba7 vk/0.132: Add vkDestroyShaderModule() 2015-07-14 10:13:09 -07:00
Chad Versace
dd67c134ad vk/0.132: Add vkDestroyImage()
We only need to add it to vulkan.h because Jason defined the function
earlier in image.c.
2015-07-14 10:13:00 -07:00
Chad Versace
e18377f435 vk/0.132: Dispatch vkDestroyObject to new destructors
Oops. My recent commits added new destructors, but forgot to teach
vkDestroyObject about them. They are:
  vkDestroyFence
  vkDestroyEvent
  vkDestroySemaphore
  vkDestroyQueryPool
  vkDestroyBuffer
2015-07-14 09:58:22 -07:00
Chad Versace
e93b6d8eb1 vk/0.132: Add vkDestroyBuffer() 2015-07-14 09:47:45 -07:00
Chad Versace
584cb7a16f vk/0.132: Add vkDestroyQueryPool() 2015-07-14 09:44:58 -07:00
Chad Versace
68c7ef502d vk/0.132: Add vkDestroyEvent() 2015-07-14 09:33:47 -07:00
Chad Versace
549070b18c vk/0.132: Add vkDestroySemaphore() 2015-07-14 09:31:34 -07:00
Chad Versace
ebb191f145 vk/0.132: Add vkDestroyFence() 2015-07-14 09:29:35 -07:00
Chad Versace
435ccf4056 vk/0.132: Rename VkDynamic*State types
sed -i -e 's/VkDynamicVpState/VkDynamicViewportState/g' \
       -e 's/VkDynamicRsState/VkDynamicRasterState/g' \
       -e 's/VkDynamicCbState/VkDynamicColorBlendState/g' \
       -e 's/VkDynamicDsState/VkDynamicDepthStencilState/g' \
       $(git ls-files include/vulkan src/vulkan)
2015-07-13 16:19:28 -07:00
Connor Abbott
ffb51fd112 nir/spirv: update to SPIR-V revision 31
This means that now the internal version of glslangValidator is
required. This includes some changes due to the sampler/texture rework,
but doesn't actually enable anything more yet. We also don't yet handle
UBO's correctly, and don't handle matrix stride and row major/column
major yet.
2015-07-13 15:01:01 -07:00
Chad Versace
45f8723f44 vk/0.132: Move VkQueryControlFlags 2015-07-13 13:09:32 -07:00
Chad Versace
180c07ee50 vk/0.132: Move VkImageAspectFlags 2015-07-13 13:08:56 -07:00
Chad Versace
4b05a8cd31 vk/0.132: Move VkCmdBufferOptimizeFlags 2015-07-13 13:08:07 -07:00
Chad Versace
f1cf55fae6 vk/0.132: Move VkWaitEvent 2015-07-13 13:06:53 -07:00
Chad Versace
3112098776 vk/0.132: Move VkCmdBufferLevel 2015-07-13 13:06:33 -07:00
Chad Versace
c633ab5822 vk/0.132: Drop VK_ATTACHMENT_STORE_OP_RESOLVE_MSAA 2015-07-13 13:05:24 -07:00
Chad Versace
8f3b2187e1 vk/0.132: Rename bool32_t -> VkBool32
sed -i 's/bool32_t/VkBool32/g' \
  $(git ls-files src/vulkan include/vulkan)
2015-07-13 13:03:36 -07:00
Chad Versace
77dcfe3c70 vk/0.132: Remove stray typedef 2015-07-13 12:58:17 -07:00
Chad Versace
601d0891a6 vk/0.132: Move VKImageUsageFlags 2015-07-13 12:48:44 -07:00
Chad Versace
829810fa27 vk/0.132: Move VkImageType and VkImageTiling 2015-07-13 11:49:56 -07:00
Chad Versace
17c8232ecf vk/0.132: Import the 0.132 header
Import it as vulkan-0.132.h.
2015-07-13 11:47:12 -07:00
Chad Versace
a158ff55f0 vk/vulkan.h: Remove headers for old API versions
Remove the temporary headers for 0.90 and 0.130.
2015-07-13 11:46:30 -07:00
Chad Versace
1c4238a8e5 vk/0.130: Bump header version to 0.130
All APIs have been updated. This eliminates the diff between the
work-in-progress header and the 0.130 header.
2015-07-10 20:06:09 -07:00
Chad Versace
f43a304dc6 vk/0.130: Update vkAllocMemory to use VkMemoryType 2015-07-10 17:35:52 -07:00
Chad Versace
df2a013881 vk/0.130: Implement vkGetPhysicalDeviceMemoryProperties() 2015-07-10 17:35:52 -07:00
Chad Versace
c7f512721c vk/gem: Change signature of anv_gem_get_aperture()
Replace the anv_device parameter with anv_physical_device, because this needs
querying before vkCreateDevice.
2015-07-10 17:35:52 -07:00
Chad Versace
8cda3e9b1b vk/device: Add member anv_physical_device::fd
During anv_physical_device_init(), we opend the DRM device to do some
queries, then promptly closed it. Now we keep it open for the lifetime
of the anv_physical_device so that we can query it some more during
vkGetPhysicalDevice*Properties() [which will happen in follow-up
commits].
2015-07-10 17:35:52 -07:00
Chad Versace
4422bd4cf6 vk/device: Add func anv_physical_device_finish()
Because in a follow-up patch I need to do some non-trival teardown on
anv_physical_device. Currently, however, anv_physical_device_finish() is
currently a no-op that's just called in the right place.

Also, rename function fill_physical_device -> anv_physical_device_init
for symmetry.
2015-07-10 17:35:52 -07:00
Jason Ekstrand
7552e026da vk/device: Add an explicit destructor for RenderPass 2015-07-10 12:33:04 -07:00
Jason Ekstrand
8b342b39a3 vk/image: Add an explicit DestroyImage function 2015-07-10 12:30:58 -07:00
Jason Ekstrand
b94b8dfad5 vk/image: Add explicit constructors for buffer/image view types 2015-07-10 12:26:31 -07:00
Jason Ekstrand
18340883e3 nir: Add C++ versions of NIR_(SRC|DEST)_INIT 2015-07-10 11:57:33 -07:00
Chad Versace
9e64a2a8e4 mesa: Fix generation of git_sha1.h.tmp for gitlinks
Don't assume that $(top_srcdir)/.git is a directory. It may be a
gitlink file [1] if $(top_srcdir) is a submodule checkout or a linked
worktree [2].

[1] A "gitlink" is a text file that specifies the real location of
    the gitdir.
[2] Linked worktrees are a new feature in Git 2.5.

Cc: "10.6, 10.5" <mesa-stable@lists.freedesktop.org>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
(cherry picked from commit 75784243df)
2015-07-10 11:24:25 -07:00
Jason Ekstrand
19f0a9b582 vk/query.c: Use the casting functions 2015-07-09 20:32:44 -07:00
Jason Ekstrand
6eb221c884 vk/pipeline.c: Use the casting functions 2015-07-09 20:28:08 -07:00
Jason Ekstrand
fb4e2195ec vk/formats.c: Use the casting functions 2015-07-09 20:24:17 -07:00
Jason Ekstrand
a52e208203 vk/image.c: Use the casting functions 2015-07-09 20:24:07 -07:00
Jason Ekstrand
b1de1d4f6e vk/device.c: One more use of a casting function 2015-07-09 20:23:46 -07:00
Jason Ekstrand
8739e8fbe2 vk/meta.c: Use the casting functions 2015-07-09 20:16:13 -07:00
Jason Ekstrand
92556c77f4 vk: Fix the build 2015-07-09 18:59:08 -07:00
Jason Ekstrand
098209eedf device.c: Use the cast helpers a bunch of places 2015-07-09 18:49:43 -07:00
Jason Ekstrand
73f9187e33 device.c: Use the cast helpers 2015-07-09 18:41:27 -07:00
Jason Ekstrand
7d24fab4ef vk/private.h: Add a bunch of static inline casting functions
We will need these as soon as we turn on type saftey.  We might as well
define and start using them now rather than later.
2015-07-09 18:40:54 -07:00
Jason Ekstrand
5c49730164 vk/device.c: Fix whitespace issues 2015-07-09 18:20:28 -07:00
Jason Ekstrand
c95f9b61f2 vk/device.c: Use ANV_FROM_HANDLE a bunch of places 2015-07-09 18:20:10 -07:00
Jason Ekstrand
335e88c8ee vk/vulkan.h: Add the pEnabledFeatures field to DeviceCreateInfo 2015-07-09 16:21:31 -07:00
Jason Ekstrand
34871cf7f3 vk/vulkan.h: Change the MsCreateInfo structure to the 130 version
We do nothing with it at the moment, so this is a no-op.
2015-07-09 16:19:54 -07:00
Jason Ekstrand
8c2c37fae7 vk: Remove the old GetPhysicalDeviceInfo call 2015-07-09 16:14:37 -07:00
Jason Ekstrand
1f907011a3 vk: Add the new PhysicalDeviceQueue queries 2015-07-09 16:14:37 -07:00
Jason Ekstrand
977a469bce vk: Support GetPhysicalDeviceProperties 2015-07-09 16:14:37 -07:00
Jason Ekstrand
65e0b304b6 vk: Add support for GetPhysicalDeviceLimits 2015-07-09 16:14:37 -07:00
Jason Ekstrand
f6d51f3fd3 vk: Add GetPhysicalDeviceFeatures 2015-07-09 16:14:37 -07:00
Chad Versace
5b75dffd04 vk/device: Fix vkEnumeratePhysicalDevices()
The Vulkan spec says that pPhysicalDeviceCount is an out parameter if
pPhysicalDevices is NULL; otherwise it's an inout parameter.

Mesa incorrectly treated it unconditionally as an inout parameter, which
could have lead to reading unitialized data.
2015-07-09 15:53:21 -07:00
Chad Versace
fa915b661d vk/device: Move device enumeration to vkEnumeratePhysicalDevices()
Don't enumerate devices in vkCreateInstance(). That's where global,
device-independent initialization should happen. Move device enumeration
to the more logical location, vkEnumeratePhysicalDevices().
2015-07-09 15:41:17 -07:00
Chad Versace
c34d314db3 vk/device: Be consistent about path to DRM device
Function fill_physical_device() has a 'path' parameter, and struct
anv_physical_device has a 'path' member. Sometimes these are used;
sometimes hardcoded "/dev/dri/renderD128" is used instead.

Be consistent. Hardcode "/dev/dri/renderD128" in exactly one location,
during initialization of the physical device.
2015-07-09 15:27:26 -07:00
Connor Abbott
cff06bbe7d vk/compiler: create an empty parameters list
Prevents problems when initializing the sanity_param_count.
2015-07-09 14:29:23 -04:00
Connor Abbott
3318a86d12 nir/spirv: fix wrong writemask for ALU operations 2015-07-09 14:28:39 -04:00
Connor Abbott
b8fedc19f5 nir/spirv: fix memory context for builtin variable
Fixes valgrind errors with func.depthstencil.basic.
2015-07-08 22:03:30 -04:00
Connor Abbott
e4292ac039 nir/spirv: zero out value array
Before values are pushed or annotated with a name, decoration, etc.,
they need to have an invalid type, NULL name, NULL decoration, etc.
ralloc zero's everything by accident, so this wasn't an issue in
practice, but we should be explicitly zero'ing it.
2015-07-08 22:03:30 -04:00
Connor Abbott
997831868f vk/compiler: create the right kind of program struct
This fixes Valgrind errors and gets all the tests to pass with
--use-spir-v.
2015-07-08 22:03:30 -04:00
Connor Abbott
a841e2c747 vk/compiler: mark inputs/outputs as read/written
This doesn't handle inputs and outputs larger than a vec4, but we plan
to add a varyiing splitting/packing pass to handle those anyways.
2015-07-08 22:03:30 -04:00
Jason Ekstrand
8640dc12dc vk/vulkan.h: Copy the VkStructureType enum from version 130
We now have the exact same structs which require pType.
2015-07-08 17:45:52 -07:00
Jason Ekstrand
5a4ebf6bc1 vk: Move to the new pipeline creation API's 2015-07-08 17:30:18 -07:00
Chad Versace
4fcb32a17d vk/0.130: Remove VkImageViewCreateInfo::minLod
It's now set solely through VkSampler.
2015-07-08 14:48:22 -07:00
Jason Ekstrand
367b9ba78f vk/vulkan.h: Move renderPassContinue from GraphicsBeginInfo to BeginInfo 2015-07-08 14:37:30 -07:00
Jason Ekstrand
d29ec8fa36 vk/vulkan.h: Update to the new UpdateDescriptorSets api 2015-07-08 14:24:56 -07:00
Jason Ekstrand
c8577b5f52 vk: Add a macro for creating anv variables from vulkan handles
This is very helpful for doing the mass bunch of casts at the top of a
function.  It will also be invaluable when we get type saftey in the API.
2015-07-08 14:24:14 -07:00
Chad Versace
ccb27a002c vk/0.130 Update VkObjectType values
Don't import any new enum tokens from the 0.130 header. Just update the
values of existing enums. This reduces the diff by about 16 lines.
2015-07-08 12:53:49 -07:00
Chad Versace
8985dd15a1 vk/0.130: Remove VkDescriptorUpdateMode
Nowhere used.
2015-07-08 12:51:46 -07:00
Chad Versace
e02dfa309a vk/0.130: Remove VK_DEVICE_CREATE_MULTI_DEVICE_IQ_MATCH_BIT 2015-07-08 12:49:48 -07:00
Chad Versace
e9034ed875 vk/0.130: Update vkCmdBlitImage signature
Add VkTexFilter param. Ignored for now.
2015-07-08 12:47:48 -07:00
Jason Ekstrand
aae45ab583 vk/vulkan.h: Add packing parameters to BufferImageCopy 2015-07-08 11:51:34 -07:00
Chad Versace
b4ef7f354b vk/0.130: Remove msaa members of VkDepthStencilViewCreateInfo 2015-07-08 11:50:51 -07:00
Jason Ekstrand
522ab835d6 vk/vulkan.h: Move over to the new border color enums 2015-07-08 11:44:52 -07:00
Jason Ekstrand
7598329774 vk/vulkan.h: Move VkFormatProperties 2015-07-08 11:16:45 -07:00
Jason Ekstrand
52940e8fcf vk/vulkan.h: Add RenderPassBeginContents 2015-07-08 10:57:13 -07:00
Jason Ekstrand
e19d6be2a9 vk/vulkan.h: Add command buffer levels 2015-07-08 10:53:32 -07:00
Jason Ekstrand
c84f2d3b8c vk/vulkan.h: Import the VkPipeEvent enum from 130
Now, VkPipeEventFlags is back in sync with VkPipeEvent
2015-07-08 10:49:46 -07:00
Jason Ekstrand
b20cc72603 vk/vulkan.h: Remove VkFormatInfoType 2015-07-08 10:39:31 -07:00
Jason Ekstrand
8e05bbeee9 vk/vulkan.h: Update extension handling to rev 130 2015-07-08 10:38:07 -07:00
Jason Ekstrand
cc29a5f4be vk/vulkan.h: Move format quering to the physical device 2015-07-08 09:34:47 -07:00
Jason Ekstrand
719fa8ac74 vk/vulkan.h: Remove some peer opening structs and STRUCTURE_TYPE enums 2015-07-08 09:25:13 -07:00
Jason Ekstrand
fc6dcc6227 vk: Add a copy of the v90 header. 2015-07-08 09:23:29 -07:00
Jason Ekstrand
12119282e6 vk/vulkan.h: Remove an unneeded comment 2015-07-08 09:18:09 -07:00
Jason Ekstrand
3c65a1ac14 vk/vulkan.h: Remove the MemoryRange stubs and add sparse stubs 2015-07-08 09:16:48 -07:00
Jason Ekstrand
bb6567f5d1 vk/vulkan.h: Switch BindObjectMemory to a device function and remove the index 2015-07-08 09:04:16 -07:00
Jason Ekstrand
e7acdda184 vk/vulkan.h: Switch to the split ProcAddr functions in 130 2015-07-07 18:51:53 -07:00
Jason Ekstrand
db24afee2f vk/vulkan.h: Switch from GetImageSubresourceInfo to GetImageSubresourceLayout 2015-07-07 18:20:18 -07:00
Jason Ekstrand
ef8980e256 vk/vulkan.h: Switch from GetObjectInfo to GetMemoryRequirements 2015-07-07 18:16:42 -07:00
Jason Ekstrand
d9c2caea6a vk: Update memory flushing functions to 130
This involves updating the prototype for FlushMappedMemory, adding
InvalidateMappedMemoryRanges, and removing PinSystemMemory.
2015-07-07 17:22:31 -07:00
Jason Ekstrand
d5349b1b18 vk/vulkan.h: Constify the pFences parameter to ResetFences 2015-07-07 17:18:00 -07:00
Jason Ekstrand
6aa1b89457 vk/vulkan.h: Move the definitions of Create(Framebuffer|RenderPass)
This better matches the 130 header.
2015-07-07 17:13:10 -07:00
Jason Ekstrand
0ff06540ae vk: Implement the GetRenderAreaGranularity function
At the moment, we're just going to scissor clears so a granularity of 1x1
is all we need.
2015-07-07 17:11:37 -07:00
Jason Ekstrand
435b062b26 vk/vulkan.h: Add a PipelineLayout parameter to BindDescriptorSets 2015-07-07 17:06:10 -07:00
Jason Ekstrand
518ca9e254 vk/vulkan.h: Add a compareEnable parameter to SamplerCreateInfo
Our hardware doesn't actually need this, so adding it is a no-op.
2015-07-07 16:49:04 -07:00
Jason Ekstrand
672590710b vk/vulkan.h: Remove initialCount from SemaphoreCreateInfo 2015-07-07 16:42:42 -07:00
Jason Ekstrand
80046a7d54 vk/vulkan.h: Update clear color handling to 130 2015-07-07 16:37:43 -07:00
Jason Ekstrand
3e4b00d283 meta: Use the VkClearColorValue structure for the color attribute 2015-07-07 16:27:06 -07:00
Jason Ekstrand
a35fef1ab2 vk/vulkan.h: Remove the pass argument from EndRenderPass 2015-07-07 16:22:23 -07:00
Jason Ekstrand
d2ca7e24b4 vk/vulkan.h: Rename VertexInputStateInfo to VertexInputStateCreateInfo 2015-07-07 16:15:55 -07:00
Jason Ekstrand
abbb776bbe vk/vulkan.h: Remove programPointSize
Instead, we auto-detect whether or not your shader writes gl_PointSize.  If
it does, we use 1.0, otherwise we take it from the shader.
2015-07-07 16:00:46 -07:00
Chad Versace
e7ddfe03ab vk/0.130: Stub vkCmdClear*Attachment() funcs
vkCmdClearColorAttachment
vkCmdClearDepthStencilAttachment
2015-07-07 15:57:37 -07:00
Chad Versace
f89e2e6304 vk/0.130: Define enum VkImageAspectFlagBits 2015-07-07 15:57:37 -07:00
Chad Versace
55ab1737d3 vk/0.130: Define VkRect3D 2015-07-07 15:55:53 -07:00
Chad Versace
11901a9100 vk/0.130: Update name of vkCmdClearDepthStencilImage() 2015-07-07 15:53:35 -07:00
Chad Versace
dff32238c7 vk/0.130: Stub vkCmdExecuteCommands() 2015-07-07 15:51:55 -07:00
Chad Versace
85c0d69be9 vk/0.130: Update vkCmdWaitEvents() signature 2015-07-07 15:49:57 -07:00
Chad Versace
0ecb789b71 vk: Remove unused 'v' param from stub() macro 2015-07-07 15:47:24 -07:00
Chad Versace
f78d684772 vk: Stub vkCmdPushConstants() from 0.130 header 2015-07-07 15:46:19 -07:00
Chad Versace
18ee32ef9d vk: Update vkCmdPipelineBarrier to 0.130 header 2015-07-07 15:43:41 -07:00
Chad Versace
4af79ab076 vk: Add func anv_clear_mask()
A little helper func for inspecting and clearing bitmasks.
2015-07-07 15:43:41 -07:00
Jason Ekstrand
788a8352b9 vk/vulkan.h: Remove some unused fields.
In particular, the following are removed:

 - disableVertexReuse
 - clipOrigin
 - depthMode
 - pointOrigin
 - provokingVertex
2015-07-07 15:33:00 -07:00
Jason Ekstrand
7fbed521bb vk/vulkan.h: Remove the explicit primitive restart index
Unfortunately, this requires some non-trivial changes to the driver.  Now
that the primitive restart index isn't given explicitly by the client, we
always use ~0 for everything like D3D does.  Unfortunately, our hardware is
awesome and a 32-bit version of ~0 doesn't match any 16-bit values.  This
means, we have to set it to either UINT16_MAX or UINT32_MAX depending on
the size of the index type.  Since we get the index type from
CmdBindIndexBuffer and the rest of the VF packet from the pipeline, we need
to lazy-emit the VF packet.
2015-07-07 15:33:00 -07:00
Chad Versace
d6b840beff vk: Delete some comments not present in 0.130 header
Deleting the comments reduces diff noise.
2015-07-07 15:16:13 -07:00
Chad Versace
84a5bc25e3 vk: Pull in remaining 0.130 handle types
This pulls in the definition of VkShaderModule and VkPipelineCache,
which nowhere used yet.
2015-07-07 15:13:01 -07:00
Chad Versace
f2899b1af2 vk: Pull in #defines from 0.130 header
Despite not being used yet, pulling in the macros does diminish the
header diff.
2015-07-07 15:11:30 -07:00
Jason Ekstrand
962d6932fa vk/vulkan.h: Rename (min|max)Depth to (min|max)DepthBounds 2015-07-07 12:37:54 -07:00
Jason Ekstrand
1fb859e4b2 vk/vulkan.h: Remove client-settable pointSize from DynamicRsState 2015-07-07 12:35:32 -07:00
Jason Ekstrand
245583075c vk/vulkan.h: Remove UINT8 index buffers 2015-07-07 11:26:49 -07:00
Jason Ekstrand
0a42332904 vk/vulkan.h: Re-order the object declarations 2015-07-07 11:26:49 -07:00
Kristian Høgsberg Kristensen
a1eea996d4 vk: Emit 3DSTATE_SAMPLE_MASK
This was missing and was causing the driver to not work with
execlists. Presumably we get a different initial hw context with
execlists enabled, that has sample mask 0 initially.

Set this to 0xffff for now.  When we add MS support, we need to take the
value from VkPipelineMsStateCreateInfo::sampleMask.
2015-07-06 23:54:12 -07:00
Kristian Høgsberg Kristensen
c325bb24b5 vk: Pull in new generated headers
The new headers use stdbool for enable/disable fields which
implicitly converts expressions like (flags & 8) to 0 or 1.
Also handles MBO (must-be-one) fields by setting them to one,
corrects a bspec typo (_3DPRIM_LISTSTRIP_ADJ -> LINESTRIP) and
makes a few enum values less clashy.
2015-07-06 22:12:26 -07:00
Chad Versace
23075bccb3 vk/image: Validate vkCreateImageView more
Exhaustively validate the function input.  If it's not validated and
doesn't have an anv_finishme(), then I overlooked it.
2015-07-06 18:28:26 -07:00
Chad Versace
69e11adecc vk/image: Add more info to VkImageViewType table
Convert the table from the direct mapping
  VkImageViewType -> SurfaceType

into a mapping to an info struct
  VkImageViewType -> struct anv_image_view_info
2015-07-06 18:28:26 -07:00
Chad Versace
b844f542e0 vk: Update VkImageViewType to 0.130.0
This splits 1D and 1D_ARRAY, 2D and 2D_ARRAY, CUBE and CUBE_ARRAY.

The new tokens are unused. This is just a header update.
2015-07-06 18:28:26 -07:00
Chad Versace
5b04db71ff vk/image: Move validation for vkCreateImageView
Move the validation from anv_CreateImageView() and anv_image_view_init()
to anv_validate_CreateImageView(). No new validation is added.
2015-07-06 18:27:14 -07:00
Jason Ekstrand
1f1b26bceb vk/vulkan.h: Rename VkRect to VkRect2D 2015-07-06 17:47:18 -07:00
Jason Ekstrand
63c1190e47 vk/vulkan.h: Rename count to arraySize in VkDescriptorSetLayoutBinding 2015-07-06 17:43:58 -07:00
Jason Ekstrand
d84f3155b1 vk/vulkan.h: Remove the Vk(Memory|Semaphor|Image)OpenInfo structs
We already deleted the functions that need them.  The structs are just
dangling uselessly.
2015-07-06 17:37:13 -07:00
Jason Ekstrand
65f9ccb4e7 vk/vulkan.h: Remove VK_MEMORY_PROPERTY_PREFER_HOST_LOCAL_BIT
We weren't doing anything with it, so this is a no-op
2015-07-06 17:33:45 -07:00
Jason Ekstrand
68fa750f2e vk/vulkan.h: Replace DEVICE_COHERENT_BIT with DEVICE_NON_COHERENT_BIT 2015-07-06 17:32:28 -07:00
Jason Ekstrand
d5b5bd67f6 vk/vulkan.h: Use the query result bits from revision 130
None of the important bits or names actually changed.  It just
added/removed some no-op names.

No functional change.
2015-07-06 17:27:11 -07:00
Jason Ekstrand
d843418c2e vk/vulkan.h: One more quick enum refactor clean-up 2015-07-06 17:26:29 -07:00
Jason Ekstrand
2b37fc28d1 vk/vulkan.h: Get rid of VERTEX_INPUT_STEP_RATE_DRAW
We never supported it, so no functional change.
2015-07-06 17:24:26 -07:00
Jason Ekstrand
a75967b1bb vk/vulkan.h: Remove the CLEAR_OPTIMAL image layout 2015-07-06 17:21:19 -07:00
Jason Ekstrand
2b404e5d00 vk: Rename CPU_READ/WRITE_BIT to HOST_READ/WRITE_BIT 2015-07-06 17:18:25 -07:00
Jason Ekstrand
c57ca3f16f vk/vulkan.h: Remove VK_IMAGE_CREATE_CLONEABLE_BIT 2015-07-06 17:14:30 -07:00
Jason Ekstrand
2de388c49c vk: Remove SHAREABLE bits
They were removed from the Vulkan API and we don't really use them because
there are no multi-GPU i965 systems.
2015-07-06 17:12:51 -07:00
Jason Ekstrand
1b0c47bba6 vk/vulkan.h: Re-order the logic op enums 2015-07-06 17:08:11 -07:00
Jason Ekstrand
c7cef662d0 vk/vulkan.h: Reformat a bunch of enums to match revision 130
In theory, no functional change.
2015-07-06 17:06:02 -07:00
Jason Ekstrand
8c5e48f307 vk: Rename NUM_SHADER_STAGE to SHADER_STAGE_NUM
This is a refactor of more than just the header but it lets us finish
reformating the shader stage enum.
2015-07-06 16:43:28 -07:00
Jason Ekstrand
d9176f2ec7 vk: Reformat a bunch of enums
This accounts for a number differences between the generated headers and
the hand-written header.  Not all reformatting is done in this commit but
it does make the headers much more diffable.

In theory, no functional change.
2015-07-06 16:41:31 -07:00
Jason Ekstrand
e95bf93e5a vk: Pull the VkResult enum from revision 130 2015-07-06 16:15:12 -07:00
Jason Ekstrand
1b7b580756 vk: re-arrange enums to match the order in revision 130 2015-07-06 16:11:05 -07:00
Jason Ekstrand
2fb524b369 vk: Rename a parameter in CmdBindDynamicStateObject 2015-07-06 15:37:17 -07:00
Jason Ekstrand
c5ffcc9958 vk: Remove multi-device stuff 2015-07-06 15:34:55 -07:00
Jason Ekstrand
c5ab5925df vk: Remove ClearDescriptorSets 2015-07-06 15:32:40 -07:00
Jason Ekstrand
ea5fbe1957 vk: Remove begin/end descriptor pool update 2015-07-06 15:32:27 -07:00
Jason Ekstrand
9a798fa946 vk: Remove stub for CloneImageData 2015-07-06 15:30:05 -07:00
Jason Ekstrand
78a0d23d4e vk: Remove the stub support for memory priorities 2015-07-06 15:28:10 -07:00
Jason Ekstrand
11cf214578 vk: Remove the stub support for explicit memory references 2015-07-06 15:27:58 -07:00
Jason Ekstrand
0dc7d4ac8a vk/vulkan.h: Reformat structs to match revision 130
Structs in the old version were specified as

typedef struct VkSomeThing_
{
   type                                        field; // comment
} VkSomeThing;

However, in the generated headers, you have

typedef struct {
   type                                        field;
} VkSomeThing;

This commit also removes some unneeded whitespaces.
2015-07-06 15:19:12 -07:00
Jason Ekstrand
19aabb5730 vk/vulkah.h: Re-arrange structures to match the order in 130 2015-07-06 15:09:30 -07:00
Connor Abbott
f9dbc34a18 nir/spirv: fix some bugs 2015-07-06 15:00:37 -07:00
Connor Abbott
f3ea3b6e58 nir/spirv: add support for builtins inside structures
We may be able to revert this depending on the outcome of bug 14190, but
for now it gets vertex shaders working with SPIR-V.
2015-07-06 15:00:37 -07:00
Connor Abbott
15047514c9 nir/spirv: fix a bug with structure creation
We were creating 2 extra bogus fields.
2015-07-06 15:00:37 -07:00
Connor Abbott
73351c6a18 nir/spirv: fix a bad assertion in the decoration handling
We should be asserting that the parent decoration didn't hand us
a member if the child decoration did, but different child decorations
may obviously have different members.
2015-07-06 15:00:37 -07:00
Connor Abbott
70d2336e7e nir/spirv: pull out logic for getting builtin locations
Also add support for more builtins.
2015-07-06 15:00:37 -07:00
Connor Abbott
aca5fc6af1 nir/spirv: plumb through the type of dereferences
We need this to know if a deref is of a builtin.
2015-07-06 15:00:37 -07:00
Connor Abbott
66375e2852 nir/spirv: handle structure member builtin decorations 2015-07-06 15:00:37 -07:00
Connor Abbott
23c179be75 nir/spirv: add a vtn_type struct
This will handle decorations that aren't in the glsl_type.
2015-07-06 15:00:37 -07:00
Connor Abbott
f9bb95ad4a nir/spirv: move 'type' into the union
Since SSA values now have their own types, it's more convenient to make
'type' only used when we want to look up an actual SPIR-V type, since
we're going to change its type soon to support various decorations that
are handled at the SPIR-V -> NIR level.
2015-07-06 15:00:37 -07:00
Jason Ekstrand
d5dccc1e7a vk: Move CreateFramebuffer and CreateRenderPass higher in the header
This matches where they are in the 130 header.
2015-07-06 14:41:43 -07:00
Jason Ekstrand
4a42f45514 vk: Remove atomic counters stubs 2015-07-06 14:38:45 -07:00
Jason Ekstrand
630b19a1c8 vk: Make vulkan.h look more like vulkan-130.h
Most of these changes are insubstantial.  The only potentially substantial
cyhange is that we added a few new #defines for API maximums.
2015-07-06 14:32:52 -07:00
Jason Ekstrand
2f9180b1b2 vk: Add a revision 130 header along-side the current header 2015-07-06 14:16:51 -07:00
Jason Ekstrand
1f1465f077 vk/meta: Add an initial implementation of ClearColorImage 2015-07-02 18:15:06 -07:00
Jason Ekstrand
8a6c8177e0 vk/meta: Factor the guts out of cmd_buffer_clear 2015-07-02 18:13:59 -07:00
Jason Ekstrand
beb0e25327 vk: Roll back to API v90
This is what version 0.1 of the Vulkan SDK is built against.
2015-07-01 16:44:12 -07:00
Jason Ekstrand
fa663c27f5 nir/spirv: Add initial structure member decoration support 2015-07-01 15:38:26 -07:00
Jason Ekstrand
e3d60d479b nir/spirv: Make vtn_handle_type match the other handler functions
Previously, the caller of vtn_handle_type had to handle actually inserting
the type.  However, this didn't really work if the type was decorated in
any way.
2015-07-01 15:34:10 -07:00
Jason Ekstrand
7a749aa4ba nir/spirv: Add basic support for Op[Group]MemberDecorate 2015-07-01 14:18:07 -07:00
Jason Ekstrand
682eb9489d vk/x11: Allow for the client querying the size of the format properties 2015-07-01 14:18:07 -07:00
Chad Versace
bba767a9af vk/formats: Fix entry for S8_UINT
I forgot to update this when fixing the depth formats.
2015-06-30 09:41:44 -07:00
Chad Versace
6720b47717 vk/formats: Document new meaning of anv_format::cpp
The way the code currently works is that anv_format::cpp is the cpp of
anv_format::surface_format.

Me and Kristian disagree about how the code *should* work. Despite that,
I think it's in our discussion's best interest to document how the code
*currently* works. That should eliminate confusion.

If and when the code begins to work differently, then we'll update the
anv_format comments.
2015-06-30 09:41:41 -07:00
Chad Versace
709fa463ec vk/depth: Add a FIXME
3DSTATE_DEPTH_BUFFER.Width,Height are wrong.
2015-06-26 22:15:03 -07:00
Chad Versace
5b3a1ceb83 vk/image: Enable 2d single-sample color miptrees
What's been tested, for both image views and color attachment views:

    - VK_FORMAT_R8G8B8A8_UNORM
    - VK_IMAGE_VIEW_TYPE_2D
    - mipLevels: 1, 2
    - baseMipLevel: 0, 1
    - arraySize: 1, 2
    - baseArraySlice: 0, 1

What's known to be broken:

    - Depth and stencil miptrees. To fix this, anv_depth_stencil_view
      needs major rework.
    - VkImageViewType != 2D
    - MSAA

Fixes Crucible tests:

  func.miptree.view-2d.levels02.array01.*
  func.miptree.view-2d.levels01.array02.*
  func.miptree.view-2d.levels02.array02.*
2015-06-26 22:11:15 -07:00
Chad Versace
c6e76aed9d vk/image: Define anv_surface, refactor anv_image
This prepares for upcoming miptree support.

anv_surface is a proxy for color surfaces, depth surfaces, and stencil
surfaces.  Embed two instances of anv_surface into anv_image: the
primary surface (color or depth), and an optional stencil surface.
2015-06-26 21:45:53 -07:00
Chad Versace
127cb3f6c5 vk/image: Reformat function signatures
Reformat them to match Mesa code-style.
2015-06-26 20:12:42 -07:00
Chad Versace
fdcd71f71d vk/image: Embed VkImageCreateInfo* into anv_image_create_info
All function signatures that matched this pattern,
  old: f(const VkImageCreateInfo *, const struct anv_image_create_info *)

were rewritten as
  new: f(const struct anv_image_create_info *)
2015-06-26 20:06:08 -07:00
Chad Versace
ca6cef3302 vk/image: Drop some tmp vars in anv_image_view_init()
Variables 'tile_mode' and 'format' are unneeded.
2015-06-26 19:50:04 -07:00
Chad Versace
9c46ba9ca2 vk/image: Abort on stencil image views
The code doesn't work. Not even close.

Replace the broken code with a FINISHME and abort.
2015-06-26 19:23:21 -07:00
Chad Versace
667529fbaa vk: Reindent struct anv_image 2015-06-26 15:27:20 -07:00
Chad Versace
74e3eb304f vk: Define MIN(a, b) macro 2015-06-26 15:09:07 -07:00
Chad Versace
55752fe94a vk: Rename functions ALIGN_*32 -> align_*32
ALIGN_U32 and ALIGN_I32 are functions, not macros. So stop using
allcaps.
2015-06-26 15:07:59 -07:00
Connor Abbott
6ee082718f Merge branch 'wip/nir-vtn' into vulkan
Adds composites and matrix multiplication, plus some control flow fixes.
2015-06-26 12:14:05 -07:00
Chad Versace
37d6e04ba1 vk/formats: Remove the cpp=0 stencil hack
The format table defined cpp = 0 for stencil-only formats. The real cpp
is 1.

When code begins to lie, especially about stencil buffers, code becomes
increasingly fragile as time progresses, and the damage becomes
increasingly hard to undo. (For precedent, see the painful history of
stencil buffer cpp in the git log for gen6 and gen7 in the i965 driver).
Let's undo the stencil buffer cpp lie now to avoid future pain.

In the format table, set cpp = 1 for VK_FORMAT_S8; replace checks for
cpp == 0; and delete all comments about the hack.
2015-06-26 09:58:22 -07:00
Chad Versace
67a7659d69 vk/image: Refactor anv_image_create()
From my experience with intel_mipmap_tree.c, I learned that for struct's
like anv_image and intel_mipmap_tree, which have sprawling
multi-function construction codepaths, it's easy to mistakenly use
unitialized struct members during construction.

Let's eliminate the risk of using unitialized anv_image members during
construction.  Fill the struct at the function bottom instead of
piecemeal throughout the constructor.
2015-06-26 09:32:59 -07:00
Chad Versace
5d7103ee15 vk/image: Group some assertions closer together
In anv_image_create(), group together the assertions on
VkImageCreateInfo.
2015-06-26 09:05:46 -07:00
Chad Versace
0349e8d607 vk/formats: #undef fmt at end of format table 2015-06-26 07:38:02 -07:00
Chad Versace
068b8a41e2 vk: Fix comment for anv_depth_stencil_view::stencil_qpitch
s/DEPTH/STENCIL/
2015-06-26 07:31:57 -07:00
Chad Versace
7ea707a42a vk/image: Add qpitch fields to anv_depth_stencil_view
For now, hard-code them to 0.
2015-06-25 20:10:16 -07:00
Chad Versace
b91a76de98 vk: Reindent and document struct anv_depth_stencil_view 2015-06-25 20:10:16 -07:00
Chad Versace
ebe1e768b8 vk/formats: Fix incorrect depth formats
anv_format::surface_format was incorrect for Vulkan depth formats.
For example, the format table mapped

    VK_FORMAT_D24_UNORM -> .surface_format = D24_UNORM_X8_UINT
    VK_FORMAT_D32_FLOAT -> .surface_format = D32_FLOAT

but should have mapped

    VK_FORMAT_D24_UNORM -> .surface_format = R24_UNORM_X8_TYPELESS
    VK_FORMAT_D32_FLOAT -> .surface_format = R32_FLOAT

The Crucible test func.depthstencil.basic passed despite the bug, but
only because it did not attempt to texture from the depth surface.

The core problem is that RENDER_SURFACE_STATE.SurfaceFormat and
3DSTATE_DEPTH_BUFFER.SurfaceFormat are distinct types. Considering them
as enum spaces, the two enum spaces have incompatible collisions.

Fix this by adding a new field 'depth_format' to struct anv_format.

Refer to brw_surface_formats.c:translate_tex_format() for precedent.
2015-06-25 20:10:16 -07:00
Chad Versace
45b804a049 vk/image: Rename local variable in anv_image_create()
This function has many local variables for info structs. Having one
named simply 'info' is confusing.  Rename it to 'format_info'.
2015-06-25 20:10:16 -07:00
Chad Versace
528071f004 vk/formats: Fix table entry for R8G8B8_SNORM
Now that anv_formats[] is formatted like a table, buggy entries are
easier to see.
2015-06-25 20:10:16 -07:00
Chad Versace
4c8146313f vk/formats: Rename anv_format::format -> surface_format
I misinterpreted anv_format::format as a VkFormat. Instead, it is
a hardware surface format (RENDER_SURFACE_STATE.SurfaceFormat). Rename
the field to 'surface_format' to make it unambiguous.
2015-06-25 20:10:16 -07:00
Chad Versace
4b8b451a1d vk/formats: Rename anv_format::channels -> num_channels
I misinterpreted anv_format::channels as a bitmask of channels.
Renaming it to 'num_channels' makes it unambiguous.
2015-06-25 20:10:16 -07:00
Chad Versace
af0ade0d6c vk: Reindent struct anv_format 2015-06-25 20:10:16 -07:00
Chad Versace
ae29fd1b55 vk/formats: Don't abbreviate tokens in the format table
Abbreviating the VK_FORMAT_* tokens doesn't help much. To the contrary,
it means grep and ctags can't find them.
2015-06-25 20:10:16 -07:00
Jason Ekstrand
d5e41a3a99 vk/compiler: Add the initial hacks to get SPIR-V up and going 2015-06-25 17:36:35 -07:00
Jason Ekstrand
c4c1d96a01 HACK: Get rid of sanity_param_count for FS 2015-06-25 17:36:34 -07:00
Jason Ekstrand
4f5ef945e0 i965: Don't print the GLSL IR if it doesn't exist 2015-06-25 17:36:34 -07:00
Jason Ekstrand
588acdb431 nir/spirv: Set the right location for shader input/outputs
We need to add FRAG_RESULT_DATA0 etc. to the input/output location.
2015-06-25 17:36:34 -07:00
Jason Ekstrand
333b8ddd6b nir/spirv: Set the interface type on uniform blocks 2015-06-25 17:36:34 -07:00
Jason Ekstrand
7e1792b1b7 nir/spirv: Set the system value mode on builtins 2015-06-25 17:36:34 -07:00
Jason Ekstrand
b72936fdad nir/spirv: Actually put variables on the right linked list 2015-06-25 17:36:34 -07:00
Jason Ekstrand
ee0a8f23e4 glsl: Move vert_attrib varying_slot and frag_result enums to shader_enums.h 2015-06-25 17:36:34 -07:00
Chad Versace
fa352969a2 vk/image: Check extent does not exceed surface type limits 2015-06-25 16:53:24 -07:00
Chad Versace
99031aa0f3 vk/image: Stop hardcoding SurfaceType of VkImageView
Instead, translate VkImageViewType to a gen SurfaceType.
2015-06-25 16:53:22 -07:00
Chad Versace
7ea121687c vk/image: Add anv_image::surf_type
This the gen SurfaceType, such as SURFTYPE_2D.
2015-06-25 16:52:16 -07:00
Chad Versace
cb30acaced vk/image: Add tables for gen SurfaceType
Tables for mapping VkImageType and VkImageViewType to gen SurfaceType.
Tables are unused.
2015-06-25 16:52:16 -07:00
Chad Versace
1132080d5d vk/util: Add anv_loge() for logging error messages 2015-06-25 16:52:16 -07:00
Chad Versace
5f2d469e37 vk: Add func anv_is_aligned() 2015-06-25 16:52:16 -07:00
Chad Versace
f7fb7575ef vk: Add anv_minify() 2015-06-25 16:52:05 -07:00
Chad Versace
7cec6c5dfd vk: Define MAX(a, b) macro 2015-06-25 16:29:42 -07:00
Jason Ekstrand
d178e15567 nir/spirv: Fix up some dererf ralloc parenting 2015-06-24 21:39:07 -07:00
Jason Ekstrand
845002e163 i965/nir: Handle returns as long as they're at the end of a function 2015-06-24 21:38:49 -07:00
Jason Ekstrand
2ecac045a4 i965/nir: Split NIR shader handling into two functions
The brw_create_nir function takes a GLSL or ARB shader and turns it into a
NIR shader.  The guts of the optimization and lowering code is now split
into a new brw_process_shader function.
2015-06-24 21:22:07 -07:00
Jason Ekstrand
e369a0eb41 nir/spirv: Use vtn_ssa_value for texture coordinates 2015-06-24 20:39:37 -07:00
Jason Ekstrand
d0bd2bc604 nir/spirv: Add support for the Uniform storage class
This is kida sketchy.  I'm not really sure this is the way it's supposed to
be used.
2015-06-24 20:32:05 -07:00
Jason Ekstrand
ba0d9d33d4 nir/spirv: Add support for some more decorations including built-in 2015-06-24 20:30:32 -07:00
Jason Ekstrand
1bc0a1ad98 nir/spirv: Make the header file C++ safe 2015-06-24 19:01:10 -07:00
Jason Ekstrand
88d02a1b27 vk: Build xmlconfig stuff into libi965_compiler 2015-06-24 15:59:09 -07:00
Kristian Høgsberg Kristensen
24dff4f8fa vk/headers: Handle MBO fields
These must be set to one.
2015-06-24 09:37:50 -07:00
Jason Ekstrand
a62edcce4e Merge remote-tracking branch 'mesa-public/master' into vulkan 2015-06-23 18:05:25 -07:00
Connor Abbott
dee4a94e69 nir/vtn: add support for phi nodes 2015-06-23 10:34:55 -07:00
Connor Abbott
fe1269cf28 nir/builder: add support for inserting before/after blocks 2015-06-23 10:34:22 -07:00
Connor Abbott
9a3dda101e nir/vtn: fix emitting code after loops
When we're done emitting the code for a loop, we need to visit the new
break block, which is the merge block of the current loop, rather than
the old merge block, which is the merge block of the loop containing the
one we just emitted code for.
2015-06-22 13:53:08 -07:00
Connor Abbott
e9c21d0ca0 unbreak things 2015-06-22 11:59:55 -07:00
Kristian Høgsberg Kristensen
9b9f973ca6 vk: Implement scratch buffers to make spilling work 2015-06-19 15:42:15 -07:00
Kristian Høgsberg Kristensen
9e59003fb1 vk: Undo relocs for scratch bos 2015-06-19 15:42:15 -07:00
Kristian Høgsberg Kristensen
b20794cfa8 vk/allocator: Get rid of non-memfd path
We can just use modern valgrind now.
2015-06-19 15:42:15 -07:00
Kristian Høgsberg Kristensen
aba75d0546 vk/headers: Make General State offsets relocations 2015-06-19 15:42:15 -07:00
Connor Abbott
841aab6f50 matrices matrices matrices 2015-06-18 18:52:44 -07:00
Connor Abbott
d0fc04aacf nir/types: be less strict about constructing matrix types 2015-06-18 18:51:51 -07:00
Connor Abbott
22854a60ef nir/builder: add a nir_fdot() convenience function 2015-06-18 17:34:55 -07:00
Connor Abbott
0e86ab7c0a nir/types: add a helper to transpose a matrix type 2015-06-18 17:34:12 -07:00
Connor Abbott
de4c31a085 fix glsl450 for composites 2015-06-18 17:33:08 -07:00
Kristian Høgsberg Kristensen
aedd3c9579 vk: Add missing gen7 RENDER_SURFACE_STATE struct 2015-06-17 21:42:29 -07:00
Connor Abbott
bf5a615659 composites composites composites 2015-06-17 16:25:38 -07:00
Kristian Høgsberg Kristensen
fa8a07748d vk: Compute CS exec mask and thread width max in pipeline
We compute the right mask and thread width max parameters as part of
pipeline creation and set them accordingly at vkCmdDispatch() and
vkCmdDispatchIndirect() time. These parameters depend only on the local
group size and the dispatch width of the program so we can figure this
out at pipeline create time.
2015-06-12 18:21:50 -07:00
Kristian Høgsberg Kristensen
c103c4990c vk: Set binding table layout for CS
We weren't setting the binding table layout for the backend compiler.
2015-06-12 18:21:49 -07:00
Kristian Høgsberg Kristensen
2fdd17d259 vk: Generate CS prog_data into the pipeline instance
We were generating the prog_data into a local variable and never
initializing the pipeline->cs_prog_data one.
2015-06-12 18:21:49 -07:00
Kristian Høgsberg Kristensen
00494c6cb7 vk: Document how depth/stencil formats work in anv_image_create()
This reverts commits

  e17ed04 * vk/image: Don't double-allocate stencil buffers
  1ee2d1c * vk/image: Teach anv_image_choose_tile_mode about WMAJOR

and instead adds a comment to describe the subtlety of how we create
images for stencil only formats.
2015-06-11 22:07:16 -07:00
Kristian Høgsberg Kristensen
fbc9fe3c92 vk: Use compute pipeline layout when binding compute sets 2015-06-11 21:57:43 -07:00
Kristian Høgsberg Kristensen
765175f5d1 vk: Implement basic compute shader support 2015-06-11 15:31:42 -07:00
Kristian Høgsberg Kristensen
7637b02aaa vk: Emit PIPELINE_SELECT on demand 2015-06-11 15:21:49 -07:00
Kristian Høgsberg Kristensen
405697eb3d vk: Stop asserting we have a fragment shader
Even for graphics, this is not a requirement, we can have a depth-only output pipeline.
2015-06-11 15:07:38 -07:00
Kristian Høgsberg Kristensen
e7edde60ba vk: Defer setting viewport dynamic state
We can't emit this until we've done a 3D pipeline select.
2015-06-11 15:04:09 -07:00
Kristian Høgsberg Kristensen
f7fe06cf0a vk: Disable shader stages in the graphics pipeline batch
We need to move this into the graphics pipeline batch so we don't  emit it
for compute pipelines.
2015-06-11 14:58:31 -07:00
Kristian Høgsberg Kristensen
9aae480cc4 vk: Don't emit STATE_SIP
We don't have a SIP kernel and don't enable exceptions.
2015-06-11 14:56:29 -07:00
Kristian Høgsberg Kristensen
923e923bbc vk: Compile fragment shader after VS and GS
Just moving code around to do shader stages in the natual order.
2015-06-11 14:55:50 -07:00
Jason Ekstrand
1dd63fcbed vk/entrypoints: Don't print every single function call 2015-06-11 10:10:13 -07:00
Kristian Høgsberg Kristensen
b581e924b6 vk: Remove left-over trp call 2015-06-11 09:26:49 -07:00
Kristian Høgsberg Kristensen
d76ea7644a vk: Set maximum point size range
We set both minimum and maximum point size to 0 in 3DSTATE_CLIP, which
will clip away all points.
2015-06-11 09:25:04 -07:00
Kristian Høgsberg Kristensen
a5b49d2799 vk: Use generated headers with fixed point support
The generated headers now convert float in the template struct to the
correct fixed point format.
2015-06-11 09:25:04 -07:00
Kristian Høgsberg Kristensen
ea7ef46cf9 vk: Regenerate headers with __gen_validate_value() 2015-06-11 09:25:03 -07:00
Jason Ekstrand
a566b1e08a vk/formats: Refactor format properties code
Along with the refactor, we now do the right thing when we hit an
unsupported format: Set the flags to 0 and return VK_SUCCESS.
2015-06-11 09:11:16 -07:00
Jason Ekstrand
2a3c29698c vk/image: Add a bunch of asserts 2015-06-10 21:04:51 -07:00
Jason Ekstrand
c8b62d109b vk: Add a couple vk_error calls 2015-06-10 21:04:13 -07:00
Jason Ekstrand
7153b56abc vk/private: Add a non-fatal assert 2015-06-10 21:03:50 -07:00
Jason Ekstrand
29d2bbb2b5 vk/cmd: Add an initial implementation of PipelineBarrier
We may want to do something more inteligent here later such as actually
handling image layout transitions.  However, this should do for now.
2015-06-10 16:37:33 -07:00
Jason Ekstrand
047ed02723 vk/emit: Use valgrind to validate every packed field 2015-06-10 12:43:02 -07:00
Jason Ekstrand
9cae3d18ac vk: Add valgrind checks in various emit functions
The check in batch_bo_finish should catch any undefined values in the batch
but isn't that great for debugging.  The checks in the various emit
functions will help get better granularity.
2015-06-09 21:51:37 -07:00
Jason Ekstrand
d5ad24e39b vk: Move the valgrind include and VG() macro to private.h 2015-06-09 21:51:37 -07:00
Chad Versace
e17ed04b03 vk/image: Don't double-allocate stencil buffers
If the main surface has format S8_UINT, then don't allocate the
auxiliary stencil surface.
2015-06-09 16:39:28 -07:00
Chad Versace
1ee2d1c3fc vk/image: Teach anv_image_choose_tile_mode about WMAJOR 2015-06-09 16:38:55 -07:00
Chad Versace
2d2e148952 vk/util: Add anv_abortf(), anv_abortfv()
Convenience functions to print an error message then abort.
2015-06-09 16:38:50 -07:00
Chad Versace
ffb1ee5d20 vk: Define anv_noreturn macro 2015-06-09 16:38:46 -07:00
Chad Versace
f1db3b3869 vk/image: Factor tile mode selection into separate function
Because it will eventually need to get smarter.
2015-06-09 16:38:42 -07:00
Jason Ekstrand
11e941900a vk/device: Actually allow destruction 2015-06-09 16:28:46 -07:00
Jason Ekstrand
5d4b6a01af vk/cmd_buffer: Properly initialize/reset dynamic states 2015-06-09 16:27:55 -07:00
Jason Ekstrand
634a6150b9 vk/pipeline: Zero out the depth-stencil state when not in use 2015-06-09 16:26:55 -07:00
Jason Ekstrand
919e7b7551 vk/device: Use anv_CreateDynamicViewportState instead of the vk one 2015-06-09 16:01:56 -07:00
Jason Ekstrand
0599d39dd9 vk/device: Dedent the vkCreateDynamicViewportState call 2015-06-09 15:53:26 -07:00
Chad Versace
d57c4cf999 vk/util: Annotate anv_finishme() as printflike 2015-06-09 14:46:49 -07:00
Chad Versace
822cb16abe vk: Define anv_printflike() macro 2015-06-09 14:46:45 -07:00
Chad Versace
081f617b5a vk/image: Stop hardcoding alignment of stencil surfaces
Look up the alignment from anv_tile_info_table.
2015-06-09 14:16:56 -07:00
Chad Versace
e6bd568f36 vk/image: Rewrite tile info table
- Reduce the number of table lookups in anv_image_create from 4 to 1.
- Add field for surface alignment.
- Shorten field names tile_width, tile_height -> width, height.
2015-06-09 14:16:45 -07:00
Chad Versace
5b777e2bcf vk/image: Delete an old comment 2015-06-09 14:14:29 -07:00
Jason Ekstrand
d842a6965f vk/compiler: Free the GL errors data 2015-06-09 12:36:23 -07:00
Jason Ekstrand
9f292219bf vk/compiler: Free more of prog_data when tearing down a pipeline 2015-06-09 12:36:23 -07:00
Jason Ekstrand
66b00d5e5a vk/queue: Embed the queue in and allocate it with the device 2015-06-09 12:36:23 -07:00
Jason Ekstrand
38f5eef59d vk/device: Free border color states when we have valgrind 2015-06-09 12:36:23 -07:00
Jason Ekstrand
999b56c507 vk/device: Destroy all batch buffers
Due to a copy+paste error, we were destroying all but the first batch or
surface state buffer.  Now we destroy them all.
2015-06-09 12:36:23 -07:00
Jason Ekstrand
3a38b0db5f vk/meta: Clean up temporary objects 2015-06-09 12:36:23 -07:00
Jason Ekstrand
9d6f55dedf vk/surface_view: Add a destructor 2015-06-09 12:36:23 -07:00
Chad Versace
e6162c2fef vk/image: Add anv_image::h_align,v_align
Use the new fields to compute RENDER_SURFACE_STATE.Surface*Alignment.
We still hardcode them to 4, though.
2015-06-09 12:19:24 -07:00
Jason Ekstrand
58afc24e57 vk/allocator: Remove the concept of a slave block pool
This reverts commit d24f8245db.
2015-06-08 17:46:32 -07:00
Jason Ekstrand
b6363c3f12 vk/device: Remove the binding table pools/streams 2015-06-08 17:45:57 -07:00
Jason Ekstrand
531549d9fc vk/pipeline: Move freeing the program stream to pipeline.c
It's created in pipeline.c so we should free it there.
2015-06-08 14:27:04 -07:00
Jason Ekstrand
66a4dab89a vk/pipeline: Don't destroy the program stream
It's freed in compiler.cpp and we don't want to free it twice.
2015-06-08 13:53:19 -07:00
Jason Ekstrand
920fb771d4 vk/allocator: Make the use of NULL_BLOCK in state_stream_finish explicit 2015-06-08 13:53:19 -07:00
Kristian Høgsberg Kristensen
52637c0996 vk: Quiet a few warnings 2015-06-08 08:51:40 -07:00
Kristian Høgsberg Kristensen
9eab70e54f vk: Create a minimal context for the compiler
This avoids the full brw context initialization and just sets up context
constants, initializes extensions and sets a few driver vfuncs for the
front-end GLSL compiler.
2015-06-08 08:51:40 -07:00
Jason Ekstrand
ce00233c13 vk/cmd_buffer: Use the dynamic state stream in emit_dynamic and merge_dynamic 2015-06-05 17:26:41 -07:00
Jason Ekstrand
e69588b764 vk/device: Use a 64-byte alignment for CC state 2015-06-05 17:26:26 -07:00
Jason Ekstrand
c2eeab305b vk/pipeline: Actually free the program stream and dynamic pool 2015-06-05 17:26:26 -07:00
Jason Ekstrand
ed2ca020f8 vk/allocator: Avoid double-free in the bo pool 2015-06-05 17:12:28 -07:00
Jason Ekstrand
aa523d3c62 vk/gem: Call VALGRIND_FREELIKE_BLOCK before unmapping 2015-06-05 16:41:49 -07:00
Chad Versace
87d98e1935 vk: Fix 2 incorrect typecasts
The compiler didn't find the cast errors because all Vulkan types are
just integers.
2015-06-04 14:32:22 -07:00
Chad Versace
b981379bcf vk: Make make clean remove generated spirv headers 2015-06-04 14:26:46 -07:00
Jason Ekstrand
8d930da35d vk/allocator: Remove an unneeded VG() wrapper 2015-06-04 09:14:33 -07:00
Jason Ekstrand
7f90e56e42 vk/device: Dissalow device destruction 2015-06-04 09:14:33 -07:00
Chad Versace
9cd42b3dea vk: Fix build
Commit 1286bd, which deleted vk.c, broke the build. Update the Makefile
to fix it.
2015-06-04 09:01:30 -07:00
Jason Ekstrand
251aea80b0 vk/DS: Mask stencil masks to 8 bits 2015-06-03 16:59:13 -07:00
Connor Abbott
47bd462b0c awesome control flow bugfixes/clarifications 2015-06-03 14:10:28 -04:00
Kristian Høgsberg Kristensen
a37d122e88 vk: Set color/blend state in meta clear if not set yet 2015-06-02 23:08:05 -07:00
Kristian Høgsberg Kristensen
1286bd3160 vk: Delete vk.c test case
We now have crucible up and running and all vk sub-cases have been moved
over. Delete this crufty old hack of a test case.
2015-06-02 22:57:42 -07:00
Kristian Høgsberg Kristensen
2f6aa424e9 vk: Update generated headers with support for 64 bit fields 2015-06-02 22:57:42 -07:00
Kristian Høgsberg Kristensen
5744d1763c vk: Set cb_state to NULL at cmd buffer create time
Dynamic color/blend state can be NULL in case we're not rendering to
color targets (only output to depth and/or stencil). Initialize
cmd_buffer->cb_state to NULL so we can reliably detect whether it's been
set or not.
2015-06-02 22:57:42 -07:00
Kristian Høgsberg Kristensen
c8f078537e vk: Implement vertexOffset parameter of vkCmdDrawIndexed()
As exposed by the func.draw_indexed test, we were ignoring the argument
and hardcoding 0.
2015-06-02 22:57:42 -07:00
Jason Ekstrand
e702197e3f vk/formats: Add a name to the metadata and better logging 2015-06-02 11:30:39 -07:00
Jason Ekstrand
fbafc946c6 vk/formats: Rework the formats table 2015-06-02 11:30:39 -07:00
Kristian Høgsberg Kristensen
f98c89ef31 vk: Move query related functionality to new file query.c 2015-06-01 21:52:45 -07:00
Jason Ekstrand
08748e3a0c i965: Use NIR by default for vertex shaders on GEN8+
GLSL IR vs. NIR shader-db results for SIMD8 vertex shaders on Broadwell:

   total instructions in shared programs: 2742062 -> 2681339 (-2.21%)
   instructions in affected programs:     1514770 -> 1454047 (-4.01%)
   helped:                                5813
   HURT:                                  1120

The gained programs are ARB vertext programs that were previously going
through the vec4 backend.  Now that we have prog_to_nir, ARB vertex
programs can go through the scalar backend so they show up as "gained" in
the shader-db results.

Acked-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Acked-by: Matt Turner <mattst88@gmail.com>
2015-06-01 12:25:58 -07:00
Jason Ekstrand
d4cbf6a728 vk/compiler: Add an index_count to the bind map and check for OOB 2015-06-01 12:25:58 -07:00
Jason Ekstrand
510b5c3bed vk/HACK: Plumb real descriptor set/index into textures 2015-06-01 12:25:58 -07:00
Jason Ekstrand
aded32bf04 NIR: Add a helper for doing sampler lowering for vulkan 2015-06-01 12:25:58 -07:00
Kristian Høgsberg Kristensen
5caa408579 vk: Indent tables to align '=' at column 48 2015-05-31 22:36:26 -07:00
Kristian Høgsberg Kristensen
76bb658518 vk: Add support for anisotropic bits 2015-05-31 22:15:34 -07:00
Kristian Høgsberg Kristensen
dc56e4f7b8 vk: Implement support for sampler border colors
This supports the three Vulkan border color types for float color
formats. The support for integer formats is a little trickier, as we
don't know the format of the texture at this time.
2015-05-31 17:20:48 -07:00
Jason Ekstrand
e497ac2c62 vk/device: Only flush the texture cache when setting state base address
After further examination, it appears that the other flushes and stalls
weren't actually needed.
2015-05-30 18:04:50 -07:00
Jason Ekstrand
2251305e1a vk/cmd_buffer: Track descriptor set dirtying per-stage 2015-05-30 10:07:29 -07:00
Jason Ekstrand
33cccbbb73 vk/device: Emit PIPE_CONTROL flushes surrounding new STATE_BASE_ADDRESS
According to the bspec, you're supposed to emit a PIPE_CONTROL with a CS
stall and a render target flush prior to chainging STATE_BASE_ADDRESS.  A
little experimentation, however, shows that this is not enough.  It also
appears as if you have to flush the texture cache after chainging base
address or things won't propagate properly.
2015-05-30 08:08:07 -07:00
Jason Ekstrand
b2b9fc9fad vk/allocator: Don't call VALGRIND_MALLOCLIKE_BLOCK on fresh gem_mmap's 2015-05-29 21:15:47 -07:00
Jason Ekstrand
03ffa9ca31 vk: Don't crash on partial descriptor sets 2015-05-29 20:43:10 -07:00
Jason Ekstrand
4ffbab5ae0 vk/device: Allow for starting a new surface state buffer
This commit allows for us to create a whole new surface state buffer when
the old one runs out of room.  We simply re-emit the state base address for
the new state, re-emit binding tables, and keep going.
2015-05-29 17:49:41 -07:00
Jason Ekstrand
c4bd5f87a0 vk/device: Do lazy surface state emission for binding tables
Before, we were emitting surface states up-front when binding tables were
updated.  Now, we wait to emit the surface states until we emit the binding
table.  This makes meta simpler and should make it easier to deal with
swapping out the surface state buffer.
2015-05-29 16:51:11 -07:00
Kristian Høgsberg Kristensen
4aecec0bd6 vk: Store dynamic slot index with struct anv_descriptor_slot
We need to make sure we use the right index into dynamic offset
array. Dynamic descriptors can be present or not in different stages and
to get the right offset, we need to compute the index at
vkCreateDescriptorSetLayout time.
2015-05-29 11:32:53 -07:00
Kristian Høgsberg Kristensen
fad418ff47 vk: Implement dynamic buffer offsets
We do this by creating a surface state on the fly that incorporates the
dynamic offset. This patch also refactor the descriptor set layout
constructor a bit to be less clever with switch statement fall
through. Instead of duplicating the subtle code to update the sampler
and surface slot map, we just use two switch statements.
2015-05-28 22:41:20 -07:00
Jason Ekstrand
9ffc1bed15 vk/device: Split state base address emit into its own function 2015-05-28 15:34:08 -07:00
Jason Ekstrand
468c89a351 vk/device: Use anv_batch_emit for MI_BATCH_BUFFER_START 2015-05-28 15:25:02 -07:00
Jason Ekstrand
2dc0f7fe5b vk/device: Actually destroy batch buffers 2015-05-28 13:08:21 -07:00
Jason Ekstrand
8cf932fd25 vk/query: Don't emit a CS stall by itself
Both the bspec and the simulator don't like this.  I'm not sure if stalling
at the scoreboard is right but it at least shuts up the simulator.
2015-05-28 10:27:53 -07:00
Jason Ekstrand
730ca0efb1 vk/device: Fixups for batch buffer chaining
Some how these didn't get merged with the other batch buffer chaining
stuff.  Oh well, it's here now.
2015-05-28 10:26:11 -07:00
Jason Ekstrand
de221a672d meta: Add a default ds_state and use it when no ds state is set 2015-05-28 10:06:45 -07:00
Jason Ekstrand
6eefeb1f84 vk/meta: Share the dummy RS and CB state between clear and blit 2015-05-28 10:00:38 -07:00
Kristian Høgsberg Kristensen
5a317ef4cb vk: Initialize dynamic state binding points to NULL
We rely on these being initialized to NULL so meta can reliably detect
whether or not they've been set. ds_state is also allowed to not be
present so we need a well-defined value for that.
2015-05-27 22:13:48 -07:00
Chad Versace
1435bf4bc4 .gitignore: Ignore spirv2nir binary 2015-05-27 17:01:09 -07:00
Chad Versace
f559fe9134 .gitignore: Scope Vulkan's generated source files
Don't ignore any file named entrypoints.{c,h}. Ignore it only if it's in
src/vulkan.
2015-05-27 16:59:53 -07:00
Chad Versace
ca385dcf2a vk: gitignore generated source files 2015-05-27 16:57:31 -07:00
Chad Versace
466f61e9f6 vk/glsl_scraper: Replace adhoc arg parsing with argparse 2015-05-27 16:56:02 -07:00
Chad Versace
fab9011c44 vk/image: Assert that VkImageTiling is valid 2015-05-27 16:21:04 -07:00
Chad Versace
c0739043b3 vk/image: Remove trailing whitespace 2015-05-27 16:15:47 -07:00
Chad Versace
4514e63893 vk/glsl: Reject invalid options
The script incorrectly interpreted --blah as the input filename.
2015-05-27 16:14:26 -07:00
Chad Versace
fd8b5e0df2 vk/glsl_scraper: Indent large text blocks
Indent them to the same level as if the text was code.

No changes in entrypoints.{c,h} after a clean build.
2015-05-27 16:09:31 -07:00
Chad Versace
df4b02f4ed vk/glsl_scraper: Fix code style for imports
Python style is one module imported per line, and imports are at the top
of the file.
2015-05-27 16:04:12 -07:00
Jason Ekstrand
b23885857f vk/meta: Actually create the CB state for blits 2015-05-27 12:06:30 -07:00
Jason Ekstrand
da8f148203 vk: Rework anv_batch and use chaining batch buffers
This mega-commit primarily does two things.  First, is to turn anv_batch
into a better abstraction of a batch.  Instead of actually having a BO, it
now has a few pointers to some piece of memory that are used to add data to
the "batch".  If it gets to the end, there is a function pointer that it
can call to attempt to grow the batch.

The second change is to start using chained batch buffers.  When the end of
the current batch BO is reached, it automatically creates a new one and
ineserts an MI_BATCH_BUFFER_START command to chain to it.  In this way, our
batch buffers are effectively infinite in length.
2015-05-27 11:48:28 -07:00
Jason Ekstrand
59def43fc8 Fixup for growable reloc lists 2015-05-27 11:48:28 -07:00
Jason Ekstrand
1c63575de8 vk/cmd_buffer: Allocate the surface_bo from device->batch_bo_pool 2015-05-27 11:48:28 -07:00
Jason Ekstrand
403266be05 vk/device: Make reloc lists growable 2015-05-27 11:48:28 -07:00
Jason Ekstrand
5ef81f0a05 vk/device: Use a bo pool for batch buffers 2015-05-27 11:48:28 -07:00
Jason Ekstrand
6f3e3c715a vk/allocator: Add a BO pool 2015-05-27 11:48:28 -07:00
Jason Ekstrand
59328bac10 vk/allocator: Add a free list that acts on pointers instead of offsets 2015-05-27 11:48:28 -07:00
Kristian Høgsberg
a1d30f867d vk: Add support for dynamic and pipeline color blend state 2015-05-26 17:12:37 -07:00
Kristian Høgsberg
2514ac5547 vk/test: Create and use color/blend dynamic and pipeline state 2015-05-26 17:12:37 -07:00
Kristian Høgsberg
1cd8437b9d vk/meta: Allocate and set color/blend state
For color blend, we have to set our own state to avoid inheriting bogus
blend state.
2015-05-26 17:12:37 -07:00
Kristian Høgsberg
610e6291da vk: Allocate samplers from dynamic stream 2015-05-26 11:50:34 -07:00
Kristian Høgsberg
b29f44218d vk: Emit color calc state
This involves pulling stencil ref values out of DS dynamic state and the
blend constant out of CB dynamic state.
2015-05-26 11:27:31 -07:00
Kristian Høgsberg
5e637c5d5a vk/pack: Generate length macros for structs 2015-05-26 11:27:31 -07:00
Kristian Høgsberg
998837764f vk: Program depth bias
This makes 3DSTATE_RASTER a split state command.
2015-05-26 11:27:31 -07:00
Kristian Høgsberg
0dbed616af vk: Add support for texture component swizzle
This also drops the share create_surface_state helper and moves filling
out SURFACE_STATE directly into anv_image_view_init() and
anv_color_attachment_view_init().
2015-05-26 11:27:29 -07:00
Kristian Høgsberg
cbe7ed416e vk: Implement dynamic and pipeline ds state 2015-05-25 20:20:31 -07:00
Kristian Høgsberg
37743f90bc vk: Set up depth and stencil buffers 2015-05-25 20:20:31 -07:00
Kristian Høgsberg
7c0d0021eb vk/test: Add new depth-stencil test
Not yet a depth stencil test, but will become one.
2015-05-25 20:20:31 -07:00
Kristian Høgsberg
0997a7b2e3 vk: Add basic MOCS settings
This matches what we do for GL.
2015-05-25 20:20:31 -07:00
Kristian Høgsberg
c03314bdd3 vk: Update to header files with nested struct support
This will let us do MOCS settings right.
2015-05-25 20:20:31 -07:00
Jason Ekstrand
ae8c93e023 vk/cmd_buffer: Initialize the pipeline pointer to NULL
If a meta operation is called before the pipeline is set, this can cause
uses of undefined values.  They *should* be harmless, but we might as well
shut up valgrind on this one too.
2015-05-25 17:14:49 -07:00
Jason Ekstrand
912944e59d vk/device: Use the correct number of viewports when creating default VP state
Fixes valgrind uninitialized value errors
2015-05-25 17:14:49 -07:00
Jason Ekstrand
1b211feb6c vk/compiler: Zero out the vs_prog_data struct when VS is disabled
Prevents uninitialized value errors
2015-05-25 17:14:49 -07:00
Jason Ekstrand
903bd4b056 vk/compiler: Fix up the binding hack and make it work in NIR 2015-05-25 12:57:32 -07:00
Jason Ekstrand
57153da2d5 vk: Actually implement some sort of destructor for all object types 2015-05-22 15:15:08 -07:00
Jason Ekstrand
0f0b5aecb8 vk/pipeline: Track VB's that are actually used by the pipeline
Previously, we just blasted out whatever VB's we had marked as "dirty"
regardless of which ones were used by the pipeline.  Given that the stride
of the VB is embedded in the pipeline this can cause problems.  One problem
is if the pipeline doesn't use the given VB binding we emit a bogus stride.
Another problem is that we weren't properly resetting the dirty bits when
the pipeline changed.
2015-05-21 16:58:53 -07:00
Jason Ekstrand
0a54751910 vk/device: Memset descriptor sets to 0 and handle descriptor set holes 2015-05-21 16:33:04 -07:00
Jason Ekstrand
519fe765e2 vk: Do relocations in surface states when they are created
Previously, we waited until later and did a pass through the used surfaces
and did the relocations then.  This lead to doing double-relocations which
was causing us to get bogus surface offsets.
2015-05-21 15:55:29 -07:00
Jason Ekstrand
ccf2bf9b99 vk/test: Use the glsl_scraper for building shaders 2015-05-21 12:24:02 -07:00
Jason Ekstrand
f3d70e4165 vk/glsl_scraper: Use the LunarG back-door for GLSL source 2015-05-21 12:22:44 -07:00
Jason Ekstrand
cb56372eeb vk/glsl_scraper: Use a fake GLSL version that glslang will accept 2015-05-21 12:21:02 -07:00
Jason Ekstrand
0e441cde71 vk: Bake the GLSL_VK_SHADER macro into the scraper output file 2015-05-21 12:21:00 -07:00
Jason Ekstrand
f17e835c26 vk/meta: Use glsl_scraper for our GLSL source
We are not yet using SPIR-V for meta but this is a first step.
2015-05-21 11:39:54 -07:00
Jason Ekstrand
b13c0f469b vk: More out-of-tree build fixes 2015-05-21 11:32:59 -07:00
Jason Ekstrand
f294154e42 vk: Fix for out-of-tree builds 2015-05-21 10:23:18 -07:00
Kristian Høgsberg
f9e66ea621 vk: Remove render pass stub call
This isn't really a stub.
2015-05-20 20:34:52 -07:00
Kristian Høgsberg
a29df71dd2 vk: Add WSI implementation 2015-05-20 20:34:52 -07:00
Kristian Høgsberg
f886647b75 vk: Add debug stubs 2015-05-20 20:34:52 -07:00
Kristian Høgsberg
63da974529 vk: Mark remaining unsupported formats as such 2015-05-20 20:34:52 -07:00
Kristian Høgsberg
387a1bb58f vk: Mark VK_FORMAT_UNDEFINED as 1 cpp, 1 channel 2015-05-20 20:34:52 -07:00
Kristian Høgsberg
a1bd426393 vk: Stream surface state instead of using the surface pool
Since the binding table pointer is only 16 bits, we can only have 64kb
of binding table state allocated at any given time. With a block size of
1kb, that amounts to just 64 command buffers, which is not enough.
2015-05-20 20:34:52 -07:00
Kristian Høgsberg
01504057f5 vk: Use surface_format_info from dri driver for vkGetFormatInfo 2015-05-20 20:34:52 -07:00
Chad Versace
a61f307996 vk: Fix result of vkCreateInstance
When fill_physical_device() fails, don't return VK_SUCCESS.
2015-05-20 19:51:10 -07:00
Jason Ekstrand
14929046ba vk/compiler: Add shader language detection
This commit adds support for the LunarG GLSL back-door as well as detecting
regular GLSL and SPIR-V.  The SPIR-V path doesn't exist yet, so that will
cause an assert-fail.
2015-05-20 17:05:41 -07:00
Jason Ekstrand
47c1cf5ce6 vk/test: Add a test for testing buffer copies 2015-05-20 16:20:04 -07:00
Jason Ekstrand
bea66ac5ad vk/meta: Add support for copying arbitrary size buffers 2015-05-20 16:20:04 -07:00
Jason Ekstrand
9557b85e3d vk/meta: Use the biggest format possible for buffer copies
This should substantially improve throughput of buffer copies.
2015-05-20 16:20:04 -07:00
Jason Ekstrand
13719e9225 vk/meta: Fix buffer copy extents 2015-05-20 16:20:04 -07:00
Jason Ekstrand
d7044a19b1 vk/meta: Use texture() instead of texture2D() 2015-05-19 12:44:35 -07:00
Jason Ekstrand
edff076188 vk: Use binding instead of index in uniform layout qualifiers
This more closely matches what the Vulkan docs say to do.
2015-05-19 12:44:22 -07:00
Jason Ekstrand
e37a89136f vk/glsl_scraper: Add a --glsl-only option 2015-05-19 11:29:07 -07:00
Jason Ekstrand
4bcf58a192 vk/glsl_scraper: Use the line number from the end of the macro
We used to use the line number from the start of the macro but this doesn't
seem to match the c preprocessor
2015-05-19 11:29:07 -07:00
Jason Ekstrand
1573913194 vk/glsl_scraper: Don't open files until needed
This prevents us from writing an empty file when the compile failed.
2015-05-19 11:29:07 -07:00
Kristian Høgsberg
e4c11f50b5 vk: Call finish for binding table state stream 2015-05-18 21:12:13 -07:00
Jason Ekstrand
851495d344 vk/meta: Use the new *view_init functions and stack-allocated views
This should save us a good deal of the leakage that meta currently has.
2015-05-18 20:57:43 -07:00
Jason Ekstrand
4668bbb161 vk/image: Factor view creation out into separate *_init functions
The *_init functions work basically the same as the Vulkan entrypoints
except that they act on an already-created view and take an optional
command buffer option.  If a command buffer is given, the surface state is
allocated out of the command buffer's state stream.
2015-05-18 20:57:43 -07:00
Jason Ekstrand
7c9f209427 Revert "vk/allocator: Don't use memfd when valgrind is detected"
This reverts commit b6ab076d6b.

It turns out setting USE_MEMFD to 0 is really bad because it means we can't
resize the pool.  Besides, valgrind SVN handles memfd so we really don't
need this fallback for valgrind anymore.
2015-05-18 20:57:43 -07:00
Jason Ekstrand
923691c70d vk: Use a separate block pool and state stream for binding tables
The binding table pointers packet only allows for a 16-bit binding table
address so all binding tables have to be in the first 64 KB of the surface
state BO.  We solve this by adding a slave block pool that pulls off the
first 64 KB worth of blocks and reserves them for binding tables.
2015-05-18 20:57:43 -07:00
Jason Ekstrand
d24f8245db vk/allocator: Add a concept of a slave block pool
We probably need a better name but this will do for now.
2015-05-18 20:57:43 -07:00
Kristian Høgsberg
997596e4c4 vk/test: Add test that prints format features 2015-05-18 20:52:44 -07:00
Kristian Høgsberg
241b59cba0 vk/test: Test timestamps and occlusion queries 2015-05-18 20:52:44 -07:00
Kristian Høgsberg
ae9ac47c74 vk: Make timestamp command work correctly
This was using the wrong timestamp register and needs to write a 64 bit
value.
2015-05-18 20:52:43 -07:00
Kristian Høgsberg
82ddab4b18 vk: Make occlusion query work, both copy and get functions 2015-05-18 20:52:43 -07:00
Kristian Høgsberg
1d40e6ade8 vk: Update generated header files
This fixes a problem where register addresses where incorrectly shifted.
2015-05-18 20:52:43 -07:00
Kristian Høgsberg
f330bad545 vk: Only fill render targets for meta clear
Clear inherits the render targets from the current render pass. This
means we need to fill out the binding table after switching to meta
bindings. However, meta copies etc happen outside a render pass and
break when we try to fill in the render targets. This change fills the
render targets only for meta clear.
2015-05-18 20:52:43 -07:00
Jason Ekstrand
b6c7d8c911 vk/pipeline: Use a state_stream for storing programs
Previously, we were effectively using a state_stream, it was just
hand-rolled based on a block pool.  Now we actually use the data structure.
2015-05-18 15:58:20 -07:00
Jason Ekstrand
4063b7deb8 vk/allocator: Add support for valgrind tracking of state pools and streams
We leave the block pool untracked so that reads/writes to freed blocks
will get caught and do the tracking at the state pool/stream level.  We
have to do a few extra gymnastics for streams because valgrind works in
terms of poitners and we work in terms of separate map and offset.
Fortunately, the users of the state pool and stream should always be using
the map pointer provided in the anv_state structure.  We just have to
track, per block, the map that was used when we initially got the block.
Then we can make sure we always use that map and valgrind should stay
happy.
2015-05-18 15:58:20 -07:00
Jason Ekstrand
b6ab076d6b vk/allocator: Don't use memfd when valgrind is detected 2015-05-18 15:58:20 -07:00
Jason Ekstrand
682d11a6e8 vk/allocator: Assert that block_pool_grow succeeds 2015-05-18 15:48:19 -07:00
Jason Ekstrand
28804fb9e4 vk/gem: VG_CLEAR the padding for the gem_mmap struct 2015-05-18 12:05:17 -07:00
Jason Ekstrand
8440b13f55 vk/meta: Rework the indentation style
No functional change.
2015-05-18 10:43:51 -07:00
Kristian Høgsberg
5286ef7849 vk: Provide more realistic values for device info 2015-05-18 10:27:08 -07:00
Kristian Høgsberg
69fd473321 vk: Use a temporary buffer for formatting in finishme
This is more likely to avoid breaking up the message when racing with
other threads.
2015-05-18 10:27:08 -07:00
Jason Ekstrand
cd7ab6ba4e vk/meta: Add an initial implementation of vkCmdCopyBuffer
Compile-tested only
2015-05-18 10:27:08 -07:00
Jason Ekstrand
c25ce55fd3 vk/meta: Add an initial implementation of vkCmdCopyBufferToImage
Compile-tested only
2015-05-18 10:27:08 -07:00
Jason Ekstrand
08bd554cda vk/meta: Add an initial implementation of vkCmdBlitImage
Compile-tested only
2015-05-18 10:27:08 -07:00
Jason Ekstrand
fb27d80781 vk/meta: Add an initial implementation of vkCmdCopyImage
Compile-tested only
2015-05-18 10:27:08 -07:00
Jason Ekstrand
c15f3834e3 vk/gem: Set the gem_mmap.flags parameter to 0 if it exists 2015-05-18 10:27:08 -07:00
Jason Ekstrand
f7b0f922be vk/gem: Only VK_CLEAR the addr_ptr in gen_mmap 2015-05-18 10:27:07 -07:00
Kristian Høgsberg
ca7e62d421 vk: Add a logger wrapper for the generated entrypoint 2015-05-18 10:27:07 -07:00
Kristian Høgsberg
eb92745b2e vk/gem: Just return -1 from anv_gem_wait() on error
We were returning -errno, unlike all the other gem functions.
2015-05-18 10:27:07 -07:00
Kristian Høgsberg
05754549e8 vk: Fix vkGetOjectInfo return values
We weren't properly returning the allocation count.
2015-05-18 10:27:07 -07:00
Kristian Høgsberg
6afb26452b vk: Implement fences
This basic implementation uses a throw-away bo for synchronization.
2015-05-18 10:27:07 -07:00
Kristian Høgsberg
e26a7ffbd9 vk/meta: Use anv_* internal entrypoints 2015-05-18 10:27:07 -07:00
Kristian Høgsberg
b7fac7a7d1 vk: Implement allocation count query 2015-05-18 10:27:07 -07:00
Kristian Høgsberg
783e6217fc vk: Change pData/pDataSize semantics
We now always copy the entire struct unless pData is NULL and
unconditionally write back the struct size. It's not clear this is
useful if the structs may grow over time, but it seems to be the
expected behaviour for now.
2015-05-18 10:27:07 -07:00
Kristian Høgsberg
b4b3bd1c51 vk: Return VK_SUCCESS from vkAllocDescriptorSets
This should've been returning VK_SUCCESS all along.
2015-05-18 10:27:07 -07:00
Kristian Høgsberg
a9f2115486 vk: Return VK_SUCCESS for all descriptor pool entry points 2015-05-18 10:27:07 -07:00
Kristian Høgsberg
60ebcbed54 vk: Start Implementing vkGetFormatInfo()
We move the format table and vkGetFormatInfo to their own file in the
process.
2015-05-18 10:27:07 -07:00
Kristian Høgsberg
454345da1e vk: Add script for generating ifunc entry points
This lets us generate a hash table for vkGetProcAddress and lets us call
public functions internally without the public entrypoint overhead.
2015-05-18 10:27:02 -07:00
Kristian Høgsberg
333bcc2072 vk: Fix vulkan header inconsistency
The function pointer typedef and the function prototype for
vkCmdClearColorImage() didn't agree. Fix the typedef to match the
prototype.
2015-05-17 21:08:31 -07:00
Kristian Høgsberg
b9eb56a404 vk: Add function pointer typedef for intel extension
Also guard function prototype by VK_PROTOTYPES.
2015-05-17 21:08:30 -07:00
Kristian Høgsberg
75cb85c56a vk: Add missing VKAPI for vkQueueRemoveMemReferences 2015-05-17 21:08:30 -07:00
Jason Ekstrand
a924ea0c75 Merge remote-tracking branch 'fdo-personal/wip/nir-vtn' into vulkan
This adds the SPIR-V -> NIR translator.
2015-05-16 12:43:16 -07:00
Jason Ekstrand
a63952510d nir/spirv: Don't assert that the current block is empty
It's possible that someone will give us SPIR-V code in which someone
needlessly branches to new blocks.  We should handle that ok now.
2015-05-16 12:34:34 -07:00
Jason Ekstrand
4e44dcc312 nir/spirv: Add initial support for samplers 2015-05-16 12:34:15 -07:00
Jason Ekstrand
d6f52dfb3e nir/spirv: Move Exp and Log to the list of currently unhandled ALU ops
NIR doesn't have the native opcodes for them anymore
2015-05-16 12:33:32 -07:00
Jason Ekstrand
a53e795524 nir/types: Add support for sampler types 2015-05-16 12:32:58 -07:00
Jason Ekstrand
0fa9211d7f nir/spirv: Make the global constants in spirv.h static
I've been promissed in a bug that this will be fixed in a future version of
the header.  However, in the interest of my branch building, I'm adding
these changes in myself for the moment.
2015-05-16 11:16:34 -07:00
Jason Ekstrand
036a4b1855 nir/spirv: Handle jump-to-loop in a more general way 2015-05-16 11:16:34 -07:00
Jason Ekstrand
56f533b3a0 nir/spirv: Handle boolean uniforms correctly 2015-05-16 11:16:34 -07:00
Jason Ekstrand
64bc58a88e nir/spirv: Handle control-flow with loops 2015-05-16 11:16:34 -07:00
Jason Ekstrand
3a2db9207d nir/spirv: Set a name on temporary variables 2015-05-16 11:16:34 -07:00
Jason Ekstrand
a28f8ad9f1 nir/spirv: Use the correct length for copying string literals 2015-05-16 11:16:34 -07:00
Jason Ekstrand
7b9c29e440 nir/spirv: Make vtn_ssa_value handle constants as well as ssa values 2015-05-16 11:16:33 -07:00
Jason Ekstrand
b0d1854efc nir/spirv: Add initial support for GLSL 4.50 builtins 2015-05-16 11:16:33 -07:00
Jason Ekstrand
1da9876486 nir/spirv: Split the core datastructures into a header file 2015-05-16 11:16:33 -07:00
Jason Ekstrand
98d78856f6 nir/spirv: Use the builder for all instructions
We don't actually use it to create all the instructions but we do use it
for insertion always.  This should make things far more consistent for
implementing extended instructions.
2015-05-16 11:16:33 -07:00
Jason Ekstrand
ff828749ea nir/spirv: Add support for a bunch of ALU operations 2015-05-16 11:16:33 -07:00
Jason Ekstrand
d2a7972557 nir/spirv: Add support for indirect array accesses 2015-05-16 11:16:33 -07:00
Jason Ekstrand
683c99908a nir/spirv: Explicitly type constants and SSA values 2015-05-16 11:16:33 -07:00
Jason Ekstrand
c5650148a9 nir/spirv: Handle OpBranchConditional
We do control-flow handling as a two-step process.  The first step is to
walk the instructions list and record various information about blocks and
functions.  This is where the acutal nir_function_overload objects get
created.  We also record the start/stop instruction for each block.  Then
a second pass walks over each of the functions and over the blocks in each
function in a way that's NIR-friendly and actually parses the instructions.
2015-05-16 11:16:33 -07:00
Jason Ekstrand
ebc152e4c9 nir/spirv: Add a helper for getting a value as an SSA value 2015-05-16 11:16:33 -07:00
Jason Ekstrand
f23afc549b nir/spirv: Split instruction handling into preamble and body sections 2015-05-16 11:16:33 -07:00
Jason Ekstrand
ae6d32c635 nir/spirv: Implement load/store instructiosn 2015-05-16 11:16:33 -07:00
Jason Ekstrand
88f6fbc897 nir: Add a helper for getting the tail of a deref chain 2015-05-16 11:16:33 -07:00
Jason Ekstrand
06acd174f3 nir/spirv: Actaully add variables to the funciton or shader 2015-05-16 11:16:33 -07:00
Jason Ekstrand
5045efa4aa nir/spirv: Add a vtn_untyped_value helper 2015-05-16 11:16:33 -07:00
Jason Ekstrand
01f3aa9c51 nir/spirv: Use vtn_value in the types code and fix a off-by-one error 2015-05-16 11:16:33 -07:00
Jason Ekstrand
6ff0830d64 nir/types: Add an is_vector_or_scalar helper 2015-05-16 11:16:33 -07:00
Jason Ekstrand
5acd472271 nir/spirv: Add support for deref chains 2015-05-16 11:16:33 -07:00
Jason Ekstrand
7182597e50 nir/types: Add a scalar type constructor 2015-05-16 11:16:32 -07:00
Jason Ekstrand
eccd798cc2 nir/spirv: Add support for OpLabel 2015-05-16 11:16:32 -07:00
Jason Ekstrand
a6cb9d9222 nir/spirv: Add support for declaring functions 2015-05-16 11:16:32 -07:00
Jason Ekstrand
8ee23dab04 nir/types: Add accessors for function parameter/return types 2015-05-16 11:16:32 -07:00
Jason Ekstrand
707b706d18 nir/spirv: Add support for declaring variables
Deref chains and variable load/store operations are still missing.
2015-05-16 11:16:32 -07:00
Jason Ekstrand
b2db85d8e4 nir/spirv: Add support for constants 2015-05-16 11:16:32 -07:00
Jason Ekstrand
3f83579664 nir/spirv: Add basic support for types 2015-05-16 11:16:32 -07:00
Jason Ekstrand
e9d3b1e694 nir/types: Add more helpers for creating types 2015-05-16 11:16:32 -07:00
Jason Ekstrand
fe550f0738 glsl/types: Expose the function_param and struct_field structs to C
Previously, they were hidden behind a #ifdef __cplusplus so C wouldn't find
them.  This commit simpliy moves the ifdef.
2015-05-16 11:16:32 -07:00
Jason Ekstrand
053778c493 glsl/types: Add support for function types 2015-05-16 11:16:32 -07:00
Jason Ekstrand
7b63b3de93 glsl: Add GLSL_TYPE_FUNCTION to the base types enums 2015-05-16 11:16:32 -07:00
Jason Ekstrand
2b570a49a9 nir/spirv: Rework the way values are added
Instead of having functions to add values and set various things, we just
have a function that does a few asserts and then returns the value.  The
caller is then responsible for setting the various fields.
2015-05-16 11:16:32 -07:00
Jason Ekstrand
f9a31ba044 nir/spirv: Add stub support for extension instructions 2015-05-16 11:16:32 -07:00
Jason Ekstrand
4763a13b07 REVERT: Add a simple helper program for testing SPIR-V -> NIR translation 2015-05-16 11:16:32 -07:00
Jason Ekstrand
cae8db6b7e glsl/compiler: Move the error_no_memory stub to standalone_scaffolding.cpp 2015-05-16 11:16:32 -07:00
Jason Ekstrand
98452cd8ae nir: Add the start of a SPIR-V to NIR translator
At the moment, it can handle the very basics of strings and can ignore
debug instructions.  It also has basic support for decorations.
2015-05-16 11:16:32 -07:00
Jason Ekstrand
573ca4a4a7 nir: Import the revision 30 SPIR-V header from Khronos 2015-05-16 11:16:31 -07:00
Jason Ekstrand
057bef8a84 vk/device: Use bias rather than layers for computing binding table size
Because we statically use the first 8 binding table entries for render
targets, we need to create a table of size 8 + surfaces.
2015-05-16 10:42:53 -07:00
Jason Ekstrand
22e61c9da4 vk/meta: Make clear a no-op if no layers need clearing
Among other things, this prevents recursive meta.
2015-05-16 10:30:05 -07:00
Jason Ekstrand
120394ac92 vk/meta: Save and restore the old bindings pointer
If we don't do this then recursive meta is completely broken.  What happens
is that the outer meta call may change the bindings pointer and the inner
meta call will change it again and, when it exits set it back to the
default.  However, the outer meta call may be relying on it being left
alone so it uses the non-meta descriptor sets instead of its own.
2015-05-16 10:28:04 -07:00
Jason Ekstrand
4223de769e vk/device: Simplify surface_count calculation 2015-05-16 10:23:09 -07:00
Jason Ekstrand
eb1952592e vk/glsl_helpers: Fix GLSL_VK_SHADER with respect to commas
Previously, the GLSL_VK_SHADER macro didn't work if the shader contained
commas outside of parentheses due to the way the C preprocessor works.
This commit fixes this by making it variadic again and doing it correctly
this time.
2015-05-15 22:17:07 -07:00
Kristian Høgsberg
3b9f32e893 vk: Make cmd_buffer->bindings a pointer
This lets us save and restore efficiently by just moving the pointer to
a temporary bindings struct for meta.
2015-05-15 18:12:07 -07:00
Kristian Høgsberg
9540130c41 vk: Move vertex buffers into struct anv_bindings 2015-05-15 16:34:31 -07:00
Kristian Høgsberg
0cfc493775 vk: Fix GLSL_VK_SHADER macro
Stringify doesn't work with __ARGV__. The last macro argument swallows
up excess arguments and as such we can just stringify that.
2015-05-15 16:15:04 -07:00
Kristian Høgsberg
af45f4a558 vk: Fix warning from missing initializer
Struct initializers need to be { 0, } to zero out the variable they're
initializing.
2015-05-15 16:07:17 -07:00
Kristian Høgsberg
bf096c9ec3 vk: Build binding tables at bind descriptor time
This changes the way descriptor sets and layouts work so that we fill
out binding table contents at the time we bind descriptor sets. We
manipulate the binding table contents and sampler state in a shadow-copy
in anv_cmd_buffer. At draw time, we allocate the actual binding table
and sampler state and flush the anv_cmd_buffer copies.
2015-05-15 16:05:31 -07:00
Kristian Høgsberg
1f6c220b45 vk: Update the bind map length to reflect MAX_SETS 2015-05-15 15:22:29 -07:00
Kristian Høgsberg
b806e80e66 vk: Flip back to using memfd for the allocators 2015-05-15 15:22:29 -07:00
Kristian Høgsberg
0a775e1eab vk: Rename dyn_state_pool to dynamic_state_pool
Given that we already tolerate surface_state_pool and the even longer
instruction_state_pool, there's no reason to arbitrarily abbreviate
dynamic.
2015-05-15 15:22:29 -07:00
Kristian Høgsberg
f5b0f1351f vk: Consolidate image, buffer and color attachment views
These are all just surface state, offset and a bo.
2015-05-15 15:22:29 -07:00
Jason Ekstrand
41db8db0f2 vk: Add a GLSL scraper utility
This new utility, glsl_scraper.py scrapes C files for instances of the
GLSL_VK_SHADER macro, pulls out the shader source, and compiles it to
SPIR-V.  The compilation is done using glslValidator.  The result is then
placed into another C file as arrays of dwords that can be easiliy handed
to a Vulkan driver.
2015-05-14 19:18:57 -07:00
Jason Ekstrand
79ace6def6 vk/meta: Add a magic GLSL shader source macro 2015-05-14 19:07:34 -07:00
Jason Ekstrand
018a0c1741 vk/meta: Add a better comment about the VS for blits 2015-05-14 11:39:32 -07:00
Jason Ekstrand
8c92701a69 vk/test: Use VK_IMAGE_TILING_OPTIMAL for the render target 2015-05-13 22:27:38 -07:00
Jason Ekstrand
4fb8bddc58 vk/test: Do a copy of the RT into a linear buffer and write that to a PNG 2015-05-13 22:23:30 -07:00
Jason Ekstrand
bd5b76d6d0 vk/meta: Add the start of a blit implementation
Currently, we only implement CopyImageToBuffer
2015-05-13 22:23:30 -07:00
Jason Ekstrand
94b8c0b810 vk/pipeline: Default to a SamplerCount of 1 for PS 2015-05-13 22:23:30 -07:00
Jason Ekstrand
d3d4776202 vk/pipeline: Add an extra flag for force-disabling the vertex shader
This way we can pass in a vertex shader and yet have the pipeline emit an
empty 3DSTATE_VS packet.  We need this for meta because we need to trick
the compiler into not deleting our inputs but at the same time disable the
VS so that we can use a rectlist.  This should go away once we actually get
SPIR-V.
2015-05-13 22:23:30 -07:00
Jason Ekstrand
a1309c5255 vk/pass: Emit a flushing pipe control at the end of the pass
This is rather crude but it at least makes sure that all the render targets
get flushed at the end of the pass.  We probably actually want to do
somthing based on image layout traansitions, but this will work for now.
2015-05-13 22:23:30 -07:00
Jason Ekstrand
07943656a7 vk/compiler: Set the binding table texture_start
This is by no means a complete solution to the binding table problems.
However, it does make texturing actually work.  Before, we were texturing
from the render target since they were both starting at 0.
2015-05-13 22:23:30 -07:00
Jason Ekstrand
cd197181f2 vk/compiler: Zero the prog data
We use prog_data[stage] != NULL to determine whether or not we need to
clean up that stage.  Make sure it default to NULL.
2015-05-13 22:22:59 -07:00
Jason Ekstrand
1f7dcf9d75 vk/image: Stash more information in images and views 2015-05-13 22:22:59 -07:00
Jason Ekstrand
43126388cd vk/meta: Save/restore more stuff in cmd_buffer_restore 2015-05-13 22:22:59 -07:00
Chad Versace
50806e8dec vk: Install headers
I need this for building a testsuite.
2015-05-13 17:49:26 -07:00
Kristian Høgsberg
83c7e1f1db vk: Add support for sampler descriptors 2015-05-13 14:47:11 -07:00
Kristian Høgsberg
4f9eaf77a5 vk: Use a typesafe anv_descriptor struct 2015-05-13 14:47:11 -07:00
Kristian Høgsberg
5c9d77600b vk: Create and bind a sampler in vk.c 2015-05-13 14:47:11 -07:00
Kristian Høgsberg
18acfa7301 vk: Fix copy-n-paste sType in vkCreateSampler 2015-05-13 14:47:11 -07:00
Kristian Høgsberg
a1ec789b0b vk: Add a dynamic state stream to anv_cmd_buffer
We'll need this for sampler state.
2015-05-13 14:47:11 -07:00
Kristian Høgsberg
3f52c016fa vk: Move struct anv_sampler to private.h 2015-05-13 14:47:11 -07:00
Kristian Høgsberg
a77229c979 vk: Allocate layout->count number of descriptors
layout->count is the number of descriptors the application
requested. layout->total is the number of entries we need across all
stages.
2015-05-13 14:47:11 -07:00
Kristian Høgsberg
a3fd136509 vk: Fill out sampler state from API values 2015-05-13 14:47:11 -07:00
Chad Versace
828817b88f vk: Ignore vk executable 2015-05-13 12:05:38 -07:00
Kristian Høgsberg
2b7a060178 vk: Fix stale error handling in vkQueueSubmit 2015-05-12 14:38:58 -07:00
Kristian Høgsberg
cb986ef597 vk: Submit all cmd buffers passed to vkQueueSubmit 2015-05-12 14:38:12 -07:00
Kristian Høgsberg
9905481552 vk: Add generated header for HSW and IVB (GEN75 and GEN7) 2015-05-12 14:29:04 -07:00
Jason Ekstrand
ffe9f60358 vk: Add stub() and stub_return() macros and mark piles of functions as stubs 2015-05-12 13:45:02 -07:00
Jason Ekstrand
d3b374ce59 vk/util: Add a anv_finishme function/macro 2015-05-12 13:43:36 -07:00
Jason Ekstrand
7727720585 vk/meta: Break setting up meta clear state into it's own functin 2015-05-12 13:03:50 -07:00
Jason Ekstrand
4336a1bc00 vk/pipeline: Add support for disabling the scissor in "extra" 2015-05-12 12:53:01 -07:00
Kristian Høgsberg
d77c34d1d2 vk: Add clear load-op for render passes 2015-05-11 23:25:29 -07:00
Kristian Høgsberg
b734e0bcc5 vk: Add support for driver-internal custom pipelines
This lets us disable the viewport, use rect lists and repclear.
2015-05-11 23:25:29 -07:00
Kristian Høgsberg
ad132bbe48 vk: Fix 3DSTATE_VERTEX_BUFFER emission
Set VertexBufferIndex to the attribute binding, not the location.
2015-05-11 23:25:29 -07:00
Kristian Høgsberg
6a895c6681 vk: Add 32 bpc signed and unsigned integer formats 2015-05-11 23:25:29 -07:00
Kristian Høgsberg
55b9b703ea vk: Add anv_batch_emit_merge() helper macro
This lets us emit a state packet by merging to half-backed versions,
typically one from the pipeline object and one from a dynamic state
objects.
2015-05-11 23:25:28 -07:00
Kristian Høgsberg
099faa1a2b vk: Store bo pointer in anv_image and anv_buffer
We don't need to point back to the memory object the bo came from.
Pointing directly to a bo lets us bind images and buffers to other
bos - like our allocator bos.
2015-05-11 23:25:28 -07:00
Kristian Høgsberg
4f25f5d86c vk: Support not having a vertex shader
This lets us bypass the vertex shader and pass data straight into
the rasterizer part of the pipeline.
2015-05-11 23:25:28 -07:00
Kristian Høgsberg
20ad071190 vk: Allow NULL as a valid pipeline layout
Vertex buffers and render targets aren't part of the layout so having
an empty layout is pretty common.
2015-05-11 22:12:56 -07:00
Kristian Høgsberg
769785c497 Add vulkan driver for BDW 2015-05-09 11:38:32 -07:00
110 changed files with 51923 additions and 211 deletions

View File

@@ -99,6 +99,7 @@ AM_PROG_CC_C_O
AM_PROG_AS
AX_CHECK_GNU_MAKE
AC_CHECK_PROGS([PYTHON2], [python2 python])
AC_CHECK_PROGS([PYTHON3], [python3])
AC_PROG_SED
AC_PROG_MKDIR_P
@@ -1517,6 +1518,12 @@ GBM_PC_LIB_PRIV="$DLOPEN_LIBS"
AC_SUBST([GBM_PC_REQ_PRIV])
AC_SUBST([GBM_PC_LIB_PRIV])
AM_CONDITIONAL(HAVE_VULKAN, true)
AC_ARG_VAR([GLSLC], [Path to the glslc executable])
AC_CHECK_PROGS([GLSLC], [glslc])
AC_SUBST([GLSLC])
dnl
dnl EGL configuration
dnl
@@ -2291,6 +2298,13 @@ AC_SUBST([XA_MINOR], $XA_MINOR)
AC_SUBST([XA_TINY], $XA_TINY)
AC_SUBST([XA_VERSION], "$XA_MAJOR.$XA_MINOR.$XA_TINY")
PKG_CHECK_MODULES(VALGRIND, [valgrind],
[have_valgrind=yes], [have_valgrind=no])
if test "x$have_valgrind" = "xyes"; then
AC_DEFINE([HAVE_VALGRIND], 1,
[Use valgrind intrinsics to suppress false warnings])
fi
dnl Restore LDFLAGS and CPPFLAGS
LDFLAGS="$_SAVE_LDFLAGS"
CPPFLAGS="$_SAVE_CPPFLAGS"
@@ -2400,6 +2414,9 @@ AC_CONFIG_FILES([Makefile
src/mesa/drivers/osmesa/osmesa.pc
src/mesa/drivers/x11/Makefile
src/mesa/main/tests/Makefile
src/vulkan/Makefile
src/vulkan/anv_icd.json
src/vulkan/tests/Makefile
src/util/Makefile
src/util/tests/hash_table/Makefile])
@@ -2518,6 +2535,7 @@ if test "x$MESA_LLVM" = x1; then
echo ""
fi
echo " PYTHON2: $PYTHON2"
echo " PYTHON3: $PYTHON3"
echo ""
echo " Run '${MAKE-make}' to build Mesa"

View File

@@ -0,0 +1,90 @@
//
// File: vk_platform.h
//
/*
** Copyright (c) 2014-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#ifndef __VK_PLATFORM_H__
#define __VK_PLATFORM_H__
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
/*
***************************************************************************************************
* Platform-specific directives and type declarations
***************************************************************************************************
*/
#if defined(_WIN32)
// On Windows, VKAPI should equate to the __stdcall convention
#define VKAPI __stdcall
#elif defined(__GNUC__)
// On other platforms using GCC, VKAPI stays undefined
#define VKAPI
#else
// Unsupported Platform!
#error "Unsupported OS Platform detected!"
#endif
#include <stddef.h>
#if !defined(VK_NO_STDINT_H)
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#endif // !defined(VK_NO_STDINT_H)
typedef uint64_t VkDeviceSize;
typedef uint32_t VkBool32;
typedef uint32_t VkSampleMask;
typedef uint32_t VkFlags;
#if (UINTPTR_MAX >= UINT64_MAX)
#define VK_UINTPTRLEAST64_MAX UINTPTR_MAX
typedef uintptr_t VkUintPtrLeast64;
#else
#define VK_UINTPTRLEAST64_MAX UINT64_MAX
typedef uint64_t VkUintPtrLeast64;
#endif
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // __VK_PLATFORM_H__

View File

@@ -0,0 +1,249 @@
//
// File: vk_wsi_device_swapchain.h
//
/*
** Copyright (c) 2014 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#ifndef __VK_WSI_DEVICE_SWAPCHAIN_H__
#define __VK_WSI_DEVICE_SWAPCHAIN_H__
#include "vulkan.h"
#define VK_WSI_DEVICE_SWAPCHAIN_REVISION 40
#define VK_WSI_DEVICE_SWAPCHAIN_EXTENSION_NUMBER 2
#define VK_WSI_DEVICE_SWAPCHAIN_EXTENSION_NAME "VK_WSI_device_swapchain"
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
// ------------------------------------------------------------------------------------------------
// Objects
VK_DEFINE_NONDISP_HANDLE(VkSwapChainWSI);
// ------------------------------------------------------------------------------------------------
// Enumeration constants
#define VK_WSI_DEVICE_SWAPCHAIN_ENUM(type,id) ((type)((int)0xc0000000 - VK_WSI_DEVICE_SWAPCHAIN_EXTENSION_NUMBER * -1024 + (id)))
#define VK_WSI_DEVICE_SWAPCHAIN_ENUM_POSITIVE(type,id) ((type)((int)0x40000000 + (VK_WSI_DEVICE_SWAPCHAIN_EXTENSION_NUMBER - 1) * 1024 + (id)))
// Extend VkStructureType enum with extension specific constants
#define VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI VK_WSI_DEVICE_SWAPCHAIN_ENUM(VkStructureType, 0)
#define VK_STRUCTURE_TYPE_QUEUE_PRESENT_INFO_WSI VK_WSI_DEVICE_SWAPCHAIN_ENUM(VkStructureType, 1)
// Extend VkImageLayout enum with extension specific constants
#define VK_IMAGE_LAYOUT_PRESENT_SOURCE_WSI VK_WSI_DEVICE_SWAPCHAIN_ENUM(VkImageLayout, 2)
// Extend VkResult enum with extension specific constants
// Return codes for successful operation execution
#define VK_SUBOPTIMAL_WSI VK_WSI_DEVICE_SWAPCHAIN_ENUM_POSITIVE(VkResult, 3)
// Error codes
#define VK_ERROR_OUT_OF_DATE_WSI VK_WSI_DEVICE_SWAPCHAIN_ENUM(VkResult, 4)
// ------------------------------------------------------------------------------------------------
// Enumerations
typedef enum VkSurfaceTransformWSI_
{
VK_SURFACE_TRANSFORM_NONE_WSI = 0,
VK_SURFACE_TRANSFORM_ROT90_WSI = 1,
VK_SURFACE_TRANSFORM_ROT180_WSI = 2,
VK_SURFACE_TRANSFORM_ROT270_WSI = 3,
VK_SURFACE_TRANSFORM_HMIRROR_WSI = 4,
VK_SURFACE_TRANSFORM_HMIRROR_ROT90_WSI = 5,
VK_SURFACE_TRANSFORM_HMIRROR_ROT180_WSI = 6,
VK_SURFACE_TRANSFORM_HMIRROR_ROT270_WSI = 7,
VK_SURFACE_TRANSFORM_INHERIT_WSI = 8,
} VkSurfaceTransformWSI;
typedef enum VkSurfaceTransformFlagBitsWSI_
{
VK_SURFACE_TRANSFORM_NONE_BIT_WSI = 0x00000001,
VK_SURFACE_TRANSFORM_ROT90_BIT_WSI = 0x00000002,
VK_SURFACE_TRANSFORM_ROT180_BIT_WSI = 0x00000004,
VK_SURFACE_TRANSFORM_ROT270_BIT_WSI = 0x00000008,
VK_SURFACE_TRANSFORM_HMIRROR_BIT_WSI = 0x00000010,
VK_SURFACE_TRANSFORM_HMIRROR_ROT90_BIT_WSI = 0x00000020,
VK_SURFACE_TRANSFORM_HMIRROR_ROT180_BIT_WSI = 0x00000040,
VK_SURFACE_TRANSFORM_HMIRROR_ROT270_BIT_WSI = 0x00000080,
VK_SURFACE_TRANSFORM_INHERIT_BIT_WSI = 0x00000100,
} VkSurfaceTransformFlagBitsWSI;
typedef VkFlags VkSurfaceTransformFlagsWSI;
typedef enum VkSurfaceInfoTypeWSI_
{
VK_SURFACE_INFO_TYPE_PROPERTIES_WSI = 0,
VK_SURFACE_INFO_TYPE_FORMATS_WSI = 1,
VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI = 2,
VK_SURFACE_INFO_TYPE_BEGIN_RANGE_WSI = VK_SURFACE_INFO_TYPE_PROPERTIES_WSI,
VK_SURFACE_INFO_TYPE_END_RANGE_WSI = VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI,
VK_SURFACE_INFO_TYPE_NUM_WSI = (VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI - VK_SURFACE_INFO_TYPE_PROPERTIES_WSI + 1),
VK_SURFACE_INFO_TYPE_MAX_ENUM_WSI = 0x7FFFFFFF
} VkSurfaceInfoTypeWSI;
typedef enum VkSwapChainInfoTypeWSI_
{
VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI = 0,
VK_SWAP_CHAIN_INFO_TYPE_BEGIN_RANGE_WSI = VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
VK_SWAP_CHAIN_INFO_TYPE_END_RANGE_WSI = VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
VK_SWAP_CHAIN_INFO_TYPE_NUM_WSI = (VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI - VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI + 1),
VK_SWAP_CHAIN_INFO_TYPE_MAX_ENUM_WSI = 0x7FFFFFFF
} VkSwapChainInfoTypeWSI;
typedef enum VkPresentModeWSI_
{
VK_PRESENT_MODE_IMMEDIATE_WSI = 0,
VK_PRESENT_MODE_MAILBOX_WSI = 1,
VK_PRESENT_MODE_FIFO_WSI = 2,
VK_PRESENT_MODE_BEGIN_RANGE_WSI = VK_PRESENT_MODE_IMMEDIATE_WSI,
VK_PRESENT_MODE_END_RANGE_WSI = VK_PRESENT_MODE_FIFO_WSI,
VK_PRESENT_MODE_NUM = (VK_PRESENT_MODE_FIFO_WSI - VK_PRESENT_MODE_IMMEDIATE_WSI + 1),
VK_PRESENT_MODE_MAX_ENUM_WSI = 0x7FFFFFFF
} VkPresentModeWSI;
// ------------------------------------------------------------------------------------------------
// Flags
// ------------------------------------------------------------------------------------------------
// Structures
typedef struct VkSurfacePropertiesWSI_
{
uint32_t minImageCount; // Supported minimum number of images for the surface
uint32_t maxImageCount; // Supported maximum number of images for the surface, 0 for unlimited
VkExtent2D currentExtent; // Current image width and height for the surface, (-1, -1) if undefined.
VkExtent2D minImageExtent; // Supported minimum image width and height for the surface
VkExtent2D maxImageExtent; // Supported maximum image width and height for the surface
VkSurfaceTransformFlagsWSI supportedTransforms;// 1 or more bits representing the transforms supported
VkSurfaceTransformWSI currentTransform; // The surface's current transform relative to the device's natural orientation.
uint32_t maxImageArraySize; // Supported maximum number of image layers for the surface
VkImageUsageFlags supportedUsageFlags;// Supported image usage flags for the surface
} VkSurfacePropertiesWSI;
typedef struct VkSurfaceFormatPropertiesWSI_
{
VkFormat format; // Supported rendering format for the surface
} VkSurfaceFormatPropertiesWSI;
typedef struct VkSurfacePresentModePropertiesWSI_
{
VkPresentModeWSI presentMode; // Supported presention mode for the surface
} VkSurfacePresentModePropertiesWSI;
typedef struct VkSwapChainCreateInfoWSI_
{
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI
const void* pNext; // Pointer to next structure
const VkSurfaceDescriptionWSI* pSurfaceDescription;// describes the swap chain's target surface
uint32_t minImageCount; // Minimum number of presentation images the application needs
VkFormat imageFormat; // Format of the presentation images
VkExtent2D imageExtent; // Dimensions of the presentation images
VkImageUsageFlags imageUsageFlags; // Bits indicating how the presentation images will be used
VkSurfaceTransformWSI preTransform; // The transform, relative to the device's natural orientation, applied to the image content prior to presentation
uint32_t imageArraySize; // Determines the number of views for multiview/stereo presentation
VkPresentModeWSI presentMode; // Which presentation mode to use for presents on this swap chain.
VkSwapChainWSI oldSwapChain; // Existing swap chain to replace, if any.
VkBool32 clipped; // Specifies whether presentable images may be affected by window clip regions.
} VkSwapChainCreateInfoWSI;
typedef struct VkSwapChainImagePropertiesWSI_
{
VkImage image; // Persistent swap chain image handle
} VkSwapChainImagePropertiesWSI;
typedef struct VkPresentInfoWSI_
{
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_QUEUE_PRESENT_INFO_WSI
const void* pNext; // Pointer to next structure
uint32_t swapChainCount; // Number of swap chains to present in this call
const VkSwapChainWSI* swapChains; // Swap chains to present an image from.
const uint32_t* imageIndices; // Indices of which swapChain images to present
} VkPresentInfoWSI;
// ------------------------------------------------------------------------------------------------
// Function types
typedef VkResult (VKAPI *PFN_vkGetSurfaceInfoWSI)(VkDevice device, const VkSurfaceDescriptionWSI* pSurfaceDescription, VkSurfaceInfoTypeWSI infoType, size_t* pDataSize, void* pData);
typedef VkResult (VKAPI *PFN_vkCreateSwapChainWSI)(VkDevice device, const VkSwapChainCreateInfoWSI* pCreateInfo, VkSwapChainWSI* pSwapChain);
typedef VkResult (VKAPI *PFN_vkDestroySwapChainWSI)(VkDevice device, VkSwapChainWSI swapChain);
typedef VkResult (VKAPI *PFN_vkGetSwapChainInfoWSI)(VkDevice device, VkSwapChainWSI swapChain, VkSwapChainInfoTypeWSI infoType, size_t* pDataSize, void* pData);
typedef VkResult (VKAPI *PFN_vkAcquireNextImageWSI)(VkDevice device, VkSwapChainWSI swapChain, uint64_t timeout, VkSemaphore semaphore, uint32_t* pImageIndex);
typedef VkResult (VKAPI *PFN_vkQueuePresentWSI)(VkQueue queue, VkPresentInfoWSI* pPresentInfo);
// ------------------------------------------------------------------------------------------------
// Function prototypes
#ifdef VK_PROTOTYPES
VkResult VKAPI vkGetSurfaceInfoWSI(
VkDevice device,
const VkSurfaceDescriptionWSI* pSurfaceDescription,
VkSurfaceInfoTypeWSI infoType,
size_t* pDataSize,
void* pData);
VkResult VKAPI vkCreateSwapChainWSI(
VkDevice device,
const VkSwapChainCreateInfoWSI* pCreateInfo,
VkSwapChainWSI* pSwapChain);
VkResult VKAPI vkDestroySwapChainWSI(
VkDevice device,
VkSwapChainWSI swapChain);
VkResult VKAPI vkGetSwapChainInfoWSI(
VkDevice device,
VkSwapChainWSI swapChain,
VkSwapChainInfoTypeWSI infoType,
size_t* pDataSize,
void* pData);
VkResult VKAPI vkAcquireNextImageWSI(
VkDevice device,
VkSwapChainWSI swapChain,
uint64_t timeout,
VkSemaphore semaphore,
uint32_t* pImageIndex);
VkResult VKAPI vkQueuePresentWSI(
VkQueue queue,
VkPresentInfoWSI* pPresentInfo);
#endif // VK_PROTOTYPES
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // __VK_WSI_SWAPCHAIN_H__

View File

@@ -0,0 +1,133 @@
//
// File: vk_wsi_swapchain.h
//
/*
** Copyright (c) 2014 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#ifndef __VK_WSI_SWAPCHAIN_H__
#define __VK_WSI_SWAPCHAIN_H__
#include "vulkan.h"
#define VK_WSI_SWAPCHAIN_REVISION 12
#define VK_WSI_SWAPCHAIN_EXTENSION_NUMBER 1
#define VK_WSI_SWAPCHAIN_EXTENSION_NAME "VK_WSI_swapchain"
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
// ------------------------------------------------------------------------------------------------
// Objects
// ------------------------------------------------------------------------------------------------
// Enumeration constants
#define VK_WSI_SWAPCHAIN_ENUM(type,id) ((type)((int)0xc0000000 - VK_WSI_SWAPCHAIN_EXTENSION_NUMBER * -1024 + (id)))
#define VK_WSI_SWAPCHAIN_ENUM_POSITIVE(type,id) ((type)((int)0x40000000 + (VK_WSI_SWAPCHAIN_EXTENSION_NUMBER - 1) * 1024 + (id)))
// Extend VkStructureType enum with extension specific constants
#define VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI VK_WSI_SWAPCHAIN_ENUM(VkStructureType, 0)
// ------------------------------------------------------------------------------------------------
// Enumerations
typedef enum VkPlatformWSI_
{
VK_PLATFORM_WIN32_WSI = 0,
VK_PLATFORM_X11_WSI = 1,
VK_PLATFORM_XCB_WSI = 2,
VK_PLATFORM_ANDROID_WSI = 3,
VK_PLATFORM_WAYLAND_WSI = 4,
VK_PLATFORM_MIR_WSI = 5,
VK_PLATFORM_BEGIN_RANGE_WSI = VK_PLATFORM_WIN32_WSI,
VK_PLATFORM_END_RANGE_WSI = VK_PLATFORM_MIR_WSI,
VK_PLATFORM_NUM_WSI = (VK_PLATFORM_MIR_WSI - VK_PLATFORM_WIN32_WSI + 1),
VK_PLATFORM_MAX_ENUM_WSI = 0x7FFFFFFF
} VkPlatformWSI;
// ------------------------------------------------------------------------------------------------
// Flags
// ------------------------------------------------------------------------------------------------
// Structures
// pPlatformHandle points to this struct when platform is VK_PLATFORM_X11_WSI
#ifdef _X11_XLIB_H_
typedef struct VkPlatformHandleX11WSI_
{
Display* dpy; // Display connection to an X server
Window root; // To identify the X screen
} VkPlatformHandleX11WSI;
#endif /* _X11_XLIB_H_ */
// pPlatformHandle points to this struct when platform is VK_PLATFORM_XCB_WSI
#ifdef __XCB_H__
typedef struct VkPlatformHandleXcbWSI_
{
xcb_connection_t* connection; // XCB connection to an X server
xcb_window_t root; // To identify the X screen
} VkPlatformHandleXcbWSI;
#endif /* __XCB_H__ */
// Placeholder structure header for the different types of surface description structures
typedef struct VkSurfaceDescriptionWSI_
{
VkStructureType sType; // Can be any of the VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_XXX_WSI constants
const void* pNext; // Pointer to next structure
} VkSurfaceDescriptionWSI;
// Surface description structure for a native platform window surface
typedef struct VkSurfaceDescriptionWindowWSI_
{
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI
const void* pNext; // Pointer to next structure
VkPlatformWSI platform; // e.g. VK_PLATFORM_*_WSI
void* pPlatformHandle;
void* pPlatformWindow;
} VkSurfaceDescriptionWindowWSI;
// ------------------------------------------------------------------------------------------------
// Function types
typedef VkResult (VKAPI *PFN_vkGetPhysicalDeviceSurfaceSupportWSI)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkSurfaceDescriptionWSI* pSurfaceDescription, VkBool32* pSupported);
// ------------------------------------------------------------------------------------------------
// Function prototypes
#ifdef VK_PROTOTYPES
VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportWSI(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
const VkSurfaceDescriptionWSI* pSurfaceDescription,
VkBool32* pSupported);
#endif // VK_PROTOTYPES
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // __VK_WSI_SWAPCHAIN_H__

3054
include/vulkan/vulkan.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef __VULKAN_INTEL_H__
#define __VULKAN_INTEL_H__
#include "vulkan.h"
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL 1024
typedef struct VkDmaBufImageCreateInfo_
{
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL
const void* pNext; // Pointer to next structure.
int fd;
VkFormat format;
VkExtent3D extent; // Depth must be 1
uint32_t strideInBytes;
} VkDmaBufImageCreateInfo;
typedef VkResult (VKAPI *PFN_vkCreateDmaBufImageINTEL)(VkDevice device, const VkDmaBufImageCreateInfo* pCreateInfo, VkDeviceMemory* pMem, VkImage* pImage);
#ifdef VK_PROTOTYPES
VkResult VKAPI vkCreateDmaBufImageINTEL(
VkDevice _device,
const VkDmaBufImageCreateInfo* pCreateInfo,
VkDeviceMemory* pMem,
VkImage* pImage);
#endif
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // __VULKAN_INTEL_H__

View File

@@ -53,6 +53,10 @@ EXTRA_DIST = \
AM_CFLAGS = $(VISIBILITY_CFLAGS)
AM_CXXFLAGS = $(VISIBILITY_CXXFLAGS)
if HAVE_VULKAN
SUBDIRS += vulkan
endif
AM_CPPFLAGS = \
-I$(top_srcdir)/include/ \
-I$(top_srcdir)/src/mapi/ \

1
src/glsl/.gitignore vendored
View File

@@ -4,6 +4,7 @@ glsl_parser.cpp
glsl_parser.h
glsl_parser.output
glsl_test
spirv2nir
subtest-cr/
subtest-lf/
subtest-cr-lf/

View File

@@ -75,7 +75,7 @@ check_PROGRAMS = \
tests/sampler-types-test \
tests/uniform-initializer-test
noinst_PROGRAMS = glsl_compiler
noinst_PROGRAMS = glsl_compiler spirv2nir
tests_blob_test_SOURCES = \
tests/blob_test.c
@@ -156,6 +156,16 @@ glsl_compiler_LDADD = \
$(top_builddir)/src/libglsl_util.la \
$(PTHREAD_LIBS)
spirv2nir_SOURCES = \
standalone_scaffolding.cpp \
standalone_scaffolding.h \
nir/spirv2nir.c
spirv2nir_LDADD = \
libglsl.la \
$(top_builddir)/src/libglsl_util.la \
$(PTHREAD_LIBS)
glsl_test_SOURCES = \
standalone_scaffolding.cpp \
test.cpp \

View File

@@ -40,6 +40,7 @@ NIR_FILES = \
nir/nir_lower_locals_to_regs.c \
nir/nir_lower_idiv.c \
nir/nir_lower_io.c \
nir/nir_lower_outputs_to_temporaries.c \
nir/nir_lower_phis_to_scalar.c \
nir/nir_lower_samplers.cpp \
nir/nir_lower_system_values.c \
@@ -64,6 +65,7 @@ NIR_FILES = \
nir/nir_remove_dead_variables.c \
nir/nir_search.c \
nir/nir_search.h \
nir/nir_spirv.h \
nir/nir_split_var_copies.c \
nir/nir_sweep.c \
nir/nir_to_ssa.c \
@@ -73,6 +75,8 @@ NIR_FILES = \
nir/nir_worklist.c \
nir/nir_worklist.h \
nir/nir_types.cpp \
nir/spirv_to_nir.c \
nir/spirv_glsl450_to_nir.c \
$(NIR_GENERATED_FILES)
# libglsl

View File

@@ -527,6 +527,9 @@ struct ast_type_qualifier {
unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */
/** \} */
/** \name Vulkan qualifiers */
unsigned vk_set:1;
/** \name Layout qualifiers for GL_ARB_tessellation_shader */
/** \{ */
/* tess eval input layout */
@@ -639,6 +642,11 @@ struct ast_type_qualifier {
*/
glsl_base_type image_base_type;
/**
* Vulkan descriptor set
*/
int set;
/**
* Return true if and only if an interpolation qualifier is present.
*/

View File

@@ -1019,6 +1019,7 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_SUBROUTINE:
/* I assume a comparison of a struct containing a sampler just
@@ -2776,7 +2777,16 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers;
}
if (qual->flags.q.explicit_location) {
if (qual->flags.q.vk_set) {
if (!qual->flags.q.explicit_binding)
_mesa_glsl_error(loc, state,
"Vulkan descriptor set layout requires both set "
"and binding qualifiers");
var->data.vk_set = true;
var->data.set = qual->set;
var->data.binding = qual->binding;
} else if (qual->flags.q.explicit_location) {
validate_explicit_location(qual, var, state, loc);
} else if (qual->flags.q.explicit_index) {
_mesa_glsl_error(loc, state, "explicit index requires explicit location");
@@ -6270,6 +6280,10 @@ ast_interface_block::hir(exec_list *instructions,
var->data.explicit_binding = this->layout.flags.q.explicit_binding;
var->data.binding = this->layout.binding;
var->data.vk_set = this->layout.flags.q.vk_set;
var->data.set = this->layout.set;
var->data.binding = this->layout.binding;
state->symbols->add_variable(var);
instructions->push_tail(var);
}
@@ -6343,6 +6357,10 @@ ast_interface_block::hir(exec_list *instructions,
var->data.explicit_binding = this->layout.flags.q.explicit_binding;
var->data.binding = this->layout.binding;
var->data.vk_set = this->layout.flags.q.vk_set;
var->data.set = this->layout.set;
var->data.binding = this->layout.binding;
state->symbols->add_variable(var);
instructions->push_tail(var);
}

View File

@@ -297,6 +297,11 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
this->image_base_type = q.image_base_type;
}
if (q.flags.q.vk_set) {
this->set = q.set;
this->binding = q.binding;
}
return true;
}

View File

@@ -1468,14 +1468,16 @@ layout_qualifier_id:
}
}
if ((state->has_420pack() ||
state->has_atomic_counters() ||
state->has_shader_storage_buffer_objects()) &&
match_layout_qualifier("binding", $1, state) == 0) {
if (match_layout_qualifier("binding", $1, state) == 0) {
$$.flags.q.explicit_binding = 1;
$$.binding = $3;
}
if (match_layout_qualifier("set", $1, state) == 0) {
$$.flags.q.vk_set = 1;
$$.set = $3;
}
if (state->has_atomic_counters() &&
match_layout_qualifier("offset", $1, state) == 0) {
$$.flags.q.explicit_offset = 1;

View File

@@ -87,6 +87,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx,
this->extensions = &ctx->Extensions;
this->ARB_compute_shader_enable = true;
this->Const.MaxLights = ctx->Const.MaxLights;
this->Const.MaxClipPlanes = ctx->Const.MaxClipPlanes;
this->Const.MaxTextureUnits = ctx->Const.MaxTextureUnits;

View File

@@ -32,6 +32,7 @@ mtx_t glsl_type::mutex = _MTX_INITIALIZER_NP;
hash_table *glsl_type::array_types = NULL;
hash_table *glsl_type::record_types = NULL;
hash_table *glsl_type::interface_types = NULL;
hash_table *glsl_type::function_types = NULL;
hash_table *glsl_type::subroutine_types = NULL;
void *glsl_type::mem_ctx = NULL;
@@ -162,6 +163,39 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
mtx_unlock(&glsl_type::mutex);
}
glsl_type::glsl_type(const glsl_type *return_type,
const glsl_function_param *params, unsigned num_params) :
gl_type(0),
base_type(GLSL_TYPE_FUNCTION),
sampler_dimensionality(0), sampler_shadow(0), sampler_array(0),
sampler_type(0), interface_packing(0),
vector_elements(0), matrix_columns(0),
length(num_params)
{
unsigned int i;
mtx_lock(&glsl_type::mutex);
init_ralloc_type_ctx();
this->fields.parameters = rzalloc_array(this->mem_ctx,
glsl_function_param, num_params + 1);
/* We store the return type as the first parameter */
this->fields.parameters[0].type = return_type;
this->fields.parameters[0].in = false;
this->fields.parameters[0].out = true;
/* We store the i'th parameter in slot i+1 */
for (i = 0; i < length; i++) {
this->fields.parameters[i + 1].type = params[i].type;
this->fields.parameters[i + 1].in = params[i].in;
this->fields.parameters[i + 1].out = params[i].out;
}
mtx_unlock(&glsl_type::mutex);
}
glsl_type::glsl_type(const char *subroutine_name) :
gl_type(0),
base_type(GLSL_TYPE_SUBROUTINE),
@@ -900,6 +934,74 @@ glsl_type::get_subroutine_instance(const char *subroutine_name)
}
static bool
function_key_compare(const void *a, const void *b)
{
const glsl_type *const key1 = (glsl_type *) a;
const glsl_type *const key2 = (glsl_type *) b;
if (key1->length != key2->length)
return 1;
return memcmp(key1->fields.parameters, key2->fields.parameters,
(key1->length + 1) * sizeof(*key1->fields.parameters));
}
static uint32_t
function_key_hash(const void *a)
{
const glsl_type *const key = (glsl_type *) a;
char hash_key[128];
unsigned size = 0;
size = snprintf(hash_key, sizeof(hash_key), "%08x", key->length);
for (unsigned i = 0; i < key->length; i++) {
if (size >= sizeof(hash_key))
break;
size += snprintf(& hash_key[size], sizeof(hash_key) - size,
"%p", (void *) key->fields.structure[i].type);
}
return _mesa_hash_string(hash_key);
}
const glsl_type *
glsl_type::get_function_instance(const glsl_type *return_type,
const glsl_function_param *params,
unsigned num_params)
{
const glsl_type key(return_type, params, num_params);
mtx_lock(&glsl_type::mutex);
if (function_types == NULL) {
function_types = _mesa_hash_table_create(NULL, function_key_hash,
function_key_compare);
}
struct hash_entry *entry = _mesa_hash_table_search(function_types, &key);
if (entry == NULL) {
mtx_unlock(&glsl_type::mutex);
const glsl_type *t = new glsl_type(return_type, params, num_params);
mtx_lock(&glsl_type::mutex);
entry = _mesa_hash_table_insert(function_types, t, (void *) t);
}
const glsl_type *t = (const glsl_type *)entry->data;
assert(t->base_type == GLSL_TYPE_FUNCTION);
assert(t->length == num_params);
mtx_unlock(&glsl_type::mutex);
return t;
}
const glsl_type *
glsl_type::get_mul_type(const glsl_type *type_a, const glsl_type *type_b)
{
@@ -1029,6 +1131,8 @@ glsl_type::component_slots() const
return 1;
case GLSL_TYPE_SUBROUTINE:
return 1;
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
@@ -1402,6 +1506,7 @@ glsl_type::count_attribute_slots() const
case GLSL_TYPE_ARRAY:
return this->length * this->fields.array->count_attribute_slots();
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
case GLSL_TYPE_ATOMIC_UINT:

View File

@@ -56,6 +56,7 @@ enum glsl_base_type {
GLSL_TYPE_IMAGE,
GLSL_TYPE_ATOMIC_UINT,
GLSL_TYPE_STRUCT,
GLSL_TYPE_FUNCTION,
GLSL_TYPE_INTERFACE,
GLSL_TYPE_ARRAY,
GLSL_TYPE_VOID,
@@ -179,7 +180,7 @@ struct glsl_type {
*/
union {
const struct glsl_type *array; /**< Type of array elements. */
const struct glsl_type *parameters; /**< Parameters to function. */
struct glsl_function_param *parameters; /**< Parameters to function. */
struct glsl_struct_field *structure; /**< List of struct fields. */
} fields;
@@ -269,6 +270,13 @@ struct glsl_type {
*/
static const glsl_type *get_subroutine_instance(const char *subroutine_name);
/**
* Get the instance of a function type
*/
static const glsl_type *get_function_instance(const struct glsl_type *return_type,
const glsl_function_param *parameters,
unsigned num_params);
/**
* Get the type resulting from a multiplication of \p type_a * \p type_b
*/
@@ -689,6 +697,10 @@ private:
glsl_type(const glsl_struct_field *fields, unsigned num_fields,
enum glsl_interface_packing packing, const char *name);
/** Constructor for interface types */
glsl_type(const glsl_type *return_type,
const glsl_function_param *params, unsigned num_params);
/** Constructor for array types */
glsl_type(const glsl_type *array, unsigned length);
@@ -707,6 +719,9 @@ private:
/** Hash table containing the known subroutine types. */
static struct hash_table *subroutine_types;
/** Hash table containing the known function types. */
static struct hash_table *function_types;
static bool record_key_compare(const void *a, const void *b);
static unsigned record_key_hash(const void *key);
@@ -734,6 +749,10 @@ private:
/*@}*/
};
#undef DECL_TYPE
#undef STRUCT_TYPE
#endif /* __cplusplus */
struct glsl_struct_field {
const struct glsl_type *type;
const char *name;
@@ -782,6 +801,7 @@ struct glsl_struct_field {
*/
int stream;
#ifdef __cplusplus
glsl_struct_field(const struct glsl_type *_type, const char *_name)
: type(_type), name(_name), location(-1), interpolation(0), centroid(0),
sample(0), matrix_layout(GLSL_MATRIX_LAYOUT_INHERITED), patch(0),
@@ -794,6 +814,14 @@ struct glsl_struct_field {
{
/* empty */
}
#endif
};
struct glsl_function_param {
const struct glsl_type *type;
bool in;
bool out;
};
static inline unsigned int
@@ -802,8 +830,4 @@ glsl_align(unsigned int a, unsigned int align)
return (a + align - 1) / align * align;
}
#undef DECL_TYPE
#undef STRUCT_TYPE
#endif /* __cplusplus */
#endif /* GLSL_TYPES_H */

View File

@@ -688,6 +688,11 @@ public:
unsigned explicit_location:1;
unsigned explicit_index:1;
/**
* Do we have a Vulkan (group, index) qualifier for this variable?
*/
unsigned vk_set:1;
/**
* Was an initial binding explicitly set in the shader?
*
@@ -757,8 +762,10 @@ public:
* \note
* The GLSL spec only allows the values 0 or 1 for the index in \b dual
* source blending.
*
* This is now also used for the Vulkan descriptor set index.
*/
unsigned index:1;
int16_t index;
/**
* \brief Layout qualifier for gl_FragDepth.
@@ -806,6 +813,11 @@ public:
*/
int16_t binding;
/**
* Vulkan descriptor set for the resource.
*/
int16_t set;
/**
* Storage location of the base of this variable
*

View File

@@ -363,6 +363,7 @@ ir_constant::clone(void *mem_ctx, struct hash_table *ht) const
return c;
}
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
case GLSL_TYPE_ATOMIC_UINT:

View File

@@ -54,6 +54,11 @@ process_block(void *mem_ctx, struct hash_table *ht, ir_variable *var)
b->binding = 0;
}
if (var->data.vk_set) {
b->set = var->data.set;
b->index = var->data.index;
}
_mesa_hash_table_insert(ht, var->get_interface_type()->name, (void *) b);
return b;
} else {

View File

@@ -35,6 +35,8 @@ struct link_uniform_block_active {
unsigned num_array_elements;
unsigned binding;
unsigned set;
unsigned index;
bool has_instance_name;
bool has_binding;

View File

@@ -293,6 +293,8 @@ link_uniform_blocks(void *mem_ctx,
blocks[i].NumUniforms =
(unsigned)(ptrdiff_t)(&variables[parcel.index] - blocks[i].Uniforms);
blocks[i].Set = b->set;
blocks[i].Binding = b->binding;
blocks[i].IsShaderStorage = b->is_shader_storage;
i++;
@@ -313,6 +315,8 @@ link_uniform_blocks(void *mem_ctx,
blocks[i].NumUniforms =
(unsigned)(ptrdiff_t)(&variables[parcel.index] - blocks[i].Uniforms);
blocks[i].Set = b->set;
blocks[i].Binding = b->binding;
blocks[i].IsShaderStorage = b->is_shader_storage;
i++;

View File

@@ -88,6 +88,7 @@ copy_constant_to_storage(union gl_constant_value *storage,
case GLSL_TYPE_IMAGE:
case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_VOID:
case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_ERROR:

View File

@@ -44,7 +44,7 @@ namespace {
class nir_visitor : public ir_visitor
{
public:
nir_visitor(nir_shader *shader);
nir_visitor(nir_shader *shader, gl_shader *sh);
~nir_visitor();
virtual void visit(ir_variable *);
@@ -84,6 +84,8 @@ private:
bool supports_ints;
struct gl_shader *sh;
nir_shader *shader;
nir_function_impl *impl;
exec_list *cf_node_list;
@@ -133,7 +135,7 @@ glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options)
{
nir_shader *shader = nir_shader_create(NULL, sh->Stage, options);
nir_visitor v1(shader);
nir_visitor v1(shader, sh);
nir_function_visitor v2(&v1);
v2.run(sh->ir);
visit_exec_list(sh->ir, &v1);
@@ -141,10 +143,11 @@ glsl_to_nir(struct gl_shader *sh, const nir_shader_compiler_options *options)
return shader;
}
nir_visitor::nir_visitor(nir_shader *shader)
nir_visitor::nir_visitor(nir_shader *shader, gl_shader *sh)
{
this->supports_ints = shader->options->native_integers;
this->shader = shader;
this->sh = sh;
this->is_global = true;
this->var_table = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
@@ -324,6 +327,7 @@ nir_visitor::visit(ir_variable *ir)
}
var->data.index = ir->data.index;
var->data.descriptor_set = ir->data.set;
var->data.binding = ir->data.binding;
/* XXX Get rid of buffer_index */
var->data.atomic.buffer_index = ir->data.binding;
@@ -998,11 +1002,21 @@ nir_visitor::visit(ir_expression *ir)
} else {
op = nir_intrinsic_load_ubo_indirect;
}
ir_constant *const_block = ir->operands[0]->as_constant();
assert(const_block && "can't figure out descriptor set index");
unsigned index = const_block->value.u[0];
unsigned set = sh->UniformBlocks[index].Set;
unsigned binding = sh->UniformBlocks[index].Binding;
nir_intrinsic_instr *load = nir_intrinsic_instr_create(this->shader, op);
load->num_components = ir->type->vector_elements;
load->const_index[0] = const_index ? const_index->value.u[0] : 0; /* base offset */
load->const_index[1] = 1; /* number of vec4's */
load->src[0] = evaluate_rvalue(ir->operands[0]);
load->const_index[0] = set;
load->const_index[1] = const_index ? const_index->value.u[0] : 0; /* base offset */
nir_load_const_instr *load_binding = nir_load_const_instr_create(shader, 1);
load_binding->value.u[0] = binding;
nir_instr_insert_after_cf_list(this->cf_node_list, &load_binding->instr);
load->src[0] = nir_src_for_ssa(&load_binding->def);
if (!const_index)
load->src[1] = evaluate_rvalue(ir->operands[1]);
add_instr(&load->instr, ir->type->vector_elements);

View File

@@ -296,6 +296,11 @@ typedef struct {
*/
int index;
/**
* Descriptor set binding for sampler or UBO.
*/
int descriptor_set;
/**
* Initial binding point for a sampler or UBO.
*
@@ -515,7 +520,11 @@ typedef struct nir_src {
bool is_ssa;
} nir_src;
#define NIR_SRC_INIT (nir_src) { { NULL } }
#ifdef __cplusplus
# define NIR_SRC_INIT nir_src()
#else
# define NIR_SRC_INIT (nir_src) { { NULL } }
#endif
#define nir_foreach_use(reg_or_ssa_def, src) \
list_for_each_entry(nir_src, src, &(reg_or_ssa_def)->uses, use_link)
@@ -538,7 +547,11 @@ typedef struct {
bool is_ssa;
} nir_dest;
#define NIR_DEST_INIT (nir_dest) { { { NULL } } }
#ifdef __cplusplus
# define NIR_DEST_INIT nir_dest()
#else
# define NIR_DEST_INIT (nir_dest) { { { NULL } } }
#endif
#define nir_foreach_def(reg, dest) \
list_for_each_entry(nir_dest, dest, &(reg)->defs, reg.def_link)
@@ -777,6 +790,15 @@ NIR_DEFINE_CAST(nir_deref_as_var, nir_deref, nir_deref_var, deref)
NIR_DEFINE_CAST(nir_deref_as_array, nir_deref, nir_deref_array, deref)
NIR_DEFINE_CAST(nir_deref_as_struct, nir_deref, nir_deref_struct, deref)
/** Returns the tail of a deref chain */
static inline nir_deref *
nir_deref_tail(nir_deref *deref)
{
while (deref->child)
deref = deref->child;
return deref;
}
typedef struct {
nir_instr instr;
@@ -971,6 +993,9 @@ typedef struct {
/* gather component selector */
unsigned component : 2;
/* The descriptor set containing this texture */
unsigned sampler_set;
/** The sampler index
*
* If this texture instruction has a nir_tex_src_sampler_offset source,
@@ -1419,6 +1444,7 @@ typedef struct nir_function {
typedef struct nir_shader_compiler_options {
bool lower_ffma;
bool lower_fdiv;
bool lower_flrp;
bool lower_fpow;
bool lower_fsat;
@@ -1571,6 +1597,17 @@ typedef struct {
};
} nir_cursor;
static inline nir_block *
nir_cursor_current_block(nir_cursor cursor)
{
if (cursor.option == nir_cursor_before_instr ||
cursor.option == nir_cursor_after_instr) {
return cursor.instr->block;
} else {
return cursor.block;
}
}
static inline nir_cursor
nir_before_block(nir_block *block)
{
@@ -1607,6 +1644,17 @@ nir_after_instr(nir_instr *instr)
return cursor;
}
static inline nir_cursor
nir_after_block_before_jump(nir_block *block)
{
nir_instr *last_instr = nir_block_last_instr(block);
if (last_instr && last_instr->type == nir_instr_type_jump) {
return nir_before_instr(last_instr);
} else {
return nir_after_block(block);
}
}
static inline nir_cursor
nir_before_cf_node(nir_cf_node *node)
{
@@ -1771,6 +1819,8 @@ void nir_lower_global_vars_to_local(nir_shader *shader);
void nir_lower_locals_to_regs(nir_shader *shader);
void nir_lower_outputs_to_temporaries(nir_shader *shader);
void nir_assign_var_locations(struct exec_list *var_list,
unsigned *size,
int (*type_size)(const struct glsl_type *));
@@ -1789,6 +1839,7 @@ void nir_lower_phis_to_scalar(nir_shader *shader);
void nir_lower_samplers(nir_shader *shader,
const struct gl_shader_program *shader_program);
void nir_lower_samplers_for_vk(nir_shader *shader);
void nir_lower_system_values(nir_shader *shader);
void nir_lower_tex_projector(nir_shader *shader);

View File

@@ -49,8 +49,7 @@ nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
nir_instr_insert(build->cursor, instr);
/* Move the cursor forward. */
if (build->cursor.option == nir_cursor_after_instr)
build->cursor.instr = instr;
build->cursor = nir_after_instr(instr);
}
static inline void
@@ -217,6 +216,23 @@ nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4],
nir_imov_alu(build, alu_src, num_components);
}
/* Selects the right fdot given the number of components in each source. */
static inline nir_ssa_def *
nir_fdot(nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1)
{
assert(src0->num_components == src1->num_components);
switch (src0->num_components) {
case 1: return nir_fmul(build, src0, src1);
case 2: return nir_fdot2(build, src0, src1);
case 3: return nir_fdot3(build, src0, src1);
case 4: return nir_fdot4(build, src0, src1);
default:
unreachable("bad component size");
}
return NULL;
}
/**
* Turns a nir_src into a nir_ssa_def * so it can be passed to
* nir_build_alu()-based builder calls.

View File

@@ -249,12 +249,7 @@ add_parallel_copy_to_end_of_block(nir_block *block, void *void_state)
nir_parallel_copy_instr *pcopy =
nir_parallel_copy_instr_create(state->dead_ctx);
nir_instr *last_instr = nir_block_last_instr(block);
if (last_instr && last_instr->type == nir_instr_type_jump) {
nir_instr_insert_before(last_instr, &pcopy->instr);
} else {
nir_instr_insert_after_block(block, &pcopy->instr);
}
nir_instr_insert(nir_after_block_before_jump(block), &pcopy->instr);
}
return true;

View File

@@ -145,8 +145,9 @@ SYSTEM_VALUE(invocation_id, 1)
* the first index is the base address and the second index is an offset that
* should be added to the base address. (This way you can determine in the
* back-end which variable is being accessed even in an array.) For inputs,
* the one and only index corresponds to the attribute slot. UBO loads also
* have a single index which is the base address to load from.
* the one and only index corresponds to the attribute slot. UBO loads
* have two indices the first of which is the descriptor set and the second
* is the base address to load from.
*
* UBO loads have a (possibly constant) source which is the UBO buffer index.
* For each type of load, the _indirect variant has one additional source
@@ -165,7 +166,7 @@ SYSTEM_VALUE(invocation_id, 1)
true, 0, 0, indices, flags)
LOAD(uniform, 0, 2, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
LOAD(ubo, 1, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
LOAD(ubo, 1, 2, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
LOAD(input, 0, 1, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
/* LOAD(ssbo, 1, 0) */

View File

@@ -0,0 +1,93 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Jason Ekstrand (jason@jlekstrand.net)
*
*/
/*
* Implements a pass that lowers output variables to a temporary plus an
* output variable with a single copy at each exit point of the shader.
* This way the output variable is only ever written.
*
* Because valid NIR requires that output variables are never read, this
* pass is more of a helper for NIR producers and must be run before the
* shader is ever validated.
*/
#include "nir.h"
static void
emit_output_copies(nir_shader *shader, nir_variable *temp, nir_variable *output)
{
nir_foreach_overload(shader, overload) {
if (!overload->impl || strcmp(overload->function->name, "main"))
continue;
struct set_entry *block_entry;
set_foreach(overload->impl->end_block->predecessors, block_entry) {
struct nir_block *block = (void *)block_entry->key;
nir_intrinsic_instr *copy =
nir_intrinsic_instr_create(shader, nir_intrinsic_copy_var);
copy->variables[0] = nir_deref_var_create(copy, output);
copy->variables[1] = nir_deref_var_create(copy, temp);
nir_instr_insert(nir_after_block_before_jump(block), &copy->instr);
}
}
}
void
nir_lower_outputs_to_temporaries(nir_shader *shader)
{
struct exec_list old_outputs;
exec_list_move_nodes_to(&shader->outputs, &old_outputs);
/* Walk over all of the outputs turn each output into a temporary and
* make a new variable for the actual output.
*/
foreach_list_typed(nir_variable, var, node, &old_outputs) {
nir_variable *output = ralloc(shader, nir_variable);
memcpy(output, var, sizeof *output);
/* The orignal is now the temporary */
nir_variable *temp = var;
/* Move the original name over to the new output */
if (output->name)
ralloc_steal(output, output->name);
/* Give the output a new name with @out-temp appended */
temp->name = ralloc_asprintf(var, "%s@out-temp", output->name);
temp->data.mode = nir_var_global;
temp->constant_initializer = NULL;
exec_list_push_tail(&shader->outputs, &output->node);
emit_output_copies(shader, temp, output);
}
exec_list_append(&shader->globals, &old_outputs);
}

View File

@@ -35,6 +35,30 @@ extern "C" {
#include "program/program.h"
}
static void
add_indirect_to_tex(nir_tex_instr *instr, nir_src indirect)
{
/* First, we have to resize the array of texture sources */
nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,
instr->num_srcs + 1);
for (unsigned i = 0; i < instr->num_srcs; i++) {
new_srcs[i].src_type = instr->src[i].src_type;
nir_instr_move_src(&instr->instr, &new_srcs[i].src, &instr->src[i].src);
}
ralloc_free(instr->src);
instr->src = new_srcs;
/* Now we can go ahead and move the source over to being a
* first-class texture source.
*/
instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;
instr->num_srcs++;
nir_instr_rewrite_src(&instr->instr, &instr->src[instr->num_srcs - 1].src,
indirect);
}
static unsigned
get_sampler_index(const struct gl_shader_program *shader_program,
gl_shader_stage stage, const char *name)
@@ -176,3 +200,49 @@ nir_lower_samplers(nir_shader *shader,
lower_impl(overload->impl, shader_program, shader->stage);
}
}
static bool
lower_samplers_for_vk_block(nir_block *block, void *data)
{
nir_foreach_instr(block, instr) {
if (instr->type != nir_instr_type_tex)
continue;
nir_tex_instr *tex = nir_instr_as_tex(instr);
assert(tex->sampler);
tex->sampler_set = tex->sampler->var->data.descriptor_set;
tex->sampler_index = tex->sampler->var->data.binding;
if (tex->sampler->deref.child) {
assert(tex->sampler->deref.child->deref_type == nir_deref_type_array);
nir_deref_array *arr = nir_deref_as_array(tex->sampler->deref.child);
/* Only one-level arrays are allowed in vulkan */
assert(arr->deref.child == NULL);
tex->sampler_index += arr->base_offset;
if (arr->deref_array_type == nir_deref_array_type_indirect) {
add_indirect_to_tex(tex, arr->indirect);
nir_instr_rewrite_src(instr, &arr->indirect, NIR_SRC_INIT);
tex->sampler_array_size = glsl_get_length(tex->sampler->deref.type);
}
}
tex->sampler = NULL;
}
return true;
}
extern "C" void
nir_lower_samplers_for_vk(nir_shader *shader)
{
nir_foreach_overload(shader, overload) {
if (overload->impl) {
nir_foreach_block(overload->impl, lower_samplers_for_vk_block, NULL);
}
}
}

View File

@@ -53,17 +53,6 @@ deref_next_wildcard_parent(nir_deref *deref)
return NULL;
}
/* Returns the last deref in the chain.
*/
static nir_deref *
get_deref_tail(nir_deref *deref)
{
while (deref->child)
deref = deref->child;
return deref;
}
/* This function recursively walks the given deref chain and replaces the
* given copy instruction with an equivalent sequence load/store
* operations.
@@ -121,8 +110,8 @@ emit_copy_load_store(nir_intrinsic_instr *copy_instr,
} else {
/* In this case, we have no wildcards anymore, so all we have to do
* is just emit the load and store operations. */
src_tail = get_deref_tail(src_tail);
dest_tail = get_deref_tail(dest_tail);
src_tail = nir_deref_tail(src_tail);
dest_tail = nir_deref_tail(dest_tail);
assert(src_tail->type == dest_tail->type);

View File

@@ -66,6 +66,7 @@ optimizations = [
(('imul', a, 1), a),
(('fmul', a, -1.0), ('fneg', a)),
(('imul', a, -1), ('ineg', a)),
(('fdiv', a, b), ('fmul', a, ('frcp', b)), 'options->lower_fdiv'),
(('ffma', 0.0, a, b), b),
(('ffma', a, 0.0, b), b),
(('ffma', a, b, 0.0), ('fmul', a, b)),

47
src/glsl/nir/nir_spirv.h Normal file
View File

@@ -0,0 +1,47 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Jason Ekstrand (jason@jlekstrand.net)
*
*/
#pragma once
#ifndef _NIR_SPIRV_H_
#define _NIR_SPIRV_H_
#include "nir.h"
#ifdef __cplusplus
extern "C" {
#endif
nir_shader *spirv_to_nir(const uint32_t *words, size_t word_count,
gl_shader_stage stage,
const nir_shader_compiler_options *options);
#ifdef __cplusplus
}
#endif
#endif /* _NIR_SPIRV_H_ */

View File

@@ -66,14 +66,6 @@ struct split_var_copies_state {
void *dead_ctx;
};
static nir_deref *
get_deref_tail(nir_deref *deref)
{
while (deref->child != NULL)
deref = deref->child;
return deref;
}
/* Recursively constructs deref chains to split a copy instruction into
* multiple (if needed) copy instructions with full-length deref chains.
* External callers of this function should pass the tail and head of the
@@ -225,8 +217,8 @@ split_var_copies_block(nir_block *block, void *void_state)
nir_deref *dest_head = &intrinsic->variables[0]->deref;
nir_deref *src_head = &intrinsic->variables[1]->deref;
nir_deref *dest_tail = get_deref_tail(dest_head);
nir_deref *src_tail = get_deref_tail(src_head);
nir_deref *dest_tail = nir_deref_tail(dest_head);
nir_deref *src_tail = nir_deref_tail(src_head);
switch (glsl_get_base_type(src_tail->type)) {
case GLSL_TYPE_ARRAY:

View File

@@ -70,6 +70,18 @@ glsl_get_struct_field(const glsl_type *type, unsigned index)
return type->fields.structure[index].type;
}
const glsl_type *
glsl_get_function_return_type(const glsl_type *type)
{
return type->fields.parameters[0].type;
}
const glsl_function_param *
glsl_get_function_param(const glsl_type *type, unsigned index)
{
return &type->fields.parameters[index + 1];
}
const struct glsl_type *
glsl_get_column_type(const struct glsl_type *type)
{
@@ -112,6 +124,20 @@ glsl_get_struct_elem_name(const struct glsl_type *type, unsigned index)
return type->fields.structure[index].name;
}
glsl_sampler_dim
glsl_get_sampler_dim(const struct glsl_type *type)
{
assert(glsl_type_is_sampler(type));
return (glsl_sampler_dim)type->sampler_dimensionality;
}
glsl_base_type
glsl_get_sampler_result_type(const struct glsl_type *type)
{
assert(glsl_type_is_sampler(type));
return (glsl_base_type)type->sampler_type;
}
bool
glsl_type_is_void(const glsl_type *type)
{
@@ -130,12 +156,50 @@ glsl_type_is_scalar(const struct glsl_type *type)
return type->is_scalar();
}
bool
glsl_type_is_vector_or_scalar(const struct glsl_type *type)
{
return type->is_vector() || type->is_scalar();
}
bool
glsl_type_is_matrix(const struct glsl_type *type)
{
return type->is_matrix();
}
bool
glsl_type_is_array(const struct glsl_type *type)
{
return type->is_array();
}
bool
glsl_type_is_struct(const struct glsl_type *type)
{
return type->is_record() || type->is_interface();
}
bool
glsl_type_is_sampler(const struct glsl_type *type)
{
return type->is_sampler();
}
bool
glsl_sampler_type_is_shadow(const struct glsl_type *type)
{
assert(glsl_type_is_sampler(type));
return type->sampler_shadow;
}
bool
glsl_sampler_type_is_array(const struct glsl_type *type)
{
assert(glsl_type_is_sampler(type));
return type->sampler_array;
}
const glsl_type *
glsl_void_type(void)
{
@@ -149,9 +213,9 @@ glsl_float_type(void)
}
const glsl_type *
glsl_vec4_type(void)
glsl_int_type(void)
{
return glsl_type::vec4_type;
return glsl_type::int_type;
}
const glsl_type *
@@ -160,8 +224,68 @@ glsl_uint_type(void)
return glsl_type::uint_type;
}
const glsl_type *
glsl_bool_type(void)
{
return glsl_type::bool_type;
}
const glsl_type *
glsl_vec4_type(void)
{
return glsl_type::vec4_type;
}
const glsl_type *
glsl_scalar_type(enum glsl_base_type base_type)
{
return glsl_type::get_instance(base_type, 1, 1);
}
const glsl_type *
glsl_vector_type(enum glsl_base_type base_type, unsigned components)
{
assert(components > 1 && components <= 4);
return glsl_type::get_instance(base_type, components, 1);
}
const glsl_type *
glsl_matrix_type(enum glsl_base_type base_type, unsigned rows, unsigned columns)
{
assert(rows > 1 && rows <= 4 && columns >= 1 && columns <= 4);
return glsl_type::get_instance(base_type, rows, columns);
}
const glsl_type *
glsl_array_type(const glsl_type *base, unsigned elements)
{
return glsl_type::get_array_instance(base, elements);
}
const glsl_type *
glsl_struct_type(const glsl_struct_field *fields,
unsigned num_fields, const char *name)
{
return glsl_type::get_record_instance(fields, num_fields, name);
}
const struct glsl_type *
glsl_sampler_type(enum glsl_sampler_dim dim, bool is_shadow, bool is_array,
enum glsl_base_type base_type)
{
return glsl_type::get_sampler_instance(dim, is_shadow, is_array, base_type);
}
const glsl_type *
glsl_function_type(const glsl_type *return_type,
const glsl_function_param *params, unsigned num_params)
{
return glsl_type::get_function_instance(return_type, params, num_params);
}
const glsl_type *
glsl_transposed_type(const struct glsl_type *type)
{
return glsl_type::get_instance(type->base_type, type->matrix_columns,
type->vector_elements);
}

View File

@@ -49,6 +49,12 @@ const struct glsl_type *glsl_get_array_element(const struct glsl_type *type);
const struct glsl_type *glsl_get_column_type(const struct glsl_type *type);
const struct glsl_type *
glsl_get_function_return_type(const struct glsl_type *type);
const struct glsl_function_param *
glsl_get_function_param(const struct glsl_type *type, unsigned index);
enum glsl_base_type glsl_get_base_type(const struct glsl_type *type);
unsigned glsl_get_vector_elements(const struct glsl_type *type);
@@ -62,18 +68,44 @@ unsigned glsl_get_length(const struct glsl_type *type);
const char *glsl_get_struct_elem_name(const struct glsl_type *type,
unsigned index);
enum glsl_sampler_dim glsl_get_sampler_dim(const struct glsl_type *type);
enum glsl_base_type glsl_get_sampler_result_type(const struct glsl_type *type);
bool glsl_type_is_void(const struct glsl_type *type);
bool glsl_type_is_vector(const struct glsl_type *type);
bool glsl_type_is_scalar(const struct glsl_type *type);
bool glsl_type_is_vector_or_scalar(const struct glsl_type *type);
bool glsl_type_is_matrix(const struct glsl_type *type);
bool glsl_type_is_array(const struct glsl_type *type);
bool glsl_type_is_struct(const struct glsl_type *type);
bool glsl_type_is_sampler(const struct glsl_type *type);
bool glsl_sampler_type_is_shadow(const struct glsl_type *type);
bool glsl_sampler_type_is_array(const struct glsl_type *type);
const struct glsl_type *glsl_void_type(void);
const struct glsl_type *glsl_float_type(void);
const struct glsl_type *glsl_vec4_type(void);
const struct glsl_type *glsl_int_type(void);
const struct glsl_type *glsl_uint_type(void);
const struct glsl_type *glsl_bool_type(void);
const struct glsl_type *glsl_vec4_type(void);
const struct glsl_type *glsl_scalar_type(enum glsl_base_type base_type);
const struct glsl_type *glsl_vector_type(enum glsl_base_type base_type,
unsigned components);
const struct glsl_type *glsl_matrix_type(enum glsl_base_type base_type,
unsigned rows, unsigned columns);
const struct glsl_type *glsl_array_type(const struct glsl_type *base,
unsigned elements);
const struct glsl_type *glsl_struct_type(const struct glsl_struct_field *fields,
unsigned num_fields, const char *name);
const struct glsl_type *glsl_sampler_type(enum glsl_sampler_dim dim,
bool is_shadow, bool is_array,
enum glsl_base_type base_type);
const struct glsl_type * glsl_function_type(const struct glsl_type *return_type,
const struct glsl_function_param *params,
unsigned num_params);
const struct glsl_type *glsl_transposed_type(const struct glsl_type *type);
#ifdef __cplusplus
}

820
src/glsl/nir/spirv.h Normal file
View File

@@ -0,0 +1,820 @@
/*
** Copyright (c) 2014-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
** to deal in the Materials without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Materials, and to permit persons to whom the
** Materials are furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Materials.
**
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
** IN THE MATERIALS.
*/
/*
** This header is automatically generated by the same tool that creates
** the Binary Section of the SPIR-V specification.
*/
/*
** Specification revision 31.
** Enumeration tokens for SPIR-V, in various styles:
** C, C++, C++11, JSON, Lua, Python
**
** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
**
** Some tokens act like mask values, which can be OR'd together,
** while others are mutually exclusive. The mask-like ones have
** "Mask" in their name, and a parallel enum that has the shift
** amount (1 << x) for each corresponding enumerant.
*/
#ifndef spirv_H
#define spirv_H
typedef unsigned int SpvId;
static const unsigned int SpvMagicNumber = 0x07230203;
static const unsigned int SpvVersion = 99;
static const unsigned int SpvRevision = 31;
static const unsigned int SpvOpCodeMask = 0xffff;
static const unsigned int SpvWordCountShift = 16;
typedef enum SpvSourceLanguage_ {
SpvSourceLanguageUnknown = 0,
SpvSourceLanguageESSL = 1,
SpvSourceLanguageGLSL = 2,
SpvSourceLanguageOpenCL = 3,
} SpvSourceLanguage;
typedef enum SpvExecutionModel_ {
SpvExecutionModelVertex = 0,
SpvExecutionModelTessellationControl = 1,
SpvExecutionModelTessellationEvaluation = 2,
SpvExecutionModelGeometry = 3,
SpvExecutionModelFragment = 4,
SpvExecutionModelGLCompute = 5,
SpvExecutionModelKernel = 6,
} SpvExecutionModel;
typedef enum SpvAddressingModel_ {
SpvAddressingModelLogical = 0,
SpvAddressingModelPhysical32 = 1,
SpvAddressingModelPhysical64 = 2,
} SpvAddressingModel;
typedef enum SpvMemoryModel_ {
SpvMemoryModelSimple = 0,
SpvMemoryModelGLSL450 = 1,
SpvMemoryModelOpenCL = 2,
} SpvMemoryModel;
typedef enum SpvExecutionMode_ {
SpvExecutionModeInvocations = 0,
SpvExecutionModeSpacingEqual = 1,
SpvExecutionModeSpacingFractionalEven = 2,
SpvExecutionModeSpacingFractionalOdd = 3,
SpvExecutionModeVertexOrderCw = 4,
SpvExecutionModeVertexOrderCcw = 5,
SpvExecutionModePixelCenterInteger = 6,
SpvExecutionModeOriginUpperLeft = 7,
SpvExecutionModeOriginLowerLeft = 8,
SpvExecutionModeEarlyFragmentTests = 9,
SpvExecutionModePointMode = 10,
SpvExecutionModeXfb = 11,
SpvExecutionModeDepthReplacing = 12,
SpvExecutionModeDepthAny = 13,
SpvExecutionModeDepthGreater = 14,
SpvExecutionModeDepthLess = 15,
SpvExecutionModeDepthUnchanged = 16,
SpvExecutionModeLocalSize = 17,
SpvExecutionModeLocalSizeHint = 18,
SpvExecutionModeInputPoints = 19,
SpvExecutionModeInputLines = 20,
SpvExecutionModeInputLinesAdjacency = 21,
SpvExecutionModeInputTriangles = 22,
SpvExecutionModeInputTrianglesAdjacency = 23,
SpvExecutionModeInputQuads = 24,
SpvExecutionModeInputIsolines = 25,
SpvExecutionModeOutputVertices = 26,
SpvExecutionModeOutputPoints = 27,
SpvExecutionModeOutputLineStrip = 28,
SpvExecutionModeOutputTriangleStrip = 29,
SpvExecutionModeVecTypeHint = 30,
SpvExecutionModeContractionOff = 31,
} SpvExecutionMode;
typedef enum SpvStorageClass_ {
SpvStorageClassUniformConstant = 0,
SpvStorageClassInput = 1,
SpvStorageClassUniform = 2,
SpvStorageClassOutput = 3,
SpvStorageClassWorkgroupLocal = 4,
SpvStorageClassWorkgroupGlobal = 5,
SpvStorageClassPrivateGlobal = 6,
SpvStorageClassFunction = 7,
SpvStorageClassGeneric = 8,
SpvStorageClassAtomicCounter = 10,
SpvStorageClassImage = 11,
} SpvStorageClass;
typedef enum SpvDim_ {
SpvDim1D = 0,
SpvDim2D = 1,
SpvDim3D = 2,
SpvDimCube = 3,
SpvDimRect = 4,
SpvDimBuffer = 5,
} SpvDim;
typedef enum SpvSamplerAddressingMode_ {
SpvSamplerAddressingModeNone = 0,
SpvSamplerAddressingModeClampToEdge = 1,
SpvSamplerAddressingModeClamp = 2,
SpvSamplerAddressingModeRepeat = 3,
SpvSamplerAddressingModeRepeatMirrored = 4,
} SpvSamplerAddressingMode;
typedef enum SpvSamplerFilterMode_ {
SpvSamplerFilterModeNearest = 0,
SpvSamplerFilterModeLinear = 1,
} SpvSamplerFilterMode;
typedef enum SpvImageFormat_ {
SpvImageFormatUnknown = 0,
SpvImageFormatRgba32f = 1,
SpvImageFormatRgba16f = 2,
SpvImageFormatR32f = 3,
SpvImageFormatRgba8 = 4,
SpvImageFormatRgba8Snorm = 5,
SpvImageFormatRg32f = 6,
SpvImageFormatRg16f = 7,
SpvImageFormatR11fG11fB10f = 8,
SpvImageFormatR16f = 9,
SpvImageFormatRgba16 = 10,
SpvImageFormatRgb10A2 = 11,
SpvImageFormatRg16 = 12,
SpvImageFormatRg8 = 13,
SpvImageFormatR16 = 14,
SpvImageFormatR8 = 15,
SpvImageFormatRgba16Snorm = 16,
SpvImageFormatRg16Snorm = 17,
SpvImageFormatRg8Snorm = 18,
SpvImageFormatR16Snorm = 19,
SpvImageFormatR8Snorm = 20,
SpvImageFormatRgba32i = 21,
SpvImageFormatRgba16i = 22,
SpvImageFormatRgba8i = 23,
SpvImageFormatR32i = 24,
SpvImageFormatRg32i = 25,
SpvImageFormatRg16i = 26,
SpvImageFormatRg8i = 27,
SpvImageFormatR16i = 28,
SpvImageFormatR8i = 29,
SpvImageFormatRgba32ui = 30,
SpvImageFormatRgba16ui = 31,
SpvImageFormatRgba8ui = 32,
SpvImageFormatR32ui = 33,
SpvImageFormatRgb10a2ui = 34,
SpvImageFormatRg32ui = 35,
SpvImageFormatRg16ui = 36,
SpvImageFormatRg8ui = 37,
SpvImageFormatR16ui = 38,
SpvImageFormatR8ui = 39,
} SpvImageFormat;
typedef enum SpvImageChannelOrder_ {
SpvImageChannelOrderR = 0,
SpvImageChannelOrderA = 1,
SpvImageChannelOrderRG = 2,
SpvImageChannelOrderRA = 3,
SpvImageChannelOrderRGB = 4,
SpvImageChannelOrderRGBA = 5,
SpvImageChannelOrderBGRA = 6,
SpvImageChannelOrderARGB = 7,
SpvImageChannelOrderIntensity = 8,
SpvImageChannelOrderLuminance = 9,
SpvImageChannelOrderRx = 10,
SpvImageChannelOrderRGx = 11,
SpvImageChannelOrderRGBx = 12,
SpvImageChannelOrderDepth = 13,
SpvImageChannelOrderDepthStencil = 14,
SpvImageChannelOrdersRGB = 15,
SpvImageChannelOrdersRGBx = 16,
SpvImageChannelOrdersRGBA = 17,
SpvImageChannelOrdersBGRA = 18,
} SpvImageChannelOrder;
typedef enum SpvImageChannelDataType_ {
SpvImageChannelDataTypeSnormInt8 = 0,
SpvImageChannelDataTypeSnormInt16 = 1,
SpvImageChannelDataTypeUnormInt8 = 2,
SpvImageChannelDataTypeUnormInt16 = 3,
SpvImageChannelDataTypeUnormShort565 = 4,
SpvImageChannelDataTypeUnormShort555 = 5,
SpvImageChannelDataTypeUnormInt101010 = 6,
SpvImageChannelDataTypeSignedInt8 = 7,
SpvImageChannelDataTypeSignedInt16 = 8,
SpvImageChannelDataTypeSignedInt32 = 9,
SpvImageChannelDataTypeUnsignedInt8 = 10,
SpvImageChannelDataTypeUnsignedInt16 = 11,
SpvImageChannelDataTypeUnsignedInt32 = 12,
SpvImageChannelDataTypeHalfFloat = 13,
SpvImageChannelDataTypeFloat = 14,
SpvImageChannelDataTypeUnormInt24 = 15,
} SpvImageChannelDataType;
typedef enum SpvImageOperandsShift_ {
SpvImageOperandsBiasShift = 0,
SpvImageOperandsLodShift = 1,
SpvImageOperandsGradShift = 2,
SpvImageOperandsConstOffsetShift = 3,
SpvImageOperandsOffsetShift = 4,
SpvImageOperandsConstOffsetsShift = 5,
SpvImageOperandsSampleShift = 6,
} SpvImageOperandsShift;
typedef enum SpvImageOperandsMask_ {
SpvImageOperandsMaskNone = 0,
SpvImageOperandsBiasMask = 0x00000001,
SpvImageOperandsLodMask = 0x00000002,
SpvImageOperandsGradMask = 0x00000004,
SpvImageOperandsConstOffsetMask = 0x00000008,
SpvImageOperandsOffsetMask = 0x00000010,
SpvImageOperandsConstOffsetsMask = 0x00000020,
SpvImageOperandsSampleMask = 0x00000040,
} SpvImageOperandsMask;
typedef enum SpvFPFastMathModeShift_ {
SpvFPFastMathModeNotNaNShift = 0,
SpvFPFastMathModeNotInfShift = 1,
SpvFPFastMathModeNSZShift = 2,
SpvFPFastMathModeAllowRecipShift = 3,
SpvFPFastMathModeFastShift = 4,
} SpvFPFastMathModeShift;
typedef enum SpvFPFastMathModeMask_ {
SpvFPFastMathModeMaskNone = 0,
SpvFPFastMathModeNotNaNMask = 0x00000001,
SpvFPFastMathModeNotInfMask = 0x00000002,
SpvFPFastMathModeNSZMask = 0x00000004,
SpvFPFastMathModeAllowRecipMask = 0x00000008,
SpvFPFastMathModeFastMask = 0x00000010,
} SpvFPFastMathModeMask;
typedef enum SpvFPRoundingMode_ {
SpvFPRoundingModeRTE = 0,
SpvFPRoundingModeRTZ = 1,
SpvFPRoundingModeRTP = 2,
SpvFPRoundingModeRTN = 3,
} SpvFPRoundingMode;
typedef enum SpvLinkageType_ {
SpvLinkageTypeExport = 0,
SpvLinkageTypeImport = 1,
} SpvLinkageType;
typedef enum SpvAccessQualifier_ {
SpvAccessQualifierReadOnly = 0,
SpvAccessQualifierWriteOnly = 1,
SpvAccessQualifierReadWrite = 2,
} SpvAccessQualifier;
typedef enum SpvFunctionParameterAttribute_ {
SpvFunctionParameterAttributeZext = 0,
SpvFunctionParameterAttributeSext = 1,
SpvFunctionParameterAttributeByVal = 2,
SpvFunctionParameterAttributeSret = 3,
SpvFunctionParameterAttributeNoAlias = 4,
SpvFunctionParameterAttributeNoCapture = 5,
SpvFunctionParameterAttributeNoWrite = 6,
SpvFunctionParameterAttributeNoReadWrite = 7,
} SpvFunctionParameterAttribute;
typedef enum SpvDecoration_ {
SpvDecorationRelaxedPrecision = 0,
SpvDecorationSpecId = 1,
SpvDecorationBlock = 2,
SpvDecorationBufferBlock = 3,
SpvDecorationRowMajor = 4,
SpvDecorationColMajor = 5,
SpvDecorationArrayStride = 6,
SpvDecorationMatrixStride = 7,
SpvDecorationGLSLShared = 8,
SpvDecorationGLSLPacked = 9,
SpvDecorationCPacked = 10,
SpvDecorationBuiltIn = 11,
SpvDecorationSmooth = 12,
SpvDecorationNoperspective = 13,
SpvDecorationFlat = 14,
SpvDecorationPatch = 15,
SpvDecorationCentroid = 16,
SpvDecorationSample = 17,
SpvDecorationInvariant = 18,
SpvDecorationRestrict = 19,
SpvDecorationAliased = 20,
SpvDecorationVolatile = 21,
SpvDecorationConstant = 22,
SpvDecorationCoherent = 23,
SpvDecorationNonwritable = 24,
SpvDecorationNonreadable = 25,
SpvDecorationUniform = 26,
SpvDecorationNoStaticUse = 27,
SpvDecorationSaturatedConversion = 28,
SpvDecorationStream = 29,
SpvDecorationLocation = 30,
SpvDecorationComponent = 31,
SpvDecorationIndex = 32,
SpvDecorationBinding = 33,
SpvDecorationDescriptorSet = 34,
SpvDecorationOffset = 35,
SpvDecorationXfbBuffer = 36,
SpvDecorationXfbStride = 37,
SpvDecorationFuncParamAttr = 38,
SpvDecorationFPRoundingMode = 39,
SpvDecorationFPFastMathMode = 40,
SpvDecorationLinkageAttributes = 41,
} SpvDecoration;
typedef enum SpvBuiltIn_ {
SpvBuiltInPosition = 0,
SpvBuiltInPointSize = 1,
SpvBuiltInClipDistance = 3,
SpvBuiltInCullDistance = 4,
SpvBuiltInVertexId = 5,
SpvBuiltInInstanceId = 6,
SpvBuiltInPrimitiveId = 7,
SpvBuiltInInvocationId = 8,
SpvBuiltInLayer = 9,
SpvBuiltInViewportIndex = 10,
SpvBuiltInTessLevelOuter = 11,
SpvBuiltInTessLevelInner = 12,
SpvBuiltInTessCoord = 13,
SpvBuiltInPatchVertices = 14,
SpvBuiltInFragCoord = 15,
SpvBuiltInPointCoord = 16,
SpvBuiltInFrontFacing = 17,
SpvBuiltInSampleId = 18,
SpvBuiltInSamplePosition = 19,
SpvBuiltInSampleMask = 20,
SpvBuiltInFragColor = 21,
SpvBuiltInFragDepth = 22,
SpvBuiltInHelperInvocation = 23,
SpvBuiltInNumWorkgroups = 24,
SpvBuiltInWorkgroupSize = 25,
SpvBuiltInWorkgroupId = 26,
SpvBuiltInLocalInvocationId = 27,
SpvBuiltInGlobalInvocationId = 28,
SpvBuiltInLocalInvocationIndex = 29,
SpvBuiltInWorkDim = 30,
SpvBuiltInGlobalSize = 31,
SpvBuiltInEnqueuedWorkgroupSize = 32,
SpvBuiltInGlobalOffset = 33,
SpvBuiltInGlobalLinearId = 34,
SpvBuiltInWorkgroupLinearId = 35,
SpvBuiltInSubgroupSize = 36,
SpvBuiltInSubgroupMaxSize = 37,
SpvBuiltInNumSubgroups = 38,
SpvBuiltInNumEnqueuedSubgroups = 39,
SpvBuiltInSubgroupId = 40,
SpvBuiltInSubgroupLocalInvocationId = 41,
} SpvBuiltIn;
typedef enum SpvSelectionControlShift_ {
SpvSelectionControlFlattenShift = 0,
SpvSelectionControlDontFlattenShift = 1,
} SpvSelectionControlShift;
typedef enum SpvSelectionControlMask_ {
SpvSelectionControlMaskNone = 0,
SpvSelectionControlFlattenMask = 0x00000001,
SpvSelectionControlDontFlattenMask = 0x00000002,
} SpvSelectionControlMask;
typedef enum SpvLoopControlShift_ {
SpvLoopControlUnrollShift = 0,
SpvLoopControlDontUnrollShift = 1,
} SpvLoopControlShift;
typedef enum SpvLoopControlMask_ {
SpvLoopControlMaskNone = 0,
SpvLoopControlUnrollMask = 0x00000001,
SpvLoopControlDontUnrollMask = 0x00000002,
} SpvLoopControlMask;
typedef enum SpvFunctionControlShift_ {
SpvFunctionControlInlineShift = 0,
SpvFunctionControlDontInlineShift = 1,
SpvFunctionControlPureShift = 2,
SpvFunctionControlConstShift = 3,
} SpvFunctionControlShift;
typedef enum SpvFunctionControlMask_ {
SpvFunctionControlMaskNone = 0,
SpvFunctionControlInlineMask = 0x00000001,
SpvFunctionControlDontInlineMask = 0x00000002,
SpvFunctionControlPureMask = 0x00000004,
SpvFunctionControlConstMask = 0x00000008,
} SpvFunctionControlMask;
typedef enum SpvMemorySemanticsShift_ {
SpvMemorySemanticsRelaxedShift = 0,
SpvMemorySemanticsSequentiallyConsistentShift = 1,
SpvMemorySemanticsAcquireShift = 2,
SpvMemorySemanticsReleaseShift = 3,
SpvMemorySemanticsUniformMemoryShift = 4,
SpvMemorySemanticsSubgroupMemoryShift = 5,
SpvMemorySemanticsWorkgroupLocalMemoryShift = 6,
SpvMemorySemanticsWorkgroupGlobalMemoryShift = 7,
SpvMemorySemanticsAtomicCounterMemoryShift = 8,
SpvMemorySemanticsImageMemoryShift = 9,
} SpvMemorySemanticsShift;
typedef enum SpvMemorySemanticsMask_ {
SpvMemorySemanticsMaskNone = 0,
SpvMemorySemanticsRelaxedMask = 0x00000001,
SpvMemorySemanticsSequentiallyConsistentMask = 0x00000002,
SpvMemorySemanticsAcquireMask = 0x00000004,
SpvMemorySemanticsReleaseMask = 0x00000008,
SpvMemorySemanticsUniformMemoryMask = 0x00000010,
SpvMemorySemanticsSubgroupMemoryMask = 0x00000020,
SpvMemorySemanticsWorkgroupLocalMemoryMask = 0x00000040,
SpvMemorySemanticsWorkgroupGlobalMemoryMask = 0x00000080,
SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000100,
SpvMemorySemanticsImageMemoryMask = 0x00000200,
} SpvMemorySemanticsMask;
typedef enum SpvMemoryAccessShift_ {
SpvMemoryAccessVolatileShift = 0,
SpvMemoryAccessAlignedShift = 1,
} SpvMemoryAccessShift;
typedef enum SpvMemoryAccessMask_ {
SpvMemoryAccessMaskNone = 0,
SpvMemoryAccessVolatileMask = 0x00000001,
SpvMemoryAccessAlignedMask = 0x00000002,
} SpvMemoryAccessMask;
typedef enum SpvScope_ {
SpvScopeCrossDevice = 0,
SpvScopeDevice = 1,
SpvScopeWorkgroup = 2,
SpvScopeSubgroup = 3,
SpvScopeInvocation = 4,
} SpvScope;
typedef enum SpvGroupOperation_ {
SpvGroupOperationReduce = 0,
SpvGroupOperationInclusiveScan = 1,
SpvGroupOperationExclusiveScan = 2,
} SpvGroupOperation;
typedef enum SpvKernelEnqueueFlags_ {
SpvKernelEnqueueFlagsNoWait = 0,
SpvKernelEnqueueFlagsWaitKernel = 1,
SpvKernelEnqueueFlagsWaitWorkGroup = 2,
} SpvKernelEnqueueFlags;
typedef enum SpvKernelProfilingInfoShift_ {
SpvKernelProfilingInfoCmdExecTimeShift = 0,
} SpvKernelProfilingInfoShift;
typedef enum SpvKernelProfilingInfoMask_ {
SpvKernelProfilingInfoMaskNone = 0,
SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001,
} SpvKernelProfilingInfoMask;
typedef enum SpvCapability_ {
SpvCapabilityMatrix = 0,
SpvCapabilityShader = 1,
SpvCapabilityGeometry = 2,
SpvCapabilityTessellation = 3,
SpvCapabilityAddresses = 4,
SpvCapabilityLinkage = 5,
SpvCapabilityKernel = 6,
SpvCapabilityVector16 = 7,
SpvCapabilityFloat16Buffer = 8,
SpvCapabilityFloat16 = 9,
SpvCapabilityFloat64 = 10,
SpvCapabilityInt64 = 11,
SpvCapabilityInt64Atomics = 12,
SpvCapabilityImageBasic = 13,
SpvCapabilityImageReadWrite = 14,
SpvCapabilityImageMipmap = 15,
SpvCapabilityImageSRGBWrite = 16,
SpvCapabilityPipes = 17,
SpvCapabilityGroups = 18,
SpvCapabilityDeviceEnqueue = 19,
SpvCapabilityLiteralSampler = 20,
SpvCapabilityAtomicStorage = 21,
SpvCapabilityInt16 = 22,
SpvCapabilityTessellationPointSize = 23,
SpvCapabilityGeometryPointSize = 24,
SpvCapabilityImageGatherExtended = 25,
SpvCapabilityStorageImageExtendedFormats = 26,
SpvCapabilityStorageImageMultisample = 27,
SpvCapabilityUniformBufferArrayDynamicIndexing = 28,
SpvCapabilitySampledImageArrayDynamicIndexing = 29,
SpvCapabilityStorageBufferArrayDynamicIndexing = 30,
SpvCapabilityStorageImageArrayDynamicIndexing = 31,
SpvCapabilityClipDistance = 32,
SpvCapabilityCullDistance = 33,
SpvCapabilityImageCubeArray = 34,
SpvCapabilitySampleRateShading = 35,
} SpvCapability;
typedef enum SpvOp_ {
SpvOpNop = 0,
SpvOpUndef = 1,
SpvOpSource = 3,
SpvOpSourceExtension = 4,
SpvOpName = 5,
SpvOpMemberName = 6,
SpvOpString = 7,
SpvOpLine = 8,
SpvOpExtension = 10,
SpvOpExtInstImport = 11,
SpvOpExtInst = 12,
SpvOpMemoryModel = 14,
SpvOpEntryPoint = 15,
SpvOpExecutionMode = 16,
SpvOpCapability = 17,
SpvOpTypeVoid = 19,
SpvOpTypeBool = 20,
SpvOpTypeInt = 21,
SpvOpTypeFloat = 22,
SpvOpTypeVector = 23,
SpvOpTypeMatrix = 24,
SpvOpTypeImage = 25,
SpvOpTypeSampler = 26,
SpvOpTypeSampledImage = 27,
SpvOpTypeArray = 28,
SpvOpTypeRuntimeArray = 29,
SpvOpTypeStruct = 30,
SpvOpTypeOpaque = 31,
SpvOpTypePointer = 32,
SpvOpTypeFunction = 33,
SpvOpTypeEvent = 34,
SpvOpTypeDeviceEvent = 35,
SpvOpTypeReserveId = 36,
SpvOpTypeQueue = 37,
SpvOpTypePipe = 38,
SpvOpConstantTrue = 41,
SpvOpConstantFalse = 42,
SpvOpConstant = 43,
SpvOpConstantComposite = 44,
SpvOpConstantSampler = 45,
SpvOpConstantNull = 46,
SpvOpSpecConstantTrue = 48,
SpvOpSpecConstantFalse = 49,
SpvOpSpecConstant = 50,
SpvOpSpecConstantComposite = 51,
SpvOpSpecConstantOp = 52,
SpvOpFunction = 54,
SpvOpFunctionParameter = 55,
SpvOpFunctionEnd = 56,
SpvOpFunctionCall = 57,
SpvOpVariable = 59,
SpvOpImageTexelPointer = 60,
SpvOpLoad = 61,
SpvOpStore = 62,
SpvOpCopyMemory = 63,
SpvOpCopyMemorySized = 64,
SpvOpAccessChain = 65,
SpvOpInBoundsAccessChain = 66,
SpvOpPtrAccessChain = 67,
SpvOpArrayLength = 68,
SpvOpGenericPtrMemSemantics = 69,
SpvOpDecorate = 71,
SpvOpMemberDecorate = 72,
SpvOpDecorationGroup = 73,
SpvOpGroupDecorate = 74,
SpvOpGroupMemberDecorate = 75,
SpvOpVectorExtractDynamic = 77,
SpvOpVectorInsertDynamic = 78,
SpvOpVectorShuffle = 79,
SpvOpCompositeConstruct = 80,
SpvOpCompositeExtract = 81,
SpvOpCompositeInsert = 82,
SpvOpCopyObject = 83,
SpvOpTranspose = 84,
SpvOpSampledImage = 86,
SpvOpImageSampleImplicitLod = 87,
SpvOpImageSampleExplicitLod = 88,
SpvOpImageSampleDrefImplicitLod = 89,
SpvOpImageSampleDrefExplicitLod = 90,
SpvOpImageSampleProjImplicitLod = 91,
SpvOpImageSampleProjExplicitLod = 92,
SpvOpImageSampleProjDrefImplicitLod = 93,
SpvOpImageSampleProjDrefExplicitLod = 94,
SpvOpImageFetch = 95,
SpvOpImageGather = 96,
SpvOpImageDrefGather = 97,
SpvOpImageRead = 98,
SpvOpImageWrite = 99,
SpvOpImageQueryDim = 100,
SpvOpImageQueryFormat = 101,
SpvOpImageQueryOrder = 102,
SpvOpImageQuerySizeLod = 103,
SpvOpImageQuerySize = 104,
SpvOpImageQueryLod = 105,
SpvOpImageQueryLevels = 106,
SpvOpImageQuerySamples = 107,
SpvOpConvertFToU = 109,
SpvOpConvertFToS = 110,
SpvOpConvertSToF = 111,
SpvOpConvertUToF = 112,
SpvOpUConvert = 113,
SpvOpSConvert = 114,
SpvOpFConvert = 115,
SpvOpQuantizeToF16 = 116,
SpvOpConvertPtrToU = 117,
SpvOpSatConvertSToU = 118,
SpvOpSatConvertUToS = 119,
SpvOpConvertUToPtr = 120,
SpvOpPtrCastToGeneric = 121,
SpvOpGenericCastToPtr = 122,
SpvOpGenericCastToPtrExplicit = 123,
SpvOpBitcast = 124,
SpvOpSNegate = 126,
SpvOpFNegate = 127,
SpvOpIAdd = 128,
SpvOpFAdd = 129,
SpvOpISub = 130,
SpvOpFSub = 131,
SpvOpIMul = 132,
SpvOpFMul = 133,
SpvOpUDiv = 134,
SpvOpSDiv = 135,
SpvOpFDiv = 136,
SpvOpUMod = 137,
SpvOpSRem = 138,
SpvOpSMod = 139,
SpvOpFRem = 140,
SpvOpFMod = 141,
SpvOpVectorTimesScalar = 142,
SpvOpMatrixTimesScalar = 143,
SpvOpVectorTimesMatrix = 144,
SpvOpMatrixTimesVector = 145,
SpvOpMatrixTimesMatrix = 146,
SpvOpOuterProduct = 147,
SpvOpDot = 148,
SpvOpIAddCarry = 149,
SpvOpISubBorrow = 150,
SpvOpIMulExtended = 151,
SpvOpAny = 154,
SpvOpAll = 155,
SpvOpIsNan = 156,
SpvOpIsInf = 157,
SpvOpIsFinite = 158,
SpvOpIsNormal = 159,
SpvOpSignBitSet = 160,
SpvOpLessOrGreater = 161,
SpvOpOrdered = 162,
SpvOpUnordered = 163,
SpvOpLogicalEqual = 164,
SpvOpLogicalNotEqual = 165,
SpvOpLogicalOr = 166,
SpvOpLogicalAnd = 167,
SpvOpLogicalNot = 168,
SpvOpSelect = 169,
SpvOpIEqual = 170,
SpvOpINotEqual = 171,
SpvOpUGreaterThan = 172,
SpvOpSGreaterThan = 173,
SpvOpUGreaterThanEqual = 174,
SpvOpSGreaterThanEqual = 175,
SpvOpULessThan = 176,
SpvOpSLessThan = 177,
SpvOpULessThanEqual = 178,
SpvOpSLessThanEqual = 179,
SpvOpFOrdEqual = 180,
SpvOpFUnordEqual = 181,
SpvOpFOrdNotEqual = 182,
SpvOpFUnordNotEqual = 183,
SpvOpFOrdLessThan = 184,
SpvOpFUnordLessThan = 185,
SpvOpFOrdGreaterThan = 186,
SpvOpFUnordGreaterThan = 187,
SpvOpFOrdLessThanEqual = 188,
SpvOpFUnordLessThanEqual = 189,
SpvOpFOrdGreaterThanEqual = 190,
SpvOpFUnordGreaterThanEqual = 191,
SpvOpShiftRightLogical = 194,
SpvOpShiftRightArithmetic = 195,
SpvOpShiftLeftLogical = 196,
SpvOpBitwiseOr = 197,
SpvOpBitwiseXor = 198,
SpvOpBitwiseAnd = 199,
SpvOpNot = 200,
SpvOpBitFieldInsert = 201,
SpvOpBitFieldSExtract = 202,
SpvOpBitFieldUExtract = 203,
SpvOpBitReverse = 204,
SpvOpBitCount = 205,
SpvOpDPdx = 207,
SpvOpDPdy = 208,
SpvOpFwidth = 209,
SpvOpDPdxFine = 210,
SpvOpDPdyFine = 211,
SpvOpFwidthFine = 212,
SpvOpDPdxCoarse = 213,
SpvOpDPdyCoarse = 214,
SpvOpFwidthCoarse = 215,
SpvOpEmitVertex = 218,
SpvOpEndPrimitive = 219,
SpvOpEmitStreamVertex = 220,
SpvOpEndStreamPrimitive = 221,
SpvOpControlBarrier = 224,
SpvOpMemoryBarrier = 225,
SpvOpAtomicLoad = 227,
SpvOpAtomicStore = 228,
SpvOpAtomicExchange = 229,
SpvOpAtomicCompareExchange = 230,
SpvOpAtomicCompareExchangeWeak = 231,
SpvOpAtomicIIncrement = 232,
SpvOpAtomicIDecrement = 233,
SpvOpAtomicIAdd = 234,
SpvOpAtomicISub = 235,
SpvOpAtomicSMin = 236,
SpvOpAtomicUMin = 237,
SpvOpAtomicSMax = 238,
SpvOpAtomicUMax = 239,
SpvOpAtomicAnd = 240,
SpvOpAtomicOr = 241,
SpvOpAtomicXor = 242,
SpvOpPhi = 245,
SpvOpLoopMerge = 246,
SpvOpSelectionMerge = 247,
SpvOpLabel = 248,
SpvOpBranch = 249,
SpvOpBranchConditional = 250,
SpvOpSwitch = 251,
SpvOpKill = 252,
SpvOpReturn = 253,
SpvOpReturnValue = 254,
SpvOpUnreachable = 255,
SpvOpLifetimeStart = 256,
SpvOpLifetimeStop = 257,
SpvOpAsyncGroupCopy = 259,
SpvOpWaitGroupEvents = 260,
SpvOpGroupAll = 261,
SpvOpGroupAny = 262,
SpvOpGroupBroadcast = 263,
SpvOpGroupIAdd = 264,
SpvOpGroupFAdd = 265,
SpvOpGroupFMin = 266,
SpvOpGroupUMin = 267,
SpvOpGroupSMin = 268,
SpvOpGroupFMax = 269,
SpvOpGroupUMax = 270,
SpvOpGroupSMax = 271,
SpvOpReadPipe = 274,
SpvOpWritePipe = 275,
SpvOpReservedReadPipe = 276,
SpvOpReservedWritePipe = 277,
SpvOpReserveReadPipePackets = 278,
SpvOpReserveWritePipePackets = 279,
SpvOpCommitReadPipe = 280,
SpvOpCommitWritePipe = 281,
SpvOpIsValidReserveId = 282,
SpvOpGetNumPipePackets = 283,
SpvOpGetMaxPipePackets = 284,
SpvOpGroupReserveReadPipePackets = 285,
SpvOpGroupReserveWritePipePackets = 286,
SpvOpGroupCommitReadPipe = 287,
SpvOpGroupCommitWritePipe = 288,
SpvOpEnqueueMarker = 291,
SpvOpEnqueueKernel = 292,
SpvOpGetKernelNDrangeSubGroupCount = 293,
SpvOpGetKernelNDrangeMaxSubGroupSize = 294,
SpvOpGetKernelWorkGroupSize = 295,
SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,
SpvOpRetainEvent = 297,
SpvOpReleaseEvent = 298,
SpvOpCreateUserEvent = 299,
SpvOpIsValidEvent = 300,
SpvOpSetUserEventStatus = 301,
SpvOpCaptureEventProfilingInfo = 302,
SpvOpGetDefaultQueue = 303,
SpvOpBuildNDRange = 304,
} SpvOp;
#endif // #ifndef spirv_H

55
src/glsl/nir/spirv2nir.c Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Jason Ekstrand (jason@jlekstrand.net)
*
*/
/*
* A simple executable that opens a SPIR-V shader, converts it to NIR, and
* dumps out the result. This should be useful for testing the
* spirv_to_nir code.
*/
#include "nir_spirv.h"
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int fd = open(argv[1], O_RDONLY);
off_t len = lseek(fd, 0, SEEK_END);
assert(len % 4 == 0);
size_t word_count = len / 4;
const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
assert(map != NULL);
nir_shader *shader = spirv_to_nir(map, MESA_SHADER_FRAGMENT,
word_count, NULL);
nir_print_shader(shader, stderr);
}

View File

@@ -0,0 +1,130 @@
/*
** Copyright (c) 2014-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
** to deal in the Materials without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Materials, and to permit persons to whom the
** Materials are furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Materials.
**
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
** IN THE MATERIALS.
*/
#ifndef GLSLstd450_H
#define GLSLstd450_H
const int GLSLstd450Version = 99;
const int GLSLstd450Revision = 2;
enum GLSLstd450 {
GLSLstd450Bad = 0, // Don't use
GLSLstd450Round = 1,
GLSLstd450RoundEven = 2,
GLSLstd450Trunc = 3,
GLSLstd450FAbs = 4,
GLSLstd450SAbs = 5,
GLSLstd450FSign = 6,
GLSLstd450SSign = 7,
GLSLstd450Floor = 8,
GLSLstd450Ceil = 9,
GLSLstd450Fract = 10,
GLSLstd450Radians = 11,
GLSLstd450Degrees = 12,
GLSLstd450Sin = 13,
GLSLstd450Cos = 14,
GLSLstd450Tan = 15,
GLSLstd450Asin = 16,
GLSLstd450Acos = 17,
GLSLstd450Atan = 18,
GLSLstd450Sinh = 19,
GLSLstd450Cosh = 20,
GLSLstd450Tanh = 21,
GLSLstd450Asinh = 22,
GLSLstd450Acosh = 23,
GLSLstd450Atanh = 24,
GLSLstd450Atan2 = 25,
GLSLstd450Pow = 26,
GLSLstd450Exp = 27,
GLSLstd450Log = 28,
GLSLstd450Exp2 = 29,
GLSLstd450Log2 = 30,
GLSLstd450Sqrt = 31,
GLSLstd450InverseSqrt = 32,
GLSLstd450Determinant = 33,
GLSLstd450MatrixInverse = 34,
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
GLSLstd450ModfStruct = 36, // no OpVariable operand
GLSLstd450FMin = 37,
GLSLstd450UMin = 38,
GLSLstd450SMin = 39,
GLSLstd450FMax = 40,
GLSLstd450UMax = 41,
GLSLstd450SMax = 42,
GLSLstd450FClamp = 43,
GLSLstd450UClamp = 44,
GLSLstd450SClamp = 45,
GLSLstd450Mix = 46,
GLSLstd450Step = 47,
GLSLstd450SmoothStep = 48,
GLSLstd450Fma = 49,
GLSLstd450Frexp = 50, // second operand needs an OpVariable to write to
GLSLstd450FrexpStruct = 51, // no OpVariable operand
GLSLstd450Ldexp = 52,
GLSLstd450PackSnorm4x8 = 53,
GLSLstd450PackUnorm4x8 = 54,
GLSLstd450PackSnorm2x16 = 55,
GLSLstd450PackUnorm2x16 = 56,
GLSLstd450PackHalf2x16 = 57,
GLSLstd450PackDouble2x32 = 58,
GLSLstd450UnpackSnorm2x16 = 59,
GLSLstd450UnpackUnorm2x16 = 60,
GLSLstd450UnpackHalf2x16 = 61,
GLSLstd450UnpackSnorm4x8 = 62,
GLSLstd450UnpackUnorm4x8 = 63,
GLSLstd450UnpackDouble2x32 = 64,
GLSLstd450Length = 65,
GLSLstd450Distance = 66,
GLSLstd450Cross = 67,
GLSLstd450Normalize = 68,
GLSLstd450FaceForward = 69,
GLSLstd450Reflect = 70,
GLSLstd450Refract = 71,
GLSLstd450FindILSB = 72,
GLSLstd450FindSMSB = 73,
GLSLstd450FindUMSB = 74,
GLSLstd450InterpolateAtCentroid = 75,
GLSLstd450InterpolateAtSample = 76,
GLSLstd450InterpolateAtOffset = 77,
GLSLstd450AddCarry = 78, // These three should move to the core instruction set
GLSLstd450SubBorrow = 79,
GLSLstd450MulExtended = 80,
GLSLstd450Count
};
#endif // #ifndef GLSLstd450_H

View File

@@ -0,0 +1,179 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Jason Ekstrand (jason@jlekstrand.net)
*
*/
#include "spirv_to_nir_private.h"
#include "spirv_glsl450.h"
static nir_ssa_def*
build_length(nir_builder *b, nir_ssa_def *vec)
{
switch (vec->num_components) {
case 1: return nir_fsqrt(b, nir_fmul(b, vec, vec));
case 2: return nir_fsqrt(b, nir_fdot2(b, vec, vec));
case 3: return nir_fsqrt(b, nir_fdot3(b, vec, vec));
case 4: return nir_fsqrt(b, nir_fdot4(b, vec, vec));
default:
unreachable("Invalid number of components");
}
}
static void
handle_glsl450_alu(struct vtn_builder *b, enum GLSLstd450 entrypoint,
const uint32_t *w, unsigned count)
{
struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
val->ssa = rzalloc(b, struct vtn_ssa_value);
val->ssa->type = vtn_value(b, w[1], vtn_value_type_type)->type->type;
/* Collect the various SSA sources */
unsigned num_inputs = count - 5;
nir_ssa_def *src[3];
for (unsigned i = 0; i < num_inputs; i++)
src[i] = vtn_ssa_value(b, w[i + 5])->def;
nir_op op;
switch (entrypoint) {
case GLSLstd450Round: op = nir_op_fround_even; break; /* TODO */
case GLSLstd450RoundEven: op = nir_op_fround_even; break;
case GLSLstd450Trunc: op = nir_op_ftrunc; break;
case GLSLstd450FAbs: op = nir_op_fabs; break;
case GLSLstd450FSign: op = nir_op_fsign; break;
case GLSLstd450Floor: op = nir_op_ffloor; break;
case GLSLstd450Ceil: op = nir_op_fceil; break;
case GLSLstd450Fract: op = nir_op_ffract; break;
case GLSLstd450Radians:
val->ssa->def = nir_fmul(&b->nb, src[0], nir_imm_float(&b->nb, 0.01745329251));
return;
case GLSLstd450Degrees:
val->ssa->def = nir_fmul(&b->nb, src[0], nir_imm_float(&b->nb, 57.2957795131));
return;
case GLSLstd450Sin: op = nir_op_fsin; break;
case GLSLstd450Cos: op = nir_op_fcos; break;
case GLSLstd450Tan:
val->ssa->def = nir_fdiv(&b->nb, nir_fsin(&b->nb, src[0]),
nir_fcos(&b->nb, src[0]));
return;
case GLSLstd450Pow: op = nir_op_fpow; break;
case GLSLstd450Exp2: op = nir_op_fexp2; break;
case GLSLstd450Log2: op = nir_op_flog2; break;
case GLSLstd450Sqrt: op = nir_op_fsqrt; break;
case GLSLstd450InverseSqrt: op = nir_op_frsq; break;
case GLSLstd450Modf: op = nir_op_fmod; break;
case GLSLstd450FMin: op = nir_op_fmin; break;
case GLSLstd450FMax: op = nir_op_fmax; break;
case GLSLstd450Mix: op = nir_op_flrp; break;
case GLSLstd450Step:
val->ssa->def = nir_sge(&b->nb, src[1], src[0]);
return;
case GLSLstd450Fma: op = nir_op_ffma; break;
case GLSLstd450Ldexp: op = nir_op_ldexp; break;
/* Packing/Unpacking functions */
case GLSLstd450PackSnorm4x8: op = nir_op_pack_snorm_4x8; break;
case GLSLstd450PackUnorm4x8: op = nir_op_pack_unorm_4x8; break;
case GLSLstd450PackSnorm2x16: op = nir_op_pack_snorm_2x16; break;
case GLSLstd450PackUnorm2x16: op = nir_op_pack_unorm_2x16; break;
case GLSLstd450PackHalf2x16: op = nir_op_pack_half_2x16; break;
case GLSLstd450UnpackSnorm4x8: op = nir_op_unpack_snorm_4x8; break;
case GLSLstd450UnpackUnorm4x8: op = nir_op_unpack_unorm_4x8; break;
case GLSLstd450UnpackSnorm2x16: op = nir_op_unpack_snorm_2x16; break;
case GLSLstd450UnpackUnorm2x16: op = nir_op_unpack_unorm_2x16; break;
case GLSLstd450UnpackHalf2x16: op = nir_op_unpack_half_2x16; break;
case GLSLstd450Length:
val->ssa->def = build_length(&b->nb, src[0]);
return;
case GLSLstd450Distance:
val->ssa->def = build_length(&b->nb, nir_fsub(&b->nb, src[0], src[1]));
return;
case GLSLstd450Normalize:
val->ssa->def = nir_fdiv(&b->nb, src[0], build_length(&b->nb, src[0]));
return;
case GLSLstd450AddCarry: op = nir_op_uadd_carry; break;
case GLSLstd450SubBorrow: op = nir_op_usub_borrow; break;
case GLSLstd450Exp:
case GLSLstd450Log:
case GLSLstd450FClamp:
case GLSLstd450UClamp:
case GLSLstd450SClamp:
case GLSLstd450Asin:
case GLSLstd450Acos:
case GLSLstd450Atan:
case GLSLstd450Atan2:
case GLSLstd450Sinh:
case GLSLstd450Cosh:
case GLSLstd450Tanh:
case GLSLstd450Asinh:
case GLSLstd450Acosh:
case GLSLstd450Atanh:
case GLSLstd450SmoothStep:
case GLSLstd450Frexp:
case GLSLstd450PackDouble2x32:
case GLSLstd450UnpackDouble2x32:
case GLSLstd450Cross:
case GLSLstd450FaceForward:
case GLSLstd450Reflect:
case GLSLstd450Refract:
case GLSLstd450MulExtended:
default:
unreachable("Unhandled opcode");
}
nir_alu_instr *instr = nir_alu_instr_create(b->shader, op);
nir_ssa_dest_init(&instr->instr, &instr->dest.dest,
glsl_get_vector_elements(val->ssa->type), val->name);
instr->dest.write_mask = (1 << instr->dest.dest.ssa.num_components) - 1;
val->ssa->def = &instr->dest.dest.ssa;
for (unsigned i = 0; i < nir_op_infos[op].num_inputs; i++)
instr->src[i].src = nir_src_for_ssa(src[i]);
nir_builder_instr_insert(&b->nb, &instr->instr);
}
bool
vtn_handle_glsl450_instruction(struct vtn_builder *b, uint32_t ext_opcode,
const uint32_t *words, unsigned count)
{
switch ((enum GLSLstd450)ext_opcode) {
case GLSLstd450Determinant:
case GLSLstd450MatrixInverse:
case GLSLstd450InterpolateAtCentroid:
case GLSLstd450InterpolateAtSample:
case GLSLstd450InterpolateAtOffset:
unreachable("Unhandled opcode");
default:
handle_glsl450_alu(b, (enum GLSLstd450)ext_opcode, words, count);
}
return true;
}

3046
src/glsl/nir/spirv_to_nir.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,227 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Jason Ekstrand (jason@jlekstrand.net)
*
*/
#include "nir.h"
#include "nir_spirv.h"
#include "nir_builder.h"
#include "spirv.h"
struct vtn_builder;
struct vtn_decoration;
enum vtn_value_type {
vtn_value_type_invalid = 0,
vtn_value_type_undef,
vtn_value_type_string,
vtn_value_type_decoration_group,
vtn_value_type_type,
vtn_value_type_constant,
vtn_value_type_deref,
vtn_value_type_function,
vtn_value_type_block,
vtn_value_type_ssa,
vtn_value_type_extension,
};
struct vtn_block {
/* Merge opcode if this block contains a merge; SpvOpNop otherwise. */
SpvOp merge_op;
uint32_t merge_block_id;
const uint32_t *label;
const uint32_t *branch;
nir_block *block;
};
struct vtn_function {
struct exec_node node;
nir_function_overload *overload;
struct vtn_block *start_block;
const uint32_t *end;
};
typedef bool (*vtn_instruction_handler)(struct vtn_builder *, uint32_t,
const uint32_t *, unsigned);
struct vtn_ssa_value {
union {
nir_ssa_def *def;
struct vtn_ssa_value **elems;
};
/* For matrices, a transposed version of the value, or NULL if it hasn't
* been computed
*/
struct vtn_ssa_value *transposed;
const struct glsl_type *type;
};
struct vtn_type {
const struct glsl_type *type;
/* for matrices, whether the matrix is stored row-major */
bool row_major;
/* for structs, the offset of each member */
unsigned *offsets;
/* for structs, whether it was decorated as a "non-SSBO-like" block */
bool block;
/* for structs, whether it was decorated as an "SSBO-like" block */
bool buffer_block;
/* for structs with block == true, whether this is a builtin block (i.e. a
* block that contains only builtins).
*/
bool builtin_block;
/* for arrays and matrices, the array stride */
unsigned stride;
/* for arrays, the vtn_type for the elements of the array */
struct vtn_type *array_element;
/* for structures, the vtn_type for each member */
struct vtn_type **members;
/* Whether this type, or a parent type, has been decorated as a builtin */
bool is_builtin;
SpvBuiltIn builtin;
};
struct vtn_value {
enum vtn_value_type value_type;
const char *name;
struct vtn_decoration *decoration;
union {
void *ptr;
char *str;
struct vtn_type *type;
struct {
nir_constant *constant;
const struct glsl_type *const_type;
};
struct {
nir_deref_var *deref;
struct vtn_type *deref_type;
};
struct vtn_function *func;
struct vtn_block *block;
struct vtn_ssa_value *ssa;
vtn_instruction_handler ext_handler;
};
};
struct vtn_decoration {
struct vtn_decoration *next;
int member; /* -1 if not a member decoration */
const uint32_t *literals;
struct vtn_value *group;
SpvDecoration decoration;
};
struct vtn_builder {
nir_builder nb;
nir_shader *shader;
nir_function_impl *impl;
struct vtn_block *block;
/*
* In SPIR-V, constants are global, whereas in NIR, the load_const
* instruction we use is per-function. So while we parse each function, we
* keep a hash table of constants we've resolved to nir_ssa_value's so
* far, and we lazily resolve them when we see them used in a function.
*/
struct hash_table *const_table;
/*
* Map from nir_block to the vtn_block which ends with it -- used for
* handling phi nodes.
*/
struct hash_table *block_table;
/*
* NIR variable for each SPIR-V builtin.
*/
nir_variable *builtins[42]; /* XXX need symbolic constant from SPIR-V header */
unsigned value_id_bound;
struct vtn_value *values;
SpvExecutionModel execution_model;
struct vtn_value *entry_point;
struct vtn_function *func;
struct exec_list functions;
};
static inline struct vtn_value *
vtn_push_value(struct vtn_builder *b, uint32_t value_id,
enum vtn_value_type value_type)
{
assert(value_id < b->value_id_bound);
assert(b->values[value_id].value_type == vtn_value_type_invalid);
b->values[value_id].value_type = value_type;
return &b->values[value_id];
}
static inline struct vtn_value *
vtn_untyped_value(struct vtn_builder *b, uint32_t value_id)
{
assert(value_id < b->value_id_bound);
return &b->values[value_id];
}
static inline struct vtn_value *
vtn_value(struct vtn_builder *b, uint32_t value_id,
enum vtn_value_type value_type)
{
struct vtn_value *val = vtn_untyped_value(b, value_id);
assert(val->value_type == value_type);
return val;
}
struct vtn_ssa_value *vtn_ssa_value(struct vtn_builder *b, uint32_t value_id);
typedef void (*vtn_decoration_foreach_cb)(struct vtn_builder *,
struct vtn_value *,
int member,
const struct vtn_decoration *,
void *);
void vtn_foreach_decoration(struct vtn_builder *b, struct vtn_value *value,
vtn_decoration_foreach_cb cb, void *data);
bool vtn_handle_glsl450_instruction(struct vtn_builder *b, uint32_t ext_opcode,
const uint32_t *words, unsigned count);

View File

@@ -45,6 +45,114 @@ typedef enum
#define MESA_SHADER_STAGES (MESA_SHADER_COMPUTE + 1)
/**
* Indexes for vertex program attributes.
* GL_NV_vertex_program aliases generic attributes over the conventional
* attributes. In GL_ARB_vertex_program shader the aliasing is optional.
* In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
* generic attributes are distinct/separate).
*/
typedef enum
{
VERT_ATTRIB_POS = 0,
VERT_ATTRIB_WEIGHT = 1,
VERT_ATTRIB_NORMAL = 2,
VERT_ATTRIB_COLOR0 = 3,
VERT_ATTRIB_COLOR1 = 4,
VERT_ATTRIB_FOG = 5,
VERT_ATTRIB_COLOR_INDEX = 6,
VERT_ATTRIB_EDGEFLAG = 7,
VERT_ATTRIB_TEX0 = 8,
VERT_ATTRIB_TEX1 = 9,
VERT_ATTRIB_TEX2 = 10,
VERT_ATTRIB_TEX3 = 11,
VERT_ATTRIB_TEX4 = 12,
VERT_ATTRIB_TEX5 = 13,
VERT_ATTRIB_TEX6 = 14,
VERT_ATTRIB_TEX7 = 15,
VERT_ATTRIB_POINT_SIZE = 16,
VERT_ATTRIB_GENERIC0 = 17,
VERT_ATTRIB_GENERIC1 = 18,
VERT_ATTRIB_GENERIC2 = 19,
VERT_ATTRIB_GENERIC3 = 20,
VERT_ATTRIB_GENERIC4 = 21,
VERT_ATTRIB_GENERIC5 = 22,
VERT_ATTRIB_GENERIC6 = 23,
VERT_ATTRIB_GENERIC7 = 24,
VERT_ATTRIB_GENERIC8 = 25,
VERT_ATTRIB_GENERIC9 = 26,
VERT_ATTRIB_GENERIC10 = 27,
VERT_ATTRIB_GENERIC11 = 28,
VERT_ATTRIB_GENERIC12 = 29,
VERT_ATTRIB_GENERIC13 = 30,
VERT_ATTRIB_GENERIC14 = 31,
VERT_ATTRIB_GENERIC15 = 32,
VERT_ATTRIB_MAX = 33
} gl_vert_attrib;
/**
* Symbolic constats to help iterating over
* specific blocks of vertex attributes.
*
* VERT_ATTRIB_FF
* includes all fixed function attributes as well as
* the aliased GL_NV_vertex_program shader attributes.
* VERT_ATTRIB_TEX
* include the classic texture coordinate attributes.
* Is a subset of VERT_ATTRIB_FF.
* VERT_ATTRIB_GENERIC
* include the OpenGL 2.0+ GLSL generic shader attributes.
* These alias the generic GL_ARB_vertex_shader attributes.
*/
#define VERT_ATTRIB_FF(i) (VERT_ATTRIB_POS + (i))
#define VERT_ATTRIB_FF_MAX VERT_ATTRIB_GENERIC0
#define VERT_ATTRIB_TEX(i) (VERT_ATTRIB_TEX0 + (i))
#define VERT_ATTRIB_TEX_MAX MAX_TEXTURE_COORD_UNITS
#define VERT_ATTRIB_GENERIC(i) (VERT_ATTRIB_GENERIC0 + (i))
#define VERT_ATTRIB_GENERIC_MAX MAX_VERTEX_GENERIC_ATTRIBS
/**
* Bitflags for vertex attributes.
* These are used in bitfields in many places.
*/
/*@{*/
#define VERT_BIT_POS BITFIELD64_BIT(VERT_ATTRIB_POS)
#define VERT_BIT_WEIGHT BITFIELD64_BIT(VERT_ATTRIB_WEIGHT)
#define VERT_BIT_NORMAL BITFIELD64_BIT(VERT_ATTRIB_NORMAL)
#define VERT_BIT_COLOR0 BITFIELD64_BIT(VERT_ATTRIB_COLOR0)
#define VERT_BIT_COLOR1 BITFIELD64_BIT(VERT_ATTRIB_COLOR1)
#define VERT_BIT_FOG BITFIELD64_BIT(VERT_ATTRIB_FOG)
#define VERT_BIT_COLOR_INDEX BITFIELD64_BIT(VERT_ATTRIB_COLOR_INDEX)
#define VERT_BIT_EDGEFLAG BITFIELD64_BIT(VERT_ATTRIB_EDGEFLAG)
#define VERT_BIT_TEX0 BITFIELD64_BIT(VERT_ATTRIB_TEX0)
#define VERT_BIT_TEX1 BITFIELD64_BIT(VERT_ATTRIB_TEX1)
#define VERT_BIT_TEX2 BITFIELD64_BIT(VERT_ATTRIB_TEX2)
#define VERT_BIT_TEX3 BITFIELD64_BIT(VERT_ATTRIB_TEX3)
#define VERT_BIT_TEX4 BITFIELD64_BIT(VERT_ATTRIB_TEX4)
#define VERT_BIT_TEX5 BITFIELD64_BIT(VERT_ATTRIB_TEX5)
#define VERT_BIT_TEX6 BITFIELD64_BIT(VERT_ATTRIB_TEX6)
#define VERT_BIT_TEX7 BITFIELD64_BIT(VERT_ATTRIB_TEX7)
#define VERT_BIT_POINT_SIZE BITFIELD64_BIT(VERT_ATTRIB_POINT_SIZE)
#define VERT_BIT_GENERIC0 BITFIELD64_BIT(VERT_ATTRIB_GENERIC0)
#define VERT_BIT(i) BITFIELD64_BIT(i)
#define VERT_BIT_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_MAX)
#define VERT_BIT_FF(i) VERT_BIT(i)
#define VERT_BIT_FF_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_FF_MAX)
#define VERT_BIT_TEX(i) VERT_BIT(VERT_ATTRIB_TEX(i))
#define VERT_BIT_TEX_ALL \
BITFIELD64_RANGE(VERT_ATTRIB_TEX(0), VERT_ATTRIB_TEX_MAX)
#define VERT_BIT_GENERIC(i) VERT_BIT(VERT_ATTRIB_GENERIC(i))
#define VERT_BIT_GENERIC_ALL \
BITFIELD64_RANGE(VERT_ATTRIB_GENERIC(0), VERT_ATTRIB_GENERIC_MAX)
/*@}*/
/**
* Indexes for vertex shader outputs, geometry shader inputs/outputs, and
* fragment shader inputs.

View File

@@ -35,6 +35,12 @@
#include "util/ralloc.h"
#include "util/strtod.h"
extern "C" void
_mesa_error_no_memory(const char *caller)
{
fprintf(stderr, "Mesa error: out of memory in %s", caller);
}
void
_mesa_warning(struct gl_context *ctx, const char *fmt, ...)
{

View File

@@ -41,7 +41,7 @@ AM_CFLAGS = \
AM_CXXFLAGS = $(AM_CFLAGS)
noinst_LTLIBRARIES = libi965_dri.la
noinst_LTLIBRARIES = libi965_dri.la libi965_compiler.la
libi965_dri_la_SOURCES = $(i965_FILES)
libi965_dri_la_LIBADD = $(INTEL_LIBS)
@@ -55,6 +55,16 @@ TEST_LIBS = \
$(CLOCK_LIB) \
../common/libdri_test_stubs.la
libi965_compiler_la_SOURCES = $(i965_FILES)
libi965_compiler_la_LIBADD = $(INTEL_LIBS) \
../common/libdricommon.la \
../common/libxmlconfig.la \
../common/libmegadriver_stub.la \
../../../libmesa.la \
$(DRI_LIB_DEPS) \
$(CLOCK_LIB) \
../common/libdri_test_stubs.la -lm
TESTS = \
test_fs_cmod_propagation \
test_fs_saturate_propagation \

View File

@@ -361,6 +361,12 @@ struct brw_stage_prog_data {
/** @} */
} binding_table;
uint32_t *map_entries;
struct {
uint32_t index_count;
uint32_t *index;
} bind_map[8]; /* MAX_SETS from vulkan/private.h */
GLuint nr_params; /**< number of float params/constants */
GLuint nr_pull_params;
unsigned nr_image_params;

View File

@@ -55,7 +55,7 @@ brw_cs_prog_data_compare(const void *in_a, const void *in_b)
}
static const unsigned *
const unsigned *
brw_cs_emit(struct brw_context *brw,
void *mem_ctx,
const struct brw_cs_prog_key *key,

View File

@@ -41,6 +41,15 @@ bool brw_cs_prog_data_compare(const void *a, const void *b);
void
brw_upload_cs_prog(struct brw_context *brw);
const unsigned *
brw_cs_emit(struct brw_context *brw,
void *mem_ctx,
const struct brw_cs_prog_key *key,
struct brw_cs_prog_data *prog_data,
struct gl_compute_program *cp,
struct gl_shader_program *prog,
unsigned *final_assembly_size);
#ifdef __cplusplus
}
#endif

View File

@@ -57,6 +57,7 @@
# define GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL (0 << 8)
# define GEN7_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM (1 << 8)
#ifndef _3DPRIM_POINTLIST /* FIXME: Avoid clashing with defines from bdw_pack.h */
#define _3DPRIM_POINTLIST 0x01
#define _3DPRIM_LINELIST 0x02
#define _3DPRIM_LINESTRIP 0x03
@@ -78,6 +79,7 @@
#define _3DPRIM_LINESTRIP_BF 0x13
#define _3DPRIM_LINESTRIP_CONT_BF 0x14
#define _3DPRIM_TRIFAN_NOSTIPPLE 0x15
#endif
/* We use this offset to be able to pass native primitive types in struct
* _mesa_prim::mode. Native primitive types are BRW_PRIM_OFFSET +

View File

@@ -373,3 +373,15 @@ brw_get_device_info(int devid, int revision)
return devinfo;
}
const char *
brw_get_device_name(int devid)
{
switch (devid) {
#undef CHIPSET
#define CHIPSET(id, family, name) case id: return name;
#include "pci_ids/i965_pci_ids.h"
default:
return NULL;
}
}

View File

@@ -87,3 +87,4 @@ struct brw_device_info
};
const struct brw_device_info *brw_get_device_info(int devid, int revision);
const char *brw_get_device_name(int devid);

View File

@@ -491,6 +491,7 @@ type_size_scalar(const struct glsl_type *type)
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_DOUBLE:
case GLSL_TYPE_FUNCTION:
unreachable("not reached");
}
@@ -1529,6 +1530,10 @@ fs_visitor::assign_vs_urb_setup()
unsigned vue_entries =
MAX2(count, vs_prog_data->base.vue_map.num_slots);
/* URB entry size is counted in units of 64 bytes (for the 3DSTATE_URB_VS
* command). Each attribute is 16 bytes (4 floats/dwords), so each unit
* fits four attributes.
*/
vs_prog_data->base.urb_entry_size = ALIGN(vue_entries, 4) / 4;
vs_prog_data->base.urb_read_length = (count + 1) / 2;
@@ -2641,9 +2646,22 @@ fs_visitor::emit_repclear_shader()
brw_wm_prog_key *key = (brw_wm_prog_key*) this->key;
int base_mrf = 1;
int color_mrf = base_mrf + 2;
fs_inst *mov;
fs_inst *mov = bld.exec_all().MOV(vec4(brw_message_reg(color_mrf)),
fs_reg(UNIFORM, 0, BRW_REGISTER_TYPE_F));
if (uniforms == 1) {
mov = bld.exec_all().MOV(vec4(brw_message_reg(color_mrf)),
fs_reg(UNIFORM, 0, BRW_REGISTER_TYPE_F));
} else {
struct brw_reg reg =
brw_reg(BRW_GENERAL_REGISTER_FILE,
2, 3, 0, 0, BRW_REGISTER_TYPE_F,
BRW_VERTICAL_STRIDE_8,
BRW_WIDTH_2,
BRW_HORIZONTAL_STRIDE_4, BRW_SWIZZLE_XYZW, WRITEMASK_XYZW);
mov = bld.exec_all().MOV(vec4(brw_message_reg(color_mrf)),
fs_reg(reg));
}
fs_inst *write;
if (key->nr_color_regions == 1) {
@@ -2672,8 +2690,10 @@ fs_visitor::emit_repclear_shader()
assign_curb_setup();
/* Now that we have the uniform assigned, go ahead and force it to a vec4. */
assert(mov->src[0].file == HW_REG);
mov->src[0] = brw_vec4_grf(mov->src[0].fixed_hw_reg.nr, 0);
if (uniforms == 1) {
assert(mov->src[0].file == HW_REG);
mov->src[0] = brw_vec4_grf(mov->src[0].fixed_hw_reg.nr, 0);
}
}
/**
@@ -4951,7 +4971,8 @@ fs_visitor::run_vs(gl_clip_plane *clip_planes)
{
assert(stage == MESA_SHADER_VERTEX);
assign_common_binding_table_offsets(0);
if (prog_data->map_entries == NULL)
assign_common_binding_table_offsets(0);
setup_vs_payload();
if (shader_time_index >= 0)
@@ -4990,9 +5011,8 @@ fs_visitor::run_fs(bool do_rep_send)
assert(stage == MESA_SHADER_FRAGMENT);
sanity_param_count = prog->Parameters->NumParameters;
assign_binding_table_offsets();
if (prog_data->map_entries == NULL)
assign_binding_table_offsets();
if (devinfo->gen >= 6)
setup_payload_gen6();
@@ -5062,13 +5082,6 @@ fs_visitor::run_fs(bool do_rep_send)
else
wm_prog_data->reg_blocks_16 = brw_register_blocks(grf_used);
/* If any state parameters were appended, then ParameterValues could have
* been realloced, in which case the driver uniform storage set up by
* _mesa_associate_uniform_storage() would point to freed memory. Make
* sure that didn't happen.
*/
assert(sanity_param_count == prog->Parameters->NumParameters);
return !failed;
}
@@ -5141,7 +5154,7 @@ brw_wm_fs_emit(struct brw_context *brw,
if (prog)
shader = (brw_shader *) prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
if (unlikely(INTEL_DEBUG & DEBUG_WM))
if (unlikely(INTEL_DEBUG & DEBUG_WM) && shader->base.ir)
brw_dump_ir("fragment", prog, &shader->base, &fp->Base);
int st_index8 = -1, st_index16 = -1;

View File

@@ -42,7 +42,8 @@ fs_visitor::emit_nir_code()
*/
nir_setup_inputs(nir);
nir_setup_outputs(nir);
nir_setup_uniforms(nir);
uniforms = nir->num_uniforms;
//nir_setup_uniforms(nir);
nir_emit_system_values(nir);
/* get the main function and emit it */
@@ -1515,13 +1516,22 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
has_indirect = true;
/* fallthrough */
case nir_intrinsic_load_ubo: {
uint32_t set = instr->const_index[0];
nir_const_value *const_index = nir_src_as_const_value(instr->src[0]);
fs_reg surf_index;
if (const_index) {
surf_index = fs_reg(stage_prog_data->binding_table.ubo_start +
const_index->u[0]);
uint32_t binding = const_index->u[0];
/* FIXME: We should probably assert here, but dota2 seems to hit
* it and we'd like to keep going.
*/
if (binding >= stage_prog_data->bind_map[set].index_count)
binding = 0;
surf_index = fs_reg(stage_prog_data->bind_map[set].index[binding]);
} else {
assert(0 && "need more info from the ir for this.");
/* The block index is not a constant. Evaluate the index expression
* per-channel and add the base UBO index; we have to select a value
* from any live channel.
@@ -1546,7 +1556,7 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
BRW_REGISTER_TYPE_D),
fs_reg(2));
unsigned vec4_offset = instr->const_index[0] / 4;
unsigned vec4_offset = instr->const_index[1] / 4;
for (int i = 0; i < instr->num_components; i++)
VARYING_PULL_CONSTANT_LOAD(bld, offset(dest, bld, i), surf_index,
base_offset, vec4_offset + i);
@@ -1554,7 +1564,7 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
fs_reg packed_consts = vgrf(glsl_type::float_type);
packed_consts.type = dest.type;
fs_reg const_offset_reg((unsigned) instr->const_index[0] & ~15);
fs_reg const_offset_reg((unsigned) instr->const_index[1] & ~15);
bld.emit(FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD, packed_consts,
surf_index, const_offset_reg);
@@ -1737,7 +1747,13 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
void
fs_visitor::nir_emit_texture(const fs_builder &bld, nir_tex_instr *instr)
{
unsigned sampler = instr->sampler_index;
uint32_t set = instr->sampler_set;
uint32_t binding = instr->sampler_index;
assert(binding < stage_prog_data->bind_map[set].index_count);
assert(stage_prog_data->bind_map[set].index[binding] < 1000);
unsigned sampler = stage_prog_data->bind_map[set].index[binding];
fs_reg sampler_reg(sampler);
/* FINISHME: We're failing to recompile our programs when the sampler is
@@ -1897,6 +1913,12 @@ fs_visitor::nir_emit_jump(const fs_builder &bld, nir_jump_instr *instr)
bld.emit(BRW_OPCODE_CONTINUE);
break;
case nir_jump_return:
/* This has to be the last block in the shader. We don't handle
* early returns.
*/
assert(nir_cf_node_next(&instr->instr.block->cf_node) == NULL &&
instr->instr.block->cf_node.parent->type == nir_cf_node_function);
break;
default:
unreachable("unknown jump");
}

View File

@@ -33,19 +33,23 @@
#include "brw_state.h"
#include "brw_ff_gs.h"
bool
brw_codegen_gs_prog(struct brw_context *brw,
brw_compile_gs_prog(struct brw_context *brw,
struct gl_shader_program *prog,
struct brw_geometry_program *gp,
struct brw_gs_prog_key *key)
struct brw_gs_prog_key *key,
struct brw_gs_compile_output *output)
{
struct brw_stage_state *stage_state = &brw->gs.base;
struct brw_gs_compile c;
memset(&c, 0, sizeof(c));
c.key = *key;
c.gp = gp;
/* We get the bind map as input in the output struct...*/
c.prog_data.base.base.map_entries = output->prog_data.base.base.map_entries;
memcpy(c.prog_data.base.base.bind_map, output->prog_data.base.base.bind_map,
sizeof(c.prog_data.base.base.bind_map));
c.prog_data.include_primitive_id =
(gp->program.Base.InputsRead & VARYING_BIT_PRIMITIVE_ID) != 0;
@@ -270,19 +274,39 @@ brw_codegen_gs_prog(struct brw_context *brw,
return false;
}
/* Scratch space is used for register spilling */
if (c.prog_data.base.base.total_scratch) {
output->mem_ctx = mem_ctx;
output->program = program;
output->program_size = program_size;
memcpy(&output->prog_data, &c.prog_data,
sizeof(output->prog_data));
return true;
}
bool
brw_codegen_gs_prog(struct brw_context *brw,
struct gl_shader_program *prog,
struct brw_geometry_program *gp,
struct brw_gs_prog_key *key)
{
struct brw_gs_compile_output output;
struct brw_stage_state *stage_state = &brw->gs.base;
if (brw_compile_gs_prog(brw, prog, gp, key, &output))
return false;
if (output.prog_data.base.base.total_scratch) {
brw_get_scratch_bo(brw, &stage_state->scratch_bo,
c.prog_data.base.base.total_scratch *
output.prog_data.base.base.total_scratch *
brw->max_gs_threads);
}
brw_upload_cache(&brw->cache, BRW_CACHE_GS_PROG,
&c.key, sizeof(c.key),
program, program_size,
&c.prog_data, sizeof(c.prog_data),
key, sizeof(*key),
output.program, output.program_size,
&output.prog_data, sizeof(output.prog_data),
&stage_state->prog_offset, &brw->gs.prog_data);
ralloc_free(mem_ctx);
ralloc_free(output.mem_ctx);
return true;
}

View File

@@ -37,6 +37,22 @@ struct gl_context;
struct gl_shader_program;
struct gl_program;
struct brw_gs_compile_output {
void *mem_ctx;
const void *program;
uint32_t program_size;
struct brw_gs_prog_data prog_data;
};
struct brw_gs_prog_key;
bool
brw_compile_gs_prog(struct brw_context *brw,
struct gl_shader_program *prog,
struct brw_geometry_program *gp,
struct brw_gs_prog_key *key,
struct brw_gs_compile_output *output);
bool brw_gs_prog_data_compare(const void *a, const void *b);
void

View File

@@ -79,7 +79,6 @@ brw_create_nir(struct brw_context *brw,
const nir_shader_compiler_options *options =
ctx->Const.ShaderCompilerOptions[stage].NirOptions;
struct gl_shader *shader = shader_prog ? shader_prog->_LinkedShaders[stage] : NULL;
bool debug_enabled = INTEL_DEBUG & intel_debug_flag_for_shader_stage(stage);
nir_shader *nir;
/* First, lower the GLSL IR or Mesa IR to NIR */
@@ -91,6 +90,27 @@ brw_create_nir(struct brw_context *brw,
}
nir_validate_shader(nir);
brw_process_nir(nir, brw->intelScreen->devinfo, shader_prog, stage, is_scalar);
static GLuint msg_id = 0;
_mesa_gl_debug(&brw->ctx, &msg_id,
MESA_DEBUG_SOURCE_SHADER_COMPILER,
MESA_DEBUG_TYPE_OTHER,
MESA_DEBUG_SEVERITY_NOTIFICATION,
"%s NIR shader:\n",
_mesa_shader_stage_to_abbrev(stage));
return nir;
}
void
brw_process_nir(nir_shader *nir,
const struct brw_device_info *devinfo,
const struct gl_shader_program *shader_prog,
gl_shader_stage stage, bool is_scalar)
{
bool debug_enabled = INTEL_DEBUG & intel_debug_flag_for_shader_stage(stage);
nir_lower_global_vars_to_local(nir);
nir_validate_shader(nir);
@@ -139,8 +159,10 @@ brw_create_nir(struct brw_context *brw,
if (shader_prog) {
nir_lower_samplers(nir, shader_prog);
nir_validate_shader(nir);
} else {
nir_lower_samplers_for_vk(nir);
}
nir_validate_shader(nir);
nir_lower_system_values(nir);
nir_validate_shader(nir);
@@ -150,7 +172,7 @@ brw_create_nir(struct brw_context *brw,
nir_optimize(nir, is_scalar);
if (brw->gen >= 6) {
if (devinfo->gen >= 6) {
/* Try and fuse multiply-adds */
nir_opt_peephole_ffma(nir);
nir_validate_shader(nir);
@@ -194,7 +216,7 @@ brw_create_nir(struct brw_context *brw,
* run it last because it stashes data in instr->pass_flags and we don't
* want that to be squashed by other NIR passes.
*/
if (brw->gen <= 5)
if (devinfo->gen <= 5)
brw_nir_analyze_boolean_resolves(nir);
nir_sweep(nir);
@@ -204,8 +226,6 @@ brw_create_nir(struct brw_context *brw,
_mesa_shader_stage_to_string(stage));
nir_print_shader(nir, stderr);
}
return nir;
}
enum brw_reg_type

View File

@@ -85,6 +85,12 @@ enum brw_reg_type brw_type_for_nir_type(nir_alu_type type);
enum glsl_base_type brw_glsl_base_type_for_nir_type(nir_alu_type type);
void
brw_process_nir(nir_shader *nir,
const struct brw_device_info *devinfo,
const struct gl_shader_program *shader_prog,
gl_shader_stage stage, bool is_scalar);
#ifdef __cplusplus
}
#endif

View File

@@ -276,7 +276,7 @@ brw_get_scratch_bo(struct brw_context *brw,
void brwInitFragProgFuncs( struct dd_function_table *functions )
{
assert(functions->ProgramStringNotify == _tnl_program_string);
/* assert(functions->ProgramStringNotify == _tnl_program_string); */
functions->NewProgram = brwNewProgram;
functions->DeleteProgram = brwDeleteProgram;

View File

@@ -96,6 +96,7 @@ brw_compiler_create(void *mem_ctx, const struct brw_device_info *devinfo)
*/
nir_options->lower_ffma = true;
nir_options->lower_sub = true;
nir_options->lower_fdiv = true;
/* We want the GLSL compiler to emit code that uses condition codes */
for (int i = 0; i < MESA_SHADER_STAGES; i++) {
@@ -459,6 +460,7 @@ brw_type_for_base_type(const struct glsl_type *type)
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_DOUBLE:
case GLSL_TYPE_FUNCTION:
unreachable("not reached");
}

View File

@@ -1917,7 +1917,7 @@ brw_vs_emit(struct brw_context *brw,
if (INTEL_DEBUG & DEBUG_SHADER_TIME)
st_index = brw_get_shader_time_index(brw, prog, &vp->Base, ST_VS);
if (unlikely(INTEL_DEBUG & DEBUG_VS))
if (unlikely(INTEL_DEBUG & DEBUG_VS) && shader->base.ir)
brw_dump_ir("vertex", prog, &shader->base, &vp->Base);
if (!vp->Base.nir &&

View File

@@ -611,17 +611,19 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
has_indirect = true;
/* fallthrough */
case nir_intrinsic_load_ubo: {
const uint32_t set = instr->const_index[0];
nir_const_value *const_block_index = nir_src_as_const_value(instr->src[0]);
src_reg surf_index;
dest = get_nir_dest(instr->dest);
if (const_block_index) {
uint32_t binding = const_block_index->u[0];
/* The block index is a constant, so just emit the binding table entry
* as an immediate.
*/
surf_index = src_reg(prog_data->base.binding_table.ubo_start +
const_block_index->u[0]);
surf_index = src_reg(stage_prog_data->bind_map[set].index[binding]);
} else {
/* The block index is not a constant. Evaluate the index expression
* per-channel and add the base UBO index; we have to select a value
@@ -641,7 +643,7 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
shader_prog->NumUniformBlocks - 1);
}
unsigned const_offset = instr->const_index[0];
unsigned const_offset = instr->const_index[1];
src_reg offset;
if (!has_indirect) {

View File

@@ -643,6 +643,7 @@ type_size_vec4(const struct glsl_type *type)
case GLSL_TYPE_DOUBLE:
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
unreachable("not reached");
}

View File

@@ -41,7 +41,7 @@
* Return a bitfield where bit n is set if barycentric interpolation mode n
* (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader.
*/
static unsigned
unsigned
brw_compute_barycentric_interp_modes(struct brw_context *brw,
bool shade_model_flat,
bool persample_shading,

View File

@@ -90,6 +90,12 @@ bool brw_wm_prog_data_compare(const void *a, const void *b);
void
brw_upload_wm_prog(struct brw_context *brw);
unsigned
brw_compute_barycentric_interp_modes(struct brw_context *brw,
bool shade_model_flat,
bool persample_shading,
const struct gl_fragment_program *fprog);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -94,113 +94,6 @@ struct vbo_context;
#define PRIM_OUTSIDE_BEGIN_END (PRIM_MAX + 1)
#define PRIM_UNKNOWN (PRIM_MAX + 2)
/**
* Indexes for vertex program attributes.
* GL_NV_vertex_program aliases generic attributes over the conventional
* attributes. In GL_ARB_vertex_program shader the aliasing is optional.
* In GL_ARB_vertex_shader / OpenGL 2.0 the aliasing is disallowed (the
* generic attributes are distinct/separate).
*/
typedef enum
{
VERT_ATTRIB_POS = 0,
VERT_ATTRIB_WEIGHT = 1,
VERT_ATTRIB_NORMAL = 2,
VERT_ATTRIB_COLOR0 = 3,
VERT_ATTRIB_COLOR1 = 4,
VERT_ATTRIB_FOG = 5,
VERT_ATTRIB_COLOR_INDEX = 6,
VERT_ATTRIB_EDGEFLAG = 7,
VERT_ATTRIB_TEX0 = 8,
VERT_ATTRIB_TEX1 = 9,
VERT_ATTRIB_TEX2 = 10,
VERT_ATTRIB_TEX3 = 11,
VERT_ATTRIB_TEX4 = 12,
VERT_ATTRIB_TEX5 = 13,
VERT_ATTRIB_TEX6 = 14,
VERT_ATTRIB_TEX7 = 15,
VERT_ATTRIB_POINT_SIZE = 16,
VERT_ATTRIB_GENERIC0 = 17,
VERT_ATTRIB_GENERIC1 = 18,
VERT_ATTRIB_GENERIC2 = 19,
VERT_ATTRIB_GENERIC3 = 20,
VERT_ATTRIB_GENERIC4 = 21,
VERT_ATTRIB_GENERIC5 = 22,
VERT_ATTRIB_GENERIC6 = 23,
VERT_ATTRIB_GENERIC7 = 24,
VERT_ATTRIB_GENERIC8 = 25,
VERT_ATTRIB_GENERIC9 = 26,
VERT_ATTRIB_GENERIC10 = 27,
VERT_ATTRIB_GENERIC11 = 28,
VERT_ATTRIB_GENERIC12 = 29,
VERT_ATTRIB_GENERIC13 = 30,
VERT_ATTRIB_GENERIC14 = 31,
VERT_ATTRIB_GENERIC15 = 32,
VERT_ATTRIB_MAX = 33
} gl_vert_attrib;
/**
* Symbolic constats to help iterating over
* specific blocks of vertex attributes.
*
* VERT_ATTRIB_FF
* includes all fixed function attributes as well as
* the aliased GL_NV_vertex_program shader attributes.
* VERT_ATTRIB_TEX
* include the classic texture coordinate attributes.
* Is a subset of VERT_ATTRIB_FF.
* VERT_ATTRIB_GENERIC
* include the OpenGL 2.0+ GLSL generic shader attributes.
* These alias the generic GL_ARB_vertex_shader attributes.
*/
#define VERT_ATTRIB_FF(i) (VERT_ATTRIB_POS + (i))
#define VERT_ATTRIB_FF_MAX VERT_ATTRIB_GENERIC0
#define VERT_ATTRIB_TEX(i) (VERT_ATTRIB_TEX0 + (i))
#define VERT_ATTRIB_TEX_MAX MAX_TEXTURE_COORD_UNITS
#define VERT_ATTRIB_GENERIC(i) (VERT_ATTRIB_GENERIC0 + (i))
#define VERT_ATTRIB_GENERIC_MAX MAX_VERTEX_GENERIC_ATTRIBS
/**
* Bitflags for vertex attributes.
* These are used in bitfields in many places.
*/
/*@{*/
#define VERT_BIT_POS BITFIELD64_BIT(VERT_ATTRIB_POS)
#define VERT_BIT_WEIGHT BITFIELD64_BIT(VERT_ATTRIB_WEIGHT)
#define VERT_BIT_NORMAL BITFIELD64_BIT(VERT_ATTRIB_NORMAL)
#define VERT_BIT_COLOR0 BITFIELD64_BIT(VERT_ATTRIB_COLOR0)
#define VERT_BIT_COLOR1 BITFIELD64_BIT(VERT_ATTRIB_COLOR1)
#define VERT_BIT_FOG BITFIELD64_BIT(VERT_ATTRIB_FOG)
#define VERT_BIT_COLOR_INDEX BITFIELD64_BIT(VERT_ATTRIB_COLOR_INDEX)
#define VERT_BIT_EDGEFLAG BITFIELD64_BIT(VERT_ATTRIB_EDGEFLAG)
#define VERT_BIT_TEX0 BITFIELD64_BIT(VERT_ATTRIB_TEX0)
#define VERT_BIT_TEX1 BITFIELD64_BIT(VERT_ATTRIB_TEX1)
#define VERT_BIT_TEX2 BITFIELD64_BIT(VERT_ATTRIB_TEX2)
#define VERT_BIT_TEX3 BITFIELD64_BIT(VERT_ATTRIB_TEX3)
#define VERT_BIT_TEX4 BITFIELD64_BIT(VERT_ATTRIB_TEX4)
#define VERT_BIT_TEX5 BITFIELD64_BIT(VERT_ATTRIB_TEX5)
#define VERT_BIT_TEX6 BITFIELD64_BIT(VERT_ATTRIB_TEX6)
#define VERT_BIT_TEX7 BITFIELD64_BIT(VERT_ATTRIB_TEX7)
#define VERT_BIT_POINT_SIZE BITFIELD64_BIT(VERT_ATTRIB_POINT_SIZE)
#define VERT_BIT_GENERIC0 BITFIELD64_BIT(VERT_ATTRIB_GENERIC0)
#define VERT_BIT(i) BITFIELD64_BIT(i)
#define VERT_BIT_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_MAX)
#define VERT_BIT_FF(i) VERT_BIT(i)
#define VERT_BIT_FF_ALL BITFIELD64_RANGE(0, VERT_ATTRIB_FF_MAX)
#define VERT_BIT_TEX(i) VERT_BIT(VERT_ATTRIB_TEX(i))
#define VERT_BIT_TEX_ALL \
BITFIELD64_RANGE(VERT_ATTRIB_TEX(0), VERT_ATTRIB_TEX_MAX)
#define VERT_BIT_GENERIC(i) VERT_BIT(VERT_ATTRIB_GENERIC(i))
#define VERT_BIT_GENERIC_ALL \
BITFIELD64_RANGE(VERT_ATTRIB_GENERIC(0), VERT_ATTRIB_GENERIC_MAX)
/*@}*/
#define VARYING_SLOT_MAX (VARYING_SLOT_VAR0 + MAX_VARYING)
#define VARYING_SLOT_PATCH0 (VARYING_SLOT_MAX)
#define VARYING_SLOT_TESS_MAX (VARYING_SLOT_PATCH0 + MAX_VARYING)
@@ -2580,6 +2473,11 @@ struct gl_uniform_block
*/
GLuint Binding;
/**
* Vulkan descriptor set qualifier for this block.
*/
GLuint Set;
/**
* Minimum size (in bytes) of a buffer object to back this uniform buffer
* (GL_UNIFORM_BLOCK_DATA_SIZE).

View File

@@ -543,6 +543,7 @@ type_size(const struct glsl_type *type)
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
assert(!"Invalid type in type_size");
break;
}
@@ -2463,6 +2464,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
case GLSL_TYPE_STRUCT:
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_FUNCTION:
assert(!"Should not get here.");
break;
}

View File

@@ -108,6 +108,28 @@ static inline unsigned list_length(struct list_head *list)
return length;
}
static inline void list_splice(struct list_head *src, struct list_head *dst)
{
if (list_empty(src))
return;
src->next->prev = dst;
src->prev->next = dst->next;
dst->next->prev = src->prev;
dst->next = src->next;
}
static inline void list_splicetail(struct list_head *src, struct list_head *dst)
{
if (list_empty(src))
return;
src->prev->next = dst;
src->next->prev = dst->prev;
dst->prev->next = src->next;
dst->prev = src->prev;
}
static inline void list_validate(struct list_head *list)
{
struct list_head *node;

6
src/vulkan/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
# Generated source files
/*_spirv_autogen.h
/anv_entrypoints.c
/anv_entrypoints.h
/wayland-drm-protocol.c
/wayland-drm-client-protocol.h

137
src/vulkan/Makefile.am Normal file
View File

@@ -0,0 +1,137 @@
# Copyright © 2015 Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
SUBDIRS = . tests
vulkan_includedir = $(includedir)/vulkan
vulkan_include_HEADERS = \
$(top_srcdir)/include/vulkan/vk_platform.h \
$(top_srcdir)/include/vulkan/vulkan.h \
$(top_srcdir)/include/vulkan/vulkan_intel.h \
$(top_srcdir)/include/vulkan/vk_wsi_swapchain.h \
$(top_srcdir)/include/vulkan/vk_wsi_device_swapchain.h
lib_LTLIBRARIES = libvulkan.la
check_LTLIBRARIES = libvulkan-test.la
# The gallium includes are for the util/u_math.h include from main/macros.h
AM_CPPFLAGS = \
$(INTEL_CFLAGS) \
$(VALGRIND_CFLAGS) \
$(DEFINES) \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/mapi \
-I$(top_srcdir)/src/mesa \
-I$(top_srcdir)/src/mesa/drivers/dri/common \
-I$(top_srcdir)/src/mesa/drivers/dri/i965 \
-I$(top_srcdir)/src/gallium/auxiliary \
-I$(top_srcdir)/src/gallium/include \
-I$(top_builddir)/src/vulkan
libvulkan_la_CFLAGS = \
-Wall -Wextra -Wno-unused-parameter -fvisibility=hidden -O0 -g \
-Wstrict-prototypes -Wmissing-prototypes -Wno-override-init
libvulkan_la_CXXFLAGS = \
-Wall -Wextra -Wno-unused-parameter -fvisibility=hidden -O0 -g
VULKAN_SOURCES = \
anv_allocator.c \
anv_cmd_buffer.c \
anv_batch_chain.c \
anv_compiler.cpp \
anv_device.c \
anv_entrypoints.c \
anv_entrypoints.h \
anv_formats.c \
anv_image.c \
anv_intel.c \
anv_meta.c \
anv_nir_apply_dynamic_offsets.c \
anv_pipeline.c \
anv_private.h \
anv_query.c \
anv_util.c \
anv_wsi.c \
anv_wsi_x11.c \
gen8_state.c \
gen8_cmd_buffer.c \
gen8_pipeline.c \
gen7_state.c \
gen7_cmd_buffer.c \
gen7_pipeline.c
BUILT_SOURCES = \
anv_entrypoints.h \
anv_entrypoints.c \
anv_meta_spirv_autogen.h
if HAVE_EGL_PLATFORM_WAYLAND
BUILT_SOURCES += \
wayland-drm-protocol.c \
wayland-drm-client-protocol.h
%-protocol.c : $(top_srcdir)/src/egl/wayland/wayland-drm/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
%-client-protocol.h : $(top_srcdir)/src/egl/wayland/wayland-drm/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
AM_CPPFLAGS += -I$(top_srcdir)/src/egl/wayland/wayland-drm
VULKAN_SOURCES += \
wayland-drm-protocol.c \
anv_wsi_wayland.c
libvulkan_la_CFLAGS += -DHAVE_WAYLAND_PLATFORM
endif
libvulkan_la_SOURCES = \
$(VULKAN_SOURCES) \
anv_gem.c
anv_entrypoints.h : anv_entrypoints_gen.py $(vulkan_include_HEADERS)
$(AM_V_GEN)cat $(vulkan_include_HEADERS) | $(PYTHON2) $< header > $@
anv_entrypoints.c : anv_entrypoints_gen.py $(vulkan_include_HEADERS)
$(AM_V_GEN)cat $(vulkan_include_HEADERS) | $(PYTHON2) $< code > $@
%_spirv_autogen.h: %.c glsl_scraper.py
$(AM_V_GEN) $(PYTHON3) $(srcdir)/glsl_scraper.py --with-glslc=$(GLSLC) -o $@ $<
CLEANFILES = $(BUILT_SOURCES)
libvulkan_la_LIBADD = $(WAYLAND_LIBS) -lxcb -lxcb-dri3 \
$(top_builddir)/src/mesa/drivers/dri/i965/libi965_compiler.la
# Libvulkan with dummy gem. Used for unit tests.
libvulkan_test_la_SOURCES = \
$(VULKAN_SOURCES) \
anv_gem_stubs.c
libvulkan_test_la_CFLAGS = $(libvulkan_la_CFLAGS)
libvulkan_test_la_CXXFLAGS = $(libvulkan_la_CXXFLAGS)
libvulkan_test_la_LIBADD = $(libvulkan_la_LIBADD)
include $(top_srcdir)/install-lib-links.mk

836
src/vulkan/anv_allocator.c Normal file
View File

@@ -0,0 +1,836 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#define _DEFAULT_SOURCE
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <values.h>
#include <assert.h>
#include <linux/futex.h>
#include <linux/memfd.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include "anv_private.h"
#ifdef HAVE_VALGRIND
#define VG_NOACCESS_READ(__ptr) ({ \
VALGRIND_MAKE_MEM_DEFINED((__ptr), sizeof(*(__ptr))); \
__typeof(*(__ptr)) __val = *(__ptr); \
VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr)));\
__val; \
})
#define VG_NOACCESS_WRITE(__ptr, __val) ({ \
VALGRIND_MAKE_MEM_UNDEFINED((__ptr), sizeof(*(__ptr))); \
*(__ptr) = (__val); \
VALGRIND_MAKE_MEM_NOACCESS((__ptr), sizeof(*(__ptr))); \
})
#else
#define VG_NOACCESS_READ(__ptr) (*(__ptr))
#define VG_NOACCESS_WRITE(__ptr, __val) (*(__ptr) = (__val))
#endif
/* Design goals:
*
* - Lock free (except when resizing underlying bos)
*
* - Constant time allocation with typically only one atomic
*
* - Multiple allocation sizes without fragmentation
*
* - Can grow while keeping addresses and offset of contents stable
*
* - All allocations within one bo so we can point one of the
* STATE_BASE_ADDRESS pointers at it.
*
* The overall design is a two-level allocator: top level is a fixed size, big
* block (8k) allocator, which operates out of a bo. Allocation is done by
* either pulling a block from the free list or growing the used range of the
* bo. Growing the range may run out of space in the bo which we then need to
* grow. Growing the bo is tricky in a multi-threaded, lockless environment:
* we need to keep all pointers and contents in the old map valid. GEM bos in
* general can't grow, but we use a trick: we create a memfd and use ftruncate
* to grow it as necessary. We mmap the new size and then create a gem bo for
* it using the new gem userptr ioctl. Without heavy-handed locking around
* our allocation fast-path, there isn't really a way to munmap the old mmap,
* so we just keep it around until garbage collection time. While the block
* allocator is lockless for normal operations, we block other threads trying
* to allocate while we're growing the map. It sholdn't happen often, and
* growing is fast anyway.
*
* At the next level we can use various sub-allocators. The state pool is a
* pool of smaller, fixed size objects, which operates much like the block
* pool. It uses a free list for freeing objects, but when it runs out of
* space it just allocates a new block from the block pool. This allocator is
* intended for longer lived state objects such as SURFACE_STATE and most
* other persistent state objects in the API. We may need to track more info
* with these object and a pointer back to the CPU object (eg VkImage). In
* those cases we just allocate a slightly bigger object and put the extra
* state after the GPU state object.
*
* The state stream allocator works similar to how the i965 DRI driver streams
* all its state. Even with Vulkan, we need to emit transient state (whether
* surface state base or dynamic state base), and for that we can just get a
* block and fill it up. These cases are local to a command buffer and the
* sub-allocator need not be thread safe. The streaming allocator gets a new
* block when it runs out of space and chains them together so they can be
* easily freed.
*/
/* Allocations are always at least 64 byte aligned, so 1 is an invalid value.
* We use it to indicate the free list is empty. */
#define EMPTY 1
struct anv_mmap_cleanup {
void *map;
size_t size;
uint32_t gem_handle;
};
#define ANV_MMAP_CLEANUP_INIT ((struct anv_mmap_cleanup){0})
static inline long
sys_futex(void *addr1, int op, int val1,
struct timespec *timeout, void *addr2, int val3)
{
return syscall(SYS_futex, addr1, op, val1, timeout, addr2, val3);
}
static inline int
futex_wake(uint32_t *addr, int count)
{
return sys_futex(addr, FUTEX_WAKE, count, NULL, NULL, 0);
}
static inline int
futex_wait(uint32_t *addr, int32_t value)
{
return sys_futex(addr, FUTEX_WAIT, value, NULL, NULL, 0);
}
static inline int
memfd_create(const char *name, unsigned int flags)
{
return syscall(SYS_memfd_create, name, flags);
}
static inline uint32_t
ilog2_round_up(uint32_t value)
{
assert(value != 0);
return 32 - __builtin_clz(value - 1);
}
static inline uint32_t
round_to_power_of_two(uint32_t value)
{
return 1 << ilog2_round_up(value);
}
static bool
anv_free_list_pop(union anv_free_list *list, void **map, int32_t *offset)
{
union anv_free_list current, new, old;
current.u64 = list->u64;
while (current.offset != EMPTY) {
/* We have to add a memory barrier here so that the list head (and
* offset) gets read before we read the map pointer. This way we
* know that the map pointer is valid for the given offset at the
* point where we read it.
*/
__sync_synchronize();
int32_t *next_ptr = *map + current.offset;
new.offset = VG_NOACCESS_READ(next_ptr);
new.count = current.count + 1;
old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, new.u64);
if (old.u64 == current.u64) {
*offset = current.offset;
return true;
}
current = old;
}
return false;
}
static void
anv_free_list_push(union anv_free_list *list, void *map, int32_t offset)
{
union anv_free_list current, old, new;
int32_t *next_ptr = map + offset;
old = *list;
do {
current = old;
VG_NOACCESS_WRITE(next_ptr, current.offset);
new.offset = offset;
new.count = current.count + 1;
old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, new.u64);
} while (old.u64 != current.u64);
}
/* All pointers in the ptr_free_list are assumed to be page-aligned. This
* means that the bottom 12 bits should all be zero.
*/
#define PFL_COUNT(x) ((uintptr_t)(x) & 0xfff)
#define PFL_PTR(x) ((void *)((uintptr_t)(x) & ~0xfff))
#define PFL_PACK(ptr, count) ({ \
assert(((uintptr_t)(ptr) & 0xfff) == 0); \
(void *)((uintptr_t)(ptr) | (uintptr_t)((count) & 0xfff)); \
})
static bool
anv_ptr_free_list_pop(void **list, void **elem)
{
void *current = *list;
while (PFL_PTR(current) != NULL) {
void **next_ptr = PFL_PTR(current);
void *new_ptr = VG_NOACCESS_READ(next_ptr);
unsigned new_count = PFL_COUNT(current) + 1;
void *new = PFL_PACK(new_ptr, new_count);
void *old = __sync_val_compare_and_swap(list, current, new);
if (old == current) {
*elem = PFL_PTR(current);
return true;
}
current = old;
}
return false;
}
static void
anv_ptr_free_list_push(void **list, void *elem)
{
void *old, *current;
void **next_ptr = elem;
old = *list;
do {
current = old;
VG_NOACCESS_WRITE(next_ptr, PFL_PTR(current));
unsigned new_count = PFL_COUNT(current) + 1;
void *new = PFL_PACK(elem, new_count);
old = __sync_val_compare_and_swap(list, current, new);
} while (old != current);
}
static uint32_t
anv_block_pool_grow(struct anv_block_pool *pool, struct anv_block_state *state);
void
anv_block_pool_init(struct anv_block_pool *pool,
struct anv_device *device, uint32_t block_size)
{
assert(util_is_power_of_two(block_size));
pool->device = device;
pool->bo.gem_handle = 0;
pool->bo.offset = 0;
pool->bo.size = 0;
pool->block_size = block_size;
pool->free_list = ANV_FREE_LIST_EMPTY;
pool->back_free_list = ANV_FREE_LIST_EMPTY;
pool->fd = memfd_create("block pool", MFD_CLOEXEC);
if (pool->fd == -1)
return;
/* Just make it 2GB up-front. The Linux kernel won't actually back it
* with pages until we either map and fault on one of them or we use
* userptr and send a chunk of it off to the GPU.
*/
if (ftruncate(pool->fd, BLOCK_POOL_MEMFD_SIZE) == -1)
return;
anv_vector_init(&pool->mmap_cleanups,
round_to_power_of_two(sizeof(struct anv_mmap_cleanup)), 128);
pool->state.next = 0;
pool->state.end = 0;
pool->back_state.next = 0;
pool->back_state.end = 0;
/* Immediately grow the pool so we'll have a backing bo. */
pool->state.end = anv_block_pool_grow(pool, &pool->state);
}
void
anv_block_pool_finish(struct anv_block_pool *pool)
{
struct anv_mmap_cleanup *cleanup;
anv_vector_foreach(cleanup, &pool->mmap_cleanups) {
if (cleanup->map)
munmap(cleanup->map, cleanup->size);
if (cleanup->gem_handle)
anv_gem_close(pool->device, cleanup->gem_handle);
}
anv_vector_finish(&pool->mmap_cleanups);
close(pool->fd);
}
#define PAGE_SIZE 4096
/** Grows and re-centers the block pool.
*
* We grow the block pool in one or both directions in such a way that the
* following conditions are met:
*
* 1) The size of the entire pool is always a power of two.
*
* 2) The pool only grows on both ends. Neither end can get
* shortened.
*
* 3) At the end of the allocation, we have about twice as much space
* allocated for each end as we have used. This way the pool doesn't
* grow too far in one direction or the other.
*
* 4) If the _alloc_back() has never been called, then the back portion of
* the pool retains a size of zero. (This makes it easier for users of
* the block pool that only want a one-sided pool.)
*
* 5) We have enough space allocated for at least one more block in
* whichever side `state` points to.
*
* 6) The center of the pool is always aligned to both the block_size of
* the pool and a 4K CPU page.
*/
static uint32_t
anv_block_pool_grow(struct anv_block_pool *pool, struct anv_block_state *state)
{
size_t size;
void *map;
int gem_handle;
struct anv_mmap_cleanup *cleanup;
pthread_mutex_lock(&pool->device->mutex);
assert(state == &pool->state || state == &pool->back_state);
/* Gather a little usage information on the pool. Since we may have
* threadsd waiting in queue to get some storage while we resize, it's
* actually possible that total_used will be larger than old_size. In
* particular, block_pool_alloc() increments state->next prior to
* calling block_pool_grow, so this ensures that we get enough space for
* which ever side tries to grow the pool.
*
* We align to a page size because it makes it easier to do our
* calculations later in such a way that we state page-aigned.
*/
uint32_t back_used = align_u32(pool->back_state.next, PAGE_SIZE);
uint32_t front_used = align_u32(pool->state.next, PAGE_SIZE);
uint32_t total_used = front_used + back_used;
assert(state == &pool->state || back_used > 0);
size_t old_size = pool->bo.size;
if (old_size != 0 &&
back_used * 2 <= pool->center_bo_offset &&
front_used * 2 <= (old_size - pool->center_bo_offset)) {
/* If we're in this case then this isn't the firsta allocation and we
* already have enough space on both sides to hold double what we
* have allocated. There's nothing for us to do.
*/
goto done;
}
if (old_size == 0) {
/* This is the first allocation */
size = MAX2(32 * pool->block_size, PAGE_SIZE);
} else {
size = old_size * 2;
}
/* We can't have a block pool bigger than 1GB because we use signed
* 32-bit offsets in the free list and we don't want overflow. We
* should never need a block pool bigger than 1GB anyway.
*/
assert(size <= (1u << 31));
/* We compute a new center_bo_offset such that, when we double the size
* of the pool, we maintain the ratio of how much is used by each side.
* This way things should remain more-or-less balanced.
*/
uint32_t center_bo_offset;
if (back_used == 0) {
/* If we're in this case then we have never called alloc_back(). In
* this case, we want keep the offset at 0 to make things as simple
* as possible for users that don't care about back allocations.
*/
center_bo_offset = 0;
} else {
/* Try to "center" the allocation based on how much is currently in
* use on each side of the center line.
*/
center_bo_offset = ((uint64_t)size * back_used) / total_used;
/* Align down to a multiple of both the block size and page size */
uint32_t granularity = MAX2(pool->block_size, PAGE_SIZE);
assert(util_is_power_of_two(granularity));
center_bo_offset &= ~(granularity - 1);
assert(center_bo_offset >= back_used);
/* Make sure we don't shrink the back end of the pool */
if (center_bo_offset < pool->back_state.end)
center_bo_offset = pool->back_state.end;
/* Make sure that we don't shrink the front end of the pool */
if (size - center_bo_offset < pool->state.end)
center_bo_offset = size - pool->state.end;
}
assert(center_bo_offset % pool->block_size == 0);
assert(center_bo_offset % PAGE_SIZE == 0);
/* Assert that we only ever grow the pool */
assert(center_bo_offset >= pool->back_state.end);
assert(size - center_bo_offset >= pool->state.end);
cleanup = anv_vector_add(&pool->mmap_cleanups);
if (!cleanup)
goto fail;
*cleanup = ANV_MMAP_CLEANUP_INIT;
/* Just leak the old map until we destroy the pool. We can't munmap it
* without races or imposing locking on the block allocate fast path. On
* the whole the leaked maps adds up to less than the size of the
* current map. MAP_POPULATE seems like the right thing to do, but we
* should try to get some numbers.
*/
map = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, pool->fd,
BLOCK_POOL_MEMFD_CENTER - center_bo_offset);
cleanup->map = map;
cleanup->size = size;
if (map == MAP_FAILED)
goto fail;
gem_handle = anv_gem_userptr(pool->device, map, size);
if (gem_handle == 0)
goto fail;
cleanup->gem_handle = gem_handle;
/* Now that we successfull allocated everything, we can write the new
* values back into pool. */
pool->map = map + center_bo_offset;
pool->center_bo_offset = center_bo_offset;
pool->bo.gem_handle = gem_handle;
pool->bo.size = size;
pool->bo.map = map;
pool->bo.index = 0;
done:
pthread_mutex_unlock(&pool->device->mutex);
/* Return the appropreate new size. This function never actually
* updates state->next. Instead, we let the caller do that because it
* needs to do so in order to maintain its concurrency model.
*/
if (state == &pool->state) {
return pool->bo.size - pool->center_bo_offset;
} else {
assert(pool->center_bo_offset > 0);
return pool->center_bo_offset;
}
fail:
pthread_mutex_unlock(&pool->device->mutex);
return 0;
}
static uint32_t
anv_block_pool_alloc_new(struct anv_block_pool *pool,
struct anv_block_state *pool_state)
{
struct anv_block_state state, old, new;
while (1) {
state.u64 = __sync_fetch_and_add(&pool_state->u64, pool->block_size);
if (state.next < state.end) {
assert(pool->map);
return state.next;
} else if (state.next == state.end) {
/* We allocated the first block outside the pool, we have to grow it.
* pool_state->next acts a mutex: threads who try to allocate now will
* get block indexes above the current limit and hit futex_wait
* below. */
new.next = state.next + pool->block_size;
new.end = anv_block_pool_grow(pool, pool_state);
assert(new.end >= new.next && new.end % pool->block_size == 0);
old.u64 = __sync_lock_test_and_set(&pool_state->u64, new.u64);
if (old.next != state.next)
futex_wake(&pool_state->end, INT_MAX);
return state.next;
} else {
futex_wait(&pool_state->end, state.end);
continue;
}
}
}
int32_t
anv_block_pool_alloc(struct anv_block_pool *pool)
{
int32_t offset;
/* Try free list first. */
if (anv_free_list_pop(&pool->free_list, &pool->map, &offset)) {
assert(offset >= 0);
assert(pool->map);
return offset;
}
return anv_block_pool_alloc_new(pool, &pool->state);
}
/* Allocates a block out of the back of the block pool.
*
* This will allocated a block earlier than the "start" of the block pool.
* The offsets returned from this function will be negative but will still
* be correct relative to the block pool's map pointer.
*
* If you ever use anv_block_pool_alloc_back, then you will have to do
* gymnastics with the block pool's BO when doing relocations.
*/
int32_t
anv_block_pool_alloc_back(struct anv_block_pool *pool)
{
int32_t offset;
/* Try free list first. */
if (anv_free_list_pop(&pool->back_free_list, &pool->map, &offset)) {
assert(offset < 0);
assert(pool->map);
return offset;
}
offset = anv_block_pool_alloc_new(pool, &pool->back_state);
/* The offset we get out of anv_block_pool_alloc_new() is actually the
* number of bytes downwards from the middle to the end of the block.
* We need to turn it into a (negative) offset from the middle to the
* start of the block.
*/
assert(offset >= 0);
return -(offset + pool->block_size);
}
void
anv_block_pool_free(struct anv_block_pool *pool, int32_t offset)
{
if (offset < 0) {
anv_free_list_push(&pool->back_free_list, pool->map, offset);
} else {
anv_free_list_push(&pool->free_list, pool->map, offset);
}
}
static void
anv_fixed_size_state_pool_init(struct anv_fixed_size_state_pool *pool,
size_t state_size)
{
/* At least a cache line and must divide the block size. */
assert(state_size >= 64 && util_is_power_of_two(state_size));
pool->state_size = state_size;
pool->free_list = ANV_FREE_LIST_EMPTY;
pool->block.next = 0;
pool->block.end = 0;
}
static uint32_t
anv_fixed_size_state_pool_alloc(struct anv_fixed_size_state_pool *pool,
struct anv_block_pool *block_pool)
{
int32_t offset;
struct anv_block_state block, old, new;
/* Try free list first. */
if (anv_free_list_pop(&pool->free_list, &block_pool->map, &offset)) {
assert(offset >= 0);
return offset;
}
/* If free list was empty (or somebody raced us and took the items) we
* allocate a new item from the end of the block */
restart:
block.u64 = __sync_fetch_and_add(&pool->block.u64, pool->state_size);
if (block.next < block.end) {
return block.next;
} else if (block.next == block.end) {
offset = anv_block_pool_alloc(block_pool);
new.next = offset + pool->state_size;
new.end = offset + block_pool->block_size;
old.u64 = __sync_lock_test_and_set(&pool->block.u64, new.u64);
if (old.next != block.next)
futex_wake(&pool->block.end, INT_MAX);
return offset;
} else {
futex_wait(&pool->block.end, block.end);
goto restart;
}
}
static void
anv_fixed_size_state_pool_free(struct anv_fixed_size_state_pool *pool,
struct anv_block_pool *block_pool,
uint32_t offset)
{
anv_free_list_push(&pool->free_list, block_pool->map, offset);
}
void
anv_state_pool_init(struct anv_state_pool *pool,
struct anv_block_pool *block_pool)
{
pool->block_pool = block_pool;
for (unsigned i = 0; i < ANV_STATE_BUCKETS; i++) {
size_t size = 1 << (ANV_MIN_STATE_SIZE_LOG2 + i);
anv_fixed_size_state_pool_init(&pool->buckets[i], size);
}
VG(VALGRIND_CREATE_MEMPOOL(pool, 0, false));
}
void
anv_state_pool_finish(struct anv_state_pool *pool)
{
VG(VALGRIND_DESTROY_MEMPOOL(pool));
}
struct anv_state
anv_state_pool_alloc(struct anv_state_pool *pool, size_t size, size_t align)
{
unsigned size_log2 = ilog2_round_up(size < align ? align : size);
assert(size_log2 <= ANV_MAX_STATE_SIZE_LOG2);
if (size_log2 < ANV_MIN_STATE_SIZE_LOG2)
size_log2 = ANV_MIN_STATE_SIZE_LOG2;
unsigned bucket = size_log2 - ANV_MIN_STATE_SIZE_LOG2;
struct anv_state state;
state.alloc_size = 1 << size_log2;
state.offset = anv_fixed_size_state_pool_alloc(&pool->buckets[bucket],
pool->block_pool);
state.map = pool->block_pool->map + state.offset;
VG(VALGRIND_MEMPOOL_ALLOC(pool, state.map, size));
return state;
}
void
anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state)
{
assert(util_is_power_of_two(state.alloc_size));
unsigned size_log2 = ilog2_round_up(state.alloc_size);
assert(size_log2 >= ANV_MIN_STATE_SIZE_LOG2 &&
size_log2 <= ANV_MAX_STATE_SIZE_LOG2);
unsigned bucket = size_log2 - ANV_MIN_STATE_SIZE_LOG2;
VG(VALGRIND_MEMPOOL_FREE(pool, state.map));
anv_fixed_size_state_pool_free(&pool->buckets[bucket],
pool->block_pool, state.offset);
}
#define NULL_BLOCK 1
struct stream_block {
uint32_t next;
/* The map for the BO at the time the block was givne to us */
void *current_map;
#ifdef HAVE_VALGRIND
void *_vg_ptr;
#endif
};
/* The state stream allocator is a one-shot, single threaded allocator for
* variable sized blocks. We use it for allocating dynamic state.
*/
void
anv_state_stream_init(struct anv_state_stream *stream,
struct anv_block_pool *block_pool)
{
stream->block_pool = block_pool;
stream->next = 0;
stream->end = 0;
stream->current_block = NULL_BLOCK;
VG(VALGRIND_CREATE_MEMPOOL(stream, 0, false));
}
void
anv_state_stream_finish(struct anv_state_stream *stream)
{
struct stream_block *sb;
uint32_t block, next_block;
block = stream->current_block;
while (block != NULL_BLOCK) {
sb = stream->block_pool->map + block;
next_block = VG_NOACCESS_READ(&sb->next);
VG(VALGRIND_MEMPOOL_FREE(stream, VG_NOACCESS_READ(&sb->_vg_ptr)));
anv_block_pool_free(stream->block_pool, block);
block = next_block;
}
VG(VALGRIND_DESTROY_MEMPOOL(stream));
}
struct anv_state
anv_state_stream_alloc(struct anv_state_stream *stream,
uint32_t size, uint32_t alignment)
{
struct stream_block *sb;
struct anv_state state;
uint32_t block;
state.offset = align_u32(stream->next, alignment);
if (state.offset + size > stream->end) {
block = anv_block_pool_alloc(stream->block_pool);
void *current_map = stream->block_pool->map;
sb = current_map + block;
VG_NOACCESS_WRITE(&sb->current_map, current_map);
VG_NOACCESS_WRITE(&sb->next, stream->current_block);
VG(VG_NOACCESS_WRITE(&sb->_vg_ptr, 0));
stream->current_block = block;
stream->next = block + sizeof(*sb);
stream->end = block + stream->block_pool->block_size;
state.offset = align_u32(stream->next, alignment);
assert(state.offset + size <= stream->end);
}
sb = stream->block_pool->map + stream->current_block;
void *current_map = VG_NOACCESS_READ(&sb->current_map);
state.map = current_map + state.offset;
state.alloc_size = size;
#ifdef HAVE_VALGRIND
void *vg_ptr = VG_NOACCESS_READ(&sb->_vg_ptr);
if (vg_ptr == NULL) {
vg_ptr = state.map;
VG_NOACCESS_WRITE(&sb->_vg_ptr, vg_ptr);
VALGRIND_MEMPOOL_ALLOC(stream, vg_ptr, size);
} else {
ptrdiff_t vg_offset = vg_ptr - current_map;
assert(vg_offset >= stream->current_block &&
vg_offset < stream->end);
VALGRIND_MEMPOOL_CHANGE(stream, vg_ptr, vg_ptr,
(state.offset + size) - vg_offset);
}
#endif
stream->next = state.offset + size;
return state;
}
struct bo_pool_bo_link {
struct bo_pool_bo_link *next;
struct anv_bo bo;
};
void
anv_bo_pool_init(struct anv_bo_pool *pool,
struct anv_device *device, uint32_t bo_size)
{
pool->device = device;
pool->bo_size = bo_size;
pool->free_list = NULL;
VG(VALGRIND_CREATE_MEMPOOL(pool, 0, false));
}
void
anv_bo_pool_finish(struct anv_bo_pool *pool)
{
struct bo_pool_bo_link *link = PFL_PTR(pool->free_list);
while (link != NULL) {
struct bo_pool_bo_link link_copy = VG_NOACCESS_READ(link);
anv_gem_munmap(link_copy.bo.map, pool->bo_size);
anv_gem_close(pool->device, link_copy.bo.gem_handle);
link = link_copy.next;
}
VG(VALGRIND_DESTROY_MEMPOOL(pool));
}
VkResult
anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo)
{
VkResult result;
void *next_free_void;
if (anv_ptr_free_list_pop(&pool->free_list, &next_free_void)) {
struct bo_pool_bo_link *next_free = next_free_void;
*bo = VG_NOACCESS_READ(&next_free->bo);
assert(bo->map == next_free);
assert(bo->size == pool->bo_size);
VG(VALGRIND_MEMPOOL_ALLOC(pool, bo->map, pool->bo_size));
return VK_SUCCESS;
}
struct anv_bo new_bo;
result = anv_bo_init_new(&new_bo, pool->device, pool->bo_size);
if (result != VK_SUCCESS)
return result;
assert(new_bo.size == pool->bo_size);
new_bo.map = anv_gem_mmap(pool->device, new_bo.gem_handle, 0, pool->bo_size);
if (new_bo.map == NULL) {
anv_gem_close(pool->device, new_bo.gem_handle);
return vk_error(VK_ERROR_MEMORY_MAP_FAILED);
}
*bo = new_bo;
VG(VALGRIND_MEMPOOL_ALLOC(pool, bo->map, pool->bo_size));
return VK_SUCCESS;
}
void
anv_bo_pool_free(struct anv_bo_pool *pool, const struct anv_bo *bo)
{
struct bo_pool_bo_link *link = bo->map;
link->bo = *bo;
VG(VALGRIND_MEMPOOL_FREE(pool, bo->map));
anv_ptr_free_list_push(&pool->free_list, link);
}

153
src/vulkan/anv_aub.h Normal file
View File

@@ -0,0 +1,153 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*
*/
/** @file intel_aub.h
*
* The AUB file is a file format used by Intel's internal simulation
* and other validation tools. It can be used at various levels by a
* driver to input state to the simulated hardware or a replaying
* debugger.
*
* We choose to dump AUB files using the trace block format for ease
* of implementation -- dump out the blocks of memory as plain blobs
* and insert ring commands to execute the batchbuffer blob.
*/
#ifndef _INTEL_AUB_H
#define _INTEL_AUB_H
#define AUB_MI_NOOP (0)
#define AUB_MI_BATCH_BUFFER_START (0x31 << 23)
#define AUB_PIPE_CONTROL (0x7a000002)
/* DW0: instruction type. */
#define CMD_AUB (7 << 29)
#define CMD_AUB_HEADER (CMD_AUB | (1 << 23) | (0x05 << 16))
/* DW1 */
# define AUB_HEADER_MAJOR_SHIFT 24
# define AUB_HEADER_MINOR_SHIFT 16
#define CMD_AUB_TRACE_HEADER_BLOCK (CMD_AUB | (1 << 23) | (0x41 << 16))
#define CMD_AUB_DUMP_BMP (CMD_AUB | (1 << 23) | (0x9e << 16))
/* DW1 */
#define AUB_TRACE_OPERATION_MASK 0x000000ff
#define AUB_TRACE_OP_COMMENT 0x00000000
#define AUB_TRACE_OP_DATA_WRITE 0x00000001
#define AUB_TRACE_OP_COMMAND_WRITE 0x00000002
#define AUB_TRACE_OP_MMIO_WRITE 0x00000003
// operation = TRACE_DATA_WRITE, Type
#define AUB_TRACE_TYPE_MASK 0x0000ff00
#define AUB_TRACE_TYPE_NOTYPE (0 << 8)
#define AUB_TRACE_TYPE_BATCH (1 << 8)
#define AUB_TRACE_TYPE_VERTEX_BUFFER (5 << 8)
#define AUB_TRACE_TYPE_2D_MAP (6 << 8)
#define AUB_TRACE_TYPE_CUBE_MAP (7 << 8)
#define AUB_TRACE_TYPE_VOLUME_MAP (9 << 8)
#define AUB_TRACE_TYPE_1D_MAP (10 << 8)
#define AUB_TRACE_TYPE_CONSTANT_BUFFER (11 << 8)
#define AUB_TRACE_TYPE_CONSTANT_URB (12 << 8)
#define AUB_TRACE_TYPE_INDEX_BUFFER (13 << 8)
#define AUB_TRACE_TYPE_GENERAL (14 << 8)
#define AUB_TRACE_TYPE_SURFACE (15 << 8)
// operation = TRACE_COMMAND_WRITE, Type =
#define AUB_TRACE_TYPE_RING_HWB (1 << 8)
#define AUB_TRACE_TYPE_RING_PRB0 (2 << 8)
#define AUB_TRACE_TYPE_RING_PRB1 (3 << 8)
#define AUB_TRACE_TYPE_RING_PRB2 (4 << 8)
// Address space
#define AUB_TRACE_ADDRESS_SPACE_MASK 0x00ff0000
#define AUB_TRACE_MEMTYPE_GTT (0 << 16)
#define AUB_TRACE_MEMTYPE_LOCAL (1 << 16)
#define AUB_TRACE_MEMTYPE_NONLOCAL (2 << 16)
#define AUB_TRACE_MEMTYPE_PCI (3 << 16)
#define AUB_TRACE_MEMTYPE_GTT_ENTRY (4 << 16)
/* DW2 */
/**
* aub_state_struct_type enum values are encoded with the top 16 bits
* representing the type to be delivered to the .aub file, and the bottom 16
* bits representing the subtype. This macro performs the encoding.
*/
#define ENCODE_SS_TYPE(type, subtype) (((type) << 16) | (subtype))
enum aub_state_struct_type {
AUB_TRACE_VS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 1),
AUB_TRACE_GS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 2),
AUB_TRACE_CLIP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 3),
AUB_TRACE_SF_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 4),
AUB_TRACE_WM_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 5),
AUB_TRACE_CC_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 6),
AUB_TRACE_CLIP_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 7),
AUB_TRACE_SF_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 8),
AUB_TRACE_CC_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x9),
AUB_TRACE_SAMPLER_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xa),
AUB_TRACE_KERNEL_INSTRUCTIONS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xb),
AUB_TRACE_SCRATCH_SPACE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xc),
AUB_TRACE_SAMPLER_DEFAULT_COLOR = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xd),
AUB_TRACE_SCISSOR_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x15),
AUB_TRACE_BLEND_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x16),
AUB_TRACE_DEPTH_STENCIL_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x17),
AUB_TRACE_VERTEX_BUFFER = ENCODE_SS_TYPE(AUB_TRACE_TYPE_VERTEX_BUFFER, 0),
AUB_TRACE_BINDING_TABLE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x100),
AUB_TRACE_SURFACE_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x200),
AUB_TRACE_VS_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 0),
AUB_TRACE_WM_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 1),
};
#undef ENCODE_SS_TYPE
/**
* Decode a aub_state_struct_type value to determine the type that should be
* stored in the .aub file.
*/
static inline uint32_t AUB_TRACE_TYPE(enum aub_state_struct_type ss_type)
{
return (ss_type & 0xFFFF0000) >> 16;
}
/**
* Decode a state_struct_type value to determine the subtype that should be
* stored in the .aub file.
*/
static inline uint32_t AUB_TRACE_SUBTYPE(enum aub_state_struct_type ss_type)
{
return ss_type & 0xFFFF;
}
/* DW3: address */
/* DW4: len */
#endif /* _INTEL_AUB_H */

View File

@@ -0,0 +1,940 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
/** \file anv_batch_chain.c
*
* This file contains functions related to anv_cmd_buffer as a data
* structure. This involves everything required to create and destroy
* the actual batch buffers as well as link them together and handle
* relocations and surface state. It specifically does *not* contain any
* handling of actual vkCmd calls beyond vkCmdExecuteCommands.
*/
/*-----------------------------------------------------------------------*
* Functions related to anv_reloc_list
*-----------------------------------------------------------------------*/
static VkResult
anv_reloc_list_init_clone(struct anv_reloc_list *list,
struct anv_device *device,
const struct anv_reloc_list *other_list)
{
if (other_list) {
list->num_relocs = other_list->num_relocs;
list->array_length = other_list->array_length;
} else {
list->num_relocs = 0;
list->array_length = 256;
}
list->relocs =
anv_device_alloc(device, list->array_length * sizeof(*list->relocs), 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (list->relocs == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
list->reloc_bos =
anv_device_alloc(device, list->array_length * sizeof(*list->reloc_bos), 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (list->reloc_bos == NULL) {
anv_device_free(device, list->relocs);
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
if (other_list) {
memcpy(list->relocs, other_list->relocs,
list->array_length * sizeof(*list->relocs));
memcpy(list->reloc_bos, other_list->reloc_bos,
list->array_length * sizeof(*list->reloc_bos));
}
return VK_SUCCESS;
}
VkResult
anv_reloc_list_init(struct anv_reloc_list *list, struct anv_device *device)
{
return anv_reloc_list_init_clone(list, device, NULL);
}
void
anv_reloc_list_finish(struct anv_reloc_list *list, struct anv_device *device)
{
anv_device_free(device, list->relocs);
anv_device_free(device, list->reloc_bos);
}
static VkResult
anv_reloc_list_grow(struct anv_reloc_list *list, struct anv_device *device,
size_t num_additional_relocs)
{
if (list->num_relocs + num_additional_relocs <= list->array_length)
return VK_SUCCESS;
size_t new_length = list->array_length * 2;
while (new_length < list->num_relocs + num_additional_relocs)
new_length *= 2;
struct drm_i915_gem_relocation_entry *new_relocs =
anv_device_alloc(device, new_length * sizeof(*list->relocs), 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (new_relocs == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
struct anv_bo **new_reloc_bos =
anv_device_alloc(device, new_length * sizeof(*list->reloc_bos), 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (new_relocs == NULL) {
anv_device_free(device, new_relocs);
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
memcpy(new_relocs, list->relocs, list->num_relocs * sizeof(*list->relocs));
memcpy(new_reloc_bos, list->reloc_bos,
list->num_relocs * sizeof(*list->reloc_bos));
anv_device_free(device, list->relocs);
anv_device_free(device, list->reloc_bos);
list->array_length = new_length;
list->relocs = new_relocs;
list->reloc_bos = new_reloc_bos;
return VK_SUCCESS;
}
uint64_t
anv_reloc_list_add(struct anv_reloc_list *list, struct anv_device *device,
uint32_t offset, struct anv_bo *target_bo, uint32_t delta)
{
struct drm_i915_gem_relocation_entry *entry;
int index;
anv_reloc_list_grow(list, device, 1);
/* TODO: Handle failure */
/* XXX: Can we use I915_EXEC_HANDLE_LUT? */
index = list->num_relocs++;
list->reloc_bos[index] = target_bo;
entry = &list->relocs[index];
entry->target_handle = target_bo->gem_handle;
entry->delta = delta;
entry->offset = offset;
entry->presumed_offset = target_bo->offset;
entry->read_domains = 0;
entry->write_domain = 0;
return target_bo->offset + delta;
}
static void
anv_reloc_list_append(struct anv_reloc_list *list, struct anv_device *device,
struct anv_reloc_list *other, uint32_t offset)
{
anv_reloc_list_grow(list, device, other->num_relocs);
/* TODO: Handle failure */
memcpy(&list->relocs[list->num_relocs], &other->relocs[0],
other->num_relocs * sizeof(other->relocs[0]));
memcpy(&list->reloc_bos[list->num_relocs], &other->reloc_bos[0],
other->num_relocs * sizeof(other->reloc_bos[0]));
for (uint32_t i = 0; i < other->num_relocs; i++)
list->relocs[i + list->num_relocs].offset += offset;
list->num_relocs += other->num_relocs;
}
/*-----------------------------------------------------------------------*
* Functions related to anv_batch
*-----------------------------------------------------------------------*/
void *
anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords)
{
if (batch->next + num_dwords * 4 > batch->end)
batch->extend_cb(batch, batch->user_data);
void *p = batch->next;
batch->next += num_dwords * 4;
assert(batch->next <= batch->end);
return p;
}
uint64_t
anv_batch_emit_reloc(struct anv_batch *batch,
void *location, struct anv_bo *bo, uint32_t delta)
{
return anv_reloc_list_add(batch->relocs, batch->device,
location - batch->start, bo, delta);
}
void
anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other)
{
uint32_t size, offset;
size = other->next - other->start;
assert(size % 4 == 0);
if (batch->next + size > batch->end)
batch->extend_cb(batch, batch->user_data);
assert(batch->next + size <= batch->end);
VG(VALGRIND_CHECK_MEM_IS_DEFINED(other->start, size));
memcpy(batch->next, other->start, size);
offset = batch->next - batch->start;
anv_reloc_list_append(batch->relocs, batch->device,
other->relocs, offset);
batch->next += size;
}
/*-----------------------------------------------------------------------*
* Functions related to anv_batch_bo
*-----------------------------------------------------------------------*/
static VkResult
anv_batch_bo_create(struct anv_device *device, struct anv_batch_bo **bbo_out)
{
VkResult result;
struct anv_batch_bo *bbo =
anv_device_alloc(device, sizeof(*bbo), 8, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (bbo == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
result = anv_bo_pool_alloc(&device->batch_bo_pool, &bbo->bo);
if (result != VK_SUCCESS)
goto fail_alloc;
result = anv_reloc_list_init(&bbo->relocs, device);
if (result != VK_SUCCESS)
goto fail_bo_alloc;
*bbo_out = bbo;
return VK_SUCCESS;
fail_bo_alloc:
anv_bo_pool_free(&device->batch_bo_pool, &bbo->bo);
fail_alloc:
anv_device_free(device, bbo);
return result;
}
static VkResult
anv_batch_bo_clone(struct anv_device *device,
const struct anv_batch_bo *other_bbo,
struct anv_batch_bo **bbo_out)
{
VkResult result;
struct anv_batch_bo *bbo =
anv_device_alloc(device, sizeof(*bbo), 8, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (bbo == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
result = anv_bo_pool_alloc(&device->batch_bo_pool, &bbo->bo);
if (result != VK_SUCCESS)
goto fail_alloc;
result = anv_reloc_list_init_clone(&bbo->relocs, device, &other_bbo->relocs);
if (result != VK_SUCCESS)
goto fail_bo_alloc;
bbo->length = other_bbo->length;
memcpy(bbo->bo.map, other_bbo->bo.map, other_bbo->length);
*bbo_out = bbo;
return VK_SUCCESS;
fail_bo_alloc:
anv_bo_pool_free(&device->batch_bo_pool, &bbo->bo);
fail_alloc:
anv_device_free(device, bbo);
return result;
}
static void
anv_batch_bo_start(struct anv_batch_bo *bbo, struct anv_batch *batch,
size_t batch_padding)
{
batch->next = batch->start = bbo->bo.map;
batch->end = bbo->bo.map + bbo->bo.size - batch_padding;
batch->relocs = &bbo->relocs;
bbo->relocs.num_relocs = 0;
}
static void
anv_batch_bo_continue(struct anv_batch_bo *bbo, struct anv_batch *batch,
size_t batch_padding)
{
batch->start = bbo->bo.map;
batch->next = bbo->bo.map + bbo->length;
batch->end = bbo->bo.map + bbo->bo.size - batch_padding;
batch->relocs = &bbo->relocs;
}
static void
anv_batch_bo_finish(struct anv_batch_bo *bbo, struct anv_batch *batch)
{
assert(batch->start == bbo->bo.map);
bbo->length = batch->next - batch->start;
VG(VALGRIND_CHECK_MEM_IS_DEFINED(batch->start, bbo->length));
}
static void
anv_batch_bo_destroy(struct anv_batch_bo *bbo, struct anv_device *device)
{
anv_reloc_list_finish(&bbo->relocs, device);
anv_bo_pool_free(&device->batch_bo_pool, &bbo->bo);
anv_device_free(device, bbo);
}
static VkResult
anv_batch_bo_list_clone(const struct list_head *list, struct anv_device *device,
struct list_head *new_list)
{
VkResult result = VK_SUCCESS;
list_inithead(new_list);
struct anv_batch_bo *prev_bbo = NULL;
list_for_each_entry(struct anv_batch_bo, bbo, list, link) {
struct anv_batch_bo *new_bbo;
result = anv_batch_bo_clone(device, bbo, &new_bbo);
if (result != VK_SUCCESS)
break;
list_addtail(&new_bbo->link, new_list);
if (prev_bbo) {
/* As we clone this list of batch_bo's, they chain one to the
* other using MI_BATCH_BUFFER_START commands. We need to fix up
* those relocations as we go. Fortunately, this is pretty easy
* as it will always be the last relocation in the list.
*/
uint32_t last_idx = prev_bbo->relocs.num_relocs - 1;
assert(prev_bbo->relocs.reloc_bos[last_idx] == &bbo->bo);
prev_bbo->relocs.reloc_bos[last_idx] = &new_bbo->bo;
}
prev_bbo = new_bbo;
}
if (result != VK_SUCCESS) {
list_for_each_entry_safe(struct anv_batch_bo, bbo, new_list, link)
anv_batch_bo_destroy(bbo, device);
}
return result;
}
/*-----------------------------------------------------------------------*
* Functions related to anv_batch_bo
*-----------------------------------------------------------------------*/
static inline struct anv_batch_bo *
anv_cmd_buffer_current_batch_bo(struct anv_cmd_buffer *cmd_buffer)
{
return LIST_ENTRY(struct anv_batch_bo, cmd_buffer->batch_bos.prev, link);
}
static inline struct anv_batch_bo *
anv_cmd_buffer_current_surface_bbo(struct anv_cmd_buffer *cmd_buffer)
{
return LIST_ENTRY(struct anv_batch_bo, cmd_buffer->surface_bos.prev, link);
}
struct anv_reloc_list *
anv_cmd_buffer_current_surface_relocs(struct anv_cmd_buffer *cmd_buffer)
{
return &anv_cmd_buffer_current_surface_bbo(cmd_buffer)->relocs;
}
struct anv_address
anv_cmd_buffer_surface_base_address(struct anv_cmd_buffer *cmd_buffer)
{
return (struct anv_address) {
.bo = &anv_cmd_buffer_current_surface_bbo(cmd_buffer)->bo,
.offset = 0,
};
}
static void
emit_batch_buffer_start(struct anv_batch *batch, struct anv_bo *bo, uint32_t offset)
{
/* In gen8+ the address field grew to two dwords to accomodate 48 bit
* offsets. The high 16 bits are in the last dword, so we can use the gen8
* version in either case, as long as we set the instruction length in the
* header accordingly. This means that we always emit three dwords here
* and all the padding and adjustment we do in this file works for all
* gens.
*/
const uint32_t gen7_length =
GEN7_MI_BATCH_BUFFER_START_length - GEN7_MI_BATCH_BUFFER_START_length_bias;
const uint32_t gen8_length =
GEN8_MI_BATCH_BUFFER_START_length - GEN8_MI_BATCH_BUFFER_START_length_bias;
anv_batch_emit(batch, GEN8_MI_BATCH_BUFFER_START,
.DwordLength = batch->device->info.gen < 8 ? gen7_length : gen8_length,
._2ndLevelBatchBuffer = _1stlevelbatch,
.AddressSpaceIndicator = ASI_PPGTT,
.BatchBufferStartAddress = { bo, offset });
}
static void
cmd_buffer_chain_to_batch_bo(struct anv_cmd_buffer *cmd_buffer,
struct anv_batch_bo *bbo)
{
struct anv_batch *batch = &cmd_buffer->batch;
struct anv_batch_bo *current_bbo =
anv_cmd_buffer_current_batch_bo(cmd_buffer);
/* We set the end of the batch a little short so we would be sure we
* have room for the chaining command. Since we're about to emit the
* chaining command, let's set it back where it should go.
*/
batch->end += GEN8_MI_BATCH_BUFFER_START_length * 4;
assert(batch->end == current_bbo->bo.map + current_bbo->bo.size);
emit_batch_buffer_start(batch, &bbo->bo, 0);
anv_batch_bo_finish(current_bbo, batch);
}
static VkResult
anv_cmd_buffer_chain_batch(struct anv_batch *batch, void *_data)
{
struct anv_cmd_buffer *cmd_buffer = _data;
struct anv_batch_bo *new_bbo;
VkResult result = anv_batch_bo_create(cmd_buffer->device, &new_bbo);
if (result != VK_SUCCESS)
return result;
struct anv_batch_bo **seen_bbo = anv_vector_add(&cmd_buffer->seen_bbos);
if (seen_bbo == NULL) {
anv_batch_bo_destroy(new_bbo, cmd_buffer->device);
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
*seen_bbo = new_bbo;
cmd_buffer_chain_to_batch_bo(cmd_buffer, new_bbo);
list_addtail(&new_bbo->link, &cmd_buffer->batch_bos);
anv_batch_bo_start(new_bbo, batch, GEN8_MI_BATCH_BUFFER_START_length * 4);
return VK_SUCCESS;
}
struct anv_state
anv_cmd_buffer_alloc_surface_state(struct anv_cmd_buffer *cmd_buffer,
uint32_t size, uint32_t alignment)
{
struct anv_bo *surface_bo =
&anv_cmd_buffer_current_surface_bbo(cmd_buffer)->bo;
struct anv_state state;
state.offset = align_u32(cmd_buffer->surface_next, alignment);
if (state.offset + size > surface_bo->size)
return (struct anv_state) { 0 };
state.map = surface_bo->map + state.offset;
state.alloc_size = size;
cmd_buffer->surface_next = state.offset + size;
assert(state.offset + size <= surface_bo->size);
return state;
}
struct anv_state
anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer,
uint32_t size, uint32_t alignment)
{
return anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream,
size, alignment);
}
VkResult
anv_cmd_buffer_new_surface_state_bo(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_batch_bo *new_bbo, *old_bbo =
anv_cmd_buffer_current_surface_bbo(cmd_buffer);
/* Finish off the old buffer */
old_bbo->length = cmd_buffer->surface_next;
VkResult result = anv_batch_bo_create(cmd_buffer->device, &new_bbo);
if (result != VK_SUCCESS)
return result;
struct anv_batch_bo **seen_bbo = anv_vector_add(&cmd_buffer->seen_bbos);
if (seen_bbo == NULL) {
anv_batch_bo_destroy(new_bbo, cmd_buffer->device);
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
*seen_bbo = new_bbo;
cmd_buffer->surface_next = 1;
list_addtail(&new_bbo->link, &cmd_buffer->surface_bos);
return VK_SUCCESS;
}
VkResult
anv_cmd_buffer_init_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_batch_bo *batch_bo, *surface_bbo;
struct anv_device *device = cmd_buffer->device;
VkResult result;
list_inithead(&cmd_buffer->batch_bos);
list_inithead(&cmd_buffer->surface_bos);
result = anv_batch_bo_create(device, &batch_bo);
if (result != VK_SUCCESS)
return result;
list_addtail(&batch_bo->link, &cmd_buffer->batch_bos);
cmd_buffer->batch.device = device;
cmd_buffer->batch.extend_cb = anv_cmd_buffer_chain_batch;
cmd_buffer->batch.user_data = cmd_buffer;
anv_batch_bo_start(batch_bo, &cmd_buffer->batch,
GEN8_MI_BATCH_BUFFER_START_length * 4);
result = anv_batch_bo_create(device, &surface_bbo);
if (result != VK_SUCCESS)
goto fail_batch_bo;
list_addtail(&surface_bbo->link, &cmd_buffer->surface_bos);
int success = anv_vector_init(&cmd_buffer->seen_bbos,
sizeof(struct anv_bo *),
8 * sizeof(struct anv_bo *));
if (!success)
goto fail_surface_bo;
*(struct anv_batch_bo **)anv_vector_add(&cmd_buffer->seen_bbos) = batch_bo;
*(struct anv_batch_bo **)anv_vector_add(&cmd_buffer->seen_bbos) = surface_bbo;
/* Start surface_next at 1 so surface offset 0 is invalid. */
cmd_buffer->surface_next = 1;
cmd_buffer->execbuf2.objects = NULL;
cmd_buffer->execbuf2.bos = NULL;
cmd_buffer->execbuf2.array_length = 0;
return VK_SUCCESS;
fail_surface_bo:
anv_batch_bo_destroy(surface_bbo, device);
fail_batch_bo:
anv_batch_bo_destroy(batch_bo, device);
return result;
}
void
anv_cmd_buffer_fini_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_device *device = cmd_buffer->device;
anv_vector_finish(&cmd_buffer->seen_bbos);
/* Destroy all of the batch buffers */
list_for_each_entry_safe(struct anv_batch_bo, bbo,
&cmd_buffer->batch_bos, link) {
anv_batch_bo_destroy(bbo, device);
}
/* Destroy all of the surface state buffers */
list_for_each_entry_safe(struct anv_batch_bo, bbo,
&cmd_buffer->surface_bos, link) {
anv_batch_bo_destroy(bbo, device);
}
anv_device_free(device, cmd_buffer->execbuf2.objects);
anv_device_free(device, cmd_buffer->execbuf2.bos);
}
void
anv_cmd_buffer_reset_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_device *device = cmd_buffer->device;
/* Delete all but the first batch bo */
assert(!list_empty(&cmd_buffer->batch_bos));
while (cmd_buffer->batch_bos.next != cmd_buffer->batch_bos.prev) {
struct anv_batch_bo *bbo = anv_cmd_buffer_current_batch_bo(cmd_buffer);
list_del(&bbo->link);
anv_batch_bo_destroy(bbo, device);
}
assert(!list_empty(&cmd_buffer->batch_bos));
anv_batch_bo_start(anv_cmd_buffer_current_batch_bo(cmd_buffer),
&cmd_buffer->batch,
GEN8_MI_BATCH_BUFFER_START_length * 4);
/* Delete all but the first batch bo */
assert(!list_empty(&cmd_buffer->batch_bos));
while (cmd_buffer->surface_bos.next != cmd_buffer->surface_bos.prev) {
struct anv_batch_bo *bbo = anv_cmd_buffer_current_surface_bbo(cmd_buffer);
list_del(&bbo->link);
anv_batch_bo_destroy(bbo, device);
}
assert(!list_empty(&cmd_buffer->batch_bos));
anv_cmd_buffer_current_surface_bbo(cmd_buffer)->relocs.num_relocs = 0;
cmd_buffer->surface_next = 1;
/* Reset the list of seen buffers */
cmd_buffer->seen_bbos.head = 0;
cmd_buffer->seen_bbos.tail = 0;
*(struct anv_batch_bo **)anv_vector_add(&cmd_buffer->seen_bbos) =
anv_cmd_buffer_current_batch_bo(cmd_buffer);
*(struct anv_batch_bo **)anv_vector_add(&cmd_buffer->seen_bbos) =
anv_cmd_buffer_current_surface_bbo(cmd_buffer);
}
void
anv_cmd_buffer_end_batch_buffer(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_batch_bo *batch_bo = anv_cmd_buffer_current_batch_bo(cmd_buffer);
struct anv_batch_bo *surface_bbo =
anv_cmd_buffer_current_surface_bbo(cmd_buffer);
if (cmd_buffer->level == VK_CMD_BUFFER_LEVEL_PRIMARY) {
anv_batch_emit(&cmd_buffer->batch, GEN7_MI_BATCH_BUFFER_END);
/* Round batch up to an even number of dwords. */
if ((cmd_buffer->batch.next - cmd_buffer->batch.start) & 4)
anv_batch_emit(&cmd_buffer->batch, GEN7_MI_NOOP);
cmd_buffer->exec_mode = ANV_CMD_BUFFER_EXEC_MODE_PRIMARY;
}
anv_batch_bo_finish(batch_bo, &cmd_buffer->batch);
surface_bbo->length = cmd_buffer->surface_next;
if (cmd_buffer->level == VK_CMD_BUFFER_LEVEL_SECONDARY) {
/* If this is a secondary command buffer, we need to determine the
* mode in which it will be executed with vkExecuteCommands. We
* determine this statically here so that this stays in sync with the
* actual ExecuteCommands implementation.
*/
if ((cmd_buffer->batch_bos.next == cmd_buffer->batch_bos.prev) &&
(anv_cmd_buffer_current_batch_bo(cmd_buffer)->length <
ANV_CMD_BUFFER_BATCH_SIZE / 2)) {
/* If the secondary has exactly one batch buffer in its list *and*
* that batch buffer is less than half of the maximum size, we're
* probably better of simply copying it into our batch.
*/
cmd_buffer->exec_mode = ANV_CMD_BUFFER_EXEC_MODE_EMIT;
} else if (cmd_buffer->opt_flags &
VK_CMD_BUFFER_OPTIMIZE_NO_SIMULTANEOUS_USE_BIT) {
cmd_buffer->exec_mode = ANV_CMD_BUFFER_EXEC_MODE_CHAIN;
/* When we chain, we need to add an MI_BATCH_BUFFER_START command
* with its relocation. In order to handle this we'll increment here
* so we can unconditionally decrement right before adding the
* MI_BATCH_BUFFER_START command.
*/
anv_cmd_buffer_current_batch_bo(cmd_buffer)->relocs.num_relocs++;
cmd_buffer->batch.next += GEN8_MI_BATCH_BUFFER_START_length * 4;
} else {
cmd_buffer->exec_mode = ANV_CMD_BUFFER_EXEC_MODE_COPY_AND_CHAIN;
}
}
}
static inline VkResult
anv_cmd_buffer_add_seen_bbos(struct anv_cmd_buffer *cmd_buffer,
struct list_head *list)
{
list_for_each_entry(struct anv_batch_bo, bbo, list, link) {
struct anv_batch_bo **bbo_ptr = anv_vector_add(&cmd_buffer->seen_bbos);
if (bbo_ptr == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
*bbo_ptr = bbo;
}
return VK_SUCCESS;
}
void
anv_cmd_buffer_add_secondary(struct anv_cmd_buffer *primary,
struct anv_cmd_buffer *secondary)
{
switch (secondary->exec_mode) {
case ANV_CMD_BUFFER_EXEC_MODE_EMIT:
anv_batch_emit_batch(&primary->batch, &secondary->batch);
break;
case ANV_CMD_BUFFER_EXEC_MODE_CHAIN: {
struct anv_batch_bo *first_bbo =
list_first_entry(&secondary->batch_bos, struct anv_batch_bo, link);
struct anv_batch_bo *last_bbo =
list_last_entry(&secondary->batch_bos, struct anv_batch_bo, link);
emit_batch_buffer_start(&primary->batch, &first_bbo->bo, 0);
struct anv_batch_bo *this_bbo = anv_cmd_buffer_current_batch_bo(primary);
assert(primary->batch.start == this_bbo->bo.map);
uint32_t offset = primary->batch.next - primary->batch.start;
/* Roll back the previous MI_BATCH_BUFFER_START and its relocation so we
* can emit a new command and relocation for the current splice. In
* order to handle the initial-use case, we incremented next and
* num_relocs in end_batch_buffer() so we can alyways just subtract
* here.
*/
last_bbo->relocs.num_relocs--;
secondary->batch.next -= GEN8_MI_BATCH_BUFFER_START_length * 4;
emit_batch_buffer_start(&secondary->batch, &this_bbo->bo, offset);
anv_cmd_buffer_add_seen_bbos(primary, &secondary->batch_bos);
break;
}
case ANV_CMD_BUFFER_EXEC_MODE_COPY_AND_CHAIN: {
struct list_head copy_list;
VkResult result = anv_batch_bo_list_clone(&secondary->batch_bos,
secondary->device,
&copy_list);
if (result != VK_SUCCESS)
return; /* FIXME */
anv_cmd_buffer_add_seen_bbos(primary, &copy_list);
struct anv_batch_bo *first_bbo =
list_first_entry(&copy_list, struct anv_batch_bo, link);
struct anv_batch_bo *last_bbo =
list_last_entry(&copy_list, struct anv_batch_bo, link);
cmd_buffer_chain_to_batch_bo(primary, first_bbo);
list_splicetail(&copy_list, &primary->batch_bos);
anv_batch_bo_continue(last_bbo, &primary->batch,
GEN8_MI_BATCH_BUFFER_START_length * 4);
anv_cmd_buffer_emit_state_base_address(primary);
break;
}
default:
assert(!"Invalid execution mode");
}
/* Mark the surface buffer from the secondary as seen */
anv_cmd_buffer_add_seen_bbos(primary, &secondary->surface_bos);
}
static VkResult
anv_cmd_buffer_add_bo(struct anv_cmd_buffer *cmd_buffer,
struct anv_bo *bo,
struct anv_reloc_list *relocs)
{
struct drm_i915_gem_exec_object2 *obj = NULL;
if (bo->index < cmd_buffer->execbuf2.bo_count &&
cmd_buffer->execbuf2.bos[bo->index] == bo)
obj = &cmd_buffer->execbuf2.objects[bo->index];
if (obj == NULL) {
/* We've never seen this one before. Add it to the list and assign
* an id that we can use later.
*/
if (cmd_buffer->execbuf2.bo_count >= cmd_buffer->execbuf2.array_length) {
uint32_t new_len = cmd_buffer->execbuf2.objects ?
cmd_buffer->execbuf2.array_length * 2 : 64;
struct drm_i915_gem_exec_object2 *new_objects =
anv_device_alloc(cmd_buffer->device, new_len * sizeof(*new_objects),
8, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (new_objects == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
struct anv_bo **new_bos =
anv_device_alloc(cmd_buffer->device, new_len * sizeof(*new_bos),
8, VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (new_objects == NULL) {
anv_device_free(cmd_buffer->device, new_objects);
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
if (cmd_buffer->execbuf2.objects) {
memcpy(new_objects, cmd_buffer->execbuf2.objects,
cmd_buffer->execbuf2.bo_count * sizeof(*new_objects));
memcpy(new_bos, cmd_buffer->execbuf2.bos,
cmd_buffer->execbuf2.bo_count * sizeof(*new_bos));
}
cmd_buffer->execbuf2.objects = new_objects;
cmd_buffer->execbuf2.bos = new_bos;
cmd_buffer->execbuf2.array_length = new_len;
}
assert(cmd_buffer->execbuf2.bo_count < cmd_buffer->execbuf2.array_length);
bo->index = cmd_buffer->execbuf2.bo_count++;
obj = &cmd_buffer->execbuf2.objects[bo->index];
cmd_buffer->execbuf2.bos[bo->index] = bo;
obj->handle = bo->gem_handle;
obj->relocation_count = 0;
obj->relocs_ptr = 0;
obj->alignment = 0;
obj->offset = bo->offset;
obj->flags = 0;
obj->rsvd1 = 0;
obj->rsvd2 = 0;
}
if (relocs != NULL && obj->relocation_count == 0) {
/* This is the first time we've ever seen a list of relocations for
* this BO. Go ahead and set the relocations and then walk the list
* of relocations and add them all.
*/
obj->relocation_count = relocs->num_relocs;
obj->relocs_ptr = (uintptr_t) relocs->relocs;
for (size_t i = 0; i < relocs->num_relocs; i++)
anv_cmd_buffer_add_bo(cmd_buffer, relocs->reloc_bos[i], NULL);
}
return VK_SUCCESS;
}
static void
anv_cmd_buffer_process_relocs(struct anv_cmd_buffer *cmd_buffer,
struct anv_reloc_list *list)
{
struct anv_bo *bo;
/* If the kernel supports I915_EXEC_NO_RELOC, it will compare offset in
* struct drm_i915_gem_exec_object2 against the bos current offset and if
* all bos haven't moved it will skip relocation processing alltogether.
* If I915_EXEC_NO_RELOC is not supported, the kernel ignores the incoming
* value of offset so we can set it either way. For that to work we need
* to make sure all relocs use the same presumed offset.
*/
for (size_t i = 0; i < list->num_relocs; i++) {
bo = list->reloc_bos[i];
if (bo->offset != list->relocs[i].presumed_offset)
cmd_buffer->execbuf2.need_reloc = true;
list->relocs[i].target_handle = bo->index;
}
}
void
anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_batch *batch = &cmd_buffer->batch;
cmd_buffer->execbuf2.bo_count = 0;
cmd_buffer->execbuf2.need_reloc = false;
/* First, we walk over all of the bos we've seen and add them and their
* relocations to the validate list.
*/
struct anv_batch_bo **bbo;
anv_vector_foreach(bbo, &cmd_buffer->seen_bbos)
anv_cmd_buffer_add_bo(cmd_buffer, &(*bbo)->bo, &(*bbo)->relocs);
struct anv_batch_bo *first_batch_bo =
list_first_entry(&cmd_buffer->batch_bos, struct anv_batch_bo, link);
/* The kernel requires that the last entry in the validation list be the
* batch buffer to execute. We can simply swap the element
* corresponding to the first batch_bo in the chain with the last
* element in the list.
*/
if (first_batch_bo->bo.index != cmd_buffer->execbuf2.bo_count - 1) {
uint32_t idx = first_batch_bo->bo.index;
uint32_t last_idx = cmd_buffer->execbuf2.bo_count - 1;
struct drm_i915_gem_exec_object2 tmp_obj =
cmd_buffer->execbuf2.objects[idx];
assert(cmd_buffer->execbuf2.bos[idx] == &first_batch_bo->bo);
cmd_buffer->execbuf2.objects[idx] = cmd_buffer->execbuf2.objects[last_idx];
cmd_buffer->execbuf2.bos[idx] = cmd_buffer->execbuf2.bos[last_idx];
cmd_buffer->execbuf2.bos[idx]->index = idx;
cmd_buffer->execbuf2.objects[last_idx] = tmp_obj;
cmd_buffer->execbuf2.bos[last_idx] = &first_batch_bo->bo;
first_batch_bo->bo.index = last_idx;
}
/* Now we go through and fixup all of the relocation lists to point to
* the correct indices in the object array. We have to do this after we
* reorder the list above as some of the indices may have changed.
*/
anv_vector_foreach(bbo, &cmd_buffer->seen_bbos)
anv_cmd_buffer_process_relocs(cmd_buffer, &(*bbo)->relocs);
cmd_buffer->execbuf2.execbuf = (struct drm_i915_gem_execbuffer2) {
.buffers_ptr = (uintptr_t) cmd_buffer->execbuf2.objects,
.buffer_count = cmd_buffer->execbuf2.bo_count,
.batch_start_offset = 0,
.batch_len = batch->next - batch->start,
.cliprects_ptr = 0,
.num_cliprects = 0,
.DR1 = 0,
.DR4 = 0,
.flags = I915_EXEC_HANDLE_LUT | I915_EXEC_RENDER |
I915_EXEC_CONSTANTS_REL_GENERAL,
.rsvd1 = cmd_buffer->device->context_id,
.rsvd2 = 0,
};
if (!cmd_buffer->execbuf2.need_reloc)
cmd_buffer->execbuf2.execbuf.flags |= I915_EXEC_NO_RELOC;
}

832
src/vulkan/anv_cmd_buffer.c Normal file
View File

@@ -0,0 +1,832 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
/** \file anv_cmd_buffer.c
*
* This file contains all of the stuff for emitting commands into a command
* buffer. This includes implementations of most of the vkCmd*
* entrypoints. This file is concerned entirely with state emission and
* not with the command buffer data structure itself. As far as this file
* is concerned, most of anv_cmd_buffer is magic.
*/
static void
anv_cmd_state_init(struct anv_cmd_state *state)
{
state->rs_state = NULL;
state->vp_state = NULL;
state->cb_state = NULL;
state->ds_state = NULL;
memset(&state->state_vf, 0, sizeof(state->state_vf));
memset(&state->descriptors, 0, sizeof(state->descriptors));
memset(&state->push_constants, 0, sizeof(state->push_constants));
state->dirty = 0;
state->vb_dirty = 0;
state->descriptors_dirty = 0;
state->push_constants_dirty = 0;
state->pipeline = NULL;
state->vp_state = NULL;
state->rs_state = NULL;
state->ds_state = NULL;
state->gen7.index_buffer = NULL;
}
static VkResult
anv_cmd_buffer_ensure_push_constants_size(struct anv_cmd_buffer *cmd_buffer,
VkShaderStage stage, uint32_t size)
{
struct anv_push_constants **ptr = &cmd_buffer->state.push_constants[stage];
if (*ptr == NULL) {
*ptr = anv_device_alloc(cmd_buffer->device, size, 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (*ptr == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
(*ptr)->size = size;
} else if ((*ptr)->size < size) {
void *new_data = anv_device_alloc(cmd_buffer->device, size, 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (new_data == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
memcpy(new_data, *ptr, (*ptr)->size);
anv_device_free(cmd_buffer->device, *ptr);
*ptr = new_data;
(*ptr)->size = size;
}
return VK_SUCCESS;
}
#define anv_cmd_buffer_ensure_push_constant_field(cmd_buffer, stage, field) \
anv_cmd_buffer_ensure_push_constants_size(cmd_buffer, stage, \
(offsetof(struct anv_push_constants, field) + \
sizeof(cmd_buffer->state.push_constants[0]->field)))
VkResult anv_CreateCommandBuffer(
VkDevice _device,
const VkCmdBufferCreateInfo* pCreateInfo,
VkCmdBuffer* pCmdBuffer)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_cmd_pool, pool, pCreateInfo->cmdPool);
struct anv_cmd_buffer *cmd_buffer;
VkResult result;
cmd_buffer = anv_device_alloc(device, sizeof(*cmd_buffer), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (cmd_buffer == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
cmd_buffer->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
cmd_buffer->device = device;
result = anv_cmd_buffer_init_batch_bo_chain(cmd_buffer);
if (result != VK_SUCCESS)
goto fail;
anv_state_stream_init(&cmd_buffer->surface_state_stream,
&device->surface_state_block_pool);
anv_state_stream_init(&cmd_buffer->dynamic_state_stream,
&device->dynamic_state_block_pool);
cmd_buffer->level = pCreateInfo->level;
cmd_buffer->opt_flags = 0;
anv_cmd_state_init(&cmd_buffer->state);
if (pool) {
list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers);
} else {
/* Init the pool_link so we can safefly call list_del when we destroy
* the command buffer
*/
list_inithead(&cmd_buffer->pool_link);
}
*pCmdBuffer = anv_cmd_buffer_to_handle(cmd_buffer);
return VK_SUCCESS;
fail: anv_device_free(device, cmd_buffer);
return result;
}
VkResult anv_DestroyCommandBuffer(
VkDevice _device,
VkCmdBuffer _cmd_buffer)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, _cmd_buffer);
list_del(&cmd_buffer->pool_link);
anv_cmd_buffer_fini_batch_bo_chain(cmd_buffer);
anv_state_stream_finish(&cmd_buffer->surface_state_stream);
anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
anv_device_free(device, cmd_buffer);
return VK_SUCCESS;
}
VkResult anv_ResetCommandBuffer(
VkCmdBuffer cmdBuffer,
VkCmdBufferResetFlags flags)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
anv_cmd_buffer_reset_batch_bo_chain(cmd_buffer);
anv_cmd_state_init(&cmd_buffer->state);
return VK_SUCCESS;
}
void
anv_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer)
{
switch (cmd_buffer->device->info.gen) {
case 7:
return gen7_cmd_buffer_emit_state_base_address(cmd_buffer);
case 8:
return gen8_cmd_buffer_emit_state_base_address(cmd_buffer);
default:
unreachable("unsupported gen\n");
}
}
VkResult anv_BeginCommandBuffer(
VkCmdBuffer cmdBuffer,
const VkCmdBufferBeginInfo* pBeginInfo)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
cmd_buffer->opt_flags = pBeginInfo->flags;
if (cmd_buffer->level == VK_CMD_BUFFER_LEVEL_SECONDARY) {
cmd_buffer->state.framebuffer =
anv_framebuffer_from_handle(pBeginInfo->framebuffer);
cmd_buffer->state.pass =
anv_render_pass_from_handle(pBeginInfo->renderPass);
/* FIXME: We shouldn't be starting on the first subpass */
anv_cmd_buffer_begin_subpass(cmd_buffer,
&cmd_buffer->state.pass->subpasses[0]);
}
anv_cmd_buffer_emit_state_base_address(cmd_buffer);
cmd_buffer->state.current_pipeline = UINT32_MAX;
return VK_SUCCESS;
}
VkResult anv_EndCommandBuffer(
VkCmdBuffer cmdBuffer)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
struct anv_device *device = cmd_buffer->device;
anv_cmd_buffer_end_batch_buffer(cmd_buffer);
if (cmd_buffer->level == VK_CMD_BUFFER_LEVEL_PRIMARY) {
/* The algorithm used to compute the validate list is not threadsafe as
* it uses the bo->index field. We have to lock the device around it.
* Fortunately, the chances for contention here are probably very low.
*/
pthread_mutex_lock(&device->mutex);
anv_cmd_buffer_prepare_execbuf(cmd_buffer);
pthread_mutex_unlock(&device->mutex);
}
return VK_SUCCESS;
}
void anv_CmdBindPipeline(
VkCmdBuffer cmdBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipeline _pipeline)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
switch (pipelineBindPoint) {
case VK_PIPELINE_BIND_POINT_COMPUTE:
cmd_buffer->state.compute_pipeline = pipeline;
cmd_buffer->state.compute_dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY;
cmd_buffer->state.push_constants_dirty |= VK_SHADER_STAGE_COMPUTE_BIT;
break;
case VK_PIPELINE_BIND_POINT_GRAPHICS:
cmd_buffer->state.pipeline = pipeline;
cmd_buffer->state.vb_dirty |= pipeline->vb_used;
cmd_buffer->state.dirty |= ANV_CMD_BUFFER_PIPELINE_DIRTY;
cmd_buffer->state.push_constants_dirty |= pipeline->active_stages;
break;
default:
assert(!"invalid bind point");
break;
}
}
void anv_CmdBindDynamicViewportState(
VkCmdBuffer cmdBuffer,
VkDynamicViewportState dynamicViewportState)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_dynamic_vp_state, vp_state, dynamicViewportState);
cmd_buffer->state.vp_state = vp_state;
cmd_buffer->state.dirty |= ANV_CMD_BUFFER_VP_DIRTY;
}
void anv_CmdBindDynamicRasterState(
VkCmdBuffer cmdBuffer,
VkDynamicRasterState dynamicRasterState)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_dynamic_rs_state, rs_state, dynamicRasterState);
cmd_buffer->state.rs_state = rs_state;
cmd_buffer->state.dirty |= ANV_CMD_BUFFER_RS_DIRTY;
}
void anv_CmdBindDynamicColorBlendState(
VkCmdBuffer cmdBuffer,
VkDynamicColorBlendState dynamicColorBlendState)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_dynamic_cb_state, cb_state, dynamicColorBlendState);
cmd_buffer->state.cb_state = cb_state;
cmd_buffer->state.dirty |= ANV_CMD_BUFFER_CB_DIRTY;
}
void anv_CmdBindDynamicDepthStencilState(
VkCmdBuffer cmdBuffer,
VkDynamicDepthStencilState dynamicDepthStencilState)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_dynamic_ds_state, ds_state, dynamicDepthStencilState);
cmd_buffer->state.ds_state = ds_state;
cmd_buffer->state.dirty |= ANV_CMD_BUFFER_DS_DIRTY;
}
void anv_CmdBindDescriptorSets(
VkCmdBuffer cmdBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout _layout,
uint32_t firstSet,
uint32_t setCount,
const VkDescriptorSet* pDescriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t* pDynamicOffsets)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
struct anv_descriptor_set_layout *set_layout;
assert(firstSet + setCount < MAX_SETS);
uint32_t dynamic_slot = 0;
for (uint32_t i = 0; i < setCount; i++) {
ANV_FROM_HANDLE(anv_descriptor_set, set, pDescriptorSets[i]);
set_layout = layout->set[firstSet + i].layout;
if (cmd_buffer->state.descriptors[firstSet + i].set != set) {
cmd_buffer->state.descriptors[firstSet + i].set = set;
cmd_buffer->state.descriptors_dirty |= set_layout->shader_stages;
}
if (set_layout->num_dynamic_buffers > 0) {
uint32_t s;
for_each_bit(s, set_layout->shader_stages) {
anv_cmd_buffer_ensure_push_constant_field(cmd_buffer, s,
dynamic_offsets);
uint32_t *offsets =
cmd_buffer->state.push_constants[s]->dynamic_offsets +
layout->set[firstSet + i].dynamic_offset_start;
memcpy(offsets, pDynamicOffsets + dynamic_slot,
set_layout->num_dynamic_buffers * sizeof(*pDynamicOffsets));
}
cmd_buffer->state.push_constants_dirty |= set_layout->shader_stages;
dynamic_slot += set_layout->num_dynamic_buffers;
}
}
}
void anv_CmdBindVertexBuffers(
VkCmdBuffer cmdBuffer,
uint32_t startBinding,
uint32_t bindingCount,
const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
struct anv_vertex_binding *vb = cmd_buffer->state.vertex_bindings;
/* We have to defer setting up vertex buffer since we need the buffer
* stride from the pipeline. */
assert(startBinding + bindingCount < MAX_VBS);
for (uint32_t i = 0; i < bindingCount; i++) {
vb[startBinding + i].buffer = anv_buffer_from_handle(pBuffers[i]);
vb[startBinding + i].offset = pOffsets[i];
cmd_buffer->state.vb_dirty |= 1 << (startBinding + i);
}
}
static void
add_surface_state_reloc(struct anv_cmd_buffer *cmd_buffer,
struct anv_state state, struct anv_bo *bo, uint32_t offset)
{
/* The address goes in SURFACE_STATE dword 1 for gens < 8 and dwords 8 and
* 9 for gen8+. We only write the first dword for gen8+ here and rely on
* the initial state to set the high bits to 0. */
const uint32_t dword = cmd_buffer->device->info.gen < 8 ? 1 : 8;
*(uint32_t *)(state.map + dword * 4) =
anv_reloc_list_add(anv_cmd_buffer_current_surface_relocs(cmd_buffer),
cmd_buffer->device, state.offset + dword * 4, bo, offset);
}
VkResult
anv_cmd_buffer_emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
unsigned stage, struct anv_state *bt_state)
{
struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
struct anv_subpass *subpass = cmd_buffer->state.subpass;
struct anv_pipeline_layout *layout;
uint32_t attachments, bias, size;
if (stage == VK_SHADER_STAGE_COMPUTE)
layout = cmd_buffer->state.compute_pipeline->layout;
else
layout = cmd_buffer->state.pipeline->layout;
if (stage == VK_SHADER_STAGE_FRAGMENT) {
bias = MAX_RTS;
attachments = subpass->color_count;
} else {
bias = 0;
attachments = 0;
}
/* This is a little awkward: layout can be NULL but we still have to
* allocate and set a binding table for the PS stage for render
* targets. */
uint32_t surface_count = layout ? layout->stage[stage].surface_count : 0;
if (attachments + surface_count == 0)
return VK_SUCCESS;
size = (bias + surface_count) * sizeof(uint32_t);
*bt_state = anv_cmd_buffer_alloc_surface_state(cmd_buffer, size, 32);
uint32_t *bt_map = bt_state->map;
if (bt_state->map == NULL)
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
/* This is highly annoying. The Vulkan spec puts the depth-stencil
* attachments in with the color attachments. Unfortunately, thanks to
* other aspects of the API, we cana't really saparate them before this
* point. Therefore, we have to walk all of the attachments but only
* put the color attachments into the binding table.
*/
for (uint32_t a = 0; a < attachments; a++) {
const struct anv_attachment_view *attachment =
fb->attachments[subpass->color_attachments[a]];
assert(attachment->attachment_type == ANV_ATTACHMENT_VIEW_TYPE_COLOR);
const struct anv_color_attachment_view *view =
(const struct anv_color_attachment_view *)attachment;
struct anv_state state =
anv_cmd_buffer_alloc_surface_state(cmd_buffer, 64, 64);
if (state.map == NULL)
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
memcpy(state.map, view->view.surface_state.map, 64);
add_surface_state_reloc(cmd_buffer, state, view->view.bo, view->view.offset);
bt_map[a] = state.offset;
}
if (layout == NULL)
return VK_SUCCESS;
for (uint32_t set = 0; set < layout->num_sets; set++) {
struct anv_descriptor_set_binding *d = &cmd_buffer->state.descriptors[set];
struct anv_descriptor_set_layout *set_layout = layout->set[set].layout;
struct anv_descriptor_slot *surface_slots =
set_layout->stage[stage].surface_start;
uint32_t start = bias + layout->set[set].stage[stage].surface_start;
for (uint32_t b = 0; b < set_layout->stage[stage].surface_count; b++) {
struct anv_surface_view *view =
d->set->descriptors[surface_slots[b].index].view;
if (!view)
continue;
struct anv_state state =
anv_cmd_buffer_alloc_surface_state(cmd_buffer, 64, 64);
if (state.map == NULL)
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
memcpy(state.map, view->surface_state.map, 64);
add_surface_state_reloc(cmd_buffer, state, view->bo, view->offset);
bt_map[start + b] = state.offset;
}
}
return VK_SUCCESS;
}
VkResult
anv_cmd_buffer_emit_samplers(struct anv_cmd_buffer *cmd_buffer,
unsigned stage, struct anv_state *state)
{
struct anv_pipeline_layout *layout;
uint32_t sampler_count;
if (stage == VK_SHADER_STAGE_COMPUTE)
layout = cmd_buffer->state.compute_pipeline->layout;
else
layout = cmd_buffer->state.pipeline->layout;
sampler_count = layout ? layout->stage[stage].sampler_count : 0;
if (sampler_count == 0)
return VK_SUCCESS;
uint32_t size = sampler_count * 16;
*state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, size, 32);
if (state->map == NULL)
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
for (uint32_t set = 0; set < layout->num_sets; set++) {
struct anv_descriptor_set_binding *d = &cmd_buffer->state.descriptors[set];
struct anv_descriptor_set_layout *set_layout = layout->set[set].layout;
struct anv_descriptor_slot *sampler_slots =
set_layout->stage[stage].sampler_start;
uint32_t start = layout->set[set].stage[stage].sampler_start;
for (uint32_t b = 0; b < set_layout->stage[stage].sampler_count; b++) {
struct anv_sampler *sampler =
d->set->descriptors[sampler_slots[b].index].sampler;
if (!sampler)
continue;
memcpy(state->map + (start + b) * 16,
sampler->state, sizeof(sampler->state));
}
}
return VK_SUCCESS;
}
static VkResult
flush_descriptor_set(struct anv_cmd_buffer *cmd_buffer, uint32_t stage)
{
struct anv_state surfaces = { 0, }, samplers = { 0, };
VkResult result;
result = anv_cmd_buffer_emit_samplers(cmd_buffer, stage, &samplers);
if (result != VK_SUCCESS)
return result;
result = anv_cmd_buffer_emit_binding_table(cmd_buffer, stage, &surfaces);
if (result != VK_SUCCESS)
return result;
static const uint32_t sampler_state_opcodes[] = {
[VK_SHADER_STAGE_VERTEX] = 43,
[VK_SHADER_STAGE_TESS_CONTROL] = 44, /* HS */
[VK_SHADER_STAGE_TESS_EVALUATION] = 45, /* DS */
[VK_SHADER_STAGE_GEOMETRY] = 46,
[VK_SHADER_STAGE_FRAGMENT] = 47,
[VK_SHADER_STAGE_COMPUTE] = 0,
};
static const uint32_t binding_table_opcodes[] = {
[VK_SHADER_STAGE_VERTEX] = 38,
[VK_SHADER_STAGE_TESS_CONTROL] = 39,
[VK_SHADER_STAGE_TESS_EVALUATION] = 40,
[VK_SHADER_STAGE_GEOMETRY] = 41,
[VK_SHADER_STAGE_FRAGMENT] = 42,
[VK_SHADER_STAGE_COMPUTE] = 0,
};
if (samplers.alloc_size > 0) {
anv_batch_emit(&cmd_buffer->batch,
GEN7_3DSTATE_SAMPLER_STATE_POINTERS_VS,
._3DCommandSubOpcode = sampler_state_opcodes[stage],
.PointertoVSSamplerState = samplers.offset);
}
if (surfaces.alloc_size > 0) {
anv_batch_emit(&cmd_buffer->batch,
GEN7_3DSTATE_BINDING_TABLE_POINTERS_VS,
._3DCommandSubOpcode = binding_table_opcodes[stage],
.PointertoVSBindingTable = surfaces.offset);
}
return VK_SUCCESS;
}
void
anv_flush_descriptor_sets(struct anv_cmd_buffer *cmd_buffer)
{
uint32_t s, dirty = cmd_buffer->state.descriptors_dirty &
cmd_buffer->state.pipeline->active_stages;
VkResult result = VK_SUCCESS;
for_each_bit(s, dirty) {
result = flush_descriptor_set(cmd_buffer, s);
if (result != VK_SUCCESS)
break;
}
if (result != VK_SUCCESS) {
assert(result == VK_ERROR_OUT_OF_DEVICE_MEMORY);
result = anv_cmd_buffer_new_surface_state_bo(cmd_buffer);
assert(result == VK_SUCCESS);
/* Re-emit state base addresses so we get the new surface state base
* address before we start emitting binding tables etc.
*/
anv_cmd_buffer_emit_state_base_address(cmd_buffer);
/* Re-emit all active binding tables */
for_each_bit(s, cmd_buffer->state.pipeline->active_stages) {
result = flush_descriptor_set(cmd_buffer, s);
/* It had better succeed this time */
assert(result == VK_SUCCESS);
}
}
cmd_buffer->state.descriptors_dirty &= ~cmd_buffer->state.pipeline->active_stages;
}
struct anv_state
anv_cmd_buffer_emit_dynamic(struct anv_cmd_buffer *cmd_buffer,
uint32_t *a, uint32_t dwords, uint32_t alignment)
{
struct anv_state state;
state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
dwords * 4, alignment);
memcpy(state.map, a, dwords * 4);
VG(VALGRIND_CHECK_MEM_IS_DEFINED(state.map, dwords * 4));
return state;
}
struct anv_state
anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer *cmd_buffer,
uint32_t *a, uint32_t *b,
uint32_t dwords, uint32_t alignment)
{
struct anv_state state;
uint32_t *p;
state = anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
dwords * 4, alignment);
p = state.map;
for (uint32_t i = 0; i < dwords; i++)
p[i] = a[i] | b[i];
VG(VALGRIND_CHECK_MEM_IS_DEFINED(p, dwords * 4));
return state;
}
void
anv_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
struct anv_subpass *subpass)
{
switch (cmd_buffer->device->info.gen) {
case 7:
gen7_cmd_buffer_begin_subpass(cmd_buffer, subpass);
break;
case 8:
gen8_cmd_buffer_begin_subpass(cmd_buffer, subpass);
break;
default:
unreachable("unsupported gen\n");
}
}
void anv_CmdSetEvent(
VkCmdBuffer cmdBuffer,
VkEvent event,
VkPipelineStageFlags stageMask)
{
stub();
}
void anv_CmdResetEvent(
VkCmdBuffer cmdBuffer,
VkEvent event,
VkPipelineStageFlags stageMask)
{
stub();
}
void anv_CmdWaitEvents(
VkCmdBuffer cmdBuffer,
uint32_t eventCount,
const VkEvent* pEvents,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags destStageMask,
uint32_t memBarrierCount,
const void* const* ppMemBarriers)
{
stub();
}
struct anv_state
anv_cmd_buffer_push_constants(struct anv_cmd_buffer *cmd_buffer,
VkShaderStage stage)
{
struct anv_push_constants *data =
cmd_buffer->state.push_constants[stage];
struct brw_stage_prog_data *prog_data =
cmd_buffer->state.pipeline->prog_data[stage];
/* If we don't actually have any push constants, bail. */
if (data == NULL || prog_data->nr_params == 0)
return (struct anv_state) { .offset = 0 };
struct anv_state state =
anv_cmd_buffer_alloc_dynamic_state(cmd_buffer,
prog_data->nr_params * sizeof(float),
32 /* bottom 5 bits MBZ */);
/* Walk through the param array and fill the buffer with data */
uint32_t *u32_map = state.map;
for (unsigned i = 0; i < prog_data->nr_params; i++) {
uint32_t offset = (uintptr_t)prog_data->param[i];
u32_map[i] = *(uint32_t *)((uint8_t *)data + offset);
}
return state;
}
void anv_CmdPushConstants(
VkCmdBuffer cmdBuffer,
VkPipelineLayout layout,
VkShaderStageFlags stageFlags,
uint32_t start,
uint32_t length,
const void* values)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
uint32_t stage;
for_each_bit(stage, stageFlags) {
anv_cmd_buffer_ensure_push_constant_field(cmd_buffer, stage, client_data);
memcpy(cmd_buffer->state.push_constants[stage]->client_data + start,
values, length);
}
cmd_buffer->state.push_constants_dirty |= stageFlags;
}
void anv_CmdExecuteCommands(
VkCmdBuffer cmdBuffer,
uint32_t cmdBuffersCount,
const VkCmdBuffer* pCmdBuffers)
{
ANV_FROM_HANDLE(anv_cmd_buffer, primary, cmdBuffer);
assert(primary->level == VK_CMD_BUFFER_LEVEL_PRIMARY);
anv_assert(primary->state.subpass == &primary->state.pass->subpasses[0]);
for (uint32_t i = 0; i < cmdBuffersCount; i++) {
ANV_FROM_HANDLE(anv_cmd_buffer, secondary, pCmdBuffers[i]);
assert(secondary->level == VK_CMD_BUFFER_LEVEL_SECONDARY);
anv_cmd_buffer_add_secondary(primary, secondary);
}
}
VkResult anv_CreateCommandPool(
VkDevice _device,
const VkCmdPoolCreateInfo* pCreateInfo,
VkCmdPool* pCmdPool)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_cmd_pool *pool;
pool = anv_device_alloc(device, sizeof(*pool), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (pool == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
list_inithead(&pool->cmd_buffers);
*pCmdPool = anv_cmd_pool_to_handle(pool);
return VK_SUCCESS;
}
VkResult anv_DestroyCommandPool(
VkDevice _device,
VkCmdPool cmdPool)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_cmd_pool, pool, cmdPool);
anv_ResetCommandPool(_device, cmdPool, 0);
anv_device_free(device, pool);
return VK_SUCCESS;
}
VkResult anv_ResetCommandPool(
VkDevice device,
VkCmdPool cmdPool,
VkCmdPoolResetFlags flags)
{
ANV_FROM_HANDLE(anv_cmd_pool, pool, cmdPool);
list_for_each_entry_safe(struct anv_cmd_buffer, cmd_buffer,
&pool->cmd_buffers, pool_link) {
anv_DestroyCommandBuffer(device, anv_cmd_buffer_to_handle(cmd_buffer));
}
return VK_SUCCESS;
}
/**
* Return NULL if the current subpass has no depthstencil attachment.
*/
const struct anv_depth_stencil_view *
anv_cmd_buffer_get_depth_stencil_view(const struct anv_cmd_buffer *cmd_buffer)
{
const struct anv_subpass *subpass = cmd_buffer->state.subpass;
const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
if (subpass->depth_stencil_attachment == VK_ATTACHMENT_UNUSED)
return NULL;
const struct anv_attachment_view *aview =
fb->attachments[subpass->depth_stencil_attachment];
assert(aview->attachment_type == ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL);
return (const struct anv_depth_stencil_view *) aview;
}

1128
src/vulkan/anv_compiler.cpp Normal file

File diff suppressed because it is too large Load Diff

2192
src/vulkan/anv_device.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,310 @@
# coding=utf-8
#
# Copyright © 2015 Intel Corporation
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
import fileinput, re, sys
# Each function typedef in the vulkan.h header is all on one line and matches
# this regepx. We hope that won't change.
p = re.compile('typedef ([^ ]*) *\(VKAPI \*PFN_vk([^(]*)\)(.*);')
entrypoints = []
# We generate a static hash table for entry point lookup
# (vkGetProcAddress). We use a linear congruential generator for our hash
# function and a power-of-two size table. The prime numbers are determined
# experimentally.
none = 0xffff
hash_size = 256
u32_mask = 2**32 - 1
hash_mask = hash_size - 1
prime_factor = 5024183
prime_step = 19
def hash(name):
h = 0;
for c in name:
h = (h * prime_factor + ord(c)) & u32_mask
return h
opt_header = False
opt_code = False
if (sys.argv[1] == "header"):
opt_header = True
sys.argv.pop()
elif (sys.argv[1] == "code"):
opt_code = True
sys.argv.pop()
# Parse the entry points in the header
i = 0
for line in fileinput.input():
m = p.match(line)
if (m):
if m.group(2) == 'VoidFunction':
continue
fullname = "vk" + m.group(2)
h = hash(fullname)
entrypoints.append((m.group(1), m.group(2), m.group(3), i, h))
i = i + 1
# For outputting entrypoints.h we generate a anv_EntryPoint() prototype
# per entry point.
if opt_header:
print "/* This file generated from vk_gen.py, don't edit directly. */\n"
print "struct anv_dispatch_table {"
print " union {"
print " void *entrypoints[%d];" % len(entrypoints)
print " struct {"
for type, name, args, num, h in entrypoints:
print " %s (*%s)%s;" % (type, name, args)
print " };\n"
print " };\n"
print "};\n"
print "void anv_set_dispatch_gen(uint32_t gen);\n"
for type, name, args, num, h in entrypoints:
print "%s anv_%s%s;" % (type, name, args)
print "%s gen7_%s%s;" % (type, name, args)
print "%s gen8_%s%s;" % (type, name, args)
print "%s anv_validate_%s%s;" % (type, name, args)
exit()
print """/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* DO NOT EDIT! This is a generated file. */
#include "anv_private.h"
struct anv_entrypoint {
uint32_t name;
uint32_t hash;
};
/* We use a big string constant to avoid lots of reloctions from the entry
* point table to lots of little strings. The entries in the entry point table
* store the index into this big string.
*/
static const char strings[] ="""
offsets = []
i = 0;
for type, name, args, num, h in entrypoints:
print " \"vk%s\\0\"" % name
offsets.append(i)
i += 2 + len(name) + 1
print """ ;
/* Weak aliases for all potential validate functions. These will resolve to
* NULL if they're not defined, which lets the resolve_entrypoint() function
* either pick a validate wrapper if available or just plug in the actual
* entry point.
*/
"""
# Now generate the table of all entry points and their validation functions
print "\nstatic const struct anv_entrypoint entrypoints[] = {"
for type, name, args, num, h in entrypoints:
print " { %5d, 0x%08x }," % (offsets[num], h)
print "};\n"
for layer in [ "anv", "validate", "gen7", "gen8" ]:
for type, name, args, num, h in entrypoints:
print "%s %s_%s%s __attribute__ ((weak));" % (type, layer, name, args)
print "\nconst struct anv_dispatch_table %s_layer = {" % layer
for type, name, args, num, h in entrypoints:
print " .%s = %s_%s," % (name, layer, name)
print "};\n"
print """
#ifdef DEBUG
static bool enable_validate = true;
#else
static bool enable_validate = false;
#endif
/* We can't use symbols that need resolving (like, oh, getenv) in the resolve
* function. This means that we have to determine whether or not to use the
* validation layer sometime before that. The constructor function attribute asks
* the dynamic linker to invoke determine_validate() at dlopen() time which
* works.
*/
static void __attribute__ ((constructor))
determine_validate(void)
{
const char *s = getenv("ANV_VALIDATE");
if (s)
enable_validate = atoi(s);
}
static uint32_t dispatch_gen;
void
anv_set_dispatch_gen(uint32_t gen)
{
dispatch_gen = gen;
}
void * __attribute__ ((noinline))
anv_resolve_entrypoint(uint32_t index)
{
if (enable_validate && validate_layer.entrypoints[index])
return validate_layer.entrypoints[index];
switch (dispatch_gen) {
case 8:
if (gen8_layer.entrypoints[index])
return gen8_layer.entrypoints[index];
/* fall through */
case 7:
if (gen7_layer.entrypoints[index])
return gen7_layer.entrypoints[index];
/* fall through */
case 0:
return anv_layer.entrypoints[index];
default:
unreachable("unsupported gen\\n");
}
}
"""
# Now output ifuncs and their resolve helpers for all entry points. The
# resolve helper calls resolve_entrypoint() with the entry point index, which
# lets the resolver look it up in the table.
for type, name, args, num, h in entrypoints:
print "static void *resolve_%s(void) { return anv_resolve_entrypoint(%d); }" % (name, num)
print "%s vk%s%s\n __attribute__ ((ifunc (\"resolve_%s\"), visibility (\"default\")));\n" % (type, name, args, name)
# Now generate the hash table used for entry point look up. This is a
# uint16_t table of entry point indices. We use 0xffff to indicate an entry
# in the hash table is empty.
map = [none for f in xrange(hash_size)]
collisions = [0 for f in xrange(10)]
for type, name, args, num, h in entrypoints:
level = 0
while map[h & hash_mask] != none:
h = h + prime_step
level = level + 1
if level > 9:
collisions[9] += 1
else:
collisions[level] += 1
map[h & hash_mask] = num
print "/* Hash table stats:"
print " * size %d entries" % hash_size
print " * collisions entries"
for i in xrange(10):
if (i == 9):
plus = "+"
else:
plus = " "
print " * %2d%s %4d" % (i, plus, collisions[i])
print " */\n"
print "#define none 0x%04x\n" % none
print "static const uint16_t map[] = {"
for i in xrange(0, hash_size, 8):
print " ",
for j in xrange(i, i + 8):
if map[j] & 0xffff == 0xffff:
print " none,",
else:
print "0x%04x," % (map[j] & 0xffff),
print
print "};"
# Finally we generate the hash table lookup function. The hash function and
# linear probing algorithm matches the hash table generated above.
print """
void *
anv_lookup_entrypoint(const char *name)
{
static const uint32_t prime_factor = %d;
static const uint32_t prime_step = %d;
const struct anv_entrypoint *e;
uint32_t hash, h, i;
const char *p;
hash = 0;
for (p = name; *p; p++)
hash = hash * prime_factor + *p;
h = hash;
do {
i = map[h & %d];
if (i == none)
return NULL;
e = &entrypoints[i];
h += prime_step;
} while (e->hash != hash);
if (strcmp(name, strings + e->name) != 0)
return NULL;
return anv_resolve_entrypoint(i);
}
""" % (prime_factor, prime_step, hash_mask)

329
src/vulkan/anv_formats.c Normal file
View File

@@ -0,0 +1,329 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "anv_private.h"
#define UNSUPPORTED 0xffff
#define fmt(__vk_fmt, ...) \
[__vk_fmt] = { .vk_format = __vk_fmt, .name = #__vk_fmt, __VA_ARGS__ }
static const struct anv_format anv_formats[] = {
fmt(VK_FORMAT_UNDEFINED, RAW, .cpp = 1, .num_channels = 1),
fmt(VK_FORMAT_R4G4_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_R4G4_USCALED, UNSUPPORTED),
fmt(VK_FORMAT_R4G4B4A4_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_R4G4B4A4_USCALED, UNSUPPORTED),
fmt(VK_FORMAT_R5G6B5_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_R5G6B5_USCALED, UNSUPPORTED),
fmt(VK_FORMAT_R5G5B5A1_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_R5G5B5A1_USCALED, UNSUPPORTED),
fmt(VK_FORMAT_R8_UNORM, R8_UNORM, .cpp = 1, .num_channels = 1),
fmt(VK_FORMAT_R8_SNORM, R8_SNORM, .cpp = 1, .num_channels = 1,),
fmt(VK_FORMAT_R8_USCALED, R8_USCALED, .cpp = 1, .num_channels = 1),
fmt(VK_FORMAT_R8_SSCALED, R8_SSCALED, .cpp = 1, .num_channels = 1),
fmt(VK_FORMAT_R8_UINT, R8_UINT, .cpp = 1, .num_channels = 1),
fmt(VK_FORMAT_R8_SINT, R8_SINT, .cpp = 1, .num_channels = 1),
fmt(VK_FORMAT_R8_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_R8G8_UNORM, R8G8_UNORM, .cpp = 2, .num_channels = 2),
fmt(VK_FORMAT_R8G8_SNORM, R8G8_SNORM, .cpp = 2, .num_channels = 2),
fmt(VK_FORMAT_R8G8_USCALED, R8G8_USCALED, .cpp = 2, .num_channels = 2),
fmt(VK_FORMAT_R8G8_SSCALED, R8G8_SSCALED, .cpp = 2, .num_channels = 2),
fmt(VK_FORMAT_R8G8_UINT, R8G8_UINT, .cpp = 2, .num_channels = 2),
fmt(VK_FORMAT_R8G8_SINT, R8G8_SINT, .cpp = 2, .num_channels = 2),
fmt(VK_FORMAT_R8G8_SRGB, UNSUPPORTED), /* L8A8_UNORM_SRGB */
fmt(VK_FORMAT_R8G8B8_UNORM, R8G8B8X8_UNORM, .cpp = 3, .num_channels = 3),
fmt(VK_FORMAT_R8G8B8_SNORM, R8G8B8_SNORM, .cpp = 3, .num_channels = 3),
fmt(VK_FORMAT_R8G8B8_USCALED, R8G8B8_USCALED, .cpp = 3, .num_channels = 3),
fmt(VK_FORMAT_R8G8B8_SSCALED, R8G8B8_SSCALED, .cpp = 3, .num_channels = 3),
fmt(VK_FORMAT_R8G8B8_UINT, R8G8B8_UINT, .cpp = 3, .num_channels = 3),
fmt(VK_FORMAT_R8G8B8_SINT, R8G8B8_SINT, .cpp = 3, .num_channels = 3),
fmt(VK_FORMAT_R8G8B8_SRGB, UNSUPPORTED), /* B8G8R8A8_UNORM_SRGB */
fmt(VK_FORMAT_R8G8B8A8_UNORM, R8G8B8A8_UNORM, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R8G8B8A8_SNORM, R8G8B8A8_SNORM, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R8G8B8A8_USCALED, R8G8B8A8_USCALED, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R8G8B8A8_SSCALED, R8G8B8A8_SSCALED, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R8G8B8A8_UINT, R8G8B8A8_UINT, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R8G8B8A8_SINT, R8G8B8A8_SINT, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R8G8B8A8_SRGB, R8G8B8A8_UNORM_SRGB, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R10G10B10A2_UNORM, R10G10B10A2_UNORM, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R10G10B10A2_SNORM, R10G10B10A2_SNORM, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R10G10B10A2_USCALED, R10G10B10A2_USCALED, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R10G10B10A2_SSCALED, R10G10B10A2_SSCALED, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R10G10B10A2_UINT, R10G10B10A2_UINT, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R10G10B10A2_SINT, R10G10B10A2_SINT, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_R16_UNORM, R16_UNORM, .cpp = 2, .num_channels = 1),
fmt(VK_FORMAT_R16_SNORM, R16_SNORM, .cpp = 2, .num_channels = 1),
fmt(VK_FORMAT_R16_USCALED, R16_USCALED, .cpp = 2, .num_channels = 1),
fmt(VK_FORMAT_R16_SSCALED, R16_SSCALED, .cpp = 2, .num_channels = 1),
fmt(VK_FORMAT_R16_UINT, R16_UINT, .cpp = 2, .num_channels = 1),
fmt(VK_FORMAT_R16_SINT, R16_SINT, .cpp = 2, .num_channels = 1),
fmt(VK_FORMAT_R16_SFLOAT, R16_FLOAT, .cpp = 2, .num_channels = 1),
fmt(VK_FORMAT_R16G16_UNORM, R16G16_UNORM, .cpp = 4, .num_channels = 2),
fmt(VK_FORMAT_R16G16_SNORM, R16G16_SNORM, .cpp = 4, .num_channels = 2),
fmt(VK_FORMAT_R16G16_USCALED, R16G16_USCALED, .cpp = 4, .num_channels = 2),
fmt(VK_FORMAT_R16G16_SSCALED, R16G16_SSCALED, .cpp = 4, .num_channels = 2),
fmt(VK_FORMAT_R16G16_UINT, R16G16_UINT, .cpp = 4, .num_channels = 2),
fmt(VK_FORMAT_R16G16_SINT, R16G16_SINT, .cpp = 4, .num_channels = 2),
fmt(VK_FORMAT_R16G16_SFLOAT, R16G16_FLOAT, .cpp = 4, .num_channels = 2),
fmt(VK_FORMAT_R16G16B16_UNORM, R16G16B16_UNORM, .cpp = 6, .num_channels = 3),
fmt(VK_FORMAT_R16G16B16_SNORM, R16G16B16_SNORM, .cpp = 6, .num_channels = 3),
fmt(VK_FORMAT_R16G16B16_USCALED, R16G16B16_USCALED, .cpp = 6, .num_channels = 3),
fmt(VK_FORMAT_R16G16B16_SSCALED, R16G16B16_SSCALED, .cpp = 6, .num_channels = 3),
fmt(VK_FORMAT_R16G16B16_UINT, R16G16B16_UINT, .cpp = 6, .num_channels = 3),
fmt(VK_FORMAT_R16G16B16_SINT, R16G16B16_SINT, .cpp = 6, .num_channels = 3),
fmt(VK_FORMAT_R16G16B16_SFLOAT, R16G16B16_FLOAT, .cpp = 6, .num_channels = 3),
fmt(VK_FORMAT_R16G16B16A16_UNORM, R16G16B16A16_UNORM, .cpp = 8, .num_channels = 4),
fmt(VK_FORMAT_R16G16B16A16_SNORM, R16G16B16A16_SNORM, .cpp = 8, .num_channels = 4),
fmt(VK_FORMAT_R16G16B16A16_USCALED, R16G16B16A16_USCALED, .cpp = 8, .num_channels = 4),
fmt(VK_FORMAT_R16G16B16A16_SSCALED, R16G16B16A16_SSCALED, .cpp = 8, .num_channels = 4),
fmt(VK_FORMAT_R16G16B16A16_UINT, R16G16B16A16_UINT, .cpp = 8, .num_channels = 4),
fmt(VK_FORMAT_R16G16B16A16_SINT, R16G16B16A16_SINT, .cpp = 8, .num_channels = 4),
fmt(VK_FORMAT_R16G16B16A16_SFLOAT, R16G16B16A16_FLOAT, .cpp = 8, .num_channels = 4),
fmt(VK_FORMAT_R32_UINT, R32_UINT, .cpp = 4, .num_channels = 1,),
fmt(VK_FORMAT_R32_SINT, R32_SINT, .cpp = 4, .num_channels = 1,),
fmt(VK_FORMAT_R32_SFLOAT, R32_FLOAT, .cpp = 4, .num_channels = 1,),
fmt(VK_FORMAT_R32G32_UINT, R32G32_UINT, .cpp = 8, .num_channels = 2,),
fmt(VK_FORMAT_R32G32_SINT, R32G32_SINT, .cpp = 8, .num_channels = 2,),
fmt(VK_FORMAT_R32G32_SFLOAT, R32G32_FLOAT, .cpp = 8, .num_channels = 2,),
fmt(VK_FORMAT_R32G32B32_UINT, R32G32B32_UINT, .cpp = 12, .num_channels = 3,),
fmt(VK_FORMAT_R32G32B32_SINT, R32G32B32_SINT, .cpp = 12, .num_channels = 3,),
fmt(VK_FORMAT_R32G32B32_SFLOAT, R32G32B32_FLOAT, .cpp = 12, .num_channels = 3,),
fmt(VK_FORMAT_R32G32B32A32_UINT, R32G32B32A32_UINT, .cpp = 16, .num_channels = 4,),
fmt(VK_FORMAT_R32G32B32A32_SINT, R32G32B32A32_SINT, .cpp = 16, .num_channels = 4,),
fmt(VK_FORMAT_R32G32B32A32_SFLOAT, R32G32B32A32_FLOAT, .cpp = 16, .num_channels = 4,),
fmt(VK_FORMAT_R64_SFLOAT, R64_FLOAT, .cpp = 8, .num_channels = 1),
fmt(VK_FORMAT_R64G64_SFLOAT, R64G64_FLOAT, .cpp = 16, .num_channels = 2),
fmt(VK_FORMAT_R64G64B64_SFLOAT, R64G64B64_FLOAT, .cpp = 24, .num_channels = 3),
fmt(VK_FORMAT_R64G64B64A64_SFLOAT, R64G64B64A64_FLOAT, .cpp = 32, .num_channels = 4),
fmt(VK_FORMAT_R11G11B10_UFLOAT, R11G11B10_FLOAT, .cpp = 4, .num_channels = 3),
fmt(VK_FORMAT_R9G9B9E5_UFLOAT, R9G9B9E5_SHAREDEXP, .cpp = 4, .num_channels = 3),
fmt(VK_FORMAT_D16_UNORM, R16_UNORM, .cpp = 2, .num_channels = 1, .depth_format = D16_UNORM),
fmt(VK_FORMAT_D24_UNORM, R24_UNORM_X8_TYPELESS, .cpp = 4, .num_channels = 1, .depth_format = D24_UNORM_X8_UINT),
fmt(VK_FORMAT_D32_SFLOAT, R32_FLOAT, .cpp = 4, .num_channels = 1, .depth_format = D32_FLOAT),
fmt(VK_FORMAT_S8_UINT, R8_UINT, .cpp = 1, .num_channels = 1, .has_stencil = true),
fmt(VK_FORMAT_D16_UNORM_S8_UINT, R16_UNORM, .cpp = 2, .num_channels = 2, .depth_format = D16_UNORM, .has_stencil = true),
fmt(VK_FORMAT_D24_UNORM_S8_UINT, R24_UNORM_X8_TYPELESS, .cpp = 4, .num_channels = 2, .depth_format = D24_UNORM_X8_UINT, .has_stencil = true),
fmt(VK_FORMAT_D32_SFLOAT_S8_UINT, R32_FLOAT, .cpp = 4, .num_channels = 2, .depth_format = D32_FLOAT, .has_stencil = true),
fmt(VK_FORMAT_BC1_RGB_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC1_RGB_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_BC1_RGBA_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC1_RGBA_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_BC2_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC2_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_BC3_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC3_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_BC4_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC4_SNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC5_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC5_SNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC6H_UFLOAT, UNSUPPORTED),
fmt(VK_FORMAT_BC6H_SFLOAT, UNSUPPORTED),
fmt(VK_FORMAT_BC7_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_BC7_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ETC2_R8G8B8_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ETC2_R8G8B8_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ETC2_R8G8B8A1_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ETC2_R8G8B8A1_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ETC2_R8G8B8A8_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ETC2_R8G8B8A8_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_EAC_R11_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_EAC_R11_SNORM, UNSUPPORTED),
fmt(VK_FORMAT_EAC_R11G11_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_EAC_R11G11_SNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_4x4_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_4x4_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_5x4_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_5x4_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_5x5_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_5x5_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_6x5_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_6x5_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_6x6_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_6x6_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_8x5_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_8x5_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_8x6_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_8x6_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_8x8_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_8x8_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_10x5_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_10x5_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_10x6_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_10x6_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_10x8_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_10x8_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_10x10_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_10x10_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_12x10_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_12x10_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_12x12_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_ASTC_12x12_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_B4G4R4A4_UNORM, B4G4R4A4_UNORM, .cpp = 2, .num_channels = 4),
fmt(VK_FORMAT_B5G5R5A1_UNORM, B5G5R5A1_UNORM, .cpp = 2, .num_channels = 4),
fmt(VK_FORMAT_B5G6R5_UNORM, B5G6R5_UNORM, .cpp = 2, .num_channels = 3),
fmt(VK_FORMAT_B5G6R5_USCALED, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8_UNORM, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8_SNORM, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8_USCALED, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8_SSCALED, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8_UINT, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8_SINT, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8_SRGB, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8A8_UNORM, B8G8R8A8_UNORM, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_B8G8R8A8_SNORM, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8A8_USCALED, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8A8_SSCALED, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8A8_UINT, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8A8_SINT, UNSUPPORTED),
fmt(VK_FORMAT_B8G8R8A8_SRGB, B8G8R8A8_UNORM_SRGB, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_B10G10R10A2_UNORM, B10G10R10A2_UNORM, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_B10G10R10A2_SNORM, B10G10R10A2_SNORM, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_B10G10R10A2_USCALED, B10G10R10A2_USCALED, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_B10G10R10A2_SSCALED, B10G10R10A2_SSCALED, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_B10G10R10A2_UINT, B10G10R10A2_UINT, .cpp = 4, .num_channels = 4),
fmt(VK_FORMAT_B10G10R10A2_SINT, B10G10R10A2_SINT, .cpp = 4, .num_channels = 4)
};
#undef fmt
const struct anv_format *const
anv_format_s8_uint = &anv_formats[VK_FORMAT_S8_UINT];
const struct anv_format *
anv_format_for_vk_format(VkFormat format)
{
return &anv_formats[format];
}
// Format capabilities
struct surface_format_info {
bool exists;
int sampling;
int filtering;
int shadow_compare;
int chroma_key;
int render_target;
int alpha_blend;
int input_vb;
int streamed_output_vb;
int color_processing;
};
extern const struct surface_format_info surface_formats[];
VkResult anv_validate_GetPhysicalDeviceFormatProperties(
VkPhysicalDevice physicalDevice,
VkFormat _format,
VkFormatProperties* pFormatProperties)
{
const struct anv_format *format = anv_format_for_vk_format(_format);
fprintf(stderr, "vkGetFormatProperties(%s)\n", format->name);
return anv_GetPhysicalDeviceFormatProperties(physicalDevice, _format, pFormatProperties);
}
VkResult anv_GetPhysicalDeviceFormatProperties(
VkPhysicalDevice physicalDevice,
VkFormat _format,
VkFormatProperties* pFormatProperties)
{
ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
const struct surface_format_info *info;
int gen;
const struct anv_format *format = anv_format_for_vk_format(_format);
if (format == NULL)
return vk_error(VK_ERROR_INVALID_VALUE);
gen = physical_device->info->gen * 10;
if (physical_device->info->is_haswell)
gen += 5;
if (format->surface_format == UNSUPPORTED)
goto unsupported;
uint32_t linear = 0, tiled = 0;
if (anv_format_is_depth_or_stencil(format)) {
tiled |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
} else {
/* The surface_formats table only contains color formats */
info = &surface_formats[format->surface_format];
if (!info->exists)
goto unsupported;
if (info->sampling <= gen) {
linear |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
tiled |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
}
if (info->render_target <= gen) {
linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
}
if (info->alpha_blend <= gen) {
linear |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
tiled |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
}
if (info->input_vb <= gen) {
linear |= VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
}
}
pFormatProperties->linearTilingFeatures = linear;
pFormatProperties->optimalTilingFeatures = tiled;
return VK_SUCCESS;
unsupported:
pFormatProperties->linearTilingFeatures = 0;
pFormatProperties->optimalTilingFeatures = 0;
return VK_SUCCESS;
}
VkResult anv_GetPhysicalDeviceImageFormatProperties(
VkPhysicalDevice physicalDevice,
VkFormat format,
VkImageType type,
VkImageTiling tiling,
VkImageUsageFlags usage,
VkImageFormatProperties* pImageFormatProperties)
{
/* TODO: We should do something here. Chad? */
stub_return(VK_UNSUPPORTED);
}
VkResult anv_GetPhysicalDeviceSparseImageFormatProperties(
VkPhysicalDevice physicalDevice,
VkFormat format,
VkImageType type,
uint32_t samples,
VkImageUsageFlags usage,
VkImageTiling tiling,
uint32_t* pNumProperties,
VkSparseImageFormatProperties* pProperties)
{
stub_return(VK_UNSUPPORTED);
}

279
src/vulkan/anv_gem.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#define _DEFAULT_SOURCE
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s)))
static int
anv_ioctl(int fd, unsigned long request, void *arg)
{
int ret;
do {
ret = ioctl(fd, request, arg);
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
return ret;
}
/**
* Wrapper around DRM_IOCTL_I915_GEM_CREATE.
*
* Return gem handle, or 0 on failure. Gem handles are never 0.
*/
uint32_t
anv_gem_create(struct anv_device *device, size_t size)
{
struct drm_i915_gem_create gem_create;
int ret;
VG_CLEAR(gem_create);
gem_create.size = size;
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create);
if (ret != 0) {
/* FIXME: What do we do if this fails? */
return 0;
}
return gem_create.handle;
}
void
anv_gem_close(struct anv_device *device, int gem_handle)
{
struct drm_gem_close close;
VG_CLEAR(close);
close.handle = gem_handle;
anv_ioctl(device->fd, DRM_IOCTL_GEM_CLOSE, &close);
}
/**
* Wrapper around DRM_IOCTL_I915_GEM_MMAP.
*/
void*
anv_gem_mmap(struct anv_device *device, uint32_t gem_handle,
uint64_t offset, uint64_t size)
{
struct drm_i915_gem_mmap gem_mmap;
int ret;
gem_mmap.handle = gem_handle;
VG_CLEAR(gem_mmap.pad);
gem_mmap.offset = offset;
gem_mmap.size = size;
VG_CLEAR(gem_mmap.addr_ptr);
#ifdef I915_MMAP_WC
gem_mmap.flags = 0;
#endif
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_mmap);
if (ret != 0) {
/* FIXME: Is NULL the right error return? Cf MAP_INVALID */
return NULL;
}
VG(VALGRIND_MALLOCLIKE_BLOCK(gem_mmap.addr_ptr, gem_mmap.size, 0, 1));
return (void *)(uintptr_t) gem_mmap.addr_ptr;
}
/* This is just a wrapper around munmap, but it also notifies valgrind that
* this map is no longer valid. Pair this with anv_gem_mmap().
*/
void
anv_gem_munmap(void *p, uint64_t size)
{
VG(VALGRIND_FREELIKE_BLOCK(p, 0));
munmap(p, size);
}
int
anv_gem_userptr(struct anv_device *device, void *mem, size_t size)
{
struct drm_i915_gem_userptr userptr;
int ret;
VG_CLEAR(userptr);
userptr.user_ptr = (__u64)((unsigned long) mem);
userptr.user_size = size;
userptr.flags = 0;
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr);
if (ret == -1)
return 0;
return userptr.handle;
}
/**
* On error, \a timeout_ns holds the remaining time.
*/
int
anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns)
{
struct drm_i915_gem_wait wait;
int ret;
VG_CLEAR(wait);
wait.bo_handle = gem_handle;
wait.timeout_ns = *timeout_ns;
wait.flags = 0;
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
*timeout_ns = wait.timeout_ns;
return ret;
}
int
anv_gem_execbuffer(struct anv_device *device,
struct drm_i915_gem_execbuffer2 *execbuf)
{
return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
}
int
anv_gem_set_tiling(struct anv_device *device,
int gem_handle, uint32_t stride, uint32_t tiling)
{
struct drm_i915_gem_set_tiling set_tiling;
int ret;
/* set_tiling overwrites the input on the error path, so we have to open
* code anv_ioctl.
*/
do {
VG_CLEAR(set_tiling);
set_tiling.handle = gem_handle;
set_tiling.tiling_mode = I915_TILING_X;
set_tiling.stride = stride;
ret = ioctl(device->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling);
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
return ret;
}
int
anv_gem_get_param(int fd, uint32_t param)
{
drm_i915_getparam_t gp;
int ret, tmp;
VG_CLEAR(gp);
gp.param = param;
gp.value = &tmp;
ret = anv_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
if (ret == 0)
return tmp;
return 0;
}
int
anv_gem_create_context(struct anv_device *device)
{
struct drm_i915_gem_context_create create;
int ret;
VG_CLEAR(create);
ret = anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
if (ret == -1)
return -1;
return create.ctx_id;
}
int
anv_gem_destroy_context(struct anv_device *device, int context)
{
struct drm_i915_gem_context_destroy destroy;
VG_CLEAR(destroy);
destroy.ctx_id = context;
return anv_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy);
}
int
anv_gem_get_aperture(int fd, uint64_t *size)
{
struct drm_i915_gem_get_aperture aperture;
int ret;
VG_CLEAR(aperture);
ret = anv_ioctl(fd, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
if (ret == -1)
return -1;
*size = aperture.aper_available_size;
return 0;
}
int
anv_gem_handle_to_fd(struct anv_device *device, int gem_handle)
{
struct drm_prime_handle args;
int ret;
VG_CLEAR(args);
args.handle = gem_handle;
args.flags = DRM_CLOEXEC;
ret = anv_ioctl(device->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
if (ret == -1)
return -1;
return args.fd;
}
int
anv_gem_fd_to_handle(struct anv_device *device, int fd)
{
struct drm_prime_handle args;
int ret;
VG_CLEAR(args);
args.fd = fd;
ret = anv_ioctl(device->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
if (ret == -1)
return 0;
return args.handle;
}

136
src/vulkan/anv_gem_stubs.c Normal file
View File

@@ -0,0 +1,136 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#define _DEFAULT_SOURCE
#include <linux/memfd.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include "anv_private.h"
static inline int
memfd_create(const char *name, unsigned int flags)
{
return syscall(SYS_memfd_create, name, flags);
}
uint32_t
anv_gem_create(struct anv_device *device, size_t size)
{
int fd = memfd_create("fake bo", MFD_CLOEXEC);
if (fd == -1)
return 0;
assert(fd != 0);
if (ftruncate(fd, size) == -1)
return 0;
return fd;
}
void
anv_gem_close(struct anv_device *device, int gem_handle)
{
close(gem_handle);
}
void*
anv_gem_mmap(struct anv_device *device, uint32_t gem_handle,
uint64_t offset, uint64_t size)
{
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
gem_handle, offset);
}
/* This is just a wrapper around munmap, but it also notifies valgrind that
* this map is no longer valid. Pair this with anv_gem_mmap().
*/
void
anv_gem_munmap(void *p, uint64_t size)
{
munmap(p, size);
}
int
anv_gem_userptr(struct anv_device *device, void *mem, size_t size)
{
return -1;
}
int
anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns)
{
return 0;
}
int
anv_gem_execbuffer(struct anv_device *device,
struct drm_i915_gem_execbuffer2 *execbuf)
{
return 0;
}
int
anv_gem_set_tiling(struct anv_device *device,
int gem_handle, uint32_t stride, uint32_t tiling)
{
return 0;
}
int
anv_gem_get_param(int fd, uint32_t param)
{
unreachable("Unused");
}
int
anv_gem_create_context(struct anv_device *device)
{
unreachable("Unused");
}
int
anv_gem_destroy_context(struct anv_device *device, int context)
{
unreachable("Unused");
}
int
anv_gem_get_aperture(int fd, uint64_t *size)
{
unreachable("Unused");
}
int
anv_gem_handle_to_fd(struct anv_device *device, int gem_handle)
{
unreachable("Unused");
}
int
anv_gem_fd_to_handle(struct anv_device *device, int fd)
{
unreachable("Unused");
}

View File

@@ -0,0 +1,8 @@
{
"file_format_version": "1.0.0",
"ICD": {
"library_path": "@abs_top_builddir@/lib/libvulkan.so.0.0.0",
"abi_versions": "0.138.2"
}
}

637
src/vulkan/anv_image.c Normal file
View File

@@ -0,0 +1,637 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
static const uint8_t anv_halign[] = {
[4] = HALIGN4,
[8] = HALIGN8,
[16] = HALIGN16,
};
static const uint8_t anv_valign[] = {
[4] = VALIGN4,
[8] = VALIGN8,
[16] = VALIGN16,
};
static const uint8_t anv_surf_type_from_image_type[] = {
[VK_IMAGE_TYPE_1D] = SURFTYPE_1D,
[VK_IMAGE_TYPE_2D] = SURFTYPE_2D,
[VK_IMAGE_TYPE_3D] = SURFTYPE_3D,
};
static const struct anv_image_view_info
anv_image_view_info_table[] = {
#define INFO(s, ...) { .surface_type = s, __VA_ARGS__ }
[VK_IMAGE_VIEW_TYPE_1D] = INFO(SURFTYPE_1D),
[VK_IMAGE_VIEW_TYPE_2D] = INFO(SURFTYPE_2D),
[VK_IMAGE_VIEW_TYPE_3D] = INFO(SURFTYPE_3D),
[VK_IMAGE_VIEW_TYPE_CUBE] = INFO(SURFTYPE_CUBE, .is_cube = 1),
[VK_IMAGE_VIEW_TYPE_1D_ARRAY] = INFO(SURFTYPE_1D, .is_array = 1),
[VK_IMAGE_VIEW_TYPE_2D_ARRAY] = INFO(SURFTYPE_2D, .is_array = 1),
[VK_IMAGE_VIEW_TYPE_CUBE_ARRAY] = INFO(SURFTYPE_CUBE, .is_array = 1, .is_cube = 1),
#undef INFO
};
const struct anv_image_view_info *
anv_image_view_info_for_vk_image_view_type(VkImageViewType type)
{
return &anv_image_view_info_table[type];
}
static const struct anv_surf_type_limits {
int32_t width;
int32_t height;
int32_t depth;
} anv_surf_type_limits[] = {
[SURFTYPE_1D] = {16384, 1, 2048},
[SURFTYPE_2D] = {16384, 16384, 2048},
[SURFTYPE_3D] = {2048, 2048, 2048},
[SURFTYPE_CUBE] = {16384, 16384, 340},
[SURFTYPE_BUFFER] = {128, 16384, 64},
[SURFTYPE_STRBUF] = {128, 16384, 64},
};
static const struct anv_tile_info {
uint32_t width;
uint32_t height;
/**
* Alignment for RENDER_SURFACE_STATE.SurfaceBaseAddress.
*
* To simplify calculations, the alignments defined in the table are
* sometimes larger than required. For example, Skylake requires that X and
* Y tiled buffers be aligned to 4K, but Broadwell permits smaller
* alignment. We choose 4K to accomodate both chipsets. The alignment of
* a linear buffer depends on its element type and usage. Linear depth
* buffers have the largest alignment, 64B, so we choose that for all linear
* buffers.
*/
uint32_t surface_alignment;
} anv_tile_info_table[] = {
[LINEAR] = { 1, 1, 64 },
[XMAJOR] = { 512, 8, 4096 },
[YMAJOR] = { 128, 32, 4096 },
[WMAJOR] = { 128, 32, 4096 },
};
/**
* Return -1 on failure.
*/
static int8_t
anv_image_choose_tile_mode(const struct anv_image_create_info *anv_info)
{
if (anv_info->force_tile_mode)
return anv_info->tile_mode;
/* The Sandybridge PRM says that the stencil buffer "is supported
* only in Tile W memory".
*/
switch (anv_info->vk_info->tiling) {
case VK_IMAGE_TILING_LINEAR:
if (unlikely(anv_info->vk_info->format == VK_FORMAT_S8_UINT)) {
return -1;
} else {
return LINEAR;
}
case VK_IMAGE_TILING_OPTIMAL:
if (unlikely(anv_info->vk_info->format == VK_FORMAT_S8_UINT)) {
return WMAJOR;
} else {
return YMAJOR;
}
default:
assert(!"bad VKImageTiling");
return LINEAR;
}
}
/**
* The \a format argument is required and overrides any format in
* struct anv_image_create_info.
*/
static VkResult
anv_image_make_surface(const struct anv_image_create_info *create_info,
const struct anv_format *format,
uint64_t *inout_image_size,
uint32_t *inout_image_alignment,
struct anv_surface *out_surface)
{
/* See RENDER_SURFACE_STATE.SurfaceQPitch */
static const uint16_t min_qpitch UNUSED = 0x4;
static const uint16_t max_qpitch UNUSED = 0x1ffc;
const VkExtent3D *restrict extent = &create_info->vk_info->extent;
const uint32_t levels = create_info->vk_info->mipLevels;
const uint32_t array_size = create_info->vk_info->arraySize;
const int8_t tile_mode = anv_image_choose_tile_mode(create_info);
if (tile_mode == -1)
return vk_error(VK_ERROR_INVALID_IMAGE);
const struct anv_tile_info *tile_info =
&anv_tile_info_table[tile_mode];
const uint32_t i = 4; /* FINISHME: Stop hardcoding subimage alignment */
const uint32_t j = 4; /* FINISHME: Stop hardcoding subimage alignment */
uint16_t qpitch = min_qpitch;
uint32_t mt_width = 0;
uint32_t mt_height = 0;
switch (create_info->vk_info->imageType) {
case VK_IMAGE_TYPE_1D:
/* From the Broadwell PRM >> Memory Views >> Common Surface Formats >>
* Surface Layout >> 1D Surfaces:
*
* One-dimensional surfaces are identical to 2D surfaces with height of one.
*
* So fallthrough...
*/
case VK_IMAGE_TYPE_2D: {
const uint32_t w0 = align_u32(extent->width, i);
const uint32_t h0 = align_u32(extent->height, j);
if (levels == 1 && array_size == 1) {
qpitch = min_qpitch;
mt_width = w0;
mt_height = h0;
} else {
uint32_t w1 = align_u32(anv_minify(extent->width, 1), i);
uint32_t h1 = align_u32(anv_minify(extent->height, 1), j);
uint32_t w2 = align_u32(anv_minify(extent->width, 2), i);
/* The QPitch equation is found in the Broadwell PRM >> Volume 5: Memory
* Views >> Common Surface Formats >> Surface Layout >> 2D Surfaces >>
* Surface Arrays >> For All Surface Other Than Separate Stencil Buffer:
*/
qpitch = h0 + h1 + 11 * j;
mt_width = MAX(w0, w1 + w2);
mt_height = array_size * qpitch;
}
break;
}
case VK_IMAGE_TYPE_3D:
/* The layout of 3D surfaces is described by the Broadwell PRM >>
* Volume 5: Memory Views >> Common Surface Formats >> Surface Layout >>
* 3D Surfaces.
*/
for (uint32_t l = 0; l < levels; ++l) {
const uint32_t w_l = align_u32(anv_minify(extent->width, l), i);
const uint32_t h_l = align_u32(anv_minify(extent->height, l), j);
const uint32_t d_l = anv_minify(extent->depth, l);
const uint32_t max_layers_horiz = MIN(d_l, 1u << l);
const uint32_t max_layers_vert = align_u32(d_l, 1u << l) / (1u << l);
mt_width = MAX(mt_width, w_l * max_layers_horiz);
mt_height += h_l * max_layers_vert;
}
break;
default:
unreachable(!"bad VkImageType");
}
assert(qpitch >= min_qpitch);
if (qpitch > max_qpitch) {
anv_loge("image qpitch > 0x%x\n", max_qpitch);
return vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
}
/* From the Broadwell PRM, RENDER_SURFACE_STATE.SurfaceQpitch:
*
* This field must be set an integer multiple of the Surface Vertical
* Alignment.
*/
assert(anv_is_aligned(qpitch, j));
uint32_t stride = align_u32(mt_width * format->cpp, tile_info->width);
if (create_info->stride > 0)
stride = create_info->stride;
const uint32_t size = stride * align_u32(mt_height, tile_info->height);
const uint32_t offset = align_u32(*inout_image_size,
tile_info->surface_alignment);
*inout_image_size = offset + size;
*inout_image_alignment = MAX(*inout_image_alignment,
tile_info->surface_alignment);
*out_surface = (struct anv_surface) {
.offset = offset,
.stride = stride,
.tile_mode = tile_mode,
.qpitch = qpitch,
.h_align = i,
.v_align = j,
};
return VK_SUCCESS;
}
VkResult
anv_image_create(VkDevice _device,
const struct anv_image_create_info *create_info,
VkImage *pImage)
{
ANV_FROM_HANDLE(anv_device, device, _device);
const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
const VkExtent3D *restrict extent = &pCreateInfo->extent;
struct anv_image *image = NULL;
VkResult r;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
anv_assert(pCreateInfo->mipLevels > 0);
anv_assert(pCreateInfo->arraySize > 0);
anv_assert(pCreateInfo->samples == 1);
anv_assert(pCreateInfo->extent.width > 0);
anv_assert(pCreateInfo->extent.height > 0);
anv_assert(pCreateInfo->extent.depth > 0);
/* TODO(chadv): How should we validate inputs? */
const uint8_t surf_type =
anv_surf_type_from_image_type[pCreateInfo->imageType];
const struct anv_surf_type_limits *limits =
&anv_surf_type_limits[surf_type];
if (extent->width > limits->width ||
extent->height > limits->height ||
extent->depth > limits->depth) {
/* TODO(chadv): What is the correct error? */
return vk_errorf(VK_ERROR_INVALID_MEMORY_SIZE, "image extent is too large");
}
image = anv_device_alloc(device, sizeof(*image), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (!image)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
memset(image, 0, sizeof(*image));
image->type = pCreateInfo->imageType;
image->extent = pCreateInfo->extent;
image->format = anv_format_for_vk_format(pCreateInfo->format);
image->levels = pCreateInfo->mipLevels;
image->array_size = pCreateInfo->arraySize;
image->surf_type = surf_type;
if (likely(anv_format_is_color(image->format))) {
r = anv_image_make_surface(create_info, image->format,
&image->size, &image->alignment,
&image->color_surface);
if (r != VK_SUCCESS)
goto fail;
} else {
if (image->format->depth_format) {
r = anv_image_make_surface(create_info, image->format,
&image->size, &image->alignment,
&image->depth_surface);
if (r != VK_SUCCESS)
goto fail;
}
if (image->format->has_stencil) {
r = anv_image_make_surface(create_info, anv_format_s8_uint,
&image->size, &image->alignment,
&image->stencil_surface);
if (r != VK_SUCCESS)
goto fail;
}
}
*pImage = anv_image_to_handle(image);
return VK_SUCCESS;
fail:
if (image)
anv_device_free(device, image);
return r;
}
VkResult
anv_CreateImage(VkDevice device,
const VkImageCreateInfo *pCreateInfo,
VkImage *pImage)
{
return anv_image_create(device,
&(struct anv_image_create_info) {
.vk_info = pCreateInfo,
},
pImage);
}
VkResult
anv_DestroyImage(VkDevice _device, VkImage _image)
{
ANV_FROM_HANDLE(anv_device, device, _device);
anv_device_free(device, anv_image_from_handle(_image));
return VK_SUCCESS;
}
VkResult anv_GetImageSubresourceLayout(
VkDevice device,
VkImage image,
const VkImageSubresource* pSubresource,
VkSubresourceLayout* pLayout)
{
stub_return(VK_UNSUPPORTED);
}
void
anv_surface_view_fini(struct anv_device *device,
struct anv_surface_view *view)
{
anv_state_pool_free(&device->surface_state_pool, view->surface_state);
}
VkResult
anv_validate_CreateImageView(VkDevice _device,
const VkImageViewCreateInfo *pCreateInfo,
VkImageView *pView)
{
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
const VkImageSubresourceRange *subresource;
const struct anv_image_view_info *view_info;
const struct anv_format *view_format_info;
/* Validate structure type before dereferencing it. */
assert(pCreateInfo);
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO);
subresource = &pCreateInfo->subresourceRange;
/* Validate viewType is in range before using it. */
assert(pCreateInfo->viewType >= VK_IMAGE_VIEW_TYPE_BEGIN_RANGE);
assert(pCreateInfo->viewType <= VK_IMAGE_VIEW_TYPE_END_RANGE);
view_info = &anv_image_view_info_table[pCreateInfo->viewType];
/* Validate format is in range before using it. */
assert(pCreateInfo->format >= VK_FORMAT_BEGIN_RANGE);
assert(pCreateInfo->format <= VK_FORMAT_END_RANGE);
view_format_info = anv_format_for_vk_format(pCreateInfo->format);
/* Validate channel swizzles. */
assert(pCreateInfo->channels.r >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
assert(pCreateInfo->channels.r <= VK_CHANNEL_SWIZZLE_END_RANGE);
assert(pCreateInfo->channels.g >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
assert(pCreateInfo->channels.g <= VK_CHANNEL_SWIZZLE_END_RANGE);
assert(pCreateInfo->channels.b >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
assert(pCreateInfo->channels.b <= VK_CHANNEL_SWIZZLE_END_RANGE);
assert(pCreateInfo->channels.a >= VK_CHANNEL_SWIZZLE_BEGIN_RANGE);
assert(pCreateInfo->channels.a <= VK_CHANNEL_SWIZZLE_END_RANGE);
/* Validate subresource. */
assert(subresource->aspect >= VK_IMAGE_ASPECT_BEGIN_RANGE);
assert(subresource->aspect <= VK_IMAGE_ASPECT_END_RANGE);
assert(subresource->mipLevels > 0);
assert(subresource->arraySize > 0);
assert(subresource->baseMipLevel < image->levels);
assert(subresource->baseMipLevel + subresource->mipLevels <= image->levels);
assert(subresource->baseArraySlice < image->array_size);
assert(subresource->baseArraySlice + subresource->arraySize <= image->array_size);
assert(pView);
if (view_info->is_cube) {
assert(subresource->baseArraySlice % 6 == 0);
assert(subresource->arraySize % 6 == 0);
}
/* Validate format. */
switch (subresource->aspect) {
case VK_IMAGE_ASPECT_COLOR:
assert(!image->format->depth_format);
assert(!image->format->has_stencil);
assert(!view_format_info->depth_format);
assert(!view_format_info->has_stencil);
assert(view_format_info->cpp == image->format->cpp);
break;
case VK_IMAGE_ASPECT_DEPTH:
assert(image->format->depth_format);
assert(view_format_info->depth_format);
assert(view_format_info->cpp == image->format->cpp);
break;
case VK_IMAGE_ASPECT_STENCIL:
/* FINISHME: Is it legal to have an R8 view of S8? */
assert(image->format->has_stencil);
assert(view_format_info->has_stencil);
break;
default:
assert(!"bad VkImageAspect");
break;
}
return anv_CreateImageView(_device, pCreateInfo, pView);
}
void
anv_image_view_init(struct anv_image_view *iview,
struct anv_device *device,
const VkImageViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
{
switch (device->info.gen) {
case 7:
gen7_image_view_init(iview, device, pCreateInfo, cmd_buffer);
break;
case 8:
gen8_image_view_init(iview, device, pCreateInfo, cmd_buffer);
break;
default:
unreachable("unsupported gen\n");
}
}
VkResult
anv_CreateImageView(VkDevice _device,
const VkImageViewCreateInfo *pCreateInfo,
VkImageView *pView)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_image_view *view;
view = anv_device_alloc(device, sizeof(*view), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (view == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
anv_image_view_init(view, device, pCreateInfo, NULL);
*pView = anv_image_view_to_handle(view);
return VK_SUCCESS;
}
VkResult
anv_DestroyImageView(VkDevice _device, VkImageView _iview)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_image_view, iview, _iview);
anv_surface_view_fini(device, &iview->view);
anv_device_free(device, iview);
return VK_SUCCESS;
}
static void
anv_depth_stencil_view_init(struct anv_depth_stencil_view *view,
const VkAttachmentViewCreateInfo *pCreateInfo)
{
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
view->base.attachment_type = ANV_ATTACHMENT_VIEW_TYPE_DEPTH_STENCIL;
/* XXX: We don't handle any of these */
anv_assert(pCreateInfo->mipLevel == 0);
anv_assert(pCreateInfo->baseArraySlice == 0);
anv_assert(pCreateInfo->arraySize == 1);
view->image = image;
view->format = anv_format_for_vk_format(pCreateInfo->format);
assert(anv_format_is_depth_or_stencil(image->format));
assert(anv_format_is_depth_or_stencil(view->format));
}
struct anv_surface *
anv_image_get_surface_for_aspect(struct anv_image *image, VkImageAspect aspect)
{
switch (aspect) {
case VK_IMAGE_ASPECT_COLOR:
assert(anv_format_is_color(image->format));
return &image->color_surface;
case VK_IMAGE_ASPECT_DEPTH:
assert(image->format->depth_format);
return &image->depth_surface;
case VK_IMAGE_ASPECT_STENCIL:
assert(image->format->has_stencil);
anv_finishme("stencil image views");
return &image->stencil_surface;
default:
unreachable("image does not have aspect");
return NULL;
}
}
/** The attachment may be a color view into a non-color image. */
struct anv_surface *
anv_image_get_surface_for_color_attachment(struct anv_image *image)
{
if (anv_format_is_color(image->format)) {
return &image->color_surface;
} else if (image->format->depth_format) {
return &image->depth_surface;
} else if (image->format->has_stencil) {
return &image->stencil_surface;
} else {
unreachable("image has bad format");
return NULL;
}
}
void
anv_color_attachment_view_init(struct anv_color_attachment_view *aview,
struct anv_device *device,
const VkAttachmentViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
{
switch (device->info.gen) {
case 7:
gen7_color_attachment_view_init(aview, device, pCreateInfo, cmd_buffer);
break;
case 8:
gen8_color_attachment_view_init(aview, device, pCreateInfo, cmd_buffer);
break;
default:
unreachable("unsupported gen\n");
}
}
VkResult
anv_CreateAttachmentView(VkDevice _device,
const VkAttachmentViewCreateInfo *pCreateInfo,
VkAttachmentView *pView)
{
ANV_FROM_HANDLE(anv_device, device, _device);
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO);
const struct anv_format *format =
anv_format_for_vk_format(pCreateInfo->format);
if (anv_format_is_depth_or_stencil(format)) {
struct anv_depth_stencil_view *view =
anv_device_alloc(device, sizeof(*view), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (view == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
anv_depth_stencil_view_init(view, pCreateInfo);
*pView = anv_attachment_view_to_handle(&view->base);
} else {
struct anv_color_attachment_view *view =
anv_device_alloc(device, sizeof(*view), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (view == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
anv_color_attachment_view_init(view, device, pCreateInfo, NULL);
*pView = anv_attachment_view_to_handle(&view->base);
}
return VK_SUCCESS;
}
VkResult
anv_DestroyAttachmentView(VkDevice _device, VkAttachmentView _view)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_attachment_view, view, _view);
if (view->attachment_type == ANV_ATTACHMENT_VIEW_TYPE_COLOR) {
struct anv_color_attachment_view *aview =
(struct anv_color_attachment_view *)view;
anv_surface_view_fini(device, &aview->view);
}
anv_device_free(device, view);
return VK_SUCCESS;
}

109
src/vulkan/anv_intel.c Normal file
View File

@@ -0,0 +1,109 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
VkResult anv_CreateDmaBufImageINTEL(
VkDevice _device,
const VkDmaBufImageCreateInfo* pCreateInfo,
VkDeviceMemory* pMem,
VkImage* pImage)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_device_memory *mem;
struct anv_image *image;
VkResult result;
VkImage image_h;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL);
mem = anv_device_alloc(device, sizeof(*mem), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (mem == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
mem->bo.gem_handle = anv_gem_fd_to_handle(device, pCreateInfo->fd);
if (!mem->bo.gem_handle) {
result = vk_error(VK_ERROR_OUT_OF_DEVICE_MEMORY);
goto fail;
}
mem->bo.map = NULL;
mem->bo.index = 0;
mem->bo.offset = 0;
mem->bo.size = pCreateInfo->strideInBytes * pCreateInfo->extent.height;
image = anv_device_alloc(device, sizeof(*image), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (image == NULL) {
result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
goto fail_mem;
}
anv_image_create(_device,
&(struct anv_image_create_info) {
.force_tile_mode = true,
.tile_mode = XMAJOR,
.stride = pCreateInfo->strideInBytes,
.vk_info =
&(VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
.format = pCreateInfo->format,
.extent = pCreateInfo->extent,
.mipLevels = 1,
.arraySize = 1,
.samples = 1,
/* FIXME: Need a way to use X tiling to allow scanout */
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.flags = 0,
}},
&image_h);
image = anv_image_from_handle(image_h);
image->bo = &mem->bo;
image->offset = 0;
assert(image->extent.width > 0);
assert(image->extent.height > 0);
assert(image->extent.depth == 1);
*pMem = anv_device_memory_to_handle(mem);
*pImage = anv_image_to_handle(image);
return VK_SUCCESS;
fail_mem:
anv_gem_close(device, mem->bo.gem_handle);
fail:
anv_device_free(device, mem);
return result;
}

1668
src/vulkan/anv_meta.c Normal file

File diff suppressed because it is too large Load Diff

46
src/vulkan/anv_nir.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#pragma once
#include "glsl/nir/nir.h"
#include "anv_private.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline VkShaderStage
anv_vk_shader_stage_for_mesa_stage(gl_shader_stage stage)
{
/* The two enums happen to line up. */
return (VkShaderStage)(int)stage;
}
void anv_nir_apply_dynamic_offsets(struct anv_pipeline *pipeline,
nir_shader *shader,
struct brw_stage_prog_data *prog_data);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,150 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "anv_nir.h"
#include "glsl/nir/nir_builder.h"
struct apply_dynamic_offsets_state {
nir_shader *shader;
nir_builder builder;
VkShaderStage stage;
struct anv_pipeline_layout *layout;
uint32_t indices_start;
};
static bool
apply_dynamic_offsets_block(nir_block *block, void *void_state)
{
struct apply_dynamic_offsets_state *state = void_state;
struct anv_descriptor_set_layout *set_layout;
const struct anv_descriptor_slot *slot;
nir_foreach_instr_safe(block, instr) {
if (instr->type != nir_instr_type_intrinsic)
continue;
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
bool has_indirect = false;
uint32_t set, binding;
switch (intrin->intrinsic) {
case nir_intrinsic_load_ubo_indirect:
has_indirect = true;
/* fallthrough */
case nir_intrinsic_load_ubo: {
set = intrin->const_index[0];
nir_const_value *const_binding = nir_src_as_const_value(intrin->src[0]);
if (const_binding) {
binding = const_binding->u[0];
} else {
assert(0 && "need more info from the ir for this.");
}
break;
}
default:
continue; /* the loop */
}
set_layout = state->layout->set[set].layout;
slot = &set_layout->stage[state->stage].surface_start[binding];
if (slot->dynamic_slot < 0)
continue;
uint32_t dynamic_index = state->layout->set[set].dynamic_offset_start +
slot->dynamic_slot;
state->builder.cursor = nir_before_instr(&intrin->instr);
nir_intrinsic_instr *offset_load =
nir_intrinsic_instr_create(state->shader, nir_intrinsic_load_uniform);
offset_load->num_components = 1;
offset_load->const_index[0] = state->indices_start + dynamic_index;
offset_load->const_index[1] = 0;
nir_ssa_dest_init(&offset_load->instr, &offset_load->dest, 1, NULL);
nir_builder_instr_insert(&state->builder, &offset_load->instr);
nir_ssa_def *offset = &offset_load->dest.ssa;
if (has_indirect) {
assert(intrin->src[1].is_ssa);
offset = nir_iadd(&state->builder, intrin->src[1].ssa, offset);
}
assert(intrin->dest.is_ssa);
nir_intrinsic_instr *new_load =
nir_intrinsic_instr_create(state->shader,
nir_intrinsic_load_ubo_indirect);
new_load->num_components = intrin->num_components;
new_load->const_index[0] = intrin->const_index[0];
new_load->const_index[1] = intrin->const_index[1];
nir_src_copy(&new_load->src[0], &intrin->src[0], &new_load->instr);
new_load->src[1] = nir_src_for_ssa(offset);
nir_ssa_dest_init(&new_load->instr, &new_load->dest,
intrin->dest.ssa.num_components,
intrin->dest.ssa.name);
nir_builder_instr_insert(&state->builder, &new_load->instr);
nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
nir_src_for_ssa(&new_load->dest.ssa),
state->shader);
nir_instr_remove(&intrin->instr);
}
return true;
}
void
anv_nir_apply_dynamic_offsets(struct anv_pipeline *pipeline,
nir_shader *shader,
struct brw_stage_prog_data *prog_data)
{
struct apply_dynamic_offsets_state state = {
.shader = shader,
.stage = anv_vk_shader_stage_for_mesa_stage(shader->stage),
.layout = pipeline->layout,
.indices_start = shader->num_uniforms,
};
if (!state.layout || !state.layout->stage[state.stage].has_dynamic_offsets)
return;
nir_foreach_overload(shader, overload) {
if (overload->impl) {
nir_builder_init(&state.builder, overload->impl);
nir_foreach_block(overload->impl, apply_dynamic_offsets_block, &state);
nir_metadata_preserve(overload->impl, nir_metadata_block_index |
nir_metadata_dominance);
}
}
struct anv_push_constants *null_data = NULL;
for (unsigned i = 0; i < MAX_DYNAMIC_BUFFERS; i++)
prog_data->param[i + shader->num_uniforms] =
(const gl_constant_value *)&null_data->dynamic_offsets[i];
shader->num_uniforms += MAX_DYNAMIC_BUFFERS;
}

430
src/vulkan/anv_pipeline.c Normal file
View File

@@ -0,0 +1,430 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
// Shader functions
VkResult anv_CreateShaderModule(
VkDevice _device,
const VkShaderModuleCreateInfo* pCreateInfo,
VkShaderModule* pShaderModule)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_shader_module *module;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
assert(pCreateInfo->flags == 0);
module = anv_device_alloc(device, sizeof(*module) + pCreateInfo->codeSize, 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (module == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
module->size = pCreateInfo->codeSize;
memcpy(module->data, pCreateInfo->pCode, module->size);
*pShaderModule = anv_shader_module_to_handle(module);
return VK_SUCCESS;
}
VkResult anv_DestroyShaderModule(
VkDevice _device,
VkShaderModule _module)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_shader_module, module, _module);
anv_device_free(device, module);
return VK_SUCCESS;
}
VkResult anv_CreateShader(
VkDevice _device,
const VkShaderCreateInfo* pCreateInfo,
VkShader* pShader)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_shader_module, module, pCreateInfo->module);
struct anv_shader *shader;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_CREATE_INFO);
assert(pCreateInfo->flags == 0);
const char *name = pCreateInfo->pName ? pCreateInfo->pName : "main";
size_t name_len = strlen(name);
if (strcmp(name, "main") != 0) {
anv_finishme("Multiple shaders per module not really supported");
}
shader = anv_device_alloc(device, sizeof(*shader) + name_len + 1, 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (shader == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
shader->module = module;
memcpy(shader->entrypoint, name, name_len + 1);
*pShader = anv_shader_to_handle(shader);
return VK_SUCCESS;
}
VkResult anv_DestroyShader(
VkDevice _device,
VkShader _shader)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_shader, shader, _shader);
anv_device_free(device, shader);
return VK_SUCCESS;
}
VkResult anv_CreatePipelineCache(
VkDevice device,
const VkPipelineCacheCreateInfo* pCreateInfo,
VkPipelineCache* pPipelineCache)
{
pPipelineCache->handle = 1;
stub_return(VK_SUCCESS);
}
VkResult anv_DestroyPipelineCache(
VkDevice _device,
VkPipelineCache _cache)
{
/* VkPipelineCache is a dummy object. */
return VK_SUCCESS;
}
size_t anv_GetPipelineCacheSize(
VkDevice device,
VkPipelineCache pipelineCache)
{
stub_return(0);
}
VkResult anv_GetPipelineCacheData(
VkDevice device,
VkPipelineCache pipelineCache,
void* pData)
{
stub_return(VK_UNSUPPORTED);
}
VkResult anv_MergePipelineCaches(
VkDevice device,
VkPipelineCache destCache,
uint32_t srcCacheCount,
const VkPipelineCache* pSrcCaches)
{
stub_return(VK_UNSUPPORTED);
}
VkResult anv_DestroyPipeline(
VkDevice _device,
VkPipeline _pipeline)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline);
anv_compiler_free(pipeline);
anv_reloc_list_finish(&pipeline->batch_relocs, pipeline->device);
anv_state_stream_finish(&pipeline->program_stream);
anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
anv_device_free(pipeline->device, pipeline);
return VK_SUCCESS;
}
static const uint32_t vk_to_gen_primitive_type[] = {
[VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST,
[VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST,
[VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN,
[VK_PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ] = _3DPRIM_LINELIST_ADJ,
[VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ] = _3DPRIM_LINESTRIP_ADJ,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ] = _3DPRIM_TRILIST_ADJ,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ] = _3DPRIM_TRISTRIP_ADJ,
[VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1
};
VkResult
anv_pipeline_init(struct anv_pipeline *pipeline, struct anv_device *device,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const struct anv_graphics_pipeline_create_info *extra)
{
VkResult result;
pipeline->device = device;
pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
result = anv_reloc_list_init(&pipeline->batch_relocs, device);
if (result != VK_SUCCESS) {
anv_device_free(device, pipeline);
return result;
}
pipeline->batch.next = pipeline->batch.start = pipeline->batch_data;
pipeline->batch.end = pipeline->batch.start + sizeof(pipeline->batch_data);
pipeline->batch.relocs = &pipeline->batch_relocs;
anv_state_stream_init(&pipeline->program_stream,
&device->instruction_block_pool);
for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
pipeline->shaders[pCreateInfo->pStages[i].stage] =
anv_shader_from_handle(pCreateInfo->pStages[i].shader);
}
if (pCreateInfo->pTessellationState)
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO");
if (pCreateInfo->pViewportState)
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO");
if (pCreateInfo->pMultisampleState)
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO");
pipeline->use_repclear = extra && extra->use_repclear;
anv_compiler_run(device->compiler, pipeline);
const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
pipeline->ps_ksp2 = 0;
pipeline->ps_grf_start2 = 0;
if (pipeline->ps_simd8 != NO_KERNEL) {
pipeline->ps_ksp0 = pipeline->ps_simd8;
pipeline->ps_grf_start0 = wm_prog_data->base.dispatch_grf_start_reg;
if (pipeline->ps_simd16 != NO_KERNEL) {
pipeline->ps_ksp2 = pipeline->ps_simd16;
pipeline->ps_grf_start2 = wm_prog_data->dispatch_grf_start_reg_16;
}
} else if (pipeline->ps_simd16 != NO_KERNEL) {
pipeline->ps_ksp0 = pipeline->ps_simd16;
pipeline->ps_grf_start0 = wm_prog_data->dispatch_grf_start_reg_16;
} else {
unreachable("no ps shader");
}
const VkPipelineVertexInputStateCreateInfo *vi_info =
pCreateInfo->pVertexInputState;
pipeline->vb_used = 0;
for (uint32_t i = 0; i < vi_info->bindingCount; i++) {
const VkVertexInputBindingDescription *desc =
&vi_info->pVertexBindingDescriptions[i];
pipeline->vb_used |= 1 << desc->binding;
pipeline->binding_stride[desc->binding] = desc->strideInBytes;
/* Step rate is programmed per vertex element (attribute), not
* binding. Set up a map of which bindings step per instance, for
* reference by vertex element setup. */
switch (desc->stepRate) {
default:
case VK_VERTEX_INPUT_STEP_RATE_VERTEX:
pipeline->instancing_enable[desc->binding] = false;
break;
case VK_VERTEX_INPUT_STEP_RATE_INSTANCE:
pipeline->instancing_enable[desc->binding] = true;
break;
}
}
const VkPipelineInputAssemblyStateCreateInfo *ia_info =
pCreateInfo->pInputAssemblyState;
pipeline->primitive_restart = ia_info->primitiveRestartEnable;
pipeline->topology = vk_to_gen_primitive_type[ia_info->topology];
if (extra && extra->use_rectlist)
pipeline->topology = _3DPRIM_RECTLIST;
return VK_SUCCESS;
}
VkResult
anv_graphics_pipeline_create(
VkDevice _device,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const struct anv_graphics_pipeline_create_info *extra,
VkPipeline *pPipeline)
{
ANV_FROM_HANDLE(anv_device, device, _device);
switch (device->info.gen) {
case 7:
return gen7_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
case 8:
return gen8_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
default:
unreachable("unsupported gen\n");
}
}
VkResult anv_CreateGraphicsPipelines(
VkDevice _device,
VkPipelineCache pipelineCache,
uint32_t count,
const VkGraphicsPipelineCreateInfo* pCreateInfos,
VkPipeline* pPipelines)
{
VkResult result = VK_SUCCESS;
unsigned i = 0;
for (; i < count; i++) {
result = anv_graphics_pipeline_create(_device, &pCreateInfos[i],
NULL, &pPipelines[i]);
if (result != VK_SUCCESS) {
for (unsigned j = 0; j < i; j++) {
anv_DestroyPipeline(_device, pPipelines[j]);
}
return result;
}
}
return VK_SUCCESS;
}
static VkResult anv_compute_pipeline_create(
VkDevice _device,
const VkComputePipelineCreateInfo* pCreateInfo,
VkPipeline* pPipeline)
{
ANV_FROM_HANDLE(anv_device, device, _device);
switch (device->info.gen) {
case 7:
return gen7_compute_pipeline_create(_device, pCreateInfo, pPipeline);
case 8:
return gen8_compute_pipeline_create(_device, pCreateInfo, pPipeline);
default:
unreachable("unsupported gen\n");
}
}
VkResult anv_CreateComputePipelines(
VkDevice _device,
VkPipelineCache pipelineCache,
uint32_t count,
const VkComputePipelineCreateInfo* pCreateInfos,
VkPipeline* pPipelines)
{
VkResult result = VK_SUCCESS;
unsigned i = 0;
for (; i < count; i++) {
result = anv_compute_pipeline_create(_device, &pCreateInfos[i],
&pPipelines[i]);
if (result != VK_SUCCESS) {
for (unsigned j = 0; j < i; j++) {
anv_DestroyPipeline(_device, pPipelines[j]);
}
return result;
}
}
return VK_SUCCESS;
}
// Pipeline layout functions
VkResult anv_CreatePipelineLayout(
VkDevice _device,
const VkPipelineLayoutCreateInfo* pCreateInfo,
VkPipelineLayout* pPipelineLayout)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_pipeline_layout *layout;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
layout = anv_device_alloc(device, sizeof(*layout), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (layout == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
layout->num_sets = pCreateInfo->descriptorSetCount;
uint32_t surface_start[VK_SHADER_STAGE_NUM] = { 0, };
uint32_t sampler_start[VK_SHADER_STAGE_NUM] = { 0, };
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
layout->stage[s].has_dynamic_offsets = false;
layout->stage[s].surface_count = 0;
layout->stage[s].sampler_count = 0;
}
uint32_t num_dynamic_offsets = 0;
for (uint32_t i = 0; i < pCreateInfo->descriptorSetCount; i++) {
ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
pCreateInfo->pSetLayouts[i]);
layout->set[i].layout = set_layout;
layout->set[i].dynamic_offset_start = num_dynamic_offsets;
num_dynamic_offsets += set_layout->num_dynamic_buffers;
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
if (set_layout->num_dynamic_buffers > 0)
layout->stage[s].has_dynamic_offsets = true;
layout->set[i].stage[s].surface_start = surface_start[s];
surface_start[s] += set_layout->stage[s].surface_count;
layout->set[i].stage[s].sampler_start = sampler_start[s];
sampler_start[s] += set_layout->stage[s].sampler_count;
layout->stage[s].surface_count += set_layout->stage[s].surface_count;
layout->stage[s].sampler_count += set_layout->stage[s].sampler_count;
}
}
*pPipelineLayout = anv_pipeline_layout_to_handle(layout);
return VK_SUCCESS;
}
VkResult anv_DestroyPipelineLayout(
VkDevice _device,
VkPipelineLayout _pipelineLayout)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _pipelineLayout);
anv_device_free(device, pipeline_layout);
return VK_SUCCESS;
}

1439
src/vulkan/anv_private.h Normal file

File diff suppressed because it is too large Load Diff

150
src/vulkan/anv_query.c Normal file
View File

@@ -0,0 +1,150 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
VkResult anv_CreateQueryPool(
VkDevice _device,
const VkQueryPoolCreateInfo* pCreateInfo,
VkQueryPool* pQueryPool)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_query_pool *pool;
VkResult result;
size_t size;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
switch (pCreateInfo->queryType) {
case VK_QUERY_TYPE_OCCLUSION:
break;
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
return VK_UNSUPPORTED;
default:
unreachable("");
}
pool = anv_device_alloc(device, sizeof(*pool), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (pool == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
size = pCreateInfo->slots * sizeof(struct anv_query_pool_slot);
result = anv_bo_init_new(&pool->bo, device, size);
if (result != VK_SUCCESS)
goto fail;
pool->bo.map = anv_gem_mmap(device, pool->bo.gem_handle, 0, size);
*pQueryPool = anv_query_pool_to_handle(pool);
return VK_SUCCESS;
fail:
anv_device_free(device, pool);
return result;
}
VkResult anv_DestroyQueryPool(
VkDevice _device,
VkQueryPool _pool)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_query_pool, pool, _pool);
anv_gem_munmap(pool->bo.map, pool->bo.size);
anv_gem_close(device, pool->bo.gem_handle);
anv_device_free(device, pool);
return VK_SUCCESS;
}
VkResult anv_GetQueryPoolResults(
VkDevice _device,
VkQueryPool queryPool,
uint32_t startQuery,
uint32_t queryCount,
size_t* pDataSize,
void* pData,
VkQueryResultFlags flags)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
struct anv_query_pool_slot *slot = pool->bo.map;
int64_t timeout = INT64_MAX;
uint32_t *dst32 = pData;
uint64_t *dst64 = pData;
uint64_t result;
int ret;
if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
/* Where is the availabilty info supposed to go? */
anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
return VK_UNSUPPORTED;
}
assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
if (flags & VK_QUERY_RESULT_64_BIT)
*pDataSize = queryCount * sizeof(uint64_t);
else
*pDataSize = queryCount * sizeof(uint32_t);
if (pData == NULL)
return VK_SUCCESS;
if (flags & VK_QUERY_RESULT_WAIT_BIT) {
ret = anv_gem_wait(device, pool->bo.gem_handle, &timeout);
if (ret == -1)
return vk_errorf(VK_ERROR_UNKNOWN, "gem_wait failed %m");
}
for (uint32_t i = 0; i < queryCount; i++) {
result = slot[startQuery + i].end - slot[startQuery + i].begin;
if (flags & VK_QUERY_RESULT_64_BIT) {
*dst64++ = result;
} else {
if (result > UINT32_MAX)
result = UINT32_MAX;
*dst32++ = result;
}
}
return VK_SUCCESS;
}
void anv_CmdResetQueryPool(
VkCmdBuffer cmdBuffer,
VkQueryPool queryPool,
uint32_t startQuery,
uint32_t queryCount)
{
stub();
}

214
src/vulkan/anv_util.c Normal file
View File

@@ -0,0 +1,214 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "anv_private.h"
/** Log an error message. */
void anv_printflike(1, 2)
anv_loge(const char *format, ...)
{
va_list va;
va_start(va, format);
anv_loge_v(format, va);
va_end(va);
}
/** \see anv_loge() */
void
anv_loge_v(const char *format, va_list va)
{
fprintf(stderr, "vk: error: ");
vfprintf(stderr, format, va);
fprintf(stderr, "\n");
}
void anv_printflike(3, 4)
__anv_finishme(const char *file, int line, const char *format, ...)
{
va_list ap;
char buffer[256];
va_start(ap, format);
vsnprintf(buffer, sizeof(buffer), format, ap);
va_end(ap);
fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buffer);
}
void anv_noreturn anv_printflike(1, 2)
anv_abortf(const char *format, ...)
{
va_list va;
va_start(va, format);
anv_abortfv(format, va);
va_end(va);
}
void anv_noreturn
anv_abortfv(const char *format, va_list va)
{
fprintf(stderr, "vk: error: ");
vfprintf(stderr, format, va);
fprintf(stderr, "\n");
abort();
}
VkResult
__vk_errorf(VkResult error, const char *file, int line, const char *format, ...)
{
va_list ap;
char buffer[256];
#define ERROR_CASE(error) case error: error_str = #error; break;
const char *error_str;
switch ((int32_t)error) {
ERROR_CASE(VK_ERROR_UNKNOWN)
ERROR_CASE(VK_ERROR_UNAVAILABLE)
ERROR_CASE(VK_ERROR_INITIALIZATION_FAILED)
ERROR_CASE(VK_ERROR_OUT_OF_HOST_MEMORY)
ERROR_CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY)
ERROR_CASE(VK_ERROR_DEVICE_ALREADY_CREATED)
ERROR_CASE(VK_ERROR_DEVICE_LOST)
ERROR_CASE(VK_ERROR_INVALID_POINTER)
ERROR_CASE(VK_ERROR_INVALID_VALUE)
ERROR_CASE(VK_ERROR_INVALID_HANDLE)
ERROR_CASE(VK_ERROR_INVALID_ORDINAL)
ERROR_CASE(VK_ERROR_INVALID_MEMORY_SIZE)
ERROR_CASE(VK_ERROR_INVALID_EXTENSION)
ERROR_CASE(VK_ERROR_INVALID_FLAGS)
ERROR_CASE(VK_ERROR_INVALID_ALIGNMENT)
ERROR_CASE(VK_ERROR_INVALID_FORMAT)
ERROR_CASE(VK_ERROR_INVALID_IMAGE)
ERROR_CASE(VK_ERROR_INVALID_DESCRIPTOR_SET_DATA)
ERROR_CASE(VK_ERROR_INVALID_QUEUE_TYPE)
ERROR_CASE(VK_ERROR_UNSUPPORTED_SHADER_IL_VERSION)
ERROR_CASE(VK_ERROR_BAD_SHADER_CODE)
ERROR_CASE(VK_ERROR_BAD_PIPELINE_DATA)
ERROR_CASE(VK_ERROR_NOT_MAPPABLE)
ERROR_CASE(VK_ERROR_MEMORY_MAP_FAILED)
ERROR_CASE(VK_ERROR_MEMORY_UNMAP_FAILED)
ERROR_CASE(VK_ERROR_INCOMPATIBLE_DEVICE)
ERROR_CASE(VK_ERROR_INCOMPATIBLE_DRIVER)
ERROR_CASE(VK_ERROR_INCOMPLETE_COMMAND_BUFFER)
ERROR_CASE(VK_ERROR_BUILDING_COMMAND_BUFFER)
ERROR_CASE(VK_ERROR_MEMORY_NOT_BOUND)
ERROR_CASE(VK_ERROR_INCOMPATIBLE_QUEUE)
ERROR_CASE(VK_ERROR_INVALID_LAYER)
ERROR_CASE(VK_ERROR_OUT_OF_DATE_WSI)
default:
assert(!"Unknown error");
error_str = "unknown error";
}
#undef ERROR_CASE
if (format) {
va_start(ap, format);
vsnprintf(buffer, sizeof(buffer), format, ap);
va_end(ap);
fprintf(stderr, "%s:%d: %s (%s)\n", file, line, buffer, error_str);
} else {
fprintf(stderr, "%s:%d: %s\n", file, line, error_str);
}
return error;
}
int
anv_vector_init(struct anv_vector *vector, uint32_t element_size, uint32_t size)
{
assert(util_is_power_of_two(size));
assert(element_size < size && util_is_power_of_two(element_size));
vector->head = 0;
vector->tail = 0;
vector->element_size = element_size;
vector->size = size;
vector->data = malloc(size);
return vector->data != NULL;
}
void *
anv_vector_add(struct anv_vector *vector)
{
uint32_t offset, size, split, tail;
void *data;
if (vector->head - vector->tail == vector->size) {
size = vector->size * 2;
data = malloc(size);
if (data == NULL)
return NULL;
split = align_u32(vector->tail, vector->size);
tail = vector->tail & (vector->size - 1);
if (vector->head - split < vector->size) {
memcpy(data + tail,
vector->data + tail,
split - vector->tail);
memcpy(data + vector->size,
vector->data, vector->head - split);
} else {
memcpy(data + tail,
vector->data + tail,
vector->head - vector->tail);
}
free(vector->data);
vector->data = data;
vector->size = size;
}
assert(vector->head - vector->tail < vector->size);
offset = vector->head & (vector->size - 1);
vector->head += vector->element_size;
return vector->data + offset;
}
void *
anv_vector_remove(struct anv_vector *vector)
{
uint32_t offset;
if (vector->head == vector->tail)
return NULL;
assert(vector->head - vector->tail <= vector->size);
offset = vector->tail & (vector->size - 1);
vector->tail += vector->element_size;
return vector->data + offset;
}

200
src/vulkan/anv_wsi.c Normal file
View File

@@ -0,0 +1,200 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "anv_wsi.h"
VkResult
anv_init_wsi(struct anv_instance *instance)
{
VkResult result;
memset(instance->wsi_impl, 0, sizeof(instance->wsi_impl));
result = anv_x11_init_wsi(instance);
if (result != VK_SUCCESS)
return result;
#ifdef HAVE_WAYLAND_PLATFORM
result = anv_wl_init_wsi(instance);
if (result != VK_SUCCESS) {
anv_x11_finish_wsi(instance);
return result;
}
#endif
return VK_SUCCESS;
}
void
anv_finish_wsi(struct anv_instance *instance)
{
#ifdef HAVE_WAYLAND_PLATFORM
anv_wl_finish_wsi(instance);
#endif
anv_x11_finish_wsi(instance);
}
VkResult
anv_GetPhysicalDeviceSurfaceSupportWSI(
VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex,
const VkSurfaceDescriptionWSI* pSurfaceDescription,
VkBool32* pSupported)
{
ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
assert(pSurfaceDescription->sType ==
VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI);
VkSurfaceDescriptionWindowWSI *window = (void *)pSurfaceDescription;
struct anv_wsi_implementation *impl =
physical_device->instance->wsi_impl[window->platform];
if (impl) {
return impl->get_window_supported(impl, physical_device,
window, pSupported);
} else {
*pSupported = false;
return VK_SUCCESS;
}
}
VkResult
anv_GetSurfaceInfoWSI(
VkDevice _device,
const VkSurfaceDescriptionWSI* pSurfaceDescription,
VkSurfaceInfoTypeWSI infoType,
size_t* pDataSize,
void* pData)
{
ANV_FROM_HANDLE(anv_device, device, _device);
assert(pSurfaceDescription->sType ==
VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI);
VkSurfaceDescriptionWindowWSI *window =
(VkSurfaceDescriptionWindowWSI *)pSurfaceDescription;
struct anv_wsi_implementation *impl =
device->instance->wsi_impl[window->platform];
assert(impl);
return impl->get_surface_info(impl, device, window, infoType,
pDataSize, pData);
}
VkResult
anv_CreateSwapChainWSI(
VkDevice _device,
const VkSwapChainCreateInfoWSI* pCreateInfo,
VkSwapChainWSI* pSwapChain)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_swap_chain *swap_chain;
VkResult result;
assert(pCreateInfo->pSurfaceDescription->sType ==
VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI);
VkSurfaceDescriptionWindowWSI *window =
(VkSurfaceDescriptionWindowWSI *)pCreateInfo->pSurfaceDescription;
struct anv_wsi_implementation *impl =
device->instance->wsi_impl[window->platform];
assert(impl);
result = impl->create_swap_chain(impl, device, pCreateInfo, &swap_chain);
if (result == VK_SUCCESS)
*pSwapChain = anv_swap_chain_to_handle(swap_chain);
return result;
}
VkResult
anv_DestroySwapChainWSI(
VkDevice device,
VkSwapChainWSI swapChain)
{
ANV_FROM_HANDLE(anv_swap_chain, swap_chain, swapChain);
assert(swap_chain->device == anv_device_from_handle(device));
return swap_chain->destroy(swap_chain);
}
VkResult
anv_GetSwapChainInfoWSI(
VkDevice device,
VkSwapChainWSI swapChain,
VkSwapChainInfoTypeWSI infoType,
size_t* pDataSize,
void* pData)
{
ANV_FROM_HANDLE(anv_swap_chain, swap_chain, swapChain);
assert(swap_chain->device == anv_device_from_handle(device));
return swap_chain->get_swap_chain_info(swap_chain, infoType,
pDataSize, pData);
}
VkResult
anv_AcquireNextImageWSI(
VkDevice device,
VkSwapChainWSI swapChain,
uint64_t timeout,
VkSemaphore semaphore,
uint32_t* pImageIndex)
{
ANV_FROM_HANDLE(anv_swap_chain, swap_chain, swapChain);
assert(swap_chain->device == anv_device_from_handle(device));
return swap_chain->acquire_next_image(swap_chain,
timeout, semaphore, pImageIndex);
}
VkResult
anv_QueuePresentWSI(
VkQueue _queue,
VkPresentInfoWSI* pPresentInfo)
{
ANV_FROM_HANDLE(anv_queue, queue, _queue);
VkResult result;
for (uint32_t i = 0; i < pPresentInfo->swapChainCount; i++) {
ANV_FROM_HANDLE(anv_swap_chain, swap_chain, pPresentInfo->swapChains[i]);
assert(swap_chain->device == queue->device);
result = swap_chain->queue_present(swap_chain, queue,
pPresentInfo->imageIndices[i]);
/* TODO: What if one of them returns OUT_OF_DATE? */
if (result != VK_SUCCESS)
return result;
}
return VK_SUCCESS;
}

64
src/vulkan/anv_wsi.h Normal file
View File

@@ -0,0 +1,64 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#pragma once
#include "anv_private.h"
struct anv_swap_chain {
struct anv_device * device;
VkResult (*destroy)(struct anv_swap_chain *swap_chain);
VkResult (*get_swap_chain_info)(struct anv_swap_chain *swap_chain,
VkSwapChainInfoTypeWSI infoType,
size_t *pDataSize, void *pData);
VkResult (*acquire_next_image)(struct anv_swap_chain *swap_chain,
uint64_t timeout, VkSemaphore semaphore,
uint32_t *image_index);
VkResult (*queue_present)(struct anv_swap_chain *swap_chain,
struct anv_queue *queue,
uint32_t image_index);
};
ANV_DEFINE_NONDISP_HANDLE_CASTS(anv_swap_chain, VkSwapChainWSI)
struct anv_wsi_implementation {
VkResult (*get_window_supported)(struct anv_wsi_implementation *impl,
struct anv_physical_device *physical_device,
const VkSurfaceDescriptionWindowWSI *window,
VkBool32 *pSupported);
VkResult (*get_surface_info)(struct anv_wsi_implementation *impl,
struct anv_device *device,
VkSurfaceDescriptionWindowWSI *window,
VkSurfaceInfoTypeWSI infoType,
size_t* pDataSize, void* pData);
VkResult (*create_swap_chain)(struct anv_wsi_implementation *impl,
struct anv_device *device,
const VkSwapChainCreateInfoWSI *pCreateInfo,
struct anv_swap_chain **swap_chain);
};
VkResult anv_x11_init_wsi(struct anv_instance *instance);
void anv_x11_finish_wsi(struct anv_instance *instance);
VkResult anv_wl_init_wsi(struct anv_instance *instance);
void anv_wl_finish_wsi(struct anv_instance *instance);

View File

@@ -0,0 +1,805 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <wayland-client.h>
#include <wayland-drm-client-protocol.h>
#include "anv_wsi.h"
#include <util/hash_table.h>
#define MIN_NUM_IMAGES 2
struct wsi_wl_display {
struct wl_display * display;
struct wl_drm * drm;
/* Vector of VkFormats supported */
struct anv_vector formats;
uint32_t capabilities;
};
struct wsi_wayland {
struct anv_wsi_implementation base;
struct anv_instance * instance;
pthread_mutex_t mutex;
/* Hash table of wl_display -> wsi_wl_display mappings */
struct hash_table * displays;
};
static void
wsi_wl_display_add_vk_format(struct wsi_wl_display *display, VkFormat format)
{
/* Don't add a format that's already in the list */
VkFormat *f;
anv_vector_foreach(f, &display->formats)
if (*f == format)
return;
/* Don't add formats which aren't supported by the driver */
if (anv_format_for_vk_format(format)->cpp == 0)
return;
f = anv_vector_add(&display->formats);
if (f)
*f = format;
}
static void
drm_handle_device(void *data, struct wl_drm *drm, const char *name)
{
fprintf(stderr, "wl_drm.device(%s)\n", name);
}
static uint32_t
wl_drm_format_for_vk_format(VkFormat vk_format, bool alpha)
{
switch (vk_format) {
case VK_FORMAT_R4G4B4A4_UNORM:
return alpha ? WL_DRM_FORMAT_ABGR4444 : WL_DRM_FORMAT_XBGR4444;
case VK_FORMAT_R5G6B5_UNORM:
return WL_DRM_FORMAT_BGR565;
case VK_FORMAT_R5G5B5A1_UNORM:
return alpha ? WL_DRM_FORMAT_ABGR1555 : WL_DRM_FORMAT_XBGR1555;
case VK_FORMAT_R8G8B8_UNORM:
return WL_DRM_FORMAT_XBGR8888;
case VK_FORMAT_R8G8B8A8_UNORM:
return alpha ? WL_DRM_FORMAT_ABGR8888 : WL_DRM_FORMAT_XBGR8888;
case VK_FORMAT_R10G10B10A2_UNORM:
return alpha ? WL_DRM_FORMAT_ABGR2101010 : WL_DRM_FORMAT_XBGR2101010;
case VK_FORMAT_B4G4R4A4_UNORM:
return alpha ? WL_DRM_FORMAT_ARGB4444 : WL_DRM_FORMAT_XRGB4444;
case VK_FORMAT_B5G6R5_UNORM:
return WL_DRM_FORMAT_RGB565;
case VK_FORMAT_B5G5R5A1_UNORM:
return alpha ? WL_DRM_FORMAT_XRGB1555 : WL_DRM_FORMAT_XRGB1555;
case VK_FORMAT_B8G8R8_UNORM:
return WL_DRM_FORMAT_BGRX8888;
case VK_FORMAT_B8G8R8A8_UNORM:
return alpha ? WL_DRM_FORMAT_ARGB8888 : WL_DRM_FORMAT_XRGB8888;
case VK_FORMAT_B10G10R10A2_UNORM:
return alpha ? WL_DRM_FORMAT_ARGB2101010 : WL_DRM_FORMAT_XRGB2101010;
default:
assert("!Unsupported Vulkan format");
return 0;
}
}
static void
drm_handle_format(void *data, struct wl_drm *drm, uint32_t wl_format)
{
struct wsi_wl_display *display = data;
switch (wl_format) {
case WL_DRM_FORMAT_ABGR4444:
case WL_DRM_FORMAT_XBGR4444:
wsi_wl_display_add_vk_format(display, VK_FORMAT_R4G4B4A4_UNORM);
break;
case WL_DRM_FORMAT_BGR565:
wsi_wl_display_add_vk_format(display, VK_FORMAT_R5G6B5_UNORM);
break;
case WL_DRM_FORMAT_ABGR1555:
case WL_DRM_FORMAT_XBGR1555:
wsi_wl_display_add_vk_format(display, VK_FORMAT_R5G5B5A1_UNORM);
break;
case WL_DRM_FORMAT_XBGR8888:
wsi_wl_display_add_vk_format(display, VK_FORMAT_R8G8B8_UNORM);
/* fallthrough */
case WL_DRM_FORMAT_ABGR8888:
wsi_wl_display_add_vk_format(display, VK_FORMAT_R8G8B8A8_UNORM);
break;
case WL_DRM_FORMAT_ABGR2101010:
case WL_DRM_FORMAT_XBGR2101010:
wsi_wl_display_add_vk_format(display, VK_FORMAT_R10G10B10A2_UNORM);
break;
case WL_DRM_FORMAT_ARGB4444:
case WL_DRM_FORMAT_XRGB4444:
wsi_wl_display_add_vk_format(display, VK_FORMAT_B4G4R4A4_UNORM);
break;
case WL_DRM_FORMAT_RGB565:
wsi_wl_display_add_vk_format(display, VK_FORMAT_B5G6R5_UNORM);
break;
case WL_DRM_FORMAT_ARGB1555:
case WL_DRM_FORMAT_XRGB1555:
wsi_wl_display_add_vk_format(display, VK_FORMAT_B5G5R5A1_UNORM);
break;
case WL_DRM_FORMAT_XRGB8888:
wsi_wl_display_add_vk_format(display, VK_FORMAT_B8G8R8_UNORM);
/* fallthrough */
case WL_DRM_FORMAT_ARGB8888:
wsi_wl_display_add_vk_format(display, VK_FORMAT_B8G8R8A8_UNORM);
break;
case WL_DRM_FORMAT_ARGB2101010:
case WL_DRM_FORMAT_XRGB2101010:
wsi_wl_display_add_vk_format(display, VK_FORMAT_B10G10R10A2_UNORM);
break;
}
}
static void
drm_handle_authenticated(void *data, struct wl_drm *drm)
{
}
static void
drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t capabilities)
{
struct wsi_wl_display *display = data;
display->capabilities = capabilities;
}
static const struct wl_drm_listener drm_listener = {
drm_handle_device,
drm_handle_format,
drm_handle_authenticated,
drm_handle_capabilities,
};
static void
registry_handle_global(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version)
{
struct wsi_wl_display *display = data;
if (strcmp(interface, "wl_drm") == 0) {
assert(display->drm == NULL);
assert(version >= 2);
display->drm = wl_registry_bind(registry, name, &wl_drm_interface, 2);
if (display->drm)
wl_drm_add_listener(display->drm, &drm_listener, display);
}
}
static void
registry_handle_global_remove(void *data, struct wl_registry *registry,
uint32_t name)
{ /* No-op */ }
static const struct wl_registry_listener registry_listener = {
registry_handle_global,
registry_handle_global_remove
};
static void
wsi_wl_display_destroy(struct wsi_wayland *wsi, struct wsi_wl_display *display)
{
anv_vector_finish(&display->formats);
if (display->drm)
wl_drm_destroy(display->drm);
anv_instance_free(wsi->instance, display);
}
static struct wsi_wl_display *
wsi_wl_display_create(struct wsi_wayland *wsi, struct wl_display *wl_display)
{
struct wsi_wl_display *display =
anv_instance_alloc(wsi->instance, sizeof(*display), 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (!display)
return NULL;
memset(display, 0, sizeof(*display));
display->display = wl_display;
if (!anv_vector_init(&display->formats, sizeof(VkFormat), 8))
goto fail;
struct wl_registry *registry = wl_display_get_registry(wl_display);
if (!registry)
return NULL;
wl_registry_add_listener(registry, &registry_listener, display);
/* Round-rip to get the wl_drm global */
wl_display_roundtrip(wl_display);
if (!display->drm)
goto fail;
/* Round-rip to get wl_drm formats and capabilities */
wl_display_roundtrip(wl_display);
/* We need prime support */
if (!(display->capabilities & WL_DRM_CAPABILITY_PRIME))
goto fail;
/* We don't need this anymore */
wl_registry_destroy(registry);
return display;
fail:
if (registry)
wl_registry_destroy(registry);
wsi_wl_display_destroy(wsi, display);
return NULL;
}
static struct wsi_wl_display *
wsi_wl_get_display(struct wsi_wayland *wsi, struct wl_display *wl_display)
{
pthread_mutex_lock(&wsi->mutex);
struct hash_entry *entry = _mesa_hash_table_search(wsi->displays,
wl_display);
if (!entry) {
/* We're about to make a bunch of blocking calls. Let's drop the
* mutex for now so we don't block up too badly.
*/
pthread_mutex_unlock(&wsi->mutex);
struct wsi_wl_display *display = wsi_wl_display_create(wsi, wl_display);
pthread_mutex_lock(&wsi->mutex);
entry = _mesa_hash_table_search(wsi->displays, wl_display);
if (entry) {
/* Oops, someone raced us to it */
wsi_wl_display_destroy(wsi, display);
} else {
entry = _mesa_hash_table_insert(wsi->displays, wl_display, display);
}
}
pthread_mutex_unlock(&wsi->mutex);
return entry->data;
}
static VkResult
wsi_wl_get_window_supported(struct anv_wsi_implementation *impl,
struct anv_physical_device *physical_device,
const VkSurfaceDescriptionWindowWSI *window,
VkBool32 *pSupported)
{
struct wsi_wayland *wsi = (struct wsi_wayland *)impl;
*pSupported = wsi_wl_get_display(wsi, window->pPlatformHandle) != NULL;
return VK_SUCCESS;
}
static const VkSurfacePresentModePropertiesWSI present_modes[] = {
{ VK_PRESENT_MODE_MAILBOX_WSI },
{ VK_PRESENT_MODE_FIFO_WSI },
};
static VkResult
wsi_wl_get_surface_info(struct anv_wsi_implementation *impl,
struct anv_device *device,
VkSurfaceDescriptionWindowWSI *window,
VkSurfaceInfoTypeWSI infoType,
size_t* pDataSize, void* pData)
{
struct wsi_wayland *wsi = (struct wsi_wayland *)impl;
if (pDataSize == NULL)
return vk_error(VK_ERROR_INVALID_POINTER);
switch (infoType) {
case VK_SURFACE_INFO_TYPE_PROPERTIES_WSI: {
VkSurfacePropertiesWSI *props = pData;
if (pData == NULL) {
*pDataSize = sizeof(*props);
return VK_SUCCESS;
}
assert(*pDataSize >= sizeof(*props));
props->minImageCount = MIN_NUM_IMAGES;
props->maxImageCount = 4;
props->currentExtent = (VkExtent2D) { -1, -1 };
props->minImageExtent = (VkExtent2D) { 1, 1 };
props->maxImageExtent = (VkExtent2D) { INT16_MAX, INT16_MAX };
props->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_WSI;
props->currentTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
props->maxImageArraySize = 1;
props->supportedUsageFlags =
VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
return VK_SUCCESS;
}
case VK_SURFACE_INFO_TYPE_FORMATS_WSI: {
VkSurfaceFormatPropertiesWSI *formats = pData;
struct wsi_wl_display *display =
wsi_wl_get_display(wsi, window->pPlatformHandle);
uint32_t size = anv_vector_length(&display->formats) * sizeof(*formats);
if (pData == NULL) {
*pDataSize = size;
return VK_SUCCESS;
}
assert(*pDataSize >= size);
*pDataSize = size;
VkFormat *f;
anv_vector_foreach(f, &display->formats)
(formats++)->format = *f;
return VK_SUCCESS;
}
case VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI:
if (pData == NULL) {
*pDataSize = sizeof(present_modes);
return VK_SUCCESS;
}
assert(*pDataSize >= sizeof(present_modes));
memcpy(pData, present_modes, *pDataSize);
return VK_SUCCESS;
default:
return vk_error(VK_ERROR_INVALID_VALUE);
}
}
struct wsi_wl_image {
struct anv_image * image;
struct anv_device_memory * memory;
struct wl_buffer * buffer;
bool busy;
};
struct wsi_wl_swap_chain {
struct anv_swap_chain base;
struct wsi_wl_display * display;
struct wl_event_queue * queue;
struct wl_surface * surface;
VkExtent2D extent;
VkFormat vk_format;
uint32_t drm_format;
VkPresentModeWSI present_mode;
bool fifo_ready;
uint32_t image_count;
struct wsi_wl_image images[0];
};
static VkResult
wsi_wl_get_swap_chain_info(struct anv_swap_chain *anv_chain,
VkSwapChainInfoTypeWSI infoType,
size_t* pDataSize, void* pData)
{
struct wsi_wl_swap_chain *chain = (struct wsi_wl_swap_chain *)anv_chain;
size_t size;
switch (infoType) {
case VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI: {
VkSwapChainImagePropertiesWSI *images = pData;
size = chain->image_count * sizeof(*images);
if (pData == NULL) {
*pDataSize = size;
return VK_SUCCESS;
}
assert(size <= *pDataSize);
for (uint32_t i = 0; i < chain->image_count; i++)
images[i].image = anv_image_to_handle(chain->images[i].image);
*pDataSize = size;
return VK_SUCCESS;
}
default:
return vk_error(VK_ERROR_INVALID_VALUE);
}
}
static VkResult
wsi_wl_acquire_next_image(struct anv_swap_chain *anv_chain,
uint64_t timeout,
VkSemaphore semaphore,
uint32_t *image_index)
{
struct wsi_wl_swap_chain *chain = (struct wsi_wl_swap_chain *)anv_chain;
int ret = wl_display_dispatch_queue_pending(chain->display->display,
chain->queue);
/* XXX: I'm not sure if out-of-date is the right error here. If
* wl_display_dispatch_queue_pending fails it most likely means we got
* kicked by the server so this seems more-or-less correct.
*/
if (ret < 0)
return vk_error(VK_ERROR_OUT_OF_DATE_WSI);
while (1) {
for (uint32_t i = 0; i < chain->image_count; i++) {
if (!chain->images[i].busy) {
/* We found a non-busy image */
*image_index = i;
return VK_SUCCESS;
}
}
/* This time we do a blocking dispatch because we can't go
* anywhere until we get an event.
*/
int ret = wl_display_dispatch_queue(chain->display->display,
chain->queue);
if (ret < 0)
return vk_error(VK_ERROR_OUT_OF_DATE_WSI);
}
}
static void
frame_handle_done(void *data, struct wl_callback *callback, uint32_t serial)
{
struct wsi_wl_swap_chain *chain = data;
chain->fifo_ready = true;
wl_callback_destroy(callback);
}
static const struct wl_callback_listener frame_listener = {
frame_handle_done,
};
static VkResult
wsi_wl_queue_present(struct anv_swap_chain *anv_chain,
struct anv_queue *queue,
uint32_t image_index)
{
struct wsi_wl_swap_chain *chain = (struct wsi_wl_swap_chain *)anv_chain;
if (chain->present_mode == VK_PRESENT_MODE_FIFO_WSI) {
while (!chain->fifo_ready) {
int ret = wl_display_dispatch_queue(chain->display->display,
chain->queue);
if (ret < 0)
return vk_error(VK_ERROR_OUT_OF_DATE_WSI);
}
}
assert(image_index < chain->image_count);
wl_surface_attach(chain->surface, chain->images[image_index].buffer, 0, 0);
wl_surface_damage(chain->surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(chain->surface);
if (chain->present_mode == VK_PRESENT_MODE_FIFO_WSI) {
struct wl_callback *frame = wl_surface_frame(chain->surface);
wl_proxy_set_queue((struct wl_proxy *)frame, chain->queue);
wl_callback_add_listener(frame, &frame_listener, chain);
}
return VK_SUCCESS;
}
static void
wsi_wl_image_finish(struct wsi_wl_swap_chain *chain, struct wsi_wl_image *image)
{
VkDevice vk_device = anv_device_to_handle(chain->base.device);
anv_FreeMemory(vk_device, anv_device_memory_to_handle(image->memory));
anv_DestroyImage(vk_device, anv_image_to_handle(image->image));
}
static void
buffer_handle_release(void *data, struct wl_buffer *buffer)
{
struct wsi_wl_image *image = data;
assert(image->buffer == buffer);
image->busy = false;
}
static const struct wl_buffer_listener buffer_listener = {
buffer_handle_release,
};
static VkResult
wsi_wl_image_init(struct wsi_wl_swap_chain *chain, struct wsi_wl_image *image)
{
VkDevice vk_device = anv_device_to_handle(chain->base.device);
VkResult result;
VkImage vk_image;
result = anv_image_create(vk_device,
&(struct anv_image_create_info) {
.force_tile_mode = true,
.tile_mode = XMAJOR,
.stride = 0,
.vk_info =
&(VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
.format = chain->vk_format,
.extent = {
.width = chain->extent.width,
.height = chain->extent.height,
.depth = 1
},
.mipLevels = 1,
.arraySize = 1,
.samples = 1,
/* FIXME: Need a way to use X tiling to allow scanout */
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.flags = 0,
}},
&vk_image);
if (result != VK_SUCCESS)
return result;
image->image = anv_image_from_handle(vk_image);
assert(anv_format_is_color(image->image->format));
struct anv_surface *surface = &image->image->color_surface;
VkDeviceMemory vk_memory;
result = anv_AllocMemory(vk_device,
&(VkMemoryAllocInfo) {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
.allocationSize = image->image->size,
.memoryTypeIndex = 0,
},
&vk_memory);
if (result != VK_SUCCESS)
goto fail_image;
image->memory = anv_device_memory_from_handle(vk_memory);
result = anv_BindImageMemory(vk_device, vk_image, vk_memory, 0);
if (result != VK_SUCCESS)
goto fail_mem;
int ret = anv_gem_set_tiling(chain->base.device,
image->memory->bo.gem_handle,
surface->stride, I915_TILING_X);
if (ret) {
result = vk_error(VK_ERROR_UNKNOWN);
goto fail_mem;
}
int fd = anv_gem_handle_to_fd(chain->base.device,
image->memory->bo.gem_handle);
if (fd == -1) {
result = vk_error(VK_ERROR_UNKNOWN);
goto fail_mem;
}
image->buffer = wl_drm_create_prime_buffer(chain->display->drm,
fd, /* name */
chain->extent.width,
chain->extent.height,
chain->drm_format,
surface->offset,
surface->stride,
0, 0, 0, 0 /* unused */);
wl_display_roundtrip(chain->display->display);
close(fd);
wl_proxy_set_queue((struct wl_proxy *)image->buffer, chain->queue);
wl_buffer_add_listener(image->buffer, &buffer_listener, image);
return VK_SUCCESS;
fail_mem:
anv_FreeMemory(vk_device, vk_memory);
fail_image:
anv_DestroyImage(vk_device, vk_image);
return result;
}
static VkResult
wsi_wl_destroy_swap_chain(struct anv_swap_chain *anv_chain)
{
struct wsi_wl_swap_chain *chain = (struct wsi_wl_swap_chain *)anv_chain;
for (uint32_t i = 0; i < chain->image_count; i++) {
if (chain->images[i].buffer)
wsi_wl_image_finish(chain, &chain->images[i]);
}
anv_device_free(chain->base.device, chain);
return VK_SUCCESS;
}
static VkResult
wsi_wl_create_swap_chain(struct anv_wsi_implementation *impl,
struct anv_device *device,
const VkSwapChainCreateInfoWSI *pCreateInfo,
struct anv_swap_chain **swap_chain_out)
{
struct wsi_wayland *wsi = (struct wsi_wayland *)impl;
struct wsi_wl_swap_chain *chain;
VkResult result;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
assert(pCreateInfo->pSurfaceDescription->sType ==
VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI);
VkSurfaceDescriptionWindowWSI *vk_window =
(VkSurfaceDescriptionWindowWSI *)pCreateInfo->pSurfaceDescription;
assert(vk_window->platform == VK_PLATFORM_WAYLAND_WSI);
int num_images = pCreateInfo->minImageCount;
assert(num_images >= MIN_NUM_IMAGES);
/* For true mailbox mode, we need at least 4 images:
* 1) One to scan out from
* 2) One to have queued for scan-out
* 3) One to be currently held by the Wayland compositor
* 4) One to render to
*/
if (pCreateInfo->presentMode == VK_PRESENT_MODE_MAILBOX_WSI)
num_images = MAX2(num_images, 4);
size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
chain = anv_device_alloc(device, size, 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (chain == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
chain->base.device = device;
chain->base.destroy = wsi_wl_destroy_swap_chain;
chain->base.get_swap_chain_info = wsi_wl_get_swap_chain_info;
chain->base.acquire_next_image = wsi_wl_acquire_next_image;
chain->base.queue_present = wsi_wl_queue_present;
chain->surface = vk_window->pPlatformWindow;
chain->extent = pCreateInfo->imageExtent;
chain->vk_format = pCreateInfo->imageFormat;
chain->drm_format = wl_drm_format_for_vk_format(chain->vk_format, false);
chain->present_mode = pCreateInfo->presentMode;
chain->fifo_ready = true;
chain->image_count = num_images;
/* Mark a bunch of stuff as NULL. This way we can just call
* destroy_swapchain for cleanup.
*/
for (uint32_t i = 0; i < chain->image_count; i++)
chain->images[i].buffer = NULL;
chain->queue = NULL;
chain->display = wsi_wl_get_display(wsi, vk_window->pPlatformHandle);
if (!chain->display)
goto fail;
chain->queue = wl_display_create_queue(chain->display->display);
if (!chain->queue)
goto fail;
for (uint32_t i = 0; i < chain->image_count; i++) {
result = wsi_wl_image_init(chain, &chain->images[i]);
if (result != VK_SUCCESS)
goto fail;
chain->images[i].busy = false;
}
*swap_chain_out = &chain->base;
return VK_SUCCESS;
fail:
wsi_wl_destroy_swap_chain(&chain->base);
return result;
}
VkResult
anv_wl_init_wsi(struct anv_instance *instance)
{
struct wsi_wayland *wsi;
VkResult result;
wsi = anv_instance_alloc(instance, sizeof(*wsi), 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (!wsi)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
wsi->base.get_window_supported = wsi_wl_get_window_supported;
wsi->base.get_surface_info = wsi_wl_get_surface_info;
wsi->base.create_swap_chain = wsi_wl_create_swap_chain;
wsi->instance = instance;
int ret = pthread_mutex_init(&wsi->mutex, NULL);
if (ret != 0) {
result = (ret == ENOMEM) ? VK_ERROR_OUT_OF_HOST_MEMORY :
VK_ERROR_UNKNOWN;
goto fail_alloc;
}
wsi->displays = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
_mesa_key_pointer_equal);
if (!wsi->displays) {
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto fail_mutex;
}
instance->wsi_impl[VK_PLATFORM_WAYLAND_WSI] = &wsi->base;
return VK_SUCCESS;
fail_mutex:
pthread_mutex_destroy(&wsi->mutex);
fail_alloc:
anv_instance_free(instance, wsi);
return result;
}
void
anv_wl_finish_wsi(struct anv_instance *instance)
{
struct wsi_wayland *wsi =
(struct wsi_wayland *)instance->wsi_impl[VK_PLATFORM_WAYLAND_WSI];
_mesa_hash_table_destroy(wsi->displays, NULL);
pthread_mutex_destroy(&wsi->mutex);
anv_instance_free(instance, wsi);
}

424
src/vulkan/anv_wsi_x11.c Normal file
View File

@@ -0,0 +1,424 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <xcb/xcb.h>
#include <xcb/dri3.h>
#include <xcb/present.h>
#include "anv_wsi.h"
static const VkFormat formats[] = {
VK_FORMAT_B5G6R5_UNORM,
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_B8G8R8A8_SRGB,
};
static const VkSurfacePresentModePropertiesWSI present_modes[] = {
{ VK_PRESENT_MODE_MAILBOX_WSI },
};
static VkResult
x11_get_window_supported(struct anv_wsi_implementation *impl,
struct anv_physical_device *physical_device,
const VkSurfaceDescriptionWindowWSI *window,
VkBool32 *pSupported)
{
*pSupported = true;
stub_return(VK_SUCCESS);
}
static VkResult
x11_get_surface_info(struct anv_wsi_implementation *impl,
struct anv_device *device,
VkSurfaceDescriptionWindowWSI *vk_window,
VkSurfaceInfoTypeWSI infoType,
size_t* pDataSize, void* pData)
{
if (pDataSize == NULL)
return vk_error(VK_ERROR_INVALID_POINTER);
switch (infoType) {
case VK_SURFACE_INFO_TYPE_PROPERTIES_WSI: {
VkSurfacePropertiesWSI *props = pData;
if (pData == NULL) {
*pDataSize = sizeof(*props);
return VK_SUCCESS;
}
assert(*pDataSize >= sizeof(*props));
VkPlatformHandleXcbWSI *vk_xcb_handle = vk_window->pPlatformHandle;
xcb_connection_t *conn = vk_xcb_handle->connection;
xcb_window_t win = (xcb_window_t)(uintptr_t)vk_window->pPlatformWindow;
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(conn, win);
xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(conn, cookie,
NULL);
VkExtent2D extent = { geom->width, geom->height };
free(geom);
props->minImageCount = 2;
props->maxImageCount = 4;
props->currentExtent = extent;
props->minImageExtent = extent;
props->maxImageExtent = extent;
props->supportedTransforms = VK_SURFACE_TRANSFORM_NONE_BIT_WSI;
props->currentTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
props->maxImageArraySize = 1;
props->supportedUsageFlags =
VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT |
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
return VK_SUCCESS;
}
case VK_SURFACE_INFO_TYPE_FORMATS_WSI:
if (pData == NULL) {
*pDataSize = sizeof(formats);
return VK_SUCCESS;
}
assert(*pDataSize >= sizeof(formats));
memcpy(pData, formats, *pDataSize);
return VK_SUCCESS;
case VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI:
if (pData == NULL) {
*pDataSize = sizeof(present_modes);
return VK_SUCCESS;
}
assert(*pDataSize >= sizeof(present_modes));
memcpy(pData, present_modes, *pDataSize);
return VK_SUCCESS;
default:
return vk_error(VK_ERROR_INVALID_VALUE);
}
}
struct x11_image {
struct anv_image * image;
struct anv_device_memory * memory;
xcb_pixmap_t pixmap;
xcb_get_geometry_cookie_t geom_cookie;
bool busy;
};
struct x11_swap_chain {
struct anv_swap_chain base;
xcb_connection_t * conn;
xcb_window_t window;
xcb_gc_t gc;
VkExtent2D extent;
uint32_t image_count;
uint32_t next_image;
struct x11_image images[0];
};
static VkResult
x11_get_swap_chain_info(struct anv_swap_chain *anv_chain,
VkSwapChainInfoTypeWSI infoType,
size_t* pDataSize, void* pData)
{
struct x11_swap_chain *chain = (struct x11_swap_chain *)anv_chain;
size_t size;
switch (infoType) {
case VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI: {
VkSwapChainImagePropertiesWSI *images = pData;
size = chain->image_count * sizeof(*images);
if (pData == NULL) {
*pDataSize = size;
return VK_SUCCESS;
}
assert(size <= *pDataSize);
for (uint32_t i = 0; i < chain->image_count; i++)
images[i].image = anv_image_to_handle(chain->images[i].image);
*pDataSize = size;
return VK_SUCCESS;
}
default:
return vk_error(VK_ERROR_INVALID_VALUE);
}
}
static VkResult
x11_acquire_next_image(struct anv_swap_chain *anv_chain,
uint64_t timeout,
VkSemaphore semaphore,
uint32_t *image_index)
{
struct x11_swap_chain *chain = (struct x11_swap_chain *)anv_chain;
struct x11_image *image = &chain->images[chain->next_image];
if (image->busy) {
xcb_get_geometry_reply_t *geom =
xcb_get_geometry_reply(chain->conn, image->geom_cookie, NULL);
image->busy = false;
if (geom->width != chain->extent.width ||
geom->height != chain->extent.height) {
free(geom);
return vk_error(VK_ERROR_OUT_OF_DATE_WSI);
}
free(geom);
}
*image_index = chain->next_image;
chain->next_image = (chain->next_image + 1) % chain->image_count;
return VK_SUCCESS;
}
static VkResult
x11_queue_present(struct anv_swap_chain *anv_chain,
struct anv_queue *queue,
uint32_t image_index)
{
struct x11_swap_chain *chain = (struct x11_swap_chain *)anv_chain;
struct x11_image *image = &chain->images[image_index];
assert(image_index < chain->image_count);
xcb_void_cookie_t cookie;
cookie = xcb_copy_area(chain->conn,
image->pixmap,
chain->window,
chain->gc,
0, 0,
0, 0,
chain->extent.width,
chain->extent.height);
xcb_discard_reply(chain->conn, cookie.sequence);
image->geom_cookie = xcb_get_geometry(chain->conn, chain->window);
image->busy = true;
xcb_flush(chain->conn);
return VK_SUCCESS;
}
static VkResult
x11_destroy_swap_chain(struct anv_swap_chain *anv_chain)
{
struct x11_swap_chain *chain = (struct x11_swap_chain *)anv_chain;
xcb_void_cookie_t cookie;
for (uint32_t i = 0; i < chain->image_count; i++) {
struct x11_image *image = &chain->images[i];
if (image->busy)
xcb_discard_reply(chain->conn, image->geom_cookie.sequence);
cookie = xcb_free_pixmap(chain->conn, image->pixmap);
xcb_discard_reply(chain->conn, cookie.sequence);
/* TODO: Delete images and free memory */
}
anv_device_free(chain->base.device, chain);
return VK_SUCCESS;
}
static VkResult
x11_create_swap_chain(struct anv_wsi_implementation *impl,
struct anv_device *device,
const VkSwapChainCreateInfoWSI *pCreateInfo,
struct anv_swap_chain **swap_chain_out)
{
struct x11_swap_chain *chain;
xcb_void_cookie_t cookie;
VkResult result;
assert(pCreateInfo->pSurfaceDescription->sType ==
VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI);
VkSurfaceDescriptionWindowWSI *vk_window =
(VkSurfaceDescriptionWindowWSI *)pCreateInfo->pSurfaceDescription;
assert(vk_window->platform == VK_PLATFORM_XCB_WSI);
int num_images = pCreateInfo->minImageCount;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
chain = anv_device_alloc(device, size, 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (chain == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
chain->base.device = device;
chain->base.destroy = x11_destroy_swap_chain;
chain->base.get_swap_chain_info = x11_get_swap_chain_info;
chain->base.acquire_next_image = x11_acquire_next_image;
chain->base.queue_present = x11_queue_present;
VkPlatformHandleXcbWSI *vk_xcb_handle = vk_window->pPlatformHandle;
chain->conn = (xcb_connection_t *) vk_xcb_handle->connection;
chain->window = (xcb_window_t) (uintptr_t)vk_window->pPlatformWindow;
chain->extent = pCreateInfo->imageExtent;
chain->image_count = num_images;
chain->next_image = 0;
for (uint32_t i = 0; i < chain->image_count; i++) {
VkDeviceMemory memory_h;
VkImage image_h;
struct anv_image *image;
struct anv_surface *surface;
struct anv_device_memory *memory;
anv_image_create(anv_device_to_handle(device),
&(struct anv_image_create_info) {
.force_tile_mode = true,
.tile_mode = XMAJOR,
.stride = 0,
.vk_info =
&(VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D,
.format = pCreateInfo->imageFormat,
.extent = {
.width = pCreateInfo->imageExtent.width,
.height = pCreateInfo->imageExtent.height,
.depth = 1
},
.mipLevels = 1,
.arraySize = 1,
.samples = 1,
/* FIXME: Need a way to use X tiling to allow scanout */
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.flags = 0,
}},
&image_h);
image = anv_image_from_handle(image_h);
assert(anv_format_is_color(image->format));
surface = &image->color_surface;
anv_AllocMemory(anv_device_to_handle(device),
&(VkMemoryAllocInfo) {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
.allocationSize = image->size,
.memoryTypeIndex = 0,
},
&memory_h);
memory = anv_device_memory_from_handle(memory_h);
anv_BindImageMemory(VK_NULL_HANDLE, anv_image_to_handle(image),
memory_h, 0);
int ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
surface->stride, I915_TILING_X);
if (ret) {
result = vk_errorf(VK_ERROR_UNKNOWN, "set_tiling failed: %m");
goto fail;
}
int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
if (fd == -1) {
result = vk_errorf(VK_ERROR_UNKNOWN, "handle_to_fd failed: %m");
goto fail;
}
uint32_t bpp = 32;
uint32_t depth = 24;
xcb_pixmap_t pixmap = xcb_generate_id(chain->conn);
cookie =
xcb_dri3_pixmap_from_buffer_checked(chain->conn,
pixmap,
chain->window,
image->size,
pCreateInfo->imageExtent.width,
pCreateInfo->imageExtent.height,
surface->stride,
depth, bpp, fd);
chain->images[i].image = image;
chain->images[i].memory = memory;
chain->images[i].pixmap = pixmap;
chain->images[i].busy = false;
xcb_discard_reply(chain->conn, cookie.sequence);
}
chain->gc = xcb_generate_id(chain->conn);
if (!chain->gc) {
result = vk_error(VK_ERROR_UNKNOWN);
goto fail;
}
cookie = xcb_create_gc(chain->conn,
chain->gc,
chain->window,
XCB_GC_GRAPHICS_EXPOSURES,
(uint32_t []) { 0 });
xcb_discard_reply(chain->conn, cookie.sequence);
*swap_chain_out = &chain->base;
return VK_SUCCESS;
fail:
return result;
}
VkResult
anv_x11_init_wsi(struct anv_instance *instance)
{
struct anv_wsi_implementation *impl;
impl = anv_instance_alloc(instance, sizeof(*impl), 8,
VK_SYSTEM_ALLOC_TYPE_INTERNAL);
if (!impl)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
impl->get_window_supported = x11_get_window_supported;
impl->get_surface_info = x11_get_surface_info;
impl->create_swap_chain = x11_create_swap_chain;
instance->wsi_impl[VK_PLATFORM_XCB_WSI] = impl;
return VK_SUCCESS;
}
void
anv_x11_finish_wsi(struct anv_instance *instance)
{
anv_instance_free(instance, instance->wsi_impl[VK_PLATFORM_XCB_WSI]);
}

8391
src/vulkan/gen75_pack.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,689 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
void
gen7_cmd_buffer_emit_state_base_address(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_device *device = cmd_buffer->device;
struct anv_bo *scratch_bo = NULL;
cmd_buffer->state.scratch_size =
anv_block_pool_size(&device->scratch_block_pool);
if (cmd_buffer->state.scratch_size > 0)
scratch_bo = &device->scratch_block_pool.bo;
anv_batch_emit(&cmd_buffer->batch, GEN7_STATE_BASE_ADDRESS,
.GeneralStateBaseAddress = { scratch_bo, 0 },
.GeneralStateMemoryObjectControlState = GEN7_MOCS,
.GeneralStateBaseAddressModifyEnable = true,
.GeneralStateAccessUpperBound = { scratch_bo, scratch_bo->size },
.GeneralStateAccessUpperBoundModifyEnable = true,
.SurfaceStateBaseAddress = anv_cmd_buffer_surface_base_address(cmd_buffer),
.SurfaceStateMemoryObjectControlState = GEN7_MOCS,
.SurfaceStateBaseAddressModifyEnable = true,
.DynamicStateBaseAddress = { &device->dynamic_state_block_pool.bo, 0 },
.DynamicStateMemoryObjectControlState = GEN7_MOCS,
.DynamicStateBaseAddressModifyEnable = true,
.DynamicStateAccessUpperBound = { &device->dynamic_state_block_pool.bo,
device->dynamic_state_block_pool.bo.size },
.DynamicStateAccessUpperBoundModifyEnable = true,
.IndirectObjectBaseAddress = { NULL, 0 },
.IndirectObjectMemoryObjectControlState = GEN7_MOCS,
.IndirectObjectBaseAddressModifyEnable = true,
.IndirectObjectAccessUpperBound = { NULL, 0xffffffff },
.IndirectObjectAccessUpperBoundModifyEnable = true,
.InstructionBaseAddress = { &device->instruction_block_pool.bo, 0 },
.InstructionMemoryObjectControlState = GEN7_MOCS,
.InstructionBaseAddressModifyEnable = true,
.InstructionAccessUpperBound = { &device->instruction_block_pool.bo,
device->instruction_block_pool.bo.size },
.InstructionAccessUpperBoundModifyEnable = true);
/* After re-setting the surface state base address, we have to do some
* cache flusing so that the sampler engine will pick up the new
* SURFACE_STATE objects and binding tables. From the Broadwell PRM,
* Shared Function > 3D Sampler > State > State Caching (page 96):
*
* Coherency with system memory in the state cache, like the texture
* cache is handled partially by software. It is expected that the
* command stream or shader will issue Cache Flush operation or
* Cache_Flush sampler message to ensure that the L1 cache remains
* coherent with system memory.
*
* [...]
*
* Whenever the value of the Dynamic_State_Base_Addr,
* Surface_State_Base_Addr are altered, the L1 state cache must be
* invalidated to ensure the new surface or sampler state is fetched
* from system memory.
*
* The PIPE_CONTROL command has a "State Cache Invalidation Enable" bit
* which, according the PIPE_CONTROL instruction documentation in the
* Broadwell PRM:
*
* Setting this bit is independent of any other bit in this packet.
* This bit controls the invalidation of the L1 and L2 state caches
* at the top of the pipe i.e. at the parsing time.
*
* Unfortunately, experimentation seems to indicate that state cache
* invalidation through a PIPE_CONTROL does nothing whatsoever in
* regards to surface state and binding tables. In stead, it seems that
* invalidating the texture cache is what is actually needed.
*
* XXX: As far as we have been able to determine through
* experimentation, shows that flush the texture cache appears to be
* sufficient. The theory here is that all of the sampling/rendering
* units cache the binding table in the texture cache. However, we have
* yet to be able to actually confirm this.
*/
anv_batch_emit(&cmd_buffer->batch, GEN7_PIPE_CONTROL,
.TextureCacheInvalidationEnable = true);
}
static const uint32_t vk_to_gen_index_type[] = {
[VK_INDEX_TYPE_UINT16] = INDEX_WORD,
[VK_INDEX_TYPE_UINT32] = INDEX_DWORD,
};
void gen7_CmdBindIndexBuffer(
VkCmdBuffer cmdBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
VkIndexType indexType)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
cmd_buffer->state.dirty |= ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY;
cmd_buffer->state.gen7.index_buffer = buffer;
cmd_buffer->state.gen7.index_type = vk_to_gen_index_type[indexType];
cmd_buffer->state.gen7.index_offset = offset;
}
static VkResult
gen7_flush_compute_descriptor_set(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_device *device = cmd_buffer->device;
struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
struct anv_state surfaces = { 0, }, samplers = { 0, };
VkResult result;
result = anv_cmd_buffer_emit_samplers(cmd_buffer,
VK_SHADER_STAGE_COMPUTE, &samplers);
if (result != VK_SUCCESS)
return result;
result = anv_cmd_buffer_emit_binding_table(cmd_buffer,
VK_SHADER_STAGE_COMPUTE, &surfaces);
if (result != VK_SUCCESS)
return result;
struct GEN7_INTERFACE_DESCRIPTOR_DATA desc = {
.KernelStartPointer = pipeline->cs_simd,
.BindingTablePointer = surfaces.offset,
.SamplerStatePointer = samplers.offset,
.NumberofThreadsinGPGPUThreadGroup = 0 /* FIXME: Really? */
};
uint32_t size = GEN7_INTERFACE_DESCRIPTOR_DATA_length * sizeof(uint32_t);
struct anv_state state =
anv_state_pool_alloc(&device->dynamic_state_pool, size, 64);
GEN7_INTERFACE_DESCRIPTOR_DATA_pack(NULL, state.map, &desc);
anv_batch_emit(&cmd_buffer->batch, GEN7_MEDIA_INTERFACE_DESCRIPTOR_LOAD,
.InterfaceDescriptorTotalLength = size,
.InterfaceDescriptorDataStartAddress = state.offset);
return VK_SUCCESS;
}
static void
gen7_cmd_buffer_flush_compute_state(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
VkResult result;
assert(pipeline->active_stages == VK_SHADER_STAGE_COMPUTE_BIT);
if (cmd_buffer->state.current_pipeline != GPGPU) {
anv_batch_emit(&cmd_buffer->batch, GEN7_PIPELINE_SELECT,
.PipelineSelection = GPGPU);
cmd_buffer->state.current_pipeline = GPGPU;
}
if (cmd_buffer->state.compute_dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY)
anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->batch);
if ((cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_COMPUTE_BIT) ||
(cmd_buffer->state.compute_dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY)) {
/* FIXME: figure out descriptors for gen7 */
result = gen7_flush_compute_descriptor_set(cmd_buffer);
assert(result == VK_SUCCESS);
cmd_buffer->state.descriptors_dirty &= ~VK_SHADER_STAGE_COMPUTE;
}
cmd_buffer->state.compute_dirty = 0;
}
static void
gen7_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
uint32_t *p;
uint32_t vb_emit = cmd_buffer->state.vb_dirty & pipeline->vb_used;
assert((pipeline->active_stages & VK_SHADER_STAGE_COMPUTE_BIT) == 0);
if (cmd_buffer->state.current_pipeline != _3D) {
anv_batch_emit(&cmd_buffer->batch, GEN7_PIPELINE_SELECT,
.PipelineSelection = _3D);
cmd_buffer->state.current_pipeline = _3D;
}
if (vb_emit) {
const uint32_t num_buffers = __builtin_popcount(vb_emit);
const uint32_t num_dwords = 1 + num_buffers * 4;
p = anv_batch_emitn(&cmd_buffer->batch, num_dwords,
GEN7_3DSTATE_VERTEX_BUFFERS);
uint32_t vb, i = 0;
for_each_bit(vb, vb_emit) {
struct anv_buffer *buffer = cmd_buffer->state.vertex_bindings[vb].buffer;
uint32_t offset = cmd_buffer->state.vertex_bindings[vb].offset;
struct GEN7_VERTEX_BUFFER_STATE state = {
.VertexBufferIndex = vb,
.BufferAccessType = pipeline->instancing_enable[vb] ? INSTANCEDATA : VERTEXDATA,
.VertexBufferMemoryObjectControlState = GEN7_MOCS,
.AddressModifyEnable = true,
.BufferPitch = pipeline->binding_stride[vb],
.BufferStartingAddress = { buffer->bo, buffer->offset + offset },
.EndAddress = { buffer->bo, buffer->offset + buffer->size - 1},
.InstanceDataStepRate = 1
};
GEN7_VERTEX_BUFFER_STATE_pack(&cmd_buffer->batch, &p[1 + i * 4], &state);
i++;
}
}
if (cmd_buffer->state.dirty & ANV_CMD_BUFFER_PIPELINE_DIRTY) {
/* If somebody compiled a pipeline after starting a command buffer the
* scratch bo may have grown since we started this cmd buffer (and
* emitted STATE_BASE_ADDRESS). If we're binding that pipeline now,
* reemit STATE_BASE_ADDRESS so that we use the bigger scratch bo. */
if (cmd_buffer->state.scratch_size < pipeline->total_scratch)
gen7_cmd_buffer_emit_state_base_address(cmd_buffer);
anv_batch_emit_batch(&cmd_buffer->batch, &pipeline->batch);
}
if (cmd_buffer->state.descriptors_dirty)
anv_flush_descriptor_sets(cmd_buffer);
if (cmd_buffer->state.dirty & ANV_CMD_BUFFER_VP_DIRTY) {
struct anv_dynamic_vp_state *vp_state = cmd_buffer->state.vp_state;
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_SCISSOR_STATE_POINTERS,
.ScissorRectPointer = vp_state->scissor.offset);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_VIEWPORT_STATE_POINTERS_CC,
.CCViewportPointer = vp_state->cc_vp.offset);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP,
.SFClipViewportPointer = vp_state->sf_clip_vp.offset);
}
if (cmd_buffer->state.dirty &
(ANV_CMD_BUFFER_PIPELINE_DIRTY | ANV_CMD_BUFFER_RS_DIRTY)) {
anv_batch_emit_merge(&cmd_buffer->batch,
cmd_buffer->state.rs_state->gen7.sf,
pipeline->gen7.sf);
}
if (cmd_buffer->state.dirty &
(ANV_CMD_BUFFER_PIPELINE_DIRTY | ANV_CMD_BUFFER_DS_DIRTY)) {
struct anv_state state;
if (cmd_buffer->state.ds_state == NULL)
state = anv_cmd_buffer_emit_dynamic(cmd_buffer,
pipeline->gen7.depth_stencil_state,
GEN7_COLOR_CALC_STATE_length, 64);
else
state = anv_cmd_buffer_merge_dynamic(cmd_buffer,
cmd_buffer->state.ds_state->gen7.depth_stencil_state,
pipeline->gen7.depth_stencil_state,
GEN7_DEPTH_STENCIL_STATE_length, 64);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_DEPTH_STENCIL_STATE_POINTERS,
.PointertoDEPTH_STENCIL_STATE = state.offset);
}
if (cmd_buffer->state.dirty &
(ANV_CMD_BUFFER_CB_DIRTY | ANV_CMD_BUFFER_DS_DIRTY)) {
struct anv_state state;
if (cmd_buffer->state.ds_state == NULL)
state = anv_cmd_buffer_emit_dynamic(cmd_buffer,
cmd_buffer->state.cb_state->color_calc_state,
GEN7_COLOR_CALC_STATE_length, 64);
else if (cmd_buffer->state.cb_state == NULL)
state = anv_cmd_buffer_emit_dynamic(cmd_buffer,
cmd_buffer->state.ds_state->gen7.color_calc_state,
GEN7_COLOR_CALC_STATE_length, 64);
else
state = anv_cmd_buffer_merge_dynamic(cmd_buffer,
cmd_buffer->state.ds_state->gen7.color_calc_state,
cmd_buffer->state.cb_state->color_calc_state,
GEN7_COLOR_CALC_STATE_length, 64);
anv_batch_emit(&cmd_buffer->batch,
GEN7_3DSTATE_CC_STATE_POINTERS,
.ColorCalcStatePointer = state.offset);
}
if (cmd_buffer->state.gen7.index_buffer &&
cmd_buffer->state.dirty & (ANV_CMD_BUFFER_PIPELINE_DIRTY |
ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY)) {
struct anv_buffer *buffer = cmd_buffer->state.gen7.index_buffer;
uint32_t offset = cmd_buffer->state.gen7.index_offset;
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_INDEX_BUFFER,
.CutIndexEnable = pipeline->primitive_restart,
.IndexFormat = cmd_buffer->state.gen7.index_type,
.MemoryObjectControlState = GEN7_MOCS,
.BufferStartingAddress = { buffer->bo, buffer->offset + offset },
.BufferEndingAddress = { buffer->bo, buffer->offset + buffer->size });
}
cmd_buffer->state.vb_dirty &= ~vb_emit;
cmd_buffer->state.dirty = 0;
}
void gen7_CmdDraw(
VkCmdBuffer cmdBuffer,
uint32_t firstVertex,
uint32_t vertexCount,
uint32_t firstInstance,
uint32_t instanceCount)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
gen7_cmd_buffer_flush_state(cmd_buffer);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DPRIMITIVE,
.VertexAccessType = SEQUENTIAL,
.PrimitiveTopologyType = pipeline->topology,
.VertexCountPerInstance = vertexCount,
.StartVertexLocation = firstVertex,
.InstanceCount = instanceCount,
.StartInstanceLocation = firstInstance,
.BaseVertexLocation = 0);
}
void gen7_CmdDrawIndexed(
VkCmdBuffer cmdBuffer,
uint32_t firstIndex,
uint32_t indexCount,
int32_t vertexOffset,
uint32_t firstInstance,
uint32_t instanceCount)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
gen7_cmd_buffer_flush_state(cmd_buffer);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DPRIMITIVE,
.VertexAccessType = RANDOM,
.PrimitiveTopologyType = pipeline->topology,
.VertexCountPerInstance = indexCount,
.StartVertexLocation = firstIndex,
.InstanceCount = instanceCount,
.StartInstanceLocation = firstInstance,
.BaseVertexLocation = vertexOffset);
}
static void
gen7_batch_lrm(struct anv_batch *batch,
uint32_t reg, struct anv_bo *bo, uint32_t offset)
{
anv_batch_emit(batch, GEN7_MI_LOAD_REGISTER_MEM,
.RegisterAddress = reg,
.MemoryAddress = { bo, offset });
}
static void
gen7_batch_lri(struct anv_batch *batch, uint32_t reg, uint32_t imm)
{
anv_batch_emit(batch, GEN7_MI_LOAD_REGISTER_IMM,
.RegisterOffset = reg,
.DataDWord = imm);
}
/* Auto-Draw / Indirect Registers */
#define GEN7_3DPRIM_END_OFFSET 0x2420
#define GEN7_3DPRIM_START_VERTEX 0x2430
#define GEN7_3DPRIM_VERTEX_COUNT 0x2434
#define GEN7_3DPRIM_INSTANCE_COUNT 0x2438
#define GEN7_3DPRIM_START_INSTANCE 0x243C
#define GEN7_3DPRIM_BASE_VERTEX 0x2440
void gen7_CmdDrawIndirect(
VkCmdBuffer cmdBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t count,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
gen7_cmd_buffer_flush_state(cmd_buffer);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_VERTEX_COUNT, bo, bo_offset);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_INSTANCE_COUNT, bo, bo_offset + 4);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_VERTEX, bo, bo_offset + 8);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 12);
gen7_batch_lri(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, 0);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DPRIMITIVE,
.IndirectParameterEnable = true,
.VertexAccessType = SEQUENTIAL,
.PrimitiveTopologyType = pipeline->topology);
}
void gen7_CmdDrawIndexedIndirect(
VkCmdBuffer cmdBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t count,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
gen7_cmd_buffer_flush_state(cmd_buffer);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_VERTEX_COUNT, bo, bo_offset);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_INSTANCE_COUNT, bo, bo_offset + 4);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_VERTEX, bo, bo_offset + 8);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, bo, bo_offset + 12);
gen7_batch_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 16);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DPRIMITIVE,
.IndirectParameterEnable = true,
.VertexAccessType = RANDOM,
.PrimitiveTopologyType = pipeline->topology);
}
void gen7_CmdDispatch(
VkCmdBuffer cmdBuffer,
uint32_t x,
uint32_t y,
uint32_t z)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
gen7_cmd_buffer_flush_compute_state(cmd_buffer);
anv_batch_emit(&cmd_buffer->batch, GEN7_GPGPU_WALKER,
.SIMDSize = prog_data->simd_size / 16,
.ThreadDepthCounterMaximum = 0,
.ThreadHeightCounterMaximum = 0,
.ThreadWidthCounterMaximum = pipeline->cs_thread_width_max,
.ThreadGroupIDXDimension = x,
.ThreadGroupIDYDimension = y,
.ThreadGroupIDZDimension = z,
.RightExecutionMask = pipeline->cs_right_mask,
.BottomExecutionMask = 0xffffffff);
anv_batch_emit(&cmd_buffer->batch, GEN7_MEDIA_STATE_FLUSH);
}
#define GPGPU_DISPATCHDIMX 0x2500
#define GPGPU_DISPATCHDIMY 0x2504
#define GPGPU_DISPATCHDIMZ 0x2508
void gen7_CmdDispatchIndirect(
VkCmdBuffer cmdBuffer,
VkBuffer _buffer,
VkDeviceSize offset)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_pipeline *pipeline = cmd_buffer->state.compute_pipeline;
struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
gen7_cmd_buffer_flush_compute_state(cmd_buffer);
gen7_batch_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMX, bo, bo_offset);
gen7_batch_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMY, bo, bo_offset + 4);
gen7_batch_lrm(&cmd_buffer->batch, GPGPU_DISPATCHDIMZ, bo, bo_offset + 8);
anv_batch_emit(&cmd_buffer->batch, GEN7_GPGPU_WALKER,
.IndirectParameterEnable = true,
.SIMDSize = prog_data->simd_size / 16,
.ThreadDepthCounterMaximum = 0,
.ThreadHeightCounterMaximum = 0,
.ThreadWidthCounterMaximum = pipeline->cs_thread_width_max,
.RightExecutionMask = pipeline->cs_right_mask,
.BottomExecutionMask = 0xffffffff);
anv_batch_emit(&cmd_buffer->batch, GEN7_MEDIA_STATE_FLUSH);
}
void gen7_CmdPipelineBarrier(
VkCmdBuffer cmdBuffer,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags destStageMask,
VkBool32 byRegion,
uint32_t memBarrierCount,
const void* const* ppMemBarriers)
{
stub();
}
static void
gen7_cmd_buffer_emit_depth_stencil(struct anv_cmd_buffer *cmd_buffer)
{
const struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
const struct anv_depth_stencil_view *view =
anv_cmd_buffer_get_depth_stencil_view(cmd_buffer);
const struct anv_image *image = view ? view->image : NULL;
const bool has_depth = view && view->format->depth_format;
const bool has_stencil = view && view->format->has_stencil;
/* Emit 3DSTATE_DEPTH_BUFFER */
if (has_depth) {
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_DEPTH_BUFFER,
.SurfaceType = SURFTYPE_2D,
.DepthWriteEnable = view->format->depth_format,
.StencilWriteEnable = has_stencil,
.HierarchicalDepthBufferEnable = false,
.SurfaceFormat = view->format->depth_format,
.SurfacePitch = image->depth_surface.stride - 1,
.SurfaceBaseAddress = {
.bo = image->bo,
.offset = image->depth_surface.offset,
},
.Height = fb->height - 1,
.Width = fb->width - 1,
.LOD = 0,
.Depth = 1 - 1,
.MinimumArrayElement = 0,
.DepthBufferObjectControlState = GEN7_MOCS,
.RenderTargetViewExtent = 1 - 1);
} else {
/* Even when no depth buffer is present, the hardware requires that
* 3DSTATE_DEPTH_BUFFER be programmed correctly. The Broadwell PRM says:
*
* If a null depth buffer is bound, the driver must instead bind depth as:
* 3DSTATE_DEPTH.SurfaceType = SURFTYPE_2D
* 3DSTATE_DEPTH.Width = 1
* 3DSTATE_DEPTH.Height = 1
* 3DSTATE_DEPTH.SuraceFormat = D16_UNORM
* 3DSTATE_DEPTH.SurfaceBaseAddress = 0
* 3DSTATE_DEPTH.HierarchicalDepthBufferEnable = 0
* 3DSTATE_WM_DEPTH_STENCIL.DepthTestEnable = 0
* 3DSTATE_WM_DEPTH_STENCIL.DepthBufferWriteEnable = 0
*
* The PRM is wrong, though. The width and height must be programmed to
* actual framebuffer's width and height, even when neither depth buffer
* nor stencil buffer is present.
*/
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_DEPTH_BUFFER,
.SurfaceType = SURFTYPE_2D,
.SurfaceFormat = D16_UNORM,
.Width = fb->width - 1,
.Height = fb->height - 1,
.StencilWriteEnable = has_stencil);
}
/* Emit 3DSTATE_STENCIL_BUFFER */
if (has_stencil) {
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_STENCIL_BUFFER,
.StencilBufferObjectControlState = GEN7_MOCS,
/* Stencil buffers have strange pitch. The PRM says:
*
* The pitch must be set to 2x the value computed based on width,
* as the stencil buffer is stored with two rows interleaved.
*/
.SurfacePitch = 2 * image->stencil_surface.stride - 1,
.SurfaceBaseAddress = {
.bo = image->bo,
.offset = image->offset + image->stencil_surface.offset,
});
} else {
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_STENCIL_BUFFER);
}
/* Disable hierarchial depth buffers. */
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_HIER_DEPTH_BUFFER);
/* Clear the clear params. */
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_CLEAR_PARAMS);
}
void
gen7_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
struct anv_subpass *subpass)
{
cmd_buffer->state.subpass = subpass;
cmd_buffer->state.descriptors_dirty |= VK_SHADER_STAGE_FRAGMENT_BIT;
gen7_cmd_buffer_emit_depth_stencil(cmd_buffer);
}
static void
begin_render_pass(struct anv_cmd_buffer *cmd_buffer,
const VkRenderPassBeginInfo* pRenderPassBegin)
{
ANV_FROM_HANDLE(anv_render_pass, pass, pRenderPassBegin->renderPass);
ANV_FROM_HANDLE(anv_framebuffer, framebuffer, pRenderPassBegin->framebuffer);
cmd_buffer->state.framebuffer = framebuffer;
cmd_buffer->state.pass = pass;
const VkRect2D *render_area = &pRenderPassBegin->renderArea;
anv_batch_emit(&cmd_buffer->batch, GEN7_3DSTATE_DRAWING_RECTANGLE,
.ClippedDrawingRectangleYMin = render_area->offset.y,
.ClippedDrawingRectangleXMin = render_area->offset.x,
.ClippedDrawingRectangleYMax =
render_area->offset.y + render_area->extent.height - 1,
.ClippedDrawingRectangleXMax =
render_area->offset.x + render_area->extent.width - 1,
.DrawingRectangleOriginY = 0,
.DrawingRectangleOriginX = 0);
anv_cmd_buffer_clear_attachments(cmd_buffer, pass,
pRenderPassBegin->pAttachmentClearValues);
}
void gen7_CmdBeginRenderPass(
VkCmdBuffer cmdBuffer,
const VkRenderPassBeginInfo* pRenderPassBegin,
VkRenderPassContents contents)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_render_pass, pass, pRenderPassBegin->renderPass);
begin_render_pass(cmd_buffer, pRenderPassBegin);
gen7_cmd_buffer_begin_subpass(cmd_buffer, pass->subpasses);
}
void gen7_CmdNextSubpass(
VkCmdBuffer cmdBuffer,
VkRenderPassContents contents)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
assert(cmd_buffer->level == VK_CMD_BUFFER_LEVEL_PRIMARY);
gen7_cmd_buffer_begin_subpass(cmd_buffer, cmd_buffer->state.subpass + 1);
}
void gen7_CmdEndRenderPass(
VkCmdBuffer cmdBuffer)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
/* Emit a flushing pipe control at the end of a pass. This is kind of a
* hack but it ensures that render targets always actually get written.
* Eventually, we should do flushing based on image format transitions
* or something of that nature.
*/
anv_batch_emit(&cmd_buffer->batch, GEN7_PIPE_CONTROL,
.PostSyncOperation = NoWrite,
.RenderTargetCacheFlushEnable = true,
.InstructionCacheInvalidateEnable = true,
.DepthCacheFlushEnable = true,
.VFCacheInvalidationEnable = true,
.TextureCacheInvalidationEnable = true,
.CommandStreamerStallEnable = true);
}

6973
src/vulkan/gen7_pack.h Normal file

File diff suppressed because it is too large Load Diff

572
src/vulkan/gen7_pipeline.c Normal file
View File

@@ -0,0 +1,572 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
static void
gen7_emit_vertex_input(struct anv_pipeline *pipeline,
const VkPipelineVertexInputStateCreateInfo *info)
{
const bool sgvs = pipeline->vs_prog_data.uses_vertexid ||
pipeline->vs_prog_data.uses_instanceid;
const uint32_t element_count = info->attributeCount + (sgvs ? 1 : 0);
const uint32_t num_dwords = 1 + element_count * 2;
uint32_t *p;
if (info->attributeCount > 0) {
p = anv_batch_emitn(&pipeline->batch, num_dwords,
GEN7_3DSTATE_VERTEX_ELEMENTS);
}
for (uint32_t i = 0; i < info->attributeCount; i++) {
const VkVertexInputAttributeDescription *desc =
&info->pVertexAttributeDescriptions[i];
const struct anv_format *format = anv_format_for_vk_format(desc->format);
struct GEN7_VERTEX_ELEMENT_STATE element = {
.VertexBufferIndex = desc->binding,
.Valid = true,
.SourceElementFormat = format->surface_format,
.EdgeFlagEnable = false,
.SourceElementOffset = desc->offsetInBytes,
.Component0Control = VFCOMP_STORE_SRC,
.Component1Control = format->num_channels >= 2 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
.Component2Control = format->num_channels >= 3 ? VFCOMP_STORE_SRC : VFCOMP_STORE_0,
.Component3Control = format->num_channels >= 4 ? VFCOMP_STORE_SRC : VFCOMP_STORE_1_FP
};
GEN7_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + i * 2], &element);
}
if (sgvs) {
struct GEN7_VERTEX_ELEMENT_STATE element = {
.Valid = true,
/* FIXME: Do we need to provide the base vertex as component 0 here
* to support the correct base vertex ID? */
.Component0Control = VFCOMP_STORE_0,
.Component1Control = VFCOMP_STORE_0,
.Component2Control = VFCOMP_STORE_VID,
.Component3Control = VFCOMP_STORE_IID
};
GEN7_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + info->attributeCount * 2], &element);
}
}
static const uint32_t vk_to_gen_cullmode[] = {
[VK_CULL_MODE_NONE] = CULLMODE_NONE,
[VK_CULL_MODE_FRONT] = CULLMODE_FRONT,
[VK_CULL_MODE_BACK] = CULLMODE_BACK,
[VK_CULL_MODE_FRONT_AND_BACK] = CULLMODE_BOTH
};
static const uint32_t vk_to_gen_fillmode[] = {
[VK_FILL_MODE_POINTS] = RASTER_POINT,
[VK_FILL_MODE_WIREFRAME] = RASTER_WIREFRAME,
[VK_FILL_MODE_SOLID] = RASTER_SOLID
};
static const uint32_t vk_to_gen_front_face[] = {
[VK_FRONT_FACE_CCW] = CounterClockwise,
[VK_FRONT_FACE_CW] = Clockwise
};
static void
gen7_emit_rs_state(struct anv_pipeline *pipeline,
const VkPipelineRasterStateCreateInfo *info,
const struct anv_graphics_pipeline_create_info *extra)
{
struct GEN7_3DSTATE_SF sf = {
GEN7_3DSTATE_SF_header,
/* FIXME: Get this from pass info */
.DepthBufferSurfaceFormat = D24_UNORM_X8_UINT,
/* LegacyGlobalDepthBiasEnable */
.StatisticsEnable = true,
.FrontFaceFillMode = vk_to_gen_fillmode[info->fillMode],
.BackFaceFillMode = vk_to_gen_fillmode[info->fillMode],
.ViewTransformEnable = !(extra && extra->disable_viewport),
.FrontWinding = vk_to_gen_front_face[info->frontFace],
/* bool AntiAliasingEnable; */
.CullMode = vk_to_gen_cullmode[info->cullMode],
/* uint32_t LineEndCapAntialiasingRegionWidth; */
.ScissorRectangleEnable = !(extra && extra->disable_scissor),
/* uint32_t MultisampleRasterizationMode; */
/* bool LastPixelEnable; */
.TriangleStripListProvokingVertexSelect = 0,
.LineStripListProvokingVertexSelect = 0,
.TriangleFanProvokingVertexSelect = 0,
/* uint32_t AALineDistanceMode; */
/* uint32_t VertexSubPixelPrecisionSelect; */
.UsePointWidthState = !pipeline->writes_point_size,
.PointWidth = 1.0,
};
GEN7_3DSTATE_SF_pack(NULL, &pipeline->gen7.sf, &sf);
}
static const uint32_t vk_to_gen_compare_op[] = {
[VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
[VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
[VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
[VK_COMPARE_OP_LESS_EQUAL] = PREFILTEROPLEQUAL,
[VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
[VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
[VK_COMPARE_OP_GREATER_EQUAL] = PREFILTEROPGEQUAL,
[VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
};
static const uint32_t vk_to_gen_stencil_op[] = {
[VK_STENCIL_OP_KEEP] = STENCILOP_KEEP,
[VK_STENCIL_OP_ZERO] = STENCILOP_ZERO,
[VK_STENCIL_OP_REPLACE] = STENCILOP_REPLACE,
[VK_STENCIL_OP_INC_CLAMP] = STENCILOP_INCRSAT,
[VK_STENCIL_OP_DEC_CLAMP] = STENCILOP_DECRSAT,
[VK_STENCIL_OP_INVERT] = STENCILOP_INVERT,
[VK_STENCIL_OP_INC_WRAP] = STENCILOP_INCR,
[VK_STENCIL_OP_DEC_WRAP] = STENCILOP_DECR,
};
static const uint32_t vk_to_gen_blend_op[] = {
[VK_BLEND_OP_ADD] = BLENDFUNCTION_ADD,
[VK_BLEND_OP_SUBTRACT] = BLENDFUNCTION_SUBTRACT,
[VK_BLEND_OP_REVERSE_SUBTRACT] = BLENDFUNCTION_REVERSE_SUBTRACT,
[VK_BLEND_OP_MIN] = BLENDFUNCTION_MIN,
[VK_BLEND_OP_MAX] = BLENDFUNCTION_MAX,
};
static const uint32_t vk_to_gen_logic_op[] = {
[VK_LOGIC_OP_COPY] = LOGICOP_COPY,
[VK_LOGIC_OP_CLEAR] = LOGICOP_CLEAR,
[VK_LOGIC_OP_AND] = LOGICOP_AND,
[VK_LOGIC_OP_AND_REVERSE] = LOGICOP_AND_REVERSE,
[VK_LOGIC_OP_AND_INVERTED] = LOGICOP_AND_INVERTED,
[VK_LOGIC_OP_NOOP] = LOGICOP_NOOP,
[VK_LOGIC_OP_XOR] = LOGICOP_XOR,
[VK_LOGIC_OP_OR] = LOGICOP_OR,
[VK_LOGIC_OP_NOR] = LOGICOP_NOR,
[VK_LOGIC_OP_EQUIV] = LOGICOP_EQUIV,
[VK_LOGIC_OP_INVERT] = LOGICOP_INVERT,
[VK_LOGIC_OP_OR_REVERSE] = LOGICOP_OR_REVERSE,
[VK_LOGIC_OP_COPY_INVERTED] = LOGICOP_COPY_INVERTED,
[VK_LOGIC_OP_OR_INVERTED] = LOGICOP_OR_INVERTED,
[VK_LOGIC_OP_NAND] = LOGICOP_NAND,
[VK_LOGIC_OP_SET] = LOGICOP_SET,
};
static const uint32_t vk_to_gen_blend[] = {
[VK_BLEND_ZERO] = BLENDFACTOR_ZERO,
[VK_BLEND_ONE] = BLENDFACTOR_ONE,
[VK_BLEND_SRC_COLOR] = BLENDFACTOR_SRC_COLOR,
[VK_BLEND_ONE_MINUS_SRC_COLOR] = BLENDFACTOR_INV_SRC_COLOR,
[VK_BLEND_DEST_COLOR] = BLENDFACTOR_DST_COLOR,
[VK_BLEND_ONE_MINUS_DEST_COLOR] = BLENDFACTOR_INV_DST_COLOR,
[VK_BLEND_SRC_ALPHA] = BLENDFACTOR_SRC_ALPHA,
[VK_BLEND_ONE_MINUS_SRC_ALPHA] = BLENDFACTOR_INV_SRC_ALPHA,
[VK_BLEND_DEST_ALPHA] = BLENDFACTOR_DST_ALPHA,
[VK_BLEND_ONE_MINUS_DEST_ALPHA] = BLENDFACTOR_INV_DST_ALPHA,
[VK_BLEND_CONSTANT_COLOR] = BLENDFACTOR_CONST_COLOR,
[VK_BLEND_ONE_MINUS_CONSTANT_COLOR] = BLENDFACTOR_INV_CONST_COLOR,
[VK_BLEND_CONSTANT_ALPHA] = BLENDFACTOR_CONST_ALPHA,
[VK_BLEND_ONE_MINUS_CONSTANT_ALPHA] = BLENDFACTOR_INV_CONST_ALPHA,
[VK_BLEND_SRC_ALPHA_SATURATE] = BLENDFACTOR_SRC_ALPHA_SATURATE,
[VK_BLEND_SRC1_COLOR] = BLENDFACTOR_SRC1_COLOR,
[VK_BLEND_ONE_MINUS_SRC1_COLOR] = BLENDFACTOR_INV_SRC1_COLOR,
[VK_BLEND_SRC1_ALPHA] = BLENDFACTOR_SRC1_ALPHA,
[VK_BLEND_ONE_MINUS_SRC1_ALPHA] = BLENDFACTOR_INV_SRC1_ALPHA,
};
static void
gen7_emit_ds_state(struct anv_pipeline *pipeline,
const VkPipelineDepthStencilStateCreateInfo *info)
{
if (info == NULL) {
/* We're going to OR this together with the dynamic state. We need
* to make sure it's initialized to something useful.
*/
memset(pipeline->gen7.depth_stencil_state, 0,
sizeof(pipeline->gen7.depth_stencil_state));
return;
}
bool has_stencil = false; /* enable if subpass has stencil? */
struct GEN7_DEPTH_STENCIL_STATE state = {
/* Is this what we need to do? */
.StencilBufferWriteEnable = has_stencil,
.StencilTestEnable = info->stencilTestEnable,
.StencilTestFunction = vk_to_gen_compare_op[info->front.stencilCompareOp],
.StencilFailOp = vk_to_gen_stencil_op[info->front.stencilFailOp],
.StencilPassDepthFailOp = vk_to_gen_stencil_op[info->front.stencilDepthFailOp],
.StencilPassDepthPassOp = vk_to_gen_stencil_op[info->front.stencilPassOp],
.DoubleSidedStencilEnable = true,
.BackFaceStencilTestFunction = vk_to_gen_compare_op[info->back.stencilCompareOp],
.BackfaceStencilFailOp = vk_to_gen_stencil_op[info->back.stencilFailOp],
.BackfaceStencilPassDepthFailOp = vk_to_gen_stencil_op[info->back.stencilDepthFailOp],
.BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info->back.stencilPassOp],
.DepthTestEnable = info->depthTestEnable,
.DepthTestFunction = vk_to_gen_compare_op[info->depthCompareOp],
.DepthBufferWriteEnable = info->depthWriteEnable,
};
GEN7_DEPTH_STENCIL_STATE_pack(NULL, &pipeline->gen7.depth_stencil_state, &state);
}
static void
gen7_emit_cb_state(struct anv_pipeline *pipeline,
const VkPipelineColorBlendStateCreateInfo *info)
{
struct anv_device *device = pipeline->device;
/* FIXME-GEN7: All render targets share blend state settings on gen7, we
* can't implement this.
*/
const VkPipelineColorBlendAttachmentState *a = &info->pAttachments[0];
uint32_t num_dwords = GEN7_BLEND_STATE_length;
pipeline->blend_state =
anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
struct GEN7_BLEND_STATE blend_state = {
.ColorBufferBlendEnable = a->blendEnable,
.IndependentAlphaBlendEnable = true, /* FIXME: yes? */
.AlphaBlendFunction = vk_to_gen_blend_op[a->blendOpAlpha],
.SourceAlphaBlendFactor = vk_to_gen_blend[a->srcBlendAlpha],
.DestinationAlphaBlendFactor = vk_to_gen_blend[a->destBlendAlpha],
.ColorBlendFunction = vk_to_gen_blend_op[a->blendOpColor],
.SourceBlendFactor = vk_to_gen_blend[a->srcBlendColor],
.DestinationBlendFactor = vk_to_gen_blend[a->destBlendColor],
.AlphaToCoverageEnable = info->alphaToCoverageEnable,
#if 0
bool AlphaToOneEnable;
bool AlphaToCoverageDitherEnable;
#endif
.WriteDisableAlpha = !(a->channelWriteMask & VK_CHANNEL_A_BIT),
.WriteDisableRed = !(a->channelWriteMask & VK_CHANNEL_R_BIT),
.WriteDisableGreen = !(a->channelWriteMask & VK_CHANNEL_G_BIT),
.WriteDisableBlue = !(a->channelWriteMask & VK_CHANNEL_B_BIT),
.LogicOpEnable = info->logicOpEnable,
.LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
#if 0
bool AlphaTestEnable;
uint32_t AlphaTestFunction;
bool ColorDitherEnable;
uint32_t XDitherOffset;
uint32_t YDitherOffset;
uint32_t ColorClampRange;
bool PreBlendColorClampEnable;
bool PostBlendColorClampEnable;
#endif
};
GEN7_BLEND_STATE_pack(NULL, pipeline->blend_state.map, &blend_state);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_BLEND_STATE_POINTERS,
.BlendStatePointer = pipeline->blend_state.offset);
}
static const uint32_t vk_to_gen_primitive_type[] = {
[VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST,
[VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST,
[VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN,
[VK_PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ] = _3DPRIM_LINELIST_ADJ,
[VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ] = _3DPRIM_LINESTRIP_ADJ,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ] = _3DPRIM_TRILIST_ADJ,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ] = _3DPRIM_TRISTRIP_ADJ,
[VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1
};
static inline uint32_t
scratch_space(const struct brw_stage_prog_data *prog_data)
{
return ffs(prog_data->total_scratch / 1024);
}
VkResult
gen7_graphics_pipeline_create(
VkDevice _device,
const VkGraphicsPipelineCreateInfo* pCreateInfo,
const struct anv_graphics_pipeline_create_info *extra,
VkPipeline* pPipeline)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_pipeline *pipeline;
VkResult result;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO);
pipeline = anv_device_alloc(device, sizeof(*pipeline), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (pipeline == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
result = anv_pipeline_init(pipeline, device, pCreateInfo, extra);
if (result != VK_SUCCESS) {
anv_device_free(device, pipeline);
return result;
}
assert(pCreateInfo->pVertexInputState);
gen7_emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
assert(pCreateInfo->pRasterState);
gen7_emit_rs_state(pipeline, pCreateInfo->pRasterState, extra);
gen7_emit_ds_state(pipeline, pCreateInfo->pDepthStencilState);
gen7_emit_cb_state(pipeline, pCreateInfo->pColorBlendState);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_VF_STATISTICS,
.StatisticsEnable = true);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_HS, .Enable = false);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_TE, .TEEnable = false);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_DS, .DSFunctionEnable = false);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_STREAMOUT, .SOFunctionEnable = false);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
.ConstantBufferOffset = 0,
.ConstantBufferSize = 4);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
.ConstantBufferOffset = 4,
.ConstantBufferSize = 4);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
.ConstantBufferOffset = 8,
.ConstantBufferSize = 4);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_AA_LINE_PARAMETERS);
const VkPipelineRasterStateCreateInfo *rs_info = pCreateInfo->pRasterState;
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_CLIP,
.FrontWinding = vk_to_gen_front_face[rs_info->frontFace],
.CullMode = vk_to_gen_cullmode[rs_info->cullMode],
.ClipEnable = true,
.APIMode = APIMODE_OGL,
.ViewportXYClipTestEnable = !(extra && extra->disable_viewport),
.ClipMode = CLIPMODE_NORMAL,
.TriangleStripListProvokingVertexSelect = 0,
.LineStripListProvokingVertexSelect = 0,
.TriangleFanProvokingVertexSelect = 0,
.MinimumPointWidth = 0.125,
.MaximumPointWidth = 255.875);
uint32_t samples = 1;
uint32_t log2_samples = __builtin_ffs(samples) - 1;
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_MULTISAMPLE,
.PixelLocation = PIXLOC_CENTER,
.NumberofMultisamples = log2_samples);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_SAMPLE_MASK,
.SampleMask = 0xff);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_URB_VS,
.VSURBStartingAddress = pipeline->urb.vs_start,
.VSURBEntryAllocationSize = pipeline->urb.vs_size - 1,
.VSNumberofURBEntries = pipeline->urb.nr_vs_entries);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_URB_GS,
.GSURBStartingAddress = pipeline->urb.gs_start,
.GSURBEntryAllocationSize = pipeline->urb.gs_size - 1,
.GSNumberofURBEntries = pipeline->urb.nr_gs_entries);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_URB_HS,
.HSURBStartingAddress = pipeline->urb.vs_start,
.HSURBEntryAllocationSize = 0,
.HSNumberofURBEntries = 0);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_URB_DS,
.DSURBStartingAddress = pipeline->urb.vs_start,
.DSURBEntryAllocationSize = 0,
.DSNumberofURBEntries = 0);
const struct brw_vue_prog_data *vue_prog_data = &pipeline->vs_prog_data.base;
/* The last geometry producing stage will set urb_offset and urb_length,
* which we use in 3DSTATE_SBE. Skip the VUE header and position slots. */
uint32_t urb_offset = 1;
uint32_t urb_length = (vue_prog_data->vue_map.num_slots + 1) / 2 - urb_offset;
#if 0
/* From gen7_vs_state.c */
/**
* From Graphics BSpec: 3D-Media-GPGPU Engine > 3D Pipeline Stages >
* Geometry > Geometry Shader > State:
*
* "Note: Because of corruption in IVB:GT2, software needs to flush the
* whole fixed function pipeline when the GS enable changes value in
* the 3DSTATE_GS."
*
* The hardware architects have clarified that in this context "flush the
* whole fixed function pipeline" means to emit a PIPE_CONTROL with the "CS
* Stall" bit set.
*/
if (!brw->is_haswell && !brw->is_baytrail)
gen7_emit_vs_workaround_flush(brw);
#endif
if (pipeline->vs_vec4 == NO_KERNEL || (extra && extra->disable_vs))
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_VS, .VSFunctionEnable = false);
else
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_VS,
.KernelStartPointer = pipeline->vs_vec4,
.ScratchSpaceBaseOffset = pipeline->scratch_start[VK_SHADER_STAGE_VERTEX],
.PerThreadScratchSpace = scratch_space(&vue_prog_data->base),
.DispatchGRFStartRegisterforURBData =
vue_prog_data->base.dispatch_grf_start_reg,
.VertexURBEntryReadLength = vue_prog_data->urb_read_length,
.VertexURBEntryReadOffset = 0,
.MaximumNumberofThreads = device->info.max_vs_threads - 1,
.StatisticsEnable = true,
.VSFunctionEnable = true);
const struct brw_gs_prog_data *gs_prog_data = &pipeline->gs_prog_data;
if (pipeline->gs_vec4 == NO_KERNEL || (extra && extra->disable_vs)) {
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_GS, .GSEnable = false);
} else {
urb_offset = 1;
urb_length = (gs_prog_data->base.vue_map.num_slots + 1) / 2 - urb_offset;
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_GS,
.KernelStartPointer = pipeline->gs_vec4,
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_GEOMETRY],
.PerThreadScratchSpace = scratch_space(&gs_prog_data->base.base),
.OutputVertexSize = gs_prog_data->output_vertex_size_hwords * 2 - 1,
.OutputTopology = gs_prog_data->output_topology,
.VertexURBEntryReadLength = gs_prog_data->base.urb_read_length,
.DispatchGRFStartRegisterforURBData =
gs_prog_data->base.base.dispatch_grf_start_reg,
.MaximumNumberofThreads = device->info.max_gs_threads - 1,
/* This in the next dword on HSW. */
.ControlDataFormat = gs_prog_data->control_data_format,
.ControlDataHeaderSize = gs_prog_data->control_data_header_size_hwords,
.InstanceControl = gs_prog_data->invocations - 1,
.DispatchMode = gs_prog_data->base.dispatch_mode,
.GSStatisticsEnable = true,
.IncludePrimitiveID = gs_prog_data->include_primitive_id,
.ReorderEnable = true,
.GSEnable = true);
}
const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
if (wm_prog_data->urb_setup[VARYING_SLOT_BFC0] != -1 ||
wm_prog_data->urb_setup[VARYING_SLOT_BFC1] != -1)
anv_finishme("two-sided color needs sbe swizzling setup");
if (wm_prog_data->urb_setup[VARYING_SLOT_PRIMITIVE_ID] != -1)
anv_finishme("primitive_id needs sbe swizzling setup");
/* FIXME: generated header doesn't emit attr swizzle fields */
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_SBE,
.NumberofSFOutputAttributes = pipeline->wm_prog_data.num_varying_inputs,
.VertexURBEntryReadLength = urb_length,
.VertexURBEntryReadOffset = urb_offset,
.PointSpriteTextureCoordinateOrigin = UPPERLEFT);
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_PS,
.KernelStartPointer0 = pipeline->ps_ksp0,
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
.PerThreadScratchSpace = scratch_space(&wm_prog_data->base),
.MaximumNumberofThreads = device->info.max_wm_threads - 1,
.PushConstantEnable = wm_prog_data->base.nr_params > 0,
.AttributeEnable = wm_prog_data->num_varying_inputs > 0,
.oMaskPresenttoRenderTarget = wm_prog_data->uses_omask,
.RenderTargetFastClearEnable = false,
.DualSourceBlendEnable = false,
.RenderTargetResolveEnable = false,
.PositionXYOffsetSelect = wm_prog_data->uses_pos_offset ?
POSOFFSET_SAMPLE : POSOFFSET_NONE,
._32PixelDispatchEnable = false,
._16PixelDispatchEnable = pipeline->ps_simd16 != NO_KERNEL,
._8PixelDispatchEnable = pipeline->ps_simd8 != NO_KERNEL,
.DispatchGRFStartRegisterforConstantSetupData0 = pipeline->ps_grf_start0,
.DispatchGRFStartRegisterforConstantSetupData1 = 0,
.DispatchGRFStartRegisterforConstantSetupData2 = pipeline->ps_grf_start2,
#if 0
/* Haswell requires the sample mask to be set in this packet as well as
* in 3DSTATE_SAMPLE_MASK; the values should match. */
/* _NEW_BUFFERS, _NEW_MULTISAMPLE */
#endif
.KernelStartPointer1 = 0,
.KernelStartPointer2 = pipeline->ps_ksp2);
/* FIXME-GEN7: This needs a lot more work, cf gen7 upload_wm_state(). */
anv_batch_emit(&pipeline->batch, GEN7_3DSTATE_WM,
.StatisticsEnable = true,
.ThreadDispatchEnable = true,
.LineEndCapAntialiasingRegionWidth = _05pixels,
.LineAntialiasingRegionWidth = _10pixels,
.EarlyDepthStencilControl = NORMAL,
.PointRasterizationRule = RASTRULE_UPPER_RIGHT,
.PixelShaderComputedDepthMode = wm_prog_data->computed_depth_mode,
.BarycentricInterpolationMode = wm_prog_data->barycentric_interp_modes);
*pPipeline = anv_pipeline_to_handle(pipeline);
return VK_SUCCESS;
}
VkResult gen7_compute_pipeline_create(
VkDevice _device,
const VkComputePipelineCreateInfo* pCreateInfo,
VkPipeline* pPipeline)
{
anv_finishme("primitive_id needs sbe swizzling setup");
return vk_error(VK_ERROR_UNAVAILABLE);
}

452
src/vulkan/gen7_state.c Normal file
View File

@@ -0,0 +1,452 @@
/*
* Copyright © 2015 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "anv_private.h"
void
gen7_fill_buffer_surface_state(void *state, const struct anv_format *format,
uint32_t offset, uint32_t range)
{
/* This assumes RGBA float format. */
uint32_t stride = 16; /* Depends on whether accessing shader is simd8 or
* vec4. Will need one of each for buffers that are
* used in both vec4 and simd8. */
uint32_t num_elements = range / stride;
struct GEN7_RENDER_SURFACE_STATE surface_state = {
.SurfaceType = SURFTYPE_BUFFER,
.SurfaceFormat = format->surface_format,
.SurfaceVerticalAlignment = VALIGN_4,
.SurfaceHorizontalAlignment = HALIGN_4,
.TiledSurface = false,
.RenderCacheReadWriteMode = false,
.SurfaceObjectControlState = GEN7_MOCS,
.Height = (num_elements >> 7) & 0x3fff,
.Width = num_elements & 0x7f,
.Depth = (num_elements >> 21) & 0x3f,
.SurfacePitch = stride - 1,
.SurfaceBaseAddress = { NULL, offset },
};
GEN7_RENDER_SURFACE_STATE_pack(NULL, state, &surface_state);
}
VkResult gen7_CreateBufferView(
VkDevice _device,
const VkBufferViewCreateInfo* pCreateInfo,
VkBufferView* pView)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_buffer_view *view;
VkResult result;
result = anv_buffer_view_create(device, pCreateInfo, &view);
if (result != VK_SUCCESS)
return result;
const struct anv_format *format =
anv_format_for_vk_format(pCreateInfo->format);
gen7_fill_buffer_surface_state(view->view.surface_state.map, format,
view->view.offset, pCreateInfo->range);
*pView = anv_buffer_view_to_handle(view);
return VK_SUCCESS;
}
static const uint32_t vk_to_gen_tex_filter[] = {
[VK_TEX_FILTER_NEAREST] = MAPFILTER_NEAREST,
[VK_TEX_FILTER_LINEAR] = MAPFILTER_LINEAR
};
static const uint32_t vk_to_gen_mipmap_mode[] = {
[VK_TEX_MIPMAP_MODE_BASE] = MIPFILTER_NONE,
[VK_TEX_MIPMAP_MODE_NEAREST] = MIPFILTER_NEAREST,
[VK_TEX_MIPMAP_MODE_LINEAR] = MIPFILTER_LINEAR
};
static const uint32_t vk_to_gen_tex_address[] = {
[VK_TEX_ADDRESS_WRAP] = TCM_WRAP,
[VK_TEX_ADDRESS_MIRROR] = TCM_MIRROR,
[VK_TEX_ADDRESS_CLAMP] = TCM_CLAMP,
[VK_TEX_ADDRESS_MIRROR_ONCE] = TCM_MIRROR_ONCE,
[VK_TEX_ADDRESS_CLAMP_BORDER] = TCM_CLAMP_BORDER,
};
static const uint32_t vk_to_gen_compare_op[] = {
[VK_COMPARE_OP_NEVER] = PREFILTEROPNEVER,
[VK_COMPARE_OP_LESS] = PREFILTEROPLESS,
[VK_COMPARE_OP_EQUAL] = PREFILTEROPEQUAL,
[VK_COMPARE_OP_LESS_EQUAL] = PREFILTEROPLEQUAL,
[VK_COMPARE_OP_GREATER] = PREFILTEROPGREATER,
[VK_COMPARE_OP_NOT_EQUAL] = PREFILTEROPNOTEQUAL,
[VK_COMPARE_OP_GREATER_EQUAL] = PREFILTEROPGEQUAL,
[VK_COMPARE_OP_ALWAYS] = PREFILTEROPALWAYS,
};
VkResult gen7_CreateSampler(
VkDevice _device,
const VkSamplerCreateInfo* pCreateInfo,
VkSampler* pSampler)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_sampler *sampler;
uint32_t mag_filter, min_filter, max_anisotropy;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
sampler = anv_device_alloc(device, sizeof(*sampler), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (!sampler)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
if (pCreateInfo->maxAnisotropy > 1) {
mag_filter = MAPFILTER_ANISOTROPIC;
min_filter = MAPFILTER_ANISOTROPIC;
max_anisotropy = (pCreateInfo->maxAnisotropy - 2) / 2;
} else {
mag_filter = vk_to_gen_tex_filter[pCreateInfo->magFilter];
min_filter = vk_to_gen_tex_filter[pCreateInfo->minFilter];
max_anisotropy = RATIO21;
}
struct GEN7_SAMPLER_STATE sampler_state = {
.SamplerDisable = false,
.TextureBorderColorMode = DX10OGL,
.BaseMipLevel = 0.0,
.MipModeFilter = vk_to_gen_mipmap_mode[pCreateInfo->mipMode],
.MagModeFilter = mag_filter,
.MinModeFilter = min_filter,
.TextureLODBias = pCreateInfo->mipLodBias * 256,
.AnisotropicAlgorithm = EWAApproximation,
.MinLOD = pCreateInfo->minLod,
.MaxLOD = pCreateInfo->maxLod,
.ChromaKeyEnable = 0,
.ChromaKeyIndex = 0,
.ChromaKeyMode = 0,
.ShadowFunction = vk_to_gen_compare_op[pCreateInfo->compareOp],
.CubeSurfaceControlMode = 0,
.BorderColorPointer =
device->border_colors.offset +
pCreateInfo->borderColor * sizeof(float) * 4,
.MaximumAnisotropy = max_anisotropy,
.RAddressMinFilterRoundingEnable = 0,
.RAddressMagFilterRoundingEnable = 0,
.VAddressMinFilterRoundingEnable = 0,
.VAddressMagFilterRoundingEnable = 0,
.UAddressMinFilterRoundingEnable = 0,
.UAddressMagFilterRoundingEnable = 0,
.TrilinearFilterQuality = 0,
.NonnormalizedCoordinateEnable = 0,
.TCXAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressU],
.TCYAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressV],
.TCZAddressControlMode = vk_to_gen_tex_address[pCreateInfo->addressW],
};
GEN7_SAMPLER_STATE_pack(NULL, sampler->state, &sampler_state);
*pSampler = anv_sampler_to_handle(sampler);
return VK_SUCCESS;
}
VkResult gen7_CreateDynamicRasterState(
VkDevice _device,
const VkDynamicRasterStateCreateInfo* pCreateInfo,
VkDynamicRasterState* pState)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_dynamic_rs_state *state;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_RASTER_STATE_CREATE_INFO);
state = anv_device_alloc(device, sizeof(*state), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (state == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
bool enable_bias = pCreateInfo->depthBias != 0.0f ||
pCreateInfo->slopeScaledDepthBias != 0.0f;
struct GEN7_3DSTATE_SF sf = {
GEN7_3DSTATE_SF_header,
.LineWidth = pCreateInfo->lineWidth,
.GlobalDepthOffsetEnableSolid = enable_bias,
.GlobalDepthOffsetEnableWireframe = enable_bias,
.GlobalDepthOffsetEnablePoint = enable_bias,
.GlobalDepthOffsetConstant = pCreateInfo->depthBias,
.GlobalDepthOffsetScale = pCreateInfo->slopeScaledDepthBias,
.GlobalDepthOffsetClamp = pCreateInfo->depthBiasClamp
};
GEN7_3DSTATE_SF_pack(NULL, state->gen7.sf, &sf);
*pState = anv_dynamic_rs_state_to_handle(state);
return VK_SUCCESS;
}
VkResult gen7_CreateDynamicDepthStencilState(
VkDevice _device,
const VkDynamicDepthStencilStateCreateInfo* pCreateInfo,
VkDynamicDepthStencilState* pState)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_dynamic_ds_state *state;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DYNAMIC_DEPTH_STENCIL_STATE_CREATE_INFO);
state = anv_device_alloc(device, sizeof(*state), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (state == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
struct GEN7_DEPTH_STENCIL_STATE depth_stencil_state = {
.StencilTestMask = pCreateInfo->stencilReadMask & 0xff,
.StencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
.BackfaceStencilTestMask = pCreateInfo->stencilReadMask & 0xff,
.BackfaceStencilWriteMask = pCreateInfo->stencilWriteMask & 0xff,
};
GEN7_DEPTH_STENCIL_STATE_pack(NULL, state->gen7.depth_stencil_state,
&depth_stencil_state);
struct GEN7_COLOR_CALC_STATE color_calc_state = {
.StencilReferenceValue = pCreateInfo->stencilFrontRef,
.BackFaceStencilReferenceValue = pCreateInfo->stencilBackRef
};
GEN7_COLOR_CALC_STATE_pack(NULL, state->gen7.color_calc_state, &color_calc_state);
*pState = anv_dynamic_ds_state_to_handle(state);
return VK_SUCCESS;
}
static const uint8_t anv_halign[] = {
[4] = HALIGN_4,
[8] = HALIGN_8,
};
static const uint8_t anv_valign[] = {
[2] = VALIGN_2,
[4] = VALIGN_4,
};
void
gen7_image_view_init(struct anv_image_view *iview,
struct anv_device *device,
const VkImageViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
{
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
struct anv_surface_view *view = &iview->view;
struct anv_surface *surface =
anv_image_get_surface_for_aspect(image, range->aspect);
const struct anv_format *format =
anv_format_for_vk_format(pCreateInfo->format);
const struct anv_image_view_info *view_type_info =
anv_image_view_info_for_vk_image_view_type(pCreateInfo->viewType);
if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
anv_finishme("non-2D image views");
view->bo = image->bo;
view->offset = image->offset + surface->offset;
view->format = anv_format_for_vk_format(pCreateInfo->format);
iview->extent = (VkExtent3D) {
.width = anv_minify(image->extent.width, range->baseMipLevel),
.height = anv_minify(image->extent.height, range->baseMipLevel),
.depth = anv_minify(image->extent.depth, range->baseMipLevel),
};
uint32_t depth = 1;
if (range->arraySize > 1) {
depth = range->arraySize;
} else if (image->extent.depth > 1) {
depth = image->extent.depth;
}
struct GEN7_RENDER_SURFACE_STATE surface_state = {
.SurfaceType = view_type_info->surface_type,
.SurfaceArray = image->array_size > 1,
.SurfaceFormat = format->surface_format,
.SurfaceVerticalAlignment = anv_valign[surface->v_align],
.SurfaceHorizontalAlignment = anv_halign[surface->h_align],
/* From bspec (DevSNB, DevIVB): "Set Tile Walk to TILEWALK_XMAJOR if
* Tiled Surface is False."
*/
.TiledSurface = surface->tile_mode > LINEAR,
.TileWalk = surface->tile_mode == YMAJOR ? TILEWALK_YMAJOR : TILEWALK_XMAJOR,
.VerticalLineStride = 0,
.VerticalLineStrideOffset = 0,
.RenderCacheReadWriteMode = false,
.Height = image->extent.height - 1,
.Width = image->extent.width - 1,
.Depth = depth - 1,
.SurfacePitch = surface->stride - 1,
.MinimumArrayElement = range->baseArraySlice,
.NumberofMultisamples = MULTISAMPLECOUNT_1,
.XOffset = 0,
.YOffset = 0,
.SurfaceObjectControlState = GEN7_MOCS,
/* For render target surfaces, the hardware interprets field MIPCount/LOD as
* LOD. The Broadwell PRM says:
*
* MIPCountLOD defines the LOD that will be rendered into.
* SurfaceMinLOD is ignored.
*/
.MIPCountLOD = range->mipLevels - 1,
.SurfaceMinLOD = range->baseMipLevel,
.MCSEnable = false,
.RedClearColor = 0,
.GreenClearColor = 0,
.BlueClearColor = 0,
.AlphaClearColor = 0,
.ResourceMinLOD = 0.0,
.SurfaceBaseAddress = { NULL, view->offset },
};
if (cmd_buffer) {
view->surface_state =
anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
} else {
view->surface_state =
anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
}
GEN7_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
}
void
gen7_color_attachment_view_init(struct anv_color_attachment_view *aview,
struct anv_device *device,
const VkAttachmentViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
{
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
struct anv_surface_view *view = &aview->view;
struct anv_surface *surface =
anv_image_get_surface_for_color_attachment(image);
aview->base.attachment_type = ANV_ATTACHMENT_VIEW_TYPE_COLOR;
anv_assert(pCreateInfo->arraySize > 0);
anv_assert(pCreateInfo->mipLevel < image->levels);
anv_assert(pCreateInfo->baseArraySlice + pCreateInfo->arraySize <= image->array_size);
view->bo = image->bo;
view->offset = image->offset + surface->offset;
view->format = anv_format_for_vk_format(pCreateInfo->format);
aview->base.extent = (VkExtent3D) {
.width = anv_minify(image->extent.width, pCreateInfo->mipLevel),
.height = anv_minify(image->extent.height, pCreateInfo->mipLevel),
.depth = anv_minify(image->extent.depth, pCreateInfo->mipLevel),
};
uint32_t depth = 1;
if (pCreateInfo->arraySize > 1) {
depth = pCreateInfo->arraySize;
} else if (image->extent.depth > 1) {
depth = image->extent.depth;
}
if (cmd_buffer) {
view->surface_state =
anv_state_stream_alloc(&cmd_buffer->surface_state_stream, 64, 64);
} else {
view->surface_state =
anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
}
struct GEN7_RENDER_SURFACE_STATE surface_state = {
.SurfaceType = SURFTYPE_2D,
.SurfaceArray = image->array_size > 1,
.SurfaceFormat = view->format->surface_format,
.SurfaceVerticalAlignment = anv_valign[surface->v_align],
.SurfaceHorizontalAlignment = anv_halign[surface->h_align],
/* From bspec (DevSNB, DevIVB): "Set Tile Walk to TILEWALK_XMAJOR if
* Tiled Surface is False."
*/
.TiledSurface = surface->tile_mode > LINEAR,
.TileWalk = surface->tile_mode == YMAJOR ? TILEWALK_YMAJOR : TILEWALK_XMAJOR,
.VerticalLineStride = 0,
.VerticalLineStrideOffset = 0,
.RenderCacheReadWriteMode = WriteOnlyCache,
.Height = image->extent.height - 1,
.Width = image->extent.width - 1,
.Depth = depth - 1,
.SurfacePitch = surface->stride - 1,
.MinimumArrayElement = pCreateInfo->baseArraySlice,
.NumberofMultisamples = MULTISAMPLECOUNT_1,
.XOffset = 0,
.YOffset = 0,
.SurfaceObjectControlState = GEN7_MOCS,
/* For render target surfaces, the hardware interprets field MIPCount/LOD as
* LOD. The Broadwell PRM says:
*
* MIPCountLOD defines the LOD that will be rendered into.
* SurfaceMinLOD is ignored.
*/
.SurfaceMinLOD = 0,
.MIPCountLOD = pCreateInfo->mipLevel,
.MCSEnable = false,
.RedClearColor = 0,
.GreenClearColor = 0,
.BlueClearColor = 0,
.AlphaClearColor = 0,
.ResourceMinLOD = 0.0,
.SurfaceBaseAddress = { NULL, view->offset },
};
GEN7_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
}

1026
src/vulkan/gen8_cmd_buffer.c Normal file

File diff suppressed because it is too large Load Diff

9179
src/vulkan/gen8_pack.h Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More