Compare commits

...

519 Commits

Author SHA1 Message Date
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
91 changed files with 50942 additions and 302 deletions

View File

@@ -1153,6 +1153,10 @@ AC_ARG_ENABLE([driglx-direct],
[driglx_direct="$enableval"],
[driglx_direct="yes"])
# Check for libcaca
PKG_CHECK_EXISTS([caca], [have_libcaca=yes], [have_libcaca=no])
AM_CONDITIONAL([HAVE_LIBCACA], [test x$have_libcaca = xyes])
dnl
dnl libGL configuration per driver
dnl
@@ -1529,6 +1533,8 @@ GBM_PC_LIB_PRIV="$DLOPEN_LIBS"
AC_SUBST([GBM_PC_REQ_PRIV])
AC_SUBST([GBM_PC_LIB_PRIV])
AM_CONDITIONAL(HAVE_VULKAN, true)
dnl
dnl EGL configuration
dnl
@@ -2318,6 +2324,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"
@@ -2425,6 +2438,7 @@ AC_CONFIG_FILES([Makefile
src/mesa/drivers/osmesa/osmesa.pc
src/mesa/drivers/x11/Makefile
src/mesa/main/tests/Makefile
src/vulkan/Makefile
src/util/Makefile
src/util/tests/hash_table/Makefile])

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 bool32_t;
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,216 @@
//
// File: vk_wsi_display.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_LUNARG_H__
#define __VK_WSI_LUNARG_H__
#include "vulkan.h"
#define VK_WSI_LUNARG_REVISION 3
#define VK_WSI_LUNARG_EXTENSION_NUMBER 1
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
// This macro defines INT_MAX in enumerations to force compilers to use 32 bits
// to represent them. This may or may not be necessary on some compilers. The
// option to compile it out may allow compilers that warn about missing enumerants
// in switch statements to be silenced.
// Using this macro is not needed for flag bit enums because those aren't used
// as storage type anywhere.
#define VK_MAX_ENUM(Prefix) VK_##Prefix##_MAX_ENUM = 0x7FFFFFFF
// This macro defines the BEGIN_RANGE, END_RANGE, NUM, and MAX_ENUM constants for
// the enumerations.
#define VK_ENUM_RANGE(Prefix, First, Last) \
VK_##Prefix##_BEGIN_RANGE = VK_##Prefix##_##First, \
VK_##Prefix##_END_RANGE = VK_##Prefix##_##Last, \
VK_NUM_##Prefix = (VK_##Prefix##_END_RANGE - VK_##Prefix##_BEGIN_RANGE + 1), \
VK_MAX_ENUM(Prefix)
// This is a helper macro to define the value of flag bit enum values.
#define VK_BIT(bit) (1 << (bit))
// ------------------------------------------------------------------------------------------------
// Objects
VK_DEFINE_DISP_SUBCLASS_HANDLE(VkDisplayWSI, VkObject)
VK_DEFINE_DISP_SUBCLASS_HANDLE(VkSwapChainWSI, VkObject)
// ------------------------------------------------------------------------------------------------
// Enumeration constants
#define VK_WSI_LUNARG_ENUM(type,id) ((type)(VK_WSI_LUNARG_EXTENSION_NUMBER * -1000 + (id)))
// Extend VkPhysicalDeviceInfoType enum with extension specific constants
#define VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI VK_WSI_LUNARG_ENUM(VkPhysicalDeviceInfoType, 0)
#define VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PRESENT_PROPERTIES_WSI VK_WSI_LUNARG_ENUM(VkPhysicalDeviceInfoType, 1)
// Extend VkStructureType enum with extension specific constants
#define VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI VK_WSI_LUNARG_ENUM(VkStructureType, 0)
#define VK_STRUCTURE_TYPE_PRESENT_INFO_WSI VK_WSI_LUNARG_ENUM(VkStructureType, 1)
// Extend VkImageLayout enum with extension specific constants
#define VK_IMAGE_LAYOUT_PRESENT_SOURCE_WSI VK_WSI_LUNARG_ENUM(VkImageLayout, 0)
// Extend VkObjectType enum for new objects
#define VK_OBJECT_TYPE_DISPLAY_WSI VK_WSI_LUNARG_ENUM(VkObjectType, 0)
#define VK_OBJECT_TYPE_SWAP_CHAIN_WSI VK_WSI_LUNARG_ENUM(VkObjectType, 1)
// ------------------------------------------------------------------------------------------------
// Enumerations
typedef enum VkDisplayInfoTypeWSI_
{
// Info type for vkGetDisplayInfo()
VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI = 0x00000003, // Return the VkFormat(s) supported for swap chains with the display
VK_ENUM_RANGE(DISPLAY_INFO_TYPE, FORMAT_PROPERTIES_WSI, FORMAT_PROPERTIES_WSI)
} VkDisplayInfoTypeWSI;
typedef enum VkSwapChainInfoTypeWSI_
{
// Info type for vkGetSwapChainInfo()
VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI = 0x00000000, // Return information about the persistent images of the swapchain
VK_ENUM_RANGE(SWAP_CHAIN_INFO_TYPE, PERSISTENT_IMAGES_WSI, PERSISTENT_IMAGES_WSI)
} VkSwapChainInfoTypeWSI;
// ------------------------------------------------------------------------------------------------
// Flags
typedef VkFlags VkSwapModeFlagsWSI;
typedef enum VkSwapModeFlagBitsWSI_
{
VK_SWAP_MODE_FLIP_BIT_WSI = VK_BIT(0),
VK_SWAP_MODE_BLIT_BIT_WSI = VK_BIT(1),
} VkSwapModeFlagBitsWSI;
// ------------------------------------------------------------------------------------------------
// Structures
typedef struct VkDisplayPropertiesWSI_
{
VkDisplayWSI display; // Handle of the display object
VkExtent2D physicalResolution; // Max resolution for CRT?
} VkDisplayPropertiesWSI;
typedef struct VkDisplayFormatPropertiesWSI_
{
VkFormat swapChainFormat; // Format of the images of the swap chain
} VkDisplayFormatPropertiesWSI;
typedef struct VkSwapChainCreateInfoWSI_
{
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI
const void* pNext; // Pointer to next structure
// TBD: It is not yet clear what the use will be for the following two
// values. It seems to be needed for more-global window-system handles
// (e.g. X11 display). If not needed for the SDK, we will drop it from
// this extension, and from a future version of this header.
const void* pNativeWindowSystemHandle; // Pointer to native window system handle
const void* pNativeWindowHandle; // Pointer to native window handle
uint32_t displayCount; // Number of displays the swap chain is created for
const VkDisplayWSI* pDisplays; // displayCount number of display objects the swap chain is created for
uint32_t imageCount; // Number of images in the swap chain
VkFormat imageFormat; // Format of the images of the swap chain
VkExtent2D imageExtent; // Width and height of the images of the swap chain
uint32_t imageArraySize; // Number of layers of the images of the swap chain (needed for multi-view rendering)
VkFlags imageUsageFlags; // Usage flags for the images of the swap chain (see VkImageUsageFlags)
VkFlags swapModeFlags; // Allowed swap modes (see VkSwapModeFlagsWSI)
} VkSwapChainCreateInfoWSI;
typedef struct VkSwapChainImageInfoWSI_
{
VkImage image; // Persistent swap chain image handle
VkDeviceMemory memory; // Persistent swap chain image's memory handle
} VkSwapChainImageInfoWSI;
typedef struct VkPhysicalDeviceQueuePresentPropertiesWSI_
{
bool32_t supportsPresent; // Tells whether the queue supports presenting
} VkPhysicalDeviceQueuePresentPropertiesWSI;
typedef struct VkPresentInfoWSI_
{
VkStructureType sType; // Must be VK_STRUCTURE_TYPE_PRESENT_INFO_WSI
const void* pNext; // Pointer to next structure
VkImage image; // Image to present
uint32_t flipInterval; // Flip interval
} VkPresentInfoWSI;
// ------------------------------------------------------------------------------------------------
// Function types
typedef VkResult (VKAPI *PFN_vkGetDisplayInfoWSI)(VkDisplayWSI display, VkDisplayInfoTypeWSI infoType, size_t* pDataSize, void* pData);
typedef VkResult (VKAPI *PFN_vkCreateSwapChainWSI)(VkDevice device, const VkSwapChainCreateInfoWSI* pCreateInfo, VkSwapChainWSI* pSwapChain);
typedef VkResult (VKAPI *PFN_vkDestroySwapChainWSI)(VkSwapChainWSI swapChain);
typedef VkResult (VKAPI *PFN_vkGetSwapChainInfoWSI)(VkSwapChainWSI swapChain, VkSwapChainInfoTypeWSI infoType, size_t* pDataSize, void* pData);
typedef VkResult (VKAPI *PFN_vkQueuePresentWSI)(VkQueue queue, const VkPresentInfoWSI* pPresentInfo);
// ------------------------------------------------------------------------------------------------
// Function prototypes
#ifdef VK_PROTOTYPES
VkResult VKAPI vkGetDisplayInfoWSI(
VkDisplayWSI display,
VkDisplayInfoTypeWSI infoType,
size_t* pDataSize,
void* pData);
VkResult VKAPI vkCreateSwapChainWSI(
VkDevice device,
const VkSwapChainCreateInfoWSI* pCreateInfo,
VkSwapChainWSI* pSwapChain);
VkResult VKAPI vkDestroySwapChainWSI(
VkSwapChainWSI swapChain);
VkResult VKAPI vkGetSwapChainInfoWSI(
VkSwapChainWSI swapChain,
VkSwapChainInfoTypeWSI infoType,
size_t* pDataSize,
void* pData);
VkResult VKAPI vkQueuePresentWSI(
VkQueue queue,
const VkPresentInfoWSI* pPresentInfo);
#endif // VK_PROTOTYPES
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // __VK_WSI_LUNARG_H__

2753
include/vulkan/vulkan-130.h Normal file

File diff suppressed because it is too large Load Diff

2894
include/vulkan/vulkan-90.h Normal file

File diff suppressed because it is too large Load Diff

2753
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

@@ -61,6 +61,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

@@ -77,7 +77,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
@@ -158,6 +158,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

@@ -59,6 +59,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 \
@@ -68,6 +69,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

@@ -514,6 +514,10 @@ struct ast_type_qualifier {
unsigned stream:1; /**< Has stream value assigned */
unsigned explicit_stream:1; /**< stream value assigned explicitly by shader code */
/** \} */
/** \name Vulkan qualifiers */
unsigned vk_set:1;
}
/** \brief Set of flags, accessed by name. */
q;
@@ -595,6 +599,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

@@ -970,6 +970,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:
/* I assume a comparison of a struct containing a sampler just
* ignores the sampler present in the type.
@@ -2644,7 +2645,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");
@@ -5886,6 +5896,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);
}
@@ -5958,6 +5972,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

@@ -252,6 +252,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

@@ -1424,13 +1424,16 @@ layout_qualifier_id:
}
}
if ((state->ARB_shading_language_420pack_enable ||
state->has_atomic_counters()) &&
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;
void *glsl_type::mem_ctx = NULL;
void
@@ -159,6 +160,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);
}
bool
glsl_type::contains_sampler() const
@@ -827,6 +861,72 @@ glsl_type::get_interface_instance(const glsl_struct_field *fields,
}
static int
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 unsigned
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 hash_table_string_hash(& 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 = hash_table_ctor(64, function_key_hash,
function_key_compare);
}
const glsl_type *t = (glsl_type *) hash_table_find(function_types, &key);
if (t == NULL) {
mtx_unlock(&glsl_type::mutex);
t = new glsl_type(return_type, params, num_params);
mtx_lock(&glsl_type::mutex);
hash_table_insert(function_types, (void *) t, t);
}
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)
{
@@ -955,6 +1055,7 @@ glsl_type::component_slots() const
case GLSL_TYPE_IMAGE:
return 1;
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_VOID:
@@ -1326,6 +1427,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,
@@ -178,7 +179,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;
@@ -263,6 +264,13 @@ struct glsl_type {
enum glsl_interface_packing packing,
const char *block_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
*/
@@ -676,6 +684,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);
@@ -688,6 +700,9 @@ private:
/** Hash table containing the known interface types. */
static struct hash_table *interface_types;
/** Hash table containing the known function types. */
static struct hash_table *function_types;
static int record_key_compare(const void *a, const void *b);
static unsigned record_key_hash(const void *key);
@@ -715,6 +730,10 @@ private:
/*@}*/
};
#undef DECL_TYPE
#undef STRUCT_TYPE
#endif /* __cplusplus */
struct glsl_struct_field {
const struct glsl_type *type;
const char *name;
@@ -758,14 +777,17 @@ struct glsl_struct_field {
int stream;
};
struct glsl_function_param {
const struct glsl_type *type;
bool in;
bool out;
};
static inline unsigned int
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

@@ -683,6 +683,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?
*
@@ -752,8 +757,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.
@@ -801,6 +808,11 @@ public:
*/
int16_t binding;
/**
* Vulkan descriptor set for the resource.
*/
int16_t set;
/**
* Storage location of the base of this variable
*

View File

@@ -357,6 +357,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

@@ -53,6 +53,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,9 @@ 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;
i++;
}
} else {
@@ -311,6 +314,9 @@ 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;
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_ERROR:
/* All other types should have already been filtered by other

View File

@@ -322,6 +322,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;

View File

@@ -300,6 +300,7 @@ typedef struct {
*
* For array types, this represents the binding point for the first element.
*/
int descriptor_set;
int binding;
/**
@@ -510,7 +511,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)
@@ -533,7 +538,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)
@@ -782,6 +791,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;
@@ -976,6 +994,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,
@@ -1661,6 +1682,7 @@ void nir_lower_phis_to_scalar(nir_shader *shader);
void nir_lower_samplers(nir_shader *shader,
const struct gl_shader_program *shader_program,
gl_shader_stage stage);
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

@@ -28,6 +28,10 @@ struct exec_list;
typedef struct nir_builder {
struct exec_list *cf_node_list;
nir_block *before_block;
nir_block *after_block;
nir_instr *before_instr;
nir_instr *after_instr;
@@ -48,6 +52,30 @@ nir_builder_insert_after_cf_list(nir_builder *build,
struct exec_list *cf_node_list)
{
build->cf_node_list = cf_node_list;
build->before_block = NULL;
build->after_block = NULL;
build->before_instr = NULL;
build->after_instr = NULL;
}
static inline void
nir_builder_insert_before_block(nir_builder *build,
nir_block *block)
{
build->cf_node_list = NULL;
build->before_block = block;
build->after_block = NULL;
build->before_instr = NULL;
build->after_instr = NULL;
}
static inline void
nir_builder_insert_after_block(nir_builder *build,
nir_block *block)
{
build->cf_node_list = NULL;
build->before_block = NULL;
build->after_block = block;
build->before_instr = NULL;
build->after_instr = NULL;
}
@@ -56,6 +84,8 @@ static inline void
nir_builder_insert_before_instr(nir_builder *build, nir_instr *before_instr)
{
build->cf_node_list = NULL;
build->before_block = NULL;
build->after_block = NULL;
build->before_instr = before_instr;
build->after_instr = NULL;
}
@@ -64,6 +94,8 @@ static inline void
nir_builder_insert_after_instr(nir_builder *build, nir_instr *after_instr)
{
build->cf_node_list = NULL;
build->before_block = NULL;
build->after_block = NULL;
build->before_instr = NULL;
build->after_instr = after_instr;
}
@@ -73,6 +105,10 @@ nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
{
if (build->cf_node_list) {
nir_instr_insert_after_cf_list(build->cf_node_list, instr);
} else if (build->before_block) {
nir_instr_insert_before_block(build->before_block, instr);
} else if (build->after_block) {
nir_instr_insert_after_block(build->after_block, instr);
} else if (build->before_instr) {
nir_instr_insert_before(build->before_instr, instr);
} else {
@@ -240,6 +276,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

@@ -67,6 +67,7 @@ type_size(const struct glsl_type *type)
return 0;
case GLSL_TYPE_IMAGE:
return 0;
case GLSL_TYPE_FUNCTION:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
case GLSL_TYPE_DOUBLE:

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, const struct gl_shader_program *shader_pr
lower_impl(overload->impl, shader_program, 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);

46
src/glsl/nir/nir_spirv.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.
*
* 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,
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,38 @@ 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_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)
{
@@ -148,14 +200,80 @@ glsl_float_type(void)
return glsl_type::float_type;
}
const glsl_type *
glsl_int_type(void)
{
return glsl_type::int_type;
}
const glsl_type *
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,17 +68,42 @@ 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_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_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
}

1304
src/glsl/nir/spirv.h Normal file

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,54 @@
/*
* 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, word_count, NULL);
nir_print_shader(shader, stderr);
}

View File

@@ -0,0 +1,285 @@
/*
* 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"
enum GLSL450Entrypoint {
Round = 0,
RoundEven = 1,
Trunc = 2,
Abs = 3,
Sign = 4,
Floor = 5,
Ceil = 6,
Fract = 7,
Radians = 8,
Degrees = 9,
Sin = 10,
Cos = 11,
Tan = 12,
Asin = 13,
Acos = 14,
Atan = 15,
Sinh = 16,
Cosh = 17,
Tanh = 18,
Asinh = 19,
Acosh = 20,
Atanh = 21,
Atan2 = 22,
Pow = 23,
Exp = 24,
Log = 25,
Exp2 = 26,
Log2 = 27,
Sqrt = 28,
InverseSqrt = 29,
Determinant = 30,
MatrixInverse = 31,
Modf = 32, // second argument needs the OpVariable = , not an OpLoad
Min = 33,
Max = 34,
Clamp = 35,
Mix = 36,
Step = 37,
SmoothStep = 38,
FloatBitsToInt = 39,
FloatBitsToUint = 40,
IntBitsToFloat = 41,
UintBitsToFloat = 42,
Fma = 43,
Frexp = 44,
Ldexp = 45,
PackSnorm4x8 = 46,
PackUnorm4x8 = 47,
PackSnorm2x16 = 48,
PackUnorm2x16 = 49,
PackHalf2x16 = 50,
PackDouble2x32 = 51,
UnpackSnorm2x16 = 52,
UnpackUnorm2x16 = 53,
UnpackHalf2x16 = 54,
UnpackSnorm4x8 = 55,
UnpackUnorm4x8 = 56,
UnpackDouble2x32 = 57,
Length = 58,
Distance = 59,
Cross = 60,
Normalize = 61,
Ftransform = 62,
FaceForward = 63,
Reflect = 64,
Refract = 65,
UaddCarry = 66,
UsubBorrow = 67,
UmulExtended = 68,
ImulExtended = 69,
BitfieldExtract = 70,
BitfieldInsert = 71,
BitfieldReverse = 72,
BitCount = 73,
FindLSB = 74,
FindMSB = 75,
InterpolateAtCentroid = 76,
InterpolateAtSample = 77,
InterpolateAtOffset = 78,
Count
};
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 GLSL450Entrypoint 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 Round: op = nir_op_fround_even; break; /* TODO */
case RoundEven: op = nir_op_fround_even; break;
case Trunc: op = nir_op_ftrunc; break;
case Abs: op = nir_op_fabs; break;
case Sign: op = nir_op_fsign; break;
case Floor: op = nir_op_ffloor; break;
case Ceil: op = nir_op_fceil; break;
case Fract: op = nir_op_ffract; break;
case Radians:
val->ssa->def = nir_fmul(&b->nb, src[0], nir_imm_float(&b->nb, 0.01745329251));
return;
case Degrees:
val->ssa->def = nir_fmul(&b->nb, src[0], nir_imm_float(&b->nb, 57.2957795131));
return;
case Sin: op = nir_op_fsin; break;
case Cos: op = nir_op_fcos; break;
case Tan:
val->ssa->def = nir_fdiv(&b->nb, nir_fsin(&b->nb, src[0]),
nir_fcos(&b->nb, src[0]));
return;
case Pow: op = nir_op_fpow; break;
case Exp2: op = nir_op_fexp2; break;
case Log2: op = nir_op_flog2; break;
case Sqrt: op = nir_op_fsqrt; break;
case InverseSqrt: op = nir_op_frsq; break;
case Modf: op = nir_op_fmod; break;
case Min: op = nir_op_fmin; break;
case Max: op = nir_op_fmax; break;
case Mix: op = nir_op_flrp; break;
case Step:
val->ssa->def = nir_sge(&b->nb, src[1], src[0]);
return;
case FloatBitsToInt:
case FloatBitsToUint:
case IntBitsToFloat:
case UintBitsToFloat:
/* Probably going to be removed from the final version of the spec. */
val->ssa->def = src[0];
return;
case Fma: op = nir_op_ffma; break;
case Ldexp: op = nir_op_ldexp; break;
/* Packing/Unpacking functions */
case PackSnorm4x8: op = nir_op_pack_snorm_4x8; break;
case PackUnorm4x8: op = nir_op_pack_unorm_4x8; break;
case PackSnorm2x16: op = nir_op_pack_snorm_2x16; break;
case PackUnorm2x16: op = nir_op_pack_unorm_2x16; break;
case PackHalf2x16: op = nir_op_pack_half_2x16; break;
case UnpackSnorm4x8: op = nir_op_unpack_snorm_4x8; break;
case UnpackUnorm4x8: op = nir_op_unpack_unorm_4x8; break;
case UnpackSnorm2x16: op = nir_op_unpack_snorm_2x16; break;
case UnpackUnorm2x16: op = nir_op_unpack_unorm_2x16; break;
case UnpackHalf2x16: op = nir_op_unpack_half_2x16; break;
case Length:
val->ssa->def = build_length(&b->nb, src[0]);
return;
case Distance:
val->ssa->def = build_length(&b->nb, nir_fsub(&b->nb, src[0], src[1]));
return;
case Normalize:
val->ssa->def = nir_fdiv(&b->nb, src[0], build_length(&b->nb, src[0]));
return;
case UaddCarry: op = nir_op_uadd_carry; break;
case UsubBorrow: op = nir_op_usub_borrow; break;
case BitfieldExtract: op = nir_op_ubitfield_extract; break; /* TODO */
case BitfieldInsert: op = nir_op_bitfield_insert; break;
case BitfieldReverse: op = nir_op_bitfield_reverse; break;
case BitCount: op = nir_op_bit_count; break;
case FindLSB: op = nir_op_find_lsb; break;
case FindMSB: op = nir_op_ufind_msb; break; /* TODO */
case Exp:
case Log:
case Clamp:
case Asin:
case Acos:
case Atan:
case Atan2:
case Sinh:
case Cosh:
case Tanh:
case Asinh:
case Acosh:
case Atanh:
case SmoothStep:
case Frexp:
case PackDouble2x32:
case UnpackDouble2x32:
case Cross:
case Ftransform:
case FaceForward:
case Reflect:
case Refract:
case UmulExtended:
case ImulExtended:
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);
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 GLSL450Entrypoint)ext_opcode) {
case Determinant:
case MatrixInverse:
case InterpolateAtCentroid:
case InterpolateAtSample:
case InterpolateAtOffset:
unreachable("Unhandled opcode");
default:
handle_glsl450_alu(b, (enum GLSL450Entrypoint)ext_opcode, words, count);
}
return true;
}

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
/*
* 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_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 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

@@ -23,6 +23,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "main/config.h"
#ifndef SHADER_ENUMS_H
#define SHADER_ENUMS_H
@@ -184,4 +186,209 @@ enum glsl_interp_qualifier
};
/**
* 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.
*
* Note that some of these values are not available to all pipeline stages.
*
* When this enum is updated, the following code must be updated too:
* - vertResults (in prog_print.c's arb_output_attrib_string())
* - fragAttribs (in prog_print.c's arb_input_attrib_string())
* - _mesa_varying_slot_in_fs()
*/
typedef enum
{
VARYING_SLOT_POS,
VARYING_SLOT_COL0, /* COL0 and COL1 must be contiguous */
VARYING_SLOT_COL1,
VARYING_SLOT_FOGC,
VARYING_SLOT_TEX0, /* TEX0-TEX7 must be contiguous */
VARYING_SLOT_TEX1,
VARYING_SLOT_TEX2,
VARYING_SLOT_TEX3,
VARYING_SLOT_TEX4,
VARYING_SLOT_TEX5,
VARYING_SLOT_TEX6,
VARYING_SLOT_TEX7,
VARYING_SLOT_PSIZ, /* Does not appear in FS */
VARYING_SLOT_BFC0, /* Does not appear in FS */
VARYING_SLOT_BFC1, /* Does not appear in FS */
VARYING_SLOT_EDGE, /* Does not appear in FS */
VARYING_SLOT_CLIP_VERTEX, /* Does not appear in FS */ VARYING_SLOT_CLIP_DIST0,
VARYING_SLOT_CLIP_DIST1,
VARYING_SLOT_PRIMITIVE_ID, /* Does not appear in VS */
VARYING_SLOT_LAYER, /* Appears as VS or GS output */
VARYING_SLOT_VIEWPORT, /* Appears as VS or GS output */
VARYING_SLOT_FACE, /* FS only */
VARYING_SLOT_PNTC, /* FS only */
VARYING_SLOT_VAR0, /* First generic varying slot */
VARYING_SLOT_MAX = VARYING_SLOT_VAR0 + MAX_VARYING
} gl_varying_slot;
/**
* Bitflags for varying slots.
*/
/*@{*/
#define VARYING_BIT_POS BITFIELD64_BIT(VARYING_SLOT_POS)
#define VARYING_BIT_COL0 BITFIELD64_BIT(VARYING_SLOT_COL0)
#define VARYING_BIT_COL1 BITFIELD64_BIT(VARYING_SLOT_COL1)
#define VARYING_BIT_FOGC BITFIELD64_BIT(VARYING_SLOT_FOGC)
#define VARYING_BIT_TEX0 BITFIELD64_BIT(VARYING_SLOT_TEX0)
#define VARYING_BIT_TEX1 BITFIELD64_BIT(VARYING_SLOT_TEX1)
#define VARYING_BIT_TEX2 BITFIELD64_BIT(VARYING_SLOT_TEX2)
#define VARYING_BIT_TEX3 BITFIELD64_BIT(VARYING_SLOT_TEX3)
#define VARYING_BIT_TEX4 BITFIELD64_BIT(VARYING_SLOT_TEX4)
#define VARYING_BIT_TEX5 BITFIELD64_BIT(VARYING_SLOT_TEX5)
#define VARYING_BIT_TEX6 BITFIELD64_BIT(VARYING_SLOT_TEX6)
#define VARYING_BIT_TEX7 BITFIELD64_BIT(VARYING_SLOT_TEX7)
#define VARYING_BIT_TEX(U) BITFIELD64_BIT(VARYING_SLOT_TEX0 + (U))
#define VARYING_BITS_TEX_ANY BITFIELD64_RANGE(VARYING_SLOT_TEX0, \
MAX_TEXTURE_COORD_UNITS)
#define VARYING_BIT_PSIZ BITFIELD64_BIT(VARYING_SLOT_PSIZ)
#define VARYING_BIT_BFC0 BITFIELD64_BIT(VARYING_SLOT_BFC0)
#define VARYING_BIT_BFC1 BITFIELD64_BIT(VARYING_SLOT_BFC1)
#define VARYING_BIT_EDGE BITFIELD64_BIT(VARYING_SLOT_EDGE)
#define VARYING_BIT_CLIP_VERTEX BITFIELD64_BIT(VARYING_SLOT_CLIP_VERTEX)
#define VARYING_BIT_CLIP_DIST0 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0)
#define VARYING_BIT_CLIP_DIST1 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1)
#define VARYING_BIT_PRIMITIVE_ID BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID)
#define VARYING_BIT_LAYER BITFIELD64_BIT(VARYING_SLOT_LAYER)
#define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT)
#define VARYING_BIT_FACE BITFIELD64_BIT(VARYING_SLOT_FACE)
#define VARYING_BIT_PNTC BITFIELD64_BIT(VARYING_SLOT_PNTC)
#define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V))
/*@}*/
/**
* Fragment program results
*/
typedef enum
{
FRAG_RESULT_DEPTH = 0,
FRAG_RESULT_STENCIL = 1,
/* If a single color should be written to all render targets, this
* register is written. No FRAG_RESULT_DATAn will be written.
*/
FRAG_RESULT_COLOR = 2,
FRAG_RESULT_SAMPLE_MASK = 3,
/* FRAG_RESULT_DATAn are the per-render-target (GLSL gl_FragData[n]
* or ARB_fragment_program fragment.color[n]) color results. If
* any are written, FRAG_RESULT_COLOR will not be written.
*/
FRAG_RESULT_DATA0 = 4,
FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
} gl_frag_result;
#endif /* SHADER_ENUMS_H */

View File

@@ -34,6 +34,12 @@
#include <string.h>
#include "util/ralloc.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

@@ -40,8 +40,11 @@ gl_HEADERS = $(top_srcdir)/include/GL/*.h
.PHONY: main/git_sha1.h.tmp
main/git_sha1.h.tmp:
@# Don't assume that $(top_srcdir)/.git is a directory. It may be
@# a gitlink file if $(top_srcdir) is a submodule checkout or a linked
@# worktree.
@touch main/git_sha1.h.tmp
@if test -d $(top_srcdir)/.git; then \
@if test -e $(top_srcdir)/.git; then \
if which git > /dev/null; then \
git --git-dir=$(top_srcdir)/.git log -n 1 --oneline | \
sed 's/^\([^ ]*\) .*/#define MESA_GIT_SHA1 "git-\1"/' \

View File

@@ -1,3 +1,4 @@
#include <stdlib.h>
#include "main/glheader.h"
#include "main/compiler.h"
#include "glapi/glapi.h"
@@ -33,12 +34,14 @@ _glapi_check_multithread(void)
PUBLIC void
_glapi_set_context(void *context)
{}
{
_glapi_Context = context;
}
PUBLIC void *
_glapi_get_context(void)
{
return 0;
return _glapi_Context;
}
PUBLIC void
@@ -84,7 +87,7 @@ _glapi_set_nop_handler(_glapi_nop_handler_proc func)
PUBLIC struct _glapi_table *
_glapi_new_nop_table(unsigned num_entries)
{
return NULL;
return malloc(16);
}
#ifndef NO_MAIN

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

@@ -311,7 +311,7 @@ brw_init_driver_functions(struct brw_context *brw,
functions->GetSamplePosition = gen6_get_sample_position;
}
static void
void
brw_initialize_context_constants(struct brw_context *brw)
{
struct gl_context *ctx = &brw->ctx;
@@ -390,7 +390,8 @@ brw_initialize_context_constants(struct brw_context *brw)
int max_samples;
const int *msaa_modes = intel_supported_msaa_modes(brw->intelScreen);
const int clamp_max_samples =
driQueryOptioni(&brw->optionCache, "clamp_max_samples");
brw->optionCache.info != NULL ?
driQueryOptioni(&brw->optionCache, "clamp_max_samples") : -1;
if (clamp_max_samples < 0) {
max_samples = msaa_modes[0];
@@ -801,6 +802,7 @@ brwCreateContext(gl_api api,
intel_batchbuffer_init(brw);
#if 0
if (brw->gen >= 6) {
/* Create a new hardware context. Using a hardware context means that
* our GPU state will be saved/restored on context switch, allowing us
@@ -819,6 +821,7 @@ brwCreateContext(gl_api api,
}
brw_init_state(brw);
#endif
intelInitExtensions(ctx);
@@ -882,8 +885,10 @@ brwCreateContext(gl_api api,
_mesa_compute_version(ctx);
#if 0
_mesa_initialize_dispatch_tables(ctx);
_mesa_initialize_vbo_vtxfmt(ctx);
#endif
if (ctx->Extensions.AMD_performance_monitor) {
brw_init_performance_monitors(brw);

View File

@@ -359,6 +359,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;
@@ -1994,6 +2000,15 @@ gen6_upload_push_constants(struct brw_context *brw,
struct brw_stage_state *stage_state,
enum aub_state_struct_type type);
struct intel_screen *intel_screen_create(int fd);
void intel_screen_destroy(struct intel_screen *screen);
struct brw_context *intel_context_create(struct intel_screen *screen);
void intel_context_destroy(struct brw_context *brw);
void
brw_initialize_context_constants(struct brw_context *brw);
bool
gen9_use_linear_1d_layout(const struct brw_context *brw,
const struct intel_mipmap_tree *mt);

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

@@ -353,3 +353,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

@@ -85,3 +85,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

@@ -525,6 +525,7 @@ fs_visitor::type_size(const struct glsl_type *type)
case GLSL_TYPE_ERROR:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_DOUBLE:
case GLSL_TYPE_FUNCTION:
unreachable("not reached");
}
@@ -1460,6 +1461,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;
@@ -2590,9 +2595,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) {
@@ -2621,8 +2639,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);
}
}
/**
@@ -3805,7 +3825,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)
@@ -3842,9 +3863,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();
@@ -3914,13 +3934,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;
}
@@ -3993,7 +4006,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

@@ -1368,9 +1368,19 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
fs_reg surf_index;
if (const_index) {
surf_index = fs_reg(stage_prog_data->binding_table.ubo_start +
const_index->u[0]);
uint32_t index = const_index->u[0];
uint32_t set = shader->base.UniformBlocks[index].Set;
uint32_t binding = shader->base.UniformBlocks[index].Binding;
/* 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.
@@ -1587,7 +1597,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
@@ -1758,6 +1774,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;
@@ -274,18 +278,41 @@ brw_codegen_gs_prog(struct brw_context *brw,
c.prog_data.base.base.total_scratch
= brw_get_scratch_size(c.base.last_scratch*REG_SIZE);
}
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

@@ -89,7 +89,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 */
@@ -101,6 +100,28 @@ brw_create_nir(struct brw_context *brw,
}
nir_validate_shader(nir);
brw_process_nir(nir, brw->intelScreen->devinfo, shader_prog, stage);
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: %d inst\n",
_mesa_shader_stage_to_abbrev(stage),
count_nir_instrs(nir));
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 debug_enabled = INTEL_DEBUG & intel_debug_flag_for_shader_stage(stage);
nir_lower_global_vars_to_local(nir);
nir_validate_shader(nir);
@@ -136,8 +157,10 @@ brw_create_nir(struct brw_context *brw,
if (shader_prog) {
nir_lower_samplers(nir, shader_prog, stage);
nir_validate_shader(nir);
} else {
nir_lower_samplers_for_vk(nir);
}
nir_validate_shader(nir);
nir_lower_system_values(nir);
nir_validate_shader(nir);
@@ -147,7 +170,7 @@ brw_create_nir(struct brw_context *brw,
nir_optimize(nir);
if (brw->gen >= 6) {
if (devinfo->gen >= 6) {
/* Try and fuse multiply-adds */
nir_opt_peephole_ffma(nir);
nir_validate_shader(nir);
@@ -178,15 +201,6 @@ brw_create_nir(struct brw_context *brw,
nir_print_shader(nir, stderr);
}
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: %d inst\n",
_mesa_shader_stage_to_abbrev(stage),
count_nir_instrs(nir));
nir_convert_from_ssa(nir);
nir_validate_shader(nir);
@@ -195,7 +209,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);
@@ -205,6 +219,4 @@ brw_create_nir(struct brw_context *brw,
_mesa_shader_stage_to_string(stage));
nir_print_shader(nir, stderr);
}
return nir;
}

View File

@@ -79,6 +79,12 @@ nir_shader *brw_create_nir(struct brw_context *brw,
const struct gl_program *prog,
gl_shader_stage stage);
void
brw_process_nir(nir_shader *nir,
const struct brw_device_info *devinfo,
const struct gl_shader_program *shader_prog,
gl_shader_stage stage);
#ifdef __cplusplus
}
#endif

View File

@@ -275,7 +275,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

@@ -441,6 +441,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

@@ -427,6 +427,9 @@ brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache)
DBG("%s\n", __func__);
if (cache->bo == NULL)
return;
if (brw->has_llc)
drm_intel_bo_unmap(cache->bo);
drm_intel_bo_unreference(cache->bo);

View File

@@ -1882,7 +1882,7 @@ brw_vs_emit(struct brw_context *brw,
st_index = brw_get_shader_time_index(brw, prog, &c->vp->program.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, &c->vp->program.Base);
if (brw->intelScreen->compiler->scalar_vs) {

View File

@@ -615,6 +615,7 @@ type_size(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

@@ -47,7 +47,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

@@ -60,7 +60,7 @@ static const struct dri_debug_control debug_control[] = {
{ "urb", DEBUG_URB },
{ "vs", DEBUG_VS },
{ "clip", DEBUG_CLIP },
{ "aub", DEBUG_AUB },
{ "foob", DEBUG_AUB }, /* disable aub dumbing in the dri driver */
{ "shader_time", DEBUG_SHADER_TIME },
{ "no16", DEBUG_NO16 },
{ "blorp", DEBUG_BLORP },

View File

@@ -275,9 +275,11 @@ intelInitExtensions(struct gl_context *ctx)
ctx->Extensions.EXT_shader_integer_mix = ctx->Const.GLSLVersion >= 130;
ctx->Extensions.EXT_timer_query = true;
if (brw->gen == 5 || can_write_oacontrol(brw)) {
ctx->Extensions.AMD_performance_monitor = true;
ctx->Extensions.INTEL_performance_query = true;
if (brw->bufmgr) {
if (brw->gen == 5 || can_write_oacontrol(brw)) {
ctx->Extensions.AMD_performance_monitor = true;
ctx->Extensions.INTEL_performance_query = true;
}
}
}
@@ -285,6 +287,7 @@ intelInitExtensions(struct gl_context *ctx)
uint64_t dummy;
ctx->Extensions.ARB_blend_func_extended =
brw->optionCache.info == NULL ||
!driQueryOptionb(&brw->optionCache, "disable_blend_func_extended");
ctx->Extensions.ARB_conditional_render_inverted = true;
ctx->Extensions.ARB_draw_buffers_blend = true;
@@ -308,7 +311,7 @@ intelInitExtensions(struct gl_context *ctx)
ctx->Extensions.OES_depth_texture_cube_map = true;
/* Test if the kernel has the ioctl. */
if (drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &dummy) == 0)
if (brw->bufmgr && drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &dummy) == 0)
ctx->Extensions.ARB_timer_query = true;
/* Only enable this in core profile because other parts of Mesa behave
@@ -331,7 +334,8 @@ intelInitExtensions(struct gl_context *ctx)
ctx->Extensions.ARB_texture_compression_bptc = true;
ctx->Extensions.ARB_texture_view = true;
if (can_do_pipelined_register_writes(brw)) {
if (brw->bufmgr &&
can_do_pipelined_register_writes(brw)) {
ctx->Extensions.ARB_draw_indirect = true;
ctx->Extensions.ARB_transform_feedback2 = true;
ctx->Extensions.ARB_transform_feedback3 = true;
@@ -359,7 +363,9 @@ intelInitExtensions(struct gl_context *ctx)
if (ctx->API != API_OPENGL_CORE)
ctx->Extensions.ARB_color_buffer_float = true;
if (ctx->Mesa_DXTn || driQueryOptionb(&brw->optionCache, "force_s3tc_enable"))
if (ctx->Mesa_DXTn ||
(brw->optionCache.info != NULL &&
driQueryOptionb(&brw->optionCache, "force_s3tc_enable")))
ctx->Extensions.EXT_texture_compression_s3tc = true;
ctx->Extensions.ANGLE_texture_compression_dxt = true;

View File

@@ -1426,6 +1426,78 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
return (const __DRIconfig**) intel_screen_make_configs(psp);
}
struct intel_screen *
intel_screen_create(int fd)
{
__DRIscreen *psp;
__DRIconfig **configs;
int i;
psp = malloc(sizeof(*psp));
if (psp == NULL)
return NULL;
psp->image.loader = (void *) 1; /* Don't complain about this being NULL */
psp->fd = fd;
psp->dri2.useInvalidate = (void *) 1;
configs = (__DRIconfig **) intelInitScreen2(psp);
for (i = 0; configs[i]; i++)
free(configs[i]);
free(configs);
return psp->driverPrivate;
}
void
intel_screen_destroy(struct intel_screen *screen)
{
__DRIscreen *psp;
psp = screen->driScrnPriv;
intelDestroyScreen(screen->driScrnPriv);
free(psp);
}
struct brw_context *
intel_context_create(struct intel_screen *screen)
{
__DRIcontext *driContextPriv;
struct brw_context *brw;
unsigned error;
driContextPriv = malloc(sizeof(*driContextPriv));
if (driContextPriv == NULL)
return NULL;
driContextPriv->driScreenPriv = screen->driScrnPriv;
brwCreateContext(API_OPENGL_CORE,
NULL, /* visual */
driContextPriv,
3, 0,
0, /* flags */
false, /* notify_reset */
&error,
NULL);
brw = driContextPriv->driverPrivate;
brw->ctx.FirstTimeCurrent = false;
return driContextPriv->driverPrivate;
}
void
intel_context_destroy(struct brw_context *brw)
{
__DRIcontext *driContextPriv;
driContextPriv = brw->driContext;
intelDestroyContext(driContextPriv);
free(driContextPriv);
}
struct intel_buffer {
__DRIbuffer base;
drm_intel_bo *bo;

View File

@@ -96,189 +96,6 @@ struct vbo_context;
/**
* 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.
*
* Note that some of these values are not available to all pipeline stages.
*
* When this enum is updated, the following code must be updated too:
* - vertResults (in prog_print.c's arb_output_attrib_string())
* - fragAttribs (in prog_print.c's arb_input_attrib_string())
* - _mesa_varying_slot_in_fs()
*/
typedef enum
{
VARYING_SLOT_POS,
VARYING_SLOT_COL0, /* COL0 and COL1 must be contiguous */
VARYING_SLOT_COL1,
VARYING_SLOT_FOGC,
VARYING_SLOT_TEX0, /* TEX0-TEX7 must be contiguous */
VARYING_SLOT_TEX1,
VARYING_SLOT_TEX2,
VARYING_SLOT_TEX3,
VARYING_SLOT_TEX4,
VARYING_SLOT_TEX5,
VARYING_SLOT_TEX6,
VARYING_SLOT_TEX7,
VARYING_SLOT_PSIZ, /* Does not appear in FS */
VARYING_SLOT_BFC0, /* Does not appear in FS */
VARYING_SLOT_BFC1, /* Does not appear in FS */
VARYING_SLOT_EDGE, /* Does not appear in FS */
VARYING_SLOT_CLIP_VERTEX, /* Does not appear in FS */
VARYING_SLOT_CLIP_DIST0,
VARYING_SLOT_CLIP_DIST1,
VARYING_SLOT_PRIMITIVE_ID, /* Does not appear in VS */
VARYING_SLOT_LAYER, /* Appears as VS or GS output */
VARYING_SLOT_VIEWPORT, /* Appears as VS or GS output */
VARYING_SLOT_FACE, /* FS only */
VARYING_SLOT_PNTC, /* FS only */
VARYING_SLOT_VAR0, /* First generic varying slot */
VARYING_SLOT_MAX = VARYING_SLOT_VAR0 + MAX_VARYING
} gl_varying_slot;
/**
* Bitflags for varying slots.
*/
/*@{*/
#define VARYING_BIT_POS BITFIELD64_BIT(VARYING_SLOT_POS)
#define VARYING_BIT_COL0 BITFIELD64_BIT(VARYING_SLOT_COL0)
#define VARYING_BIT_COL1 BITFIELD64_BIT(VARYING_SLOT_COL1)
#define VARYING_BIT_FOGC BITFIELD64_BIT(VARYING_SLOT_FOGC)
#define VARYING_BIT_TEX0 BITFIELD64_BIT(VARYING_SLOT_TEX0)
#define VARYING_BIT_TEX1 BITFIELD64_BIT(VARYING_SLOT_TEX1)
#define VARYING_BIT_TEX2 BITFIELD64_BIT(VARYING_SLOT_TEX2)
#define VARYING_BIT_TEX3 BITFIELD64_BIT(VARYING_SLOT_TEX3)
#define VARYING_BIT_TEX4 BITFIELD64_BIT(VARYING_SLOT_TEX4)
#define VARYING_BIT_TEX5 BITFIELD64_BIT(VARYING_SLOT_TEX5)
#define VARYING_BIT_TEX6 BITFIELD64_BIT(VARYING_SLOT_TEX6)
#define VARYING_BIT_TEX7 BITFIELD64_BIT(VARYING_SLOT_TEX7)
#define VARYING_BIT_TEX(U) BITFIELD64_BIT(VARYING_SLOT_TEX0 + (U))
#define VARYING_BITS_TEX_ANY BITFIELD64_RANGE(VARYING_SLOT_TEX0, \
MAX_TEXTURE_COORD_UNITS)
#define VARYING_BIT_PSIZ BITFIELD64_BIT(VARYING_SLOT_PSIZ)
#define VARYING_BIT_BFC0 BITFIELD64_BIT(VARYING_SLOT_BFC0)
#define VARYING_BIT_BFC1 BITFIELD64_BIT(VARYING_SLOT_BFC1)
#define VARYING_BIT_EDGE BITFIELD64_BIT(VARYING_SLOT_EDGE)
#define VARYING_BIT_CLIP_VERTEX BITFIELD64_BIT(VARYING_SLOT_CLIP_VERTEX)
#define VARYING_BIT_CLIP_DIST0 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST0)
#define VARYING_BIT_CLIP_DIST1 BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1)
#define VARYING_BIT_PRIMITIVE_ID BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_ID)
#define VARYING_BIT_LAYER BITFIELD64_BIT(VARYING_SLOT_LAYER)
#define VARYING_BIT_VIEWPORT BITFIELD64_BIT(VARYING_SLOT_VIEWPORT)
#define VARYING_BIT_FACE BITFIELD64_BIT(VARYING_SLOT_FACE)
#define VARYING_BIT_PNTC BITFIELD64_BIT(VARYING_SLOT_PNTC)
#define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V))
/*@}*/
/**
* Determine if the given gl_varying_slot appears in the fragment shader.
*/
@@ -299,28 +116,6 @@ _mesa_varying_slot_in_fs(gl_varying_slot slot)
}
/**
* Fragment program results
*/
typedef enum
{
FRAG_RESULT_DEPTH = 0,
FRAG_RESULT_STENCIL = 1,
/* If a single color should be written to all render targets, this
* register is written. No FRAG_RESULT_DATAn will be written.
*/
FRAG_RESULT_COLOR = 2,
FRAG_RESULT_SAMPLE_MASK = 3,
/* FRAG_RESULT_DATAn are the per-render-target (GLSL gl_FragData[n]
* or ARB_fragment_program fragment.color[n]) color results. If
* any are written, FRAG_RESULT_COLOR will not be written.
*/
FRAG_RESULT_DATA0 = 4,
FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
} gl_frag_result;
/**
* Indexes for all renderbuffers
*/
@@ -2558,6 +2353,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

@@ -542,6 +542,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;
}
@@ -2460,6 +2461,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;
}

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

@@ -0,0 +1,4 @@
# Generated source files
/*-spirv.h
/entrypoints.c
/entrypoints.h

93
src/vulkan/Makefile.am Normal file
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.
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_lunarg.h
lib_LTLIBRARIES = libvulkan.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
libvulkan_la_SOURCES = \
private.h \
gem.c \
device.c \
aub.c \
allocator.c \
util.c \
pipeline.c \
image.c \
meta.c \
intel.c \
entrypoints.c \
entrypoints.h \
x11.c \
formats.c \
compiler.cpp \
query.c
BUILT_SOURCES = \
entrypoints.h \
entrypoints.c \
meta-spirv.h
entrypoints.h : vk_gen.py $(vulkan_include_HEADERS)
$(AM_V_GEN)cat $(vulkan_include_HEADERS) | $(PYTHON2) $< header > $@
entrypoints.c : vk_gen.py $(vulkan_include_HEADERS)
$(AM_V_GEN)cat $(vulkan_include_HEADERS) | $(PYTHON2) $< code > $@
%-spirv.h: %.c glsl_scraper.py
$(AM_V_GEN) $(PYTHON2) $(srcdir)/glsl_scraper.py --glsl-only -o $@ $<
CLEANFILES = $(BUILT_SOURCES)
libvulkan_la_LIBADD = -lxcb -lxcb-dri3 \
$(top_builddir)/src/mesa/drivers/dri/i965/libi965_compiler.la
include $(top_srcdir)/install-lib-links.mk

665
src/vulkan/allocator.c Normal file
View File

@@ -0,0 +1,665 @@
/*
* 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 "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, uint32_t *offset)
{
union anv_free_list current, next, old;
current = *list;
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();
uint32_t *next_ptr = *map + current.offset;
next.offset = VG_NOACCESS_READ(next_ptr);
next.count = current.count + 1;
old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, next.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, uint32_t offset)
{
union anv_free_list current, old, new;
uint32_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 int
anv_block_pool_grow(struct anv_block_pool *pool);
void
anv_block_pool_init(struct anv_block_pool *pool,
struct anv_device *device, uint32_t block_size)
{
assert(is_power_of_two(block_size));
pool->device = device;
pool->bo.gem_handle = 0;
pool->bo.offset = 0;
pool->size = 0;
pool->block_size = block_size;
pool->next_block = 0;
pool->free_list = ANV_FREE_LIST_EMPTY;
anv_vector_init(&pool->mmap_cleanups,
round_to_power_of_two(sizeof(struct anv_mmap_cleanup)), 128);
/* Immediately grow the pool so we'll have a backing bo. */
anv_block_pool_grow(pool);
}
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);
}
static int
anv_block_pool_grow(struct anv_block_pool *pool)
{
size_t size;
void *map;
int gem_handle;
struct anv_mmap_cleanup *cleanup;
if (pool->size == 0) {
size = 32 * pool->block_size;
} else {
size = pool->size * 2;
}
cleanup = anv_vector_add(&pool->mmap_cleanups);
if (!cleanup)
return -1;
*cleanup = ANV_MMAP_CLEANUP_INIT;
if (pool->size == 0)
pool->fd = memfd_create("block pool", MFD_CLOEXEC);
if (pool->fd == -1)
return -1;
if (ftruncate(pool->fd, size) == -1)
return -1;
/* First try to see if mremap can grow the map in place. */
map = MAP_FAILED;
if (pool->size > 0)
map = mremap(pool->map, pool->size, size, 0);
if (map == MAP_FAILED) {
/* 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, 0);
cleanup->map = map;
cleanup->size = size;
}
if (map == MAP_FAILED)
return -1;
gem_handle = anv_gem_userptr(pool->device, map, size);
if (gem_handle == 0)
return -1;
cleanup->gem_handle = gem_handle;
/* Now that we successfull allocated everything, we can write the new
* values back into pool. */
pool->map = map;
pool->bo.gem_handle = gem_handle;
pool->bo.size = size;
pool->bo.map = map;
pool->bo.index = 0;
/* Write size last and after the memory barrier here. We need the memory
* barrier to make sure map and gem_handle are written before other threads
* see the new size. A thread could allocate a block and then go try using
* the old pool->map and access out of bounds. */
__sync_synchronize();
pool->size = size;
return 0;
}
uint32_t
anv_block_pool_alloc(struct anv_block_pool *pool)
{
uint32_t offset, block, size;
/* Try free list first. */
if (anv_free_list_pop(&pool->free_list, &pool->map, &offset)) {
assert(pool->map);
return offset;
}
restart:
size = pool->size;
block = __sync_fetch_and_add(&pool->next_block, pool->block_size);
if (block < size) {
assert(pool->map);
return block;
} else if (block == size) {
/* We allocated the first block outside the pool, we have to grow it.
* pool->next_block acts a mutex: threads who try to allocate now will
* get block indexes above the current limit and hit futex_wait
* below. */
int err = anv_block_pool_grow(pool);
assert(err == 0);
(void) err;
futex_wake(&pool->size, INT_MAX);
} else {
futex_wait(&pool->size, size);
__sync_fetch_and_add(&pool->next_block, -pool->block_size);
goto restart;
}
return block;
}
void
anv_block_pool_free(struct anv_block_pool *pool, uint32_t offset)
{
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 && 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)
{
uint32_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))
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) {
new.next = anv_block_pool_alloc(block_pool);
new.end = new.next + block_pool->block_size;
old.u64 = __sync_fetch_and_add(&pool->block.u64, new.u64 - block.u64);
if (old.next != block.next)
futex_wake(&pool->block.end, INT_MAX);
return new.next;
} else {
futex_wait(&pool->block.end, block.end);
__sync_fetch_and_add(&pool->block.u64, -pool->state_size);
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);
}
}
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_MALLOCLIKE_BLOCK(state.map, size, 0, false));
return state;
}
void
anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state)
{
assert(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_FREELIKE_BLOCK(state.map, 0));
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;
}
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_FREELIKE_BLOCK(VG_NOACCESS_READ(&sb->_vg_ptr), 0));
anv_block_pool_free(stream->block_pool, block);
block = next_block;
}
}
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_MALLOCLIKE_BLOCK(vg_ptr, size, 0, false);
} else {
ptrdiff_t vg_offset = vg_ptr - current_map;
assert(vg_offset >= stream->current_block &&
vg_offset < stream->end);
VALGRIND_RESIZEINPLACE_BLOCK(vg_ptr,
stream->next - vg_offset,
(state.offset + size) - vg_offset,
0);
}
#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;
}
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);
/* The anv_gem_m[un]map() functions are also valgrind-safe so they
* act as an alloc/free. In order to avoid a double-free warning, we
* need to mark thiss as malloc'd before we unmap it.
*/
VG(VALGRIND_MALLOCLIKE_BLOCK(link_copy.bo.map, pool->bo_size, 0, false));
anv_gem_munmap(link_copy.bo.map, pool->bo_size);
anv_gem_close(pool->device, link_copy.bo.gem_handle);
link = link_copy.next;
}
}
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_MALLOCLIKE_BLOCK(bo->map, pool->bo_size, 0, false));
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);
}
/* We don't need to call VALGRIND_MALLOCLIKE_BLOCK here because gem_mmap
* calls it for us. If we really want to be pedantic we could do a
* VALGRIND_FREELIKE_BLOCK right after the mmap, but there's no good
* reason.
*/
*bo = new_bo;
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_FREELIKE_BLOCK(bo->map, 0));
anv_ptr_free_list_push(&pool->free_list, link);
}

310
src/vulkan/aub.c Normal file
View File

@@ -0,0 +1,310 @@
/*
* 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 <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <drm.h>
#include <i915_drm.h>
#include "private.h"
#include "aub.h"
struct anv_aub_writer {
FILE *file;
uint32_t offset;
int gen;
};
static void
aub_out(struct anv_aub_writer *writer, uint32_t data)
{
fwrite(&data, 1, 4, writer->file);
}
static void
aub_out_data(struct anv_aub_writer *writer, const void *data, size_t size)
{
fwrite(data, 1, size, writer->file);
}
static struct anv_aub_writer *
get_anv_aub_writer(struct anv_device *device)
{
struct anv_aub_writer *writer = device->aub_writer;
int entry = 0x200003;
int i;
int gtt_size = 0x10000;
const char *filename;
if (geteuid() != getuid())
return NULL;
if (writer)
return writer;
writer = malloc(sizeof(*writer));
if (writer == NULL)
return NULL;
filename = "intel.aub";
writer->gen = device->info.gen;
writer->file = fopen(filename, "w+");
if (!writer->file) {
free(writer);
return NULL;
}
/* Start allocating objects from just after the GTT. */
writer->offset = gtt_size;
/* Start with a (required) version packet. */
aub_out(writer, CMD_AUB_HEADER | (13 - 2));
aub_out(writer,
(4 << AUB_HEADER_MAJOR_SHIFT) |
(0 << AUB_HEADER_MINOR_SHIFT));
for (i = 0; i < 8; i++) {
aub_out(writer, 0); /* app name */
}
aub_out(writer, 0); /* timestamp */
aub_out(writer, 0); /* timestamp */
aub_out(writer, 0); /* comment len */
/* Set up the GTT. The max we can handle is 256M */
aub_out(writer, CMD_AUB_TRACE_HEADER_BLOCK | ((writer->gen >= 8 ? 6 : 5) - 2));
aub_out(writer,
AUB_TRACE_MEMTYPE_GTT_ENTRY |
AUB_TRACE_TYPE_NOTYPE | AUB_TRACE_OP_DATA_WRITE);
aub_out(writer, 0); /* subtype */
aub_out(writer, 0); /* offset */
aub_out(writer, gtt_size); /* size */
if (writer->gen >= 8)
aub_out(writer, 0);
for (i = 0x000; i < gtt_size; i += 4, entry += 0x1000) {
aub_out(writer, entry);
}
return device->aub_writer = writer;
}
void
anv_aub_writer_destroy(struct anv_aub_writer *writer)
{
fclose(writer->file);
free(writer);
}
/**
* Break up large objects into multiple writes. Otherwise a 128kb VBO
* would overflow the 16 bits of size field in the packet header and
* everything goes badly after that.
*/
static void
aub_write_trace_block(struct anv_aub_writer *writer, uint32_t type,
void *virtual, uint32_t size, uint32_t gtt_offset)
{
uint32_t block_size;
uint32_t offset;
uint32_t subtype = 0;
static const char null_block[8 * 4096];
for (offset = 0; offset < size; offset += block_size) {
block_size = size - offset;
if (block_size > 8 * 4096)
block_size = 8 * 4096;
aub_out(writer,
CMD_AUB_TRACE_HEADER_BLOCK |
((writer->gen >= 8 ? 6 : 5) - 2));
aub_out(writer,
AUB_TRACE_MEMTYPE_GTT |
type | AUB_TRACE_OP_DATA_WRITE);
aub_out(writer, subtype);
aub_out(writer, gtt_offset + offset);
aub_out(writer, align_u32(block_size, 4));
if (writer->gen >= 8)
aub_out(writer, 0);
if (virtual)
aub_out_data(writer, (char *) virtual + offset, block_size);
else
aub_out_data(writer, null_block, block_size);
/* Pad to a multiple of 4 bytes. */
aub_out_data(writer, null_block, -block_size & 3);
}
}
/*
* Make a ringbuffer on fly and dump it
*/
static void
aub_build_dump_ringbuffer(struct anv_aub_writer *writer,
uint32_t batch_offset, uint32_t offset,
int ring_flag)
{
uint32_t ringbuffer[4096];
int ring = AUB_TRACE_TYPE_RING_PRB0; /* The default ring */
int ring_count = 0;
if (ring_flag == I915_EXEC_BSD)
ring = AUB_TRACE_TYPE_RING_PRB1;
else if (ring_flag == I915_EXEC_BLT)
ring = AUB_TRACE_TYPE_RING_PRB2;
/* Make a ring buffer to execute our batchbuffer. */
memset(ringbuffer, 0, sizeof(ringbuffer));
if (writer->gen >= 8) {
ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START | (3 - 2);
ringbuffer[ring_count++] = batch_offset;
ringbuffer[ring_count++] = 0;
} else {
ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START;
ringbuffer[ring_count++] = batch_offset;
}
/* Write out the ring. This appears to trigger execution of
* the ring in the simulator.
*/
aub_out(writer,
CMD_AUB_TRACE_HEADER_BLOCK |
((writer->gen >= 8 ? 6 : 5) - 2));
aub_out(writer,
AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE);
aub_out(writer, 0); /* general/surface subtype */
aub_out(writer, offset);
aub_out(writer, ring_count * 4);
if (writer->gen >= 8)
aub_out(writer, 0);
/* FIXME: Need some flush operations here? */
aub_out_data(writer, ringbuffer, ring_count * 4);
}
struct aub_bo {
uint32_t offset;
void *map;
void *relocated;
};
static void
relocate_bo(struct anv_bo *bo, struct drm_i915_gem_relocation_entry *relocs,
size_t num_relocs, struct aub_bo *bos)
{
struct aub_bo *aub_bo = &bos[bo->index];
struct drm_i915_gem_relocation_entry *reloc;
uint32_t *dw;
aub_bo->relocated = malloc(bo->size);
memcpy(aub_bo->relocated, aub_bo->map, bo->size);
for (size_t i = 0; i < num_relocs; i++) {
reloc = &relocs[i];
assert(reloc->offset < bo->size);
dw = aub_bo->relocated + reloc->offset;
*dw = bos[reloc->target_handle].offset + reloc->delta;
}
}
void
anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_device *device = cmd_buffer->device;
struct anv_batch *batch = &cmd_buffer->batch;
struct anv_aub_writer *writer;
struct anv_bo *bo;
uint32_t ring_flag = 0;
uint32_t offset;
struct aub_bo *aub_bos;
writer = get_anv_aub_writer(device);
if (writer == NULL)
return;
aub_bos = malloc(cmd_buffer->bo_count * sizeof(aub_bos[0]));
offset = writer->offset;
for (uint32_t i = 0; i < cmd_buffer->bo_count; i++) {
bo = cmd_buffer->exec2_bos[i];
if (bo->map)
aub_bos[i].map = bo->map;
else
aub_bos[i].map = anv_gem_mmap(device, bo->gem_handle, 0, bo->size);
aub_bos[i].relocated = aub_bos[i].map;
aub_bos[i].offset = offset;
offset = align_u32(offset + bo->size + 4095, 4096);
}
struct anv_batch_bo *first_bbo;
for (struct anv_batch_bo *bbo = cmd_buffer->last_batch_bo;
bbo != NULL; bbo = bbo->prev_batch_bo) {
/* Keep stashing the current BO until we get to the beginning */
first_bbo = bbo;
/* Handle relocations for this batch BO */
relocate_bo(&bbo->bo, &batch->relocs.relocs[bbo->first_reloc],
bbo->num_relocs, aub_bos);
}
assert(first_bbo->prev_batch_bo == NULL);
for (struct anv_batch_bo *bbo = cmd_buffer->surface_batch_bo;
bbo != NULL; bbo = bbo->prev_batch_bo) {
/* Handle relocations for this surface state BO */
relocate_bo(&bbo->bo,
&cmd_buffer->surface_relocs.relocs[bbo->first_reloc],
bbo->num_relocs, aub_bos);
}
for (uint32_t i = 0; i < cmd_buffer->bo_count; i++) {
bo = cmd_buffer->exec2_bos[i];
if (i == cmd_buffer->bo_count - 1) {
assert(bo == &first_bbo->bo);
aub_write_trace_block(writer, AUB_TRACE_TYPE_BATCH,
aub_bos[i].relocated,
first_bbo->length, aub_bos[i].offset);
} else {
aub_write_trace_block(writer, AUB_TRACE_TYPE_NOTYPE,
aub_bos[i].relocated,
bo->size, aub_bos[i].offset);
}
if (aub_bos[i].relocated != aub_bos[i].map)
free(aub_bos[i].relocated);
if (aub_bos[i].map != bo->map)
anv_gem_munmap(aub_bos[i].map, bo->size);
}
/* Dump ring buffer */
aub_build_dump_ringbuffer(writer, aub_bos[first_bbo->bo.index].offset,
offset, ring_flag);
free(aub_bos);
fflush(writer->file);
}

153
src/vulkan/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 */

1213
src/vulkan/compiler.cpp Normal file

File diff suppressed because it is too large Load Diff

3943
src/vulkan/device.c Normal file

File diff suppressed because it is too large Load Diff

296
src/vulkan/formats.c Normal file
View File

@@ -0,0 +1,296 @@
/*
* 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 "private.h"
#define UNSUPPORTED 0xffff
#define fmt(__vk_fmt, ...) \
[__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 *
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_GetPhysicalDeviceFormatInfo(
VkPhysicalDevice physicalDevice,
VkFormat _format,
VkFormatProperties* pFormatInfo)
{
const struct anv_format *format = anv_format_for_vk_format(_format);
fprintf(stderr, "vkGetFormatInfo(%s)\n", format->name);
return anv_GetPhysicalDeviceFormatInfo(physicalDevice, _format, pFormatInfo);
}
VkResult anv_GetPhysicalDeviceFormatInfo(
VkPhysicalDevice physicalDevice,
VkFormat _format,
VkFormatProperties* pFormatInfo)
{
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;
info = &surface_formats[format->surface_format];
if (!info->exists)
goto unsupported;
uint32_t linear = 0, tiled = 0;
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;
}
pFormatInfo->linearTilingFeatures = linear;
pFormatInfo->optimalTilingFeatures = tiled;
return VK_SUCCESS;
unsupported:
pFormatInfo->linearTilingFeatures = 0;
pFormatInfo->optimalTilingFeatures = 0;
return VK_SUCCESS;
}

279
src/vulkan/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 "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(struct anv_physical_device *physical_dev, uint64_t *size)
{
struct drm_i915_gem_get_aperture aperture;
int ret;
VG_CLEAR(aperture);
ret = anv_ioctl(physical_dev->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;
}

8144
src/vulkan/gen75_pack.h Normal file

File diff suppressed because it is too large Load Diff

6852
src/vulkan/gen7_pack.h Normal file

File diff suppressed because it is too large Load Diff

8960
src/vulkan/gen8_pack.h Normal file

File diff suppressed because it is too large Load Diff

274
src/vulkan/glsl_scraper.py Normal file
View File

@@ -0,0 +1,274 @@
#! /usr/bin/env python
import argparse
import cStringIO
import os
import re
import shutil
import struct
import subprocess
import sys
import tempfile
from textwrap import dedent
class Shader:
def __init__(self, stage):
self.stream = cStringIO.StringIO()
self.stage = stage
if self.stage == 'VERTEX':
self.ext = 'vert'
elif self.stage == 'TESS_CONTROL':
self.ext = 'tesc'
elif self.stage == 'TESS_EVALUATION':
self.ext = 'tese'
elif self.stage == 'GEOMETRY':
self.ext = 'geom'
elif self.stage == 'FRAGMENT':
self.ext = 'frag'
elif self.stage == 'COMPUTE':
self.ext = 'comp'
else:
assert False
def add_text(self, s):
self.stream.write(s)
def finish_text(self, line):
self.line = line
def glsl_source(self):
return self.stream.getvalue()
def compile(self):
# We can assume if we got here that we have a temp directory and that
# we're currently living in it.
glsl_fname = 'shader{0}.{1}'.format(self.line, self.ext)
spirv_fname = self.ext + '.spv'
glsl_file = open(glsl_fname, 'w')
glsl_file.write('#version 420 core\n')
glsl_file.write(self.glsl_source())
glsl_file.close()
out = open('glslang.out', 'wb')
err = subprocess.call([glslang, '-V', glsl_fname], stdout=out)
if err != 0:
out = open('glslang.out', 'r')
sys.stderr.write(out.read())
out.close()
exit(1)
def dwords(f):
while True:
dword_str = f.read(4)
if not dword_str:
return
assert len(dword_str) == 4
yield struct.unpack('I', dword_str)[0]
spirv_file = open(spirv_fname, 'rb')
self.dwords = list(dwords(spirv_file))
spirv_file.close()
os.remove(glsl_fname)
os.remove(spirv_fname)
def dump_c_code(self, f, glsl_only = False):
f.write('\n\n')
var_prefix = '_glsl_helpers_shader{0}'.format(self.line)
# First dump the GLSL source as strings
f.write('static const char {0}_glsl_src[] ='.format(var_prefix))
f.write('\n_ANV_SPIRV_' + self.stage)
f.write('\n"#version 330\\n"')
for line in self.glsl_source().splitlines():
if not line.strip():
continue
f.write('\n"{0}\\n"'.format(line))
f.write(';\n\n')
if glsl_only:
return
# Now dump the SPIR-V source
f.write('static const uint32_t {0}_spir_v_src[] = {{'.format(var_prefix))
line_start = 0
while line_start < len(self.dwords):
f.write('\n ')
for i in range(line_start, min(line_start + 6, len(self.dwords))):
f.write(' 0x{:08x},'.format(self.dwords[i]))
line_start += 6
f.write('\n};\n')
token_exp = re.compile(r'(GLSL_VK_SHADER_MODULE|\(|\)|,)')
class Parser:
def __init__(self, f):
self.infile = f
self.paren_depth = 0
self.shader = None
self.line_number = 1
self.shaders = []
def tokenize(f):
leftover = ''
for line in f:
pos = 0
while True:
m = token_exp.search(line, pos)
if m:
if m.start() > pos:
leftover += line[pos:m.start()]
pos = m.end()
if leftover:
yield leftover
leftover = ''
yield m.group(0)
else:
leftover += line[pos:]
break
self.line_number += 1
if leftover:
yield leftover
self.token_iter = tokenize(self.infile)
def handle_shader_src(self):
paren_depth = 1
for t in self.token_iter:
if t == '(':
paren_depth += 1
elif t == ')':
paren_depth -= 1
if paren_depth == 0:
return
self.current_shader.add_text(t)
def handle_macro(self):
t = self.token_iter.next()
assert t == '('
t = self.token_iter.next()
t = self.token_iter.next()
assert t == ','
stage = self.token_iter.next().strip()
t = self.token_iter.next()
assert t == ','
self.current_shader = Shader(stage)
self.handle_shader_src()
self.current_shader.finish_text(self.line_number)
self.shaders.append(self.current_shader)
self.current_shader = None
def run(self):
for t in self.token_iter:
if t == 'GLSL_VK_SHADER_MODULE':
self.handle_macro()
def open_file(name, mode):
if name == '-':
if mode == 'w':
return sys.stdout
elif mode == 'r':
return sys.stdin
else:
assert False
else:
return open(name, mode)
def parse_args():
description = dedent("""\
This program scrapes a C file for any instance of the
GLSL_VK_SHADER_MODULE macro, grabs the GLSL source code, compiles it
to SPIR-V. The resulting SPIR-V code is written to another C file as
an array of 32-bit words.
If '-' is passed as the input file or output file, stdin or stdout will be
used instead of a file on disc.""")
p = argparse.ArgumentParser(
description=description,
formatter_class=argparse.RawDescriptionHelpFormatter)
p.add_argument('-o', '--outfile', default='-',
help='Output to the given file (default: stdout).')
p.add_argument('--with-glslang', metavar='PATH',
default='glslangValidator',
dest='glslang',
help='Full path to the glslangValidator program.')
p.add_argument('--glsl-only', action='store_true')
p.add_argument('infile', metavar='INFILE')
return p.parse_args()
args = parse_args()
infname = args.infile
outfname = args.outfile
glslang = args.glslang
glsl_only = args.glsl_only
with open_file(infname, 'r') as infile:
parser = Parser(infile)
parser.run()
if not glsl_only:
# glslangValidator has an absolutely *insane* interface. We pretty much
# have to run in a temporary directory. Sad day.
current_dir = os.getcwd()
tmpdir = tempfile.mkdtemp('glsl_scraper')
try:
os.chdir(tmpdir)
for shader in parser.shaders:
shader.compile()
os.chdir(current_dir)
finally:
shutil.rmtree(tmpdir)
with open_file(outfname, 'w') as outfile:
outfile.write(dedent("""\
/* =========================== DO NOT EDIT! ===========================
* This file is autogenerated by glsl_scraper.py.
*/
#include <stdint.h>
#define _ANV_SPIRV_MAGIC "\\x03\\x02\\x23\\x07\\0\\0\\0\\0"
#define _ANV_SPIRV_VERTEX _ANV_SPIRV_MAGIC "\\0\\0\\0\\0"
#define _ANV_SPIRV_TESS_CONTROL _ANV_SPIRV_MAGIC "\\1\\0\\0\\0"
#define _ANV_SPIRV_TESS_EVALUATION _ANV_SPIRV_MAGIC "\\2\\0\\0\\0"
#define _ANV_SPIRV_GEOMETRY _ANV_SPIRV_MAGIC "\\3\\0\\0\\0"
#define _ANV_SPIRV_FRAGMENT _ANV_SPIRV_MAGIC "\\4\\0\\0\\0"
#define _ANV_SPIRV_COMPUTE _ANV_SPIRV_MAGIC "\\5\\0\\0\\0"
#define _ANV_GLSL_SRC_VAR2(_line) _glsl_helpers_shader ## _line ## _glsl_src
#define _ANV_GLSL_SRC_VAR(_line) _ANV_GLSL_SRC_VAR2(_line)
#define GLSL_VK_SHADER_MODULE(device, stage, ...) ({ \\
VkShaderModule __module; \\
VkShaderModuleCreateInfo __shader_create_info = { \\
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, \\
.codeSize = sizeof(_ANV_GLSL_SRC_VAR(__LINE__)), \\
.pCode = _ANV_GLSL_SRC_VAR(__LINE__), \\
}; \\
vkCreateShaderModule((VkDevice) device, \\
&__shader_create_info, &__module); \\
__module; \\
})
"""))
for shader in parser.shaders:
shader.dump_c_code(outfile, glsl_only)

744
src/vulkan/image.c Normal file
View File

@@ -0,0 +1,744 @@
/*
* 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 "private.h"
struct anv_image_view_info {
uint8_t surface_type; /**< RENDER_SURFACE_STATE.SurfaceType */
bool is_array:1; /**< RENDER_SURFACE_STATE.SurfaceArray */
bool is_cube:1; /**< RENDER_SURFACE_STATE.CubeFaceEnable* */
};
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
};
static const struct anv_surf_type_limits {
int32_t width;
int32_t height;
int32_t depth;
} anv_surf_type_limits[] = {
[SURFTYPE_1D] = {16384, 0, 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 },
};
static uint32_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;
if (anv_info->vk_info->format == VK_FORMAT_S8_UINT)
return WMAJOR;
switch (anv_info->vk_info->tiling) {
case VK_IMAGE_TILING_LINEAR:
return LINEAR;
case VK_IMAGE_TILING_OPTIMAL:
return YMAJOR;
default:
assert(!"bad VKImageTiling");
return LINEAR;
}
}
static VkResult
anv_image_make_surface(const struct anv_image_create_info *create_info,
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 uint8_t tile_mode = anv_image_choose_tile_mode(create_info);
const struct anv_tile_info *tile_info =
&anv_tile_info_table[tile_mode];
const struct anv_format *format_info =
anv_format_for_vk_format(create_info->vk_info->format);
const uint32_t i = 4; /* FINISHME: Stop hardcoding subimage alignment */
const uint32_t j = 4; /* FINISHME: Stop hardcoding subimage alignment */
const uint32_t w0 = align_u32(extent->width, i);
const uint32_t h0 = align_u32(extent->height, j);
uint16_t qpitch;
uint32_t mt_width;
uint32_t mt_height;
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);
qpitch = h0 + h1 + 11 * j;
mt_width = MAX(w0, w1 + w2);
mt_height = array_size * qpitch;
}
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));
const uint32_t stride = align_u32(mt_width * format_info->cpp,
tile_info->width);
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);
/* XXX: We don't handle any of these */
anv_assert(pCreateInfo->imageType == VK_IMAGE_TYPE_2D);
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? */
anv_loge("image extent is too large");
return vk_error(VK_ERROR_INVALID_MEMORY_SIZE);
}
const struct anv_format *format_info =
anv_format_for_vk_format(pCreateInfo->format);
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 = pCreateInfo->format;
image->levels = pCreateInfo->mipLevels;
image->array_size = pCreateInfo->arraySize;
image->surf_type = surf_type;
if (likely(!format_info->has_stencil || format_info->depth_format)) {
/* The image's primary surface is a color or depth surface. */
r = anv_image_make_surface(create_info, &image->size, &image->alignment,
&image->primary_surface);
if (r != VK_SUCCESS)
goto fail;
}
if (format_info->has_stencil) {
/* From the GPU's perspective, the depth buffer and stencil buffer are
* separate buffers. From Vulkan's perspective, though, depth and
* stencil reside in the same image. To satisfy Vulkan and the GPU, we
* place the depth and stencil buffers in the same bo.
*/
VkImageCreateInfo stencil_info = *pCreateInfo;
stencil_info.format = VK_FORMAT_S8_UINT;
r = anv_image_make_surface(
&(struct anv_image_create_info) {
.vk_info = &stencil_info,
},
&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_destroy(struct anv_device *device,
struct anv_surface_view *view)
{
anv_state_pool_free(&device->surface_state_pool, view->surface_state);
anv_device_free(device, view);
}
void
anv_image_view_init(struct anv_surface_view *view,
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 *surface;
const struct anv_format *format_info =
anv_format_for_vk_format(pCreateInfo->format);
const struct anv_image_view_info *view_type_info
= &anv_image_view_info_table[pCreateInfo->viewType];
if (pCreateInfo->viewType != VK_IMAGE_VIEW_TYPE_2D)
anv_finishme("non-2D image views");
switch (pCreateInfo->subresourceRange.aspect) {
case VK_IMAGE_ASPECT_STENCIL:
anv_finishme("stencil image views");
abort();
break;
case VK_IMAGE_ASPECT_DEPTH:
case VK_IMAGE_ASPECT_COLOR:
view->offset = image->offset;
surface = &image->primary_surface;
break;
default:
unreachable("");
break;
}
view->bo = image->bo;
view->offset = image->offset + surface->offset;
view->format = pCreateInfo->format;
view->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;
}
static const uint32_t vk_to_gen_swizzle[] = {
[VK_CHANNEL_SWIZZLE_ZERO] = SCS_ZERO,
[VK_CHANNEL_SWIZZLE_ONE] = SCS_ONE,
[VK_CHANNEL_SWIZZLE_R] = SCS_RED,
[VK_CHANNEL_SWIZZLE_G] = SCS_GREEN,
[VK_CHANNEL_SWIZZLE_B] = SCS_BLUE,
[VK_CHANNEL_SWIZZLE_A] = SCS_ALPHA
};
struct GEN8_RENDER_SURFACE_STATE surface_state = {
.SurfaceType = view_type_info->surface_type,
.SurfaceArray = image->array_size > 1,
.SurfaceFormat = format_info->surface_format,
.SurfaceVerticalAlignment = anv_valign[surface->v_align],
.SurfaceHorizontalAlignment = anv_halign[surface->h_align],
.TileMode = surface->tile_mode,
.VerticalLineStride = 0,
.VerticalLineStrideOffset = 0,
.SamplerL2BypassModeDisable = true,
.RenderCacheReadWriteMode = WriteOnlyCache,
.MemoryObjectControlState = GEN8_MOCS,
/* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
* RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
* both Base Mip Level fields nonzero".
*/
.BaseMipLevel = 0.0,
.SurfaceQPitch = surface->qpitch >> 2,
.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,
/* For sampler surfaces, the hardware interprets field MIPCount/LOD as
* MIPCount. The range of levels accessible by the sampler engine is
* [SurfaceMinLOD, SurfaceMinLOD + MIPCountLOD].
*/
.MIPCountLOD = range->mipLevels - 1,
.SurfaceMinLOD = range->baseMipLevel,
.AuxiliarySurfaceMode = AUX_NONE,
.RedClearColor = 0,
.GreenClearColor = 0,
.BlueClearColor = 0,
.AlphaClearColor = 0,
.ShaderChannelSelectRed = vk_to_gen_swizzle[pCreateInfo->channels.r],
.ShaderChannelSelectGreen = vk_to_gen_swizzle[pCreateInfo->channels.g],
.ShaderChannelSelectBlue = vk_to_gen_swizzle[pCreateInfo->channels.b],
.ShaderChannelSelectAlpha = vk_to_gen_swizzle[pCreateInfo->channels.a],
.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);
GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &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;
const struct anv_format *image_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);
image_format_info = anv_format_for_vk_format(image->format);
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_info->depth_format);
assert(!image_format_info->has_stencil);
assert(!view_format_info->depth_format);
assert(!view_format_info->has_stencil);
assert(view_format_info->cpp == image_format_info->cpp);
break;
case VK_IMAGE_ASPECT_DEPTH:
assert(image_format_info->depth_format);
assert(view_format_info->depth_format);
assert(view_format_info->cpp == image_format_info->cpp);
break;
case VK_IMAGE_ASPECT_STENCIL:
/* FINISHME: Is it legal to have an R8 view of S8? */
assert(image_format_info->has_stencil);
assert(view_format_info->has_stencil);
break;
default:
assert(!"bad VkImageAspect");
break;
}
return anv_CreateImageView(_device, pCreateInfo, pView);
}
VkResult
anv_CreateImageView(VkDevice _device,
const VkImageViewCreateInfo *pCreateInfo,
VkImageView *pView)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_surface_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 = (VkImageView) view;
return VK_SUCCESS;
}
VkResult
anv_DestroyImageView(VkDevice _device, VkImageView _view)
{
ANV_FROM_HANDLE(anv_device, device, _device);
anv_surface_view_destroy(device, (struct anv_surface_view *)_view);
return VK_SUCCESS;
}
void
anv_color_attachment_view_init(struct anv_surface_view *view,
struct anv_device *device,
const VkColorAttachmentViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer)
{
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
struct anv_surface *surface = &image->primary_surface;
const struct anv_format *format_info =
anv_format_for_vk_format(pCreateInfo->format);
anv_assert(pCreateInfo->arraySize > 0);
anv_assert(pCreateInfo->mipLevel < image->levels);
anv_assert(pCreateInfo->baseArraySlice + pCreateInfo->arraySize <= image->array_size);
if (pCreateInfo->msaaResolveImage)
anv_finishme("msaaResolveImage");
view->bo = image->bo;
view->offset = image->offset + surface->offset;
view->format = pCreateInfo->format;
view->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 GEN8_RENDER_SURFACE_STATE surface_state = {
.SurfaceType = SURFTYPE_2D,
.SurfaceArray = image->array_size > 1,
.SurfaceFormat = format_info->surface_format,
.SurfaceVerticalAlignment = anv_valign[surface->v_align],
.SurfaceHorizontalAlignment = anv_halign[surface->h_align],
.TileMode = surface->tile_mode,
.VerticalLineStride = 0,
.VerticalLineStrideOffset = 0,
.SamplerL2BypassModeDisable = true,
.RenderCacheReadWriteMode = WriteOnlyCache,
.MemoryObjectControlState = GEN8_MOCS,
/* The driver sets BaseMipLevel in SAMPLER_STATE, not here in
* RENDER_SURFACE_STATE. The Broadwell PRM says "it is illegal to have
* both Base Mip Level fields nonzero".
*/
.BaseMipLevel = 0.0,
.SurfaceQPitch = surface->qpitch >> 2,
.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,
/* 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,
.AuxiliarySurfaceMode = AUX_NONE,
.RedClearColor = 0,
.GreenClearColor = 0,
.BlueClearColor = 0,
.AlphaClearColor = 0,
.ShaderChannelSelectRed = SCS_RED,
.ShaderChannelSelectGreen = SCS_GREEN,
.ShaderChannelSelectBlue = SCS_BLUE,
.ShaderChannelSelectAlpha = SCS_ALPHA,
.ResourceMinLOD = 0.0,
.SurfaceBaseAddress = { NULL, view->offset },
};
GEN8_RENDER_SURFACE_STATE_pack(NULL, view->surface_state.map, &surface_state);
}
VkResult
anv_CreateColorAttachmentView(VkDevice _device,
const VkColorAttachmentViewCreateInfo *pCreateInfo,
VkColorAttachmentView *pView)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_surface_view *view;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COLOR_ATTACHMENT_VIEW_CREATE_INFO);
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 = (VkColorAttachmentView) view;
return VK_SUCCESS;
}
VkResult
anv_DestroyColorAttachmentView(VkDevice _device, VkColorAttachmentView _view)
{
ANV_FROM_HANDLE(anv_device, device, _device);
anv_surface_view_destroy(device, (struct anv_surface_view *)_view);
return VK_SUCCESS;
}
VkResult
anv_CreateDepthStencilView(VkDevice _device,
const VkDepthStencilViewCreateInfo *pCreateInfo,
VkDepthStencilView *pView)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
struct anv_depth_stencil_view *view;
struct anv_surface *depth_surface = &image->primary_surface;
struct anv_surface *stencil_surface = &image->stencil_surface;
const struct anv_format *format =
anv_format_for_vk_format(image->format);
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEPTH_STENCIL_VIEW_CREATE_INFO);
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);
/* XXX: We don't handle any of these */
anv_assert(pCreateInfo->mipLevel == 0);
anv_assert(pCreateInfo->baseArraySlice == 0);
anv_assert(pCreateInfo->arraySize == 1);
view->bo = image->bo;
view->depth_stride = depth_surface->stride;
view->depth_offset = image->offset + depth_surface->offset;
view->depth_format = format->depth_format;
view->depth_qpitch = 0; /* FINISHME: QPitch */
view->stencil_stride = stencil_surface->stride;
view->stencil_offset = image->offset + stencil_surface->offset;
view->stencil_qpitch = 0; /* FINISHME: QPitch */
*pView = anv_depth_stencil_view_to_handle(view);
return VK_SUCCESS;
}
VkResult
anv_DestroyDepthStencilView(VkDevice _device, VkDepthStencilView _view)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_depth_stencil_view, view, _view);
anv_device_free(device, view);
return VK_SUCCESS;
}

97
src/vulkan/intel.c Normal file
View File

@@ -0,0 +1,97 @@
/*
* 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 "private.h"
VkResult anv_CreateDmaBufImageINTEL(
VkDevice _device,
const VkDmaBufImageCreateInfo* pCreateInfo,
VkDeviceMemory* pMem,
VkImage* pImage)
{
struct anv_device *device = (struct anv_device *) _device;
struct anv_device_memory *mem;
struct anv_image *image;
VkResult result;
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;
}
*image = (struct anv_image) {
.bo = &mem->bo,
.offset = 0,
.type = VK_IMAGE_TYPE_2D,
.extent = pCreateInfo->extent,
.size = mem->bo.size,
.primary_surface = {
.offset = 0,
.stride = pCreateInfo->strideInBytes,
.tile_mode = XMAJOR,
},
};
assert(image->extent.width > 0);
assert(image->extent.height > 0);
assert(image->extent.depth == 1);
*pMem = (VkDeviceMemory) mem;
*pImage = (VkImage) image;
return VK_SUCCESS;
fail_mem:
anv_gem_close(device, mem->bo.gem_handle);
fail:
anv_device_free(device, mem);
return result;
}

1387
src/vulkan/meta.c Normal file

File diff suppressed because it is too large Load Diff

911
src/vulkan/pipeline.c Normal file
View File

@@ -0,0 +1,911 @@
/*
* 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 "private.h"
// Shader functions
VkResult anv_CreateShaderModule(
VkDevice _device,
const VkShaderModuleCreateInfo* pCreateInfo,
VkShader* 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_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);
size_t name_len = strlen(pCreateInfo->pName);
if (strcmp(pCreateInfo->pName, "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, pCreateInfo->pName, name_len + 1);
*pShader = anv_shader_to_handle(shader);
return VK_SUCCESS;
}
VkResult anv_CreatePipelineCache(
VkDevice device,
const VkPipelineCacheCreateInfo* pCreateInfo,
VkPipelineCache* pPipelineCache)
{
*pPipelineCache = 1;
stub_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);
}
// Pipeline functions
static void
emit_vertex_input(struct anv_pipeline *pipeline,
const VkPipelineVertexInputStateCreateInfo *info)
{
const uint32_t num_dwords = 1 + info->attributeCount * 2;
uint32_t *p;
bool instancing_enable[32];
pipeline->vb_used = 0;
for (uint32_t i = 0; i < info->bindingCount; i++) {
const VkVertexInputBindingDescription *desc =
&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:
instancing_enable[desc->binding] = false;
break;
case VK_VERTEX_INPUT_STEP_RATE_INSTANCE:
instancing_enable[desc->binding] = true;
break;
}
}
p = anv_batch_emitn(&pipeline->batch, num_dwords,
GEN8_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 GEN8_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
};
GEN8_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + i * 2], &element);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_INSTANCING,
.InstancingEnable = instancing_enable[desc->binding],
.VertexElementIndex = i,
/* Vulkan so far doesn't have an instance divisor, so
* this is always 1 (ignored if not instancing). */
.InstanceDataStepRate = 1);
}
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_SGVS,
.VertexIDEnable = pipeline->vs_prog_data.uses_vertexid,
.VertexIDComponentNumber = 2,
.VertexIDElementOffset = info->bindingCount,
.InstanceIDEnable = pipeline->vs_prog_data.uses_instanceid,
.InstanceIDComponentNumber = 3,
.InstanceIDElementOffset = info->bindingCount);
}
static void
emit_ia_state(struct anv_pipeline *pipeline,
const VkPipelineIaStateCreateInfo *info,
const struct anv_pipeline_create_info *extra)
{
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
};
uint32_t topology = vk_to_gen_primitive_type[info->topology];
if (extra && extra->use_rectlist)
topology = _3DPRIM_RECTLIST;
struct GEN8_3DSTATE_VF vf = {
GEN8_3DSTATE_VF_header,
.IndexedDrawCutIndexEnable = info->primitiveRestartEnable,
};
GEN8_3DSTATE_VF_pack(NULL, pipeline->state_vf, &vf);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_TOPOLOGY,
.PrimitiveTopologyType = topology);
}
static void
emit_rs_state(struct anv_pipeline *pipeline,
const VkPipelineRsStateCreateInfo *info,
const struct anv_pipeline_create_info *extra)
{
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
};
struct GEN8_3DSTATE_SF sf = {
GEN8_3DSTATE_SF_header,
.ViewportTransformEnable = !(extra && extra->disable_viewport),
.TriangleStripListProvokingVertexSelect = 0,
.LineStripListProvokingVertexSelect = 0,
.TriangleFanProvokingVertexSelect = 0,
.PointWidthSource = pipeline->writes_point_size ? Vertex : State,
.PointWidth = 1.0,
};
/* FINISHME: bool32_t rasterizerDiscardEnable; */
GEN8_3DSTATE_SF_pack(NULL, pipeline->state_sf, &sf);
struct GEN8_3DSTATE_RASTER raster = {
GEN8_3DSTATE_RASTER_header,
.FrontWinding = vk_to_gen_front_face[info->frontFace],
.CullMode = vk_to_gen_cullmode[info->cullMode],
.FrontFaceFillMode = vk_to_gen_fillmode[info->fillMode],
.BackFaceFillMode = vk_to_gen_fillmode[info->fillMode],
.ScissorRectangleEnable = !(extra && extra->disable_scissor),
.ViewportZClipTestEnable = info->depthClipEnable
};
GEN8_3DSTATE_RASTER_pack(NULL, pipeline->state_raster, &raster);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE,
.ForceVertexURBEntryReadLength = false,
.ForceVertexURBEntryReadOffset = false,
.PointSpriteTextureCoordinateOrigin = UPPERLEFT,
.NumberofSFOutputAttributes =
pipeline->wm_prog_data.num_varying_inputs);
}
static void
emit_cb_state(struct anv_pipeline *pipeline,
const VkPipelineCbStateCreateInfo *info)
{
struct anv_device *device = pipeline->device;
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 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,
};
uint32_t num_dwords = 1 + info->attachmentCount * 2;
pipeline->blend_state =
anv_state_pool_alloc(&device->dynamic_state_pool, num_dwords * 4, 64);
struct GEN8_BLEND_STATE blend_state = {
.AlphaToCoverageEnable = info->alphaToCoverageEnable,
};
uint32_t *state = pipeline->blend_state.map;
GEN8_BLEND_STATE_pack(NULL, state, &blend_state);
for (uint32_t i = 0; i < info->attachmentCount; i++) {
const VkPipelineCbAttachmentState *a = &info->pAttachments[i];
struct GEN8_BLEND_STATE_ENTRY entry = {
.LogicOpEnable = info->logicOpEnable,
.LogicOpFunction = vk_to_gen_logic_op[info->logicOp],
.ColorBufferBlendEnable = a->blendEnable,
.PreBlendSourceOnlyClampEnable = false,
.PreBlendColorClampEnable = false,
.PostBlendColorClampEnable = false,
.SourceBlendFactor = vk_to_gen_blend[a->srcBlendColor],
.DestinationBlendFactor = vk_to_gen_blend[a->destBlendColor],
.ColorBlendFunction = vk_to_gen_blend_op[a->blendOpColor],
.SourceAlphaBlendFactor = vk_to_gen_blend[a->srcBlendAlpha],
.DestinationAlphaBlendFactor = vk_to_gen_blend[a->destBlendAlpha],
.AlphaBlendFunction = vk_to_gen_blend_op[a->blendOpAlpha],
.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),
};
GEN8_BLEND_STATE_ENTRY_pack(NULL, state + i * 2 + 1, &entry);
}
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_BLEND_STATE_POINTERS,
.BlendStatePointer = pipeline->blend_state.offset,
.BlendStatePointerValid = true);
}
static const uint32_t vk_to_gen_compare_op[] = {
[VK_COMPARE_OP_NEVER] = COMPAREFUNCTION_NEVER,
[VK_COMPARE_OP_LESS] = COMPAREFUNCTION_LESS,
[VK_COMPARE_OP_EQUAL] = COMPAREFUNCTION_EQUAL,
[VK_COMPARE_OP_LESS_EQUAL] = COMPAREFUNCTION_LEQUAL,
[VK_COMPARE_OP_GREATER] = COMPAREFUNCTION_GREATER,
[VK_COMPARE_OP_NOT_EQUAL] = COMPAREFUNCTION_NOTEQUAL,
[VK_COMPARE_OP_GREATER_EQUAL] = COMPAREFUNCTION_GEQUAL,
[VK_COMPARE_OP_ALWAYS] = COMPAREFUNCTION_ALWAYS,
};
static const uint32_t vk_to_gen_stencil_op[] = {
[VK_STENCIL_OP_KEEP] = 0,
[VK_STENCIL_OP_ZERO] = 0,
[VK_STENCIL_OP_REPLACE] = 0,
[VK_STENCIL_OP_INC_CLAMP] = 0,
[VK_STENCIL_OP_DEC_CLAMP] = 0,
[VK_STENCIL_OP_INVERT] = 0,
[VK_STENCIL_OP_INC_WRAP] = 0,
[VK_STENCIL_OP_DEC_WRAP] = 0
};
static void
emit_ds_state(struct anv_pipeline *pipeline,
const VkPipelineDsStateCreateInfo *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->state_wm_depth_stencil, 0,
sizeof(pipeline->state_wm_depth_stencil));
return;
}
/* bool32_t depthBoundsEnable; // optional (depth_bounds_test) */
struct GEN8_3DSTATE_WM_DEPTH_STENCIL wm_depth_stencil = {
.DepthTestEnable = info->depthTestEnable,
.DepthBufferWriteEnable = info->depthWriteEnable,
.DepthTestFunction = vk_to_gen_compare_op[info->depthCompareOp],
.DoubleSidedStencilEnable = true,
.StencilTestEnable = info->stencilTestEnable,
.StencilFailOp = vk_to_gen_stencil_op[info->front.stencilFailOp],
.StencilPassDepthPassOp = vk_to_gen_stencil_op[info->front.stencilPassOp],
.StencilPassDepthFailOp = vk_to_gen_stencil_op[info->front.stencilDepthFailOp],
.StencilTestFunction = vk_to_gen_compare_op[info->front.stencilCompareOp],
.BackfaceStencilFailOp = vk_to_gen_stencil_op[info->back.stencilFailOp],
.BackfaceStencilPassDepthPassOp = vk_to_gen_stencil_op[info->back.stencilPassOp],
.BackfaceStencilPassDepthFailOp =vk_to_gen_stencil_op[info->back.stencilDepthFailOp],
.BackfaceStencilTestFunction = vk_to_gen_compare_op[info->back.stencilCompareOp],
};
GEN8_3DSTATE_WM_DEPTH_STENCIL_pack(NULL, pipeline->state_wm_depth_stencil, &wm_depth_stencil);
}
static void
anv_pipeline_destroy(struct anv_device *device,
struct anv_object *object,
VkObjectType obj_type)
{
struct anv_pipeline *pipeline = (struct anv_pipeline*) object;
assert(obj_type == VK_OBJECT_TYPE_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);
}
VkResult
anv_pipeline_create(
VkDevice _device,
const VkGraphicsPipelineCreateInfo* pCreateInfo,
const struct anv_pipeline_create_info * extra,
VkPipeline* pPipeline)
{
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_pipeline *pipeline;
VkResult result;
uint32_t offset, length;
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);
pipeline->base.destructor = anv_pipeline_destroy;
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);
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->pTessState)
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO");
if (pCreateInfo->pVpState)
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_VP_STATE_CREATE_INFO");
if (pCreateInfo->pMsState)
anv_finishme("VK_STRUCTURE_TYPE_PIPELINE_MS_STATE_CREATE_INFO");
pipeline->use_repclear = extra && extra->use_repclear;
anv_compiler_run(device->compiler, pipeline);
/* FIXME: The compiler dead-codes FS inputs when we don't have a VS, so we
* hard code this to num_attributes - 2. This is because the attributes
* include VUE header and position, which aren't counted as varying
* inputs. */
if (pipeline->vs_simd8 == NO_KERNEL) {
pipeline->wm_prog_data.num_varying_inputs =
pCreateInfo->pVertexInputState->attributeCount - 2;
}
assert(pCreateInfo->pVertexInputState);
emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
assert(pCreateInfo->pIaState);
emit_ia_state(pipeline, pCreateInfo->pIaState, extra);
assert(pCreateInfo->pRsState);
emit_rs_state(pipeline, pCreateInfo->pRsState, extra);
emit_ds_state(pipeline, pCreateInfo->pDsState);
emit_cb_state(pipeline, pCreateInfo->pCbState);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VF_STATISTICS,
.StatisticsEnable = true);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_HS, .Enable = false);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_TE, .TEEnable = false);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_DS, .FunctionEnable = false);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_STREAMOUT, .SOFunctionEnable = false);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
.ConstantBufferOffset = 0,
.ConstantBufferSize = 4);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
.ConstantBufferOffset = 4,
.ConstantBufferSize = 4);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
.ConstantBufferOffset = 8,
.ConstantBufferSize = 4);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM_CHROMAKEY,
.ChromaKeyKillEnable = false);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SBE_SWIZ);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_AA_LINE_PARAMETERS);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_CLIP,
.ClipEnable = true,
.ViewportXYClipTestEnable = !(extra && extra->disable_viewport),
.MinimumPointWidth = 0.125,
.MaximumPointWidth = 255.875);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_WM,
.StatisticsEnable = true,
.LineEndCapAntialiasingRegionWidth = _05pixels,
.LineAntialiasingRegionWidth = _10pixels,
.EarlyDepthStencilControl = NORMAL,
.ForceThreadDispatchEnable = NORMAL,
.PointRasterizationRule = RASTRULE_UPPER_RIGHT,
.BarycentricInterpolationMode =
pipeline->wm_prog_data.barycentric_interp_modes);
uint32_t samples = 1;
uint32_t log2_samples = __builtin_ffs(samples) - 1;
bool enable_sampling = samples > 1 ? true : false;
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_MULTISAMPLE,
.PixelPositionOffsetEnable = enable_sampling,
.PixelLocation = CENTER,
.NumberofMultisamples = log2_samples);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_SAMPLE_MASK,
.SampleMask = 0xffff);
anv_batch_emit(&pipeline->batch, GEN8_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, GEN8_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, GEN8_3DSTATE_URB_HS,
.HSURBStartingAddress = pipeline->urb.vs_start,
.HSURBEntryAllocationSize = 0,
.HSNumberofURBEntries = 0);
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_URB_DS,
.DSURBStartingAddress = pipeline->urb.vs_start,
.DSURBEntryAllocationSize = 0,
.DSNumberofURBEntries = 0);
const struct brw_gs_prog_data *gs_prog_data = &pipeline->gs_prog_data;
offset = 1;
length = (gs_prog_data->base.vue_map.num_slots + 1) / 2 - offset;
if (pipeline->gs_vec4 == NO_KERNEL)
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS, .Enable = false);
else
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_GS,
.SingleProgramFlow = false,
.KernelStartPointer = pipeline->gs_vec4,
.VectorMaskEnable = Vmask,
.SamplerCount = 0,
.BindingTableEntryCount = 0,
.ExpectedVertexCount = pipeline->gs_vertex_count,
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_GEOMETRY],
.PerThreadScratchSpace = ffs(gs_prog_data->base.base.total_scratch / 2048),
.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,
.ControlDataHeaderSize = gs_prog_data->control_data_header_size_hwords,
//pipeline->gs_prog_data.dispatch_mode |
.StatisticsEnable = true,
.IncludePrimitiveID = gs_prog_data->include_primitive_id,
.ReorderMode = TRAILING,
.Enable = true,
.ControlDataFormat = gs_prog_data->control_data_format,
/* FIXME: mesa sets this based on ctx->Transform.ClipPlanesEnabled:
* UserClipDistanceClipTestEnableBitmask_3DSTATE_GS(v)
* UserClipDistanceCullTestEnableBitmask(v)
*/
.VertexURBEntryOutputReadOffset = offset,
.VertexURBEntryOutputLength = length);
const struct brw_vue_prog_data *vue_prog_data = &pipeline->vs_prog_data.base;
/* Skip the VUE header and position slots */
offset = 1;
length = (vue_prog_data->vue_map.num_slots + 1) / 2 - offset;
if (pipeline->vs_simd8 == NO_KERNEL || (extra && extra->disable_vs))
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
.FunctionEnable = false,
.VertexURBEntryOutputReadOffset = 1,
/* Even if VS is disabled, SBE still gets the amount of
* vertex data to read from this field. We use attribute
* count - 1, as we don't count the VUE header here. */
.VertexURBEntryOutputLength =
DIV_ROUND_UP(pCreateInfo->pVertexInputState->attributeCount - 1, 2));
else
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_VS,
.KernelStartPointer = pipeline->vs_simd8,
.SingleVertexDispatch = Multiple,
.VectorMaskEnable = Dmask,
.SamplerCount = 0,
.BindingTableEntryCount =
vue_prog_data->base.binding_table.size_bytes / 4,
.ThreadDispatchPriority = Normal,
.FloatingPointMode = IEEE754,
.IllegalOpcodeExceptionEnable = false,
.AccessesUAV = false,
.SoftwareExceptionEnable = false,
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_VERTEX],
.PerThreadScratchSpace = ffs(vue_prog_data->base.total_scratch / 2048),
.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 = false,
.SIMD8DispatchEnable = true,
.VertexCacheDisable = false,
.FunctionEnable = true,
.VertexURBEntryOutputReadOffset = offset,
.VertexURBEntryOutputLength = length,
.UserClipDistanceClipTestEnableBitmask = 0,
.UserClipDistanceCullTestEnableBitmask = 0);
const struct brw_wm_prog_data *wm_prog_data = &pipeline->wm_prog_data;
uint32_t ksp0, ksp2, grf_start0, grf_start2;
ksp2 = 0;
grf_start2 = 0;
if (pipeline->ps_simd8 != NO_KERNEL) {
ksp0 = pipeline->ps_simd8;
grf_start0 = wm_prog_data->base.dispatch_grf_start_reg;
if (pipeline->ps_simd16 != NO_KERNEL) {
ksp2 = pipeline->ps_simd16;
grf_start2 = wm_prog_data->dispatch_grf_start_reg_16;
}
} else if (pipeline->ps_simd16 != NO_KERNEL) {
ksp0 = pipeline->ps_simd16;
grf_start0 = wm_prog_data->dispatch_grf_start_reg_16;
} else {
unreachable("no ps shader");
}
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS,
.KernelStartPointer0 = ksp0,
.SingleProgramFlow = false,
.VectorMaskEnable = true,
.SamplerCount = 1,
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
.PerThreadScratchSpace = ffs(wm_prog_data->base.total_scratch / 2048),
.MaximumNumberofThreadsPerPSD = 64 - 2,
.PositionXYOffsetSelect = wm_prog_data->uses_pos_offset ?
POSOFFSET_SAMPLE: POSOFFSET_NONE,
.PushConstantEnable = wm_prog_data->base.nr_params > 0,
._8PixelDispatchEnable = pipeline->ps_simd8 != NO_KERNEL,
._16PixelDispatchEnable = pipeline->ps_simd16 != NO_KERNEL,
._32PixelDispatchEnable = false,
.DispatchGRFStartRegisterForConstantSetupData0 = grf_start0,
.DispatchGRFStartRegisterForConstantSetupData1 = 0,
.DispatchGRFStartRegisterForConstantSetupData2 = grf_start2,
.KernelStartPointer1 = 0,
.KernelStartPointer2 = ksp2);
bool per_sample_ps = false;
anv_batch_emit(&pipeline->batch, GEN8_3DSTATE_PS_EXTRA,
.PixelShaderValid = true,
.PixelShaderKillsPixel = wm_prog_data->uses_kill,
.PixelShaderComputedDepthMode = wm_prog_data->computed_depth_mode,
.AttributeEnable = wm_prog_data->num_varying_inputs > 0,
.oMaskPresenttoRenderTarget = wm_prog_data->uses_omask,
.PixelShaderIsPerSample = per_sample_ps);
*pPipeline = anv_pipeline_to_handle(pipeline);
return VK_SUCCESS;
}
VkResult anv_CreateGraphicsPipelines(
VkDevice _device,
VkPipelineCache pipelineCache,
uint32_t count,
const VkGraphicsPipelineCreateInfo* pCreateInfos,
VkPipeline* pPipelines)
{
ANV_FROM_HANDLE(anv_device, device, _device);
VkResult result = VK_SUCCESS;
unsigned i = 0;
for (; i < count; i++) {
result = anv_pipeline_create(_device, &pCreateInfos[i],
NULL, &pPipelines[i]);
if (result != VK_SUCCESS) {
for (unsigned j = 0; j < i; j++) {
anv_pipeline_destroy(device, (struct anv_object *)pPipelines[j],
VK_OBJECT_TYPE_PIPELINE);
}
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);
struct anv_pipeline *pipeline;
VkResult result;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_COMPUTE_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);
pipeline->base.destructor = anv_pipeline_destroy;
pipeline->device = device;
pipeline->layout = anv_pipeline_layout_from_handle(pCreateInfo->layout);
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);
anv_state_stream_init(&pipeline->program_stream,
&device->instruction_block_pool);
memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
pipeline->shaders[VK_SHADER_STAGE_COMPUTE] =
anv_shader_from_handle(pCreateInfo->cs.shader);
pipeline->use_repclear = false;
anv_compiler_run(device->compiler, pipeline);
const struct brw_cs_prog_data *cs_prog_data = &pipeline->cs_prog_data;
anv_batch_emit(&pipeline->batch, GEN8_MEDIA_VFE_STATE,
.ScratchSpaceBasePointer = pipeline->scratch_start[VK_SHADER_STAGE_FRAGMENT],
.PerThreadScratchSpace = ffs(cs_prog_data->base.total_scratch / 2048),
.ScratchSpaceBasePointerHigh = 0,
.StackSize = 0,
.MaximumNumberofThreads = device->info.max_cs_threads - 1,
.NumberofURBEntries = 2,
.ResetGatewayTimer = true,
.BypassGatewayControl = true,
.URBEntryAllocationSize = 2,
.CURBEAllocationSize = 0);
struct brw_cs_prog_data *prog_data = &pipeline->cs_prog_data;
uint32_t group_size = prog_data->local_size[0] *
prog_data->local_size[1] * prog_data->local_size[2];
pipeline->cs_thread_width_max = DIV_ROUND_UP(group_size, prog_data->simd_size);
uint32_t remainder = group_size & (prog_data->simd_size - 1);
if (remainder > 0)
pipeline->cs_right_mask = ~0u >> (32 - remainder);
else
pipeline->cs_right_mask = ~0u >> (32 - prog_data->simd_size);
*pPipeline = anv_pipeline_to_handle(pipeline);
return VK_SUCCESS;
}
VkResult anv_CreateComputePipelines(
VkDevice _device,
VkPipelineCache pipelineCache,
uint32_t count,
const VkComputePipelineCreateInfo* pCreateInfos,
VkPipeline* pPipelines)
{
ANV_FROM_HANDLE(anv_device, device, _device);
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_pipeline_destroy(device, (struct anv_object *)pPipelines[j],
VK_OBJECT_TYPE_PIPELINE);
}
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].surface_count = 0;
layout->stage[s].sampler_count = 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;
for (uint32_t s = 0; s < VK_SHADER_STAGE_NUM; s++) {
layout->set[i].surface_start[s] = surface_start[s];
surface_start[s] += set_layout->stage[s].surface_count;
layout->set[i].sampler_start[s] = 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;
}

998
src/vulkan/private.h Normal file
View File

@@ -0,0 +1,998 @@
/*
* 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 <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <pthread.h>
#include <assert.h>
#include <i915_drm.h>
#ifdef HAVE_VALGRIND
#include <valgrind.h>
#include <memcheck.h>
#define VG(x) x
#define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))
#else
#define VG(x)
#endif
#include "brw_device_info.h"
#include "util/macros.h"
#define VK_PROTOTYPES
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_intel.h>
#include <vulkan/vk_wsi_lunarg.h>
#include "entrypoints.h"
#include "brw_context.h"
#ifdef __cplusplus
extern "C" {
#endif
#define anv_noreturn __attribute__((__noreturn__))
#define anv_printflike(a, b) __attribute__((__format__(__printf__, a, b)))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
static inline uint32_t
align_u32(uint32_t v, uint32_t a)
{
return (v + a - 1) & ~(a - 1);
}
static inline int32_t
align_i32(int32_t v, int32_t a)
{
return (v + a - 1) & ~(a - 1);
}
/** Alignment must be a power of 2. */
static inline bool
anv_is_aligned(uintmax_t n, uintmax_t a)
{
assert(a == (a & -a));
return (n & (a - 1)) == 0;
}
static inline uint32_t
anv_minify(uint32_t n, uint32_t levels)
{
if (unlikely(n == 0))
return 0;
else
return MAX(n >> levels, 1);
}
static inline bool
anv_clear_mask(uint32_t *inout_mask, uint32_t clear_mask)
{
if (*inout_mask & clear_mask) {
*inout_mask &= ~clear_mask;
return true;
} else {
return false;
}
}
#define for_each_bit(b, dword) \
for (uint32_t __dword = (dword); \
(b) = __builtin_ffs(__dword) - 1, __dword; \
__dword &= ~(1 << (b)))
/* Define no kernel as 1, since that's an illegal offset for a kernel */
#define NO_KERNEL 1
struct anv_common {
VkStructureType sType;
const void* pNext;
};
/* Whenever we generate an error, pass it through this function. Useful for
* debugging, where we can break on it. Only call at error site, not when
* propagating errors. Might be useful to plug in a stack trace here.
*/
static inline VkResult
vk_error(VkResult error)
{
#ifdef DEBUG
fprintf(stderr, "vk_error: %x\n", error);
#endif
return error;
}
void __anv_finishme(const char *file, int line, const char *format, ...)
anv_printflike(3, 4);
void anv_loge(const char *format, ...) anv_printflike(1, 2);
void anv_loge_v(const char *format, va_list va);
/**
* Print a FINISHME message, including its source location.
*/
#define anv_finishme(format, ...) \
__anv_finishme(__FILE__, __LINE__, format, ##__VA_ARGS__);
/* A non-fatal assert. Useful for debugging. */
#ifdef DEBUG
#define anv_assert(x) ({ \
if (unlikely(!(x))) \
fprintf(stderr, "%s:%d ASSERT: %s\n", __FILE__, __LINE__, #x); \
})
#else
#define anv_assert(x)
#endif
void anv_abortf(const char *format, ...) anv_noreturn anv_printflike(1, 2);
void anv_abortfv(const char *format, va_list va) anv_noreturn;
#define stub_return(v) \
do { \
anv_finishme("stub %s", __func__); \
return (v); \
} while (0)
#define stub() \
do { \
anv_finishme("stub %s", __func__); \
return; \
} while (0)
/**
* A dynamically growable, circular buffer. Elements are added at head and
* removed from tail. head and tail are free-running uint32_t indices and we
* only compute the modulo with size when accessing the array. This way,
* number of bytes in the queue is always head - tail, even in case of
* wraparound.
*/
struct anv_vector {
uint32_t head;
uint32_t tail;
uint32_t element_size;
uint32_t size;
void *data;
};
int anv_vector_init(struct anv_vector *queue, uint32_t element_size, uint32_t size);
void *anv_vector_add(struct anv_vector *queue);
void *anv_vector_remove(struct anv_vector *queue);
static inline int
anv_vector_length(struct anv_vector *queue)
{
return (queue->head - queue->tail) / queue->element_size;
}
static inline void
anv_vector_finish(struct anv_vector *queue)
{
free(queue->data);
}
#define anv_vector_foreach(elem, queue) \
static_assert(__builtin_types_compatible_p(__typeof__(queue), struct anv_vector *), ""); \
for (uint32_t __anv_vector_offset = (queue)->tail; \
elem = (queue)->data + (__anv_vector_offset & ((queue)->size - 1)), __anv_vector_offset < (queue)->head; \
__anv_vector_offset += (queue)->element_size)
struct anv_bo {
int gem_handle;
uint32_t index;
uint64_t offset;
uint64_t size;
/* This field is here for the benefit of the aub dumper. It can (and for
* userptr bos it must) be set to the cpu map of the buffer. Destroying
* the bo won't clean up the mmap, it's still the responsibility of the bo
* user to do that. */
void *map;
};
/* Represents a lock-free linked list of "free" things. This is used by
* both the block pool and the state pools. Unfortunately, in order to
* solve the ABA problem, we can't use a single uint32_t head.
*/
union anv_free_list {
struct {
uint32_t offset;
/* A simple count that is incremented every time the head changes. */
uint32_t count;
};
uint64_t u64;
};
#define ANV_FREE_LIST_EMPTY ((union anv_free_list) { { 1, 0 } })
struct anv_block_pool {
struct anv_device *device;
struct anv_bo bo;
void *map;
int fd;
uint32_t size;
/**
* Array of mmaps and gem handles owned by the block pool, reclaimed when
* the block pool is destroyed.
*/
struct anv_vector mmap_cleanups;
uint32_t block_size;
uint32_t next_block;
union anv_free_list free_list;
};
struct anv_block_state {
union {
struct {
uint32_t next;
uint32_t end;
};
uint64_t u64;
};
};
struct anv_state {
uint32_t offset;
uint32_t alloc_size;
void *map;
};
struct anv_fixed_size_state_pool {
size_t state_size;
union anv_free_list free_list;
struct anv_block_state block;
};
#define ANV_MIN_STATE_SIZE_LOG2 6
#define ANV_MAX_STATE_SIZE_LOG2 10
#define ANV_STATE_BUCKETS (ANV_MAX_STATE_SIZE_LOG2 - ANV_MIN_STATE_SIZE_LOG2)
struct anv_state_pool {
struct anv_block_pool *block_pool;
struct anv_fixed_size_state_pool buckets[ANV_STATE_BUCKETS];
};
struct anv_state_stream {
struct anv_block_pool *block_pool;
uint32_t next;
uint32_t current_block;
uint32_t end;
};
void anv_block_pool_init(struct anv_block_pool *pool,
struct anv_device *device, uint32_t block_size);
void anv_block_pool_finish(struct anv_block_pool *pool);
uint32_t anv_block_pool_alloc(struct anv_block_pool *pool);
void anv_block_pool_free(struct anv_block_pool *pool, uint32_t offset);
void anv_state_pool_init(struct anv_state_pool *pool,
struct anv_block_pool *block_pool);
struct anv_state anv_state_pool_alloc(struct anv_state_pool *pool,
size_t state_size, size_t alignment);
void anv_state_pool_free(struct anv_state_pool *pool, struct anv_state state);
void anv_state_stream_init(struct anv_state_stream *stream,
struct anv_block_pool *block_pool);
void anv_state_stream_finish(struct anv_state_stream *stream);
struct anv_state anv_state_stream_alloc(struct anv_state_stream *stream,
uint32_t size, uint32_t alignment);
/**
* Implements a pool of re-usable BOs. The interface is identical to that
* of block_pool except that each block is its own BO.
*/
struct anv_bo_pool {
struct anv_device *device;
uint32_t bo_size;
void *free_list;
};
void anv_bo_pool_init(struct anv_bo_pool *pool,
struct anv_device *device, uint32_t block_size);
void anv_bo_pool_finish(struct anv_bo_pool *pool);
VkResult anv_bo_pool_alloc(struct anv_bo_pool *pool, struct anv_bo *bo);
void anv_bo_pool_free(struct anv_bo_pool *pool, const struct anv_bo *bo);
struct anv_object;
struct anv_device;
typedef void (*anv_object_destructor_cb)(struct anv_device *,
struct anv_object *,
VkObjectType);
struct anv_object {
anv_object_destructor_cb destructor;
};
struct anv_physical_device {
struct anv_instance * instance;
uint32_t chipset_id;
bool no_hw;
const char * path;
const char * name;
const struct brw_device_info * info;
int fd;
};
struct anv_instance {
void * pAllocUserData;
PFN_vkAllocFunction pfnAlloc;
PFN_vkFreeFunction pfnFree;
uint32_t apiVersion;
uint32_t physicalDeviceCount;
struct anv_physical_device physicalDevice;
};
struct anv_meta_state {
struct {
VkPipeline pipeline;
} clear;
struct {
VkPipeline pipeline;
VkPipelineLayout pipeline_layout;
VkDescriptorSetLayout ds_layout;
} blit;
struct {
VkDynamicRsState rs_state;
VkDynamicCbState cb_state;
VkDynamicDsState ds_state;
} shared;
};
struct anv_queue {
struct anv_device * device;
struct anv_state_pool * pool;
/**
* Serial number of the most recently completed batch executed on the
* engine.
*/
struct anv_state completed_serial;
/**
* The next batch submitted to the engine will be assigned this serial
* number.
*/
uint32_t next_serial;
uint32_t last_collected_serial;
};
struct anv_device {
struct anv_instance * instance;
uint32_t chipset_id;
struct brw_device_info info;
int context_id;
int fd;
bool no_hw;
bool dump_aub;
struct anv_bo_pool batch_bo_pool;
struct anv_block_pool dynamic_state_block_pool;
struct anv_state_pool dynamic_state_pool;
struct anv_block_pool instruction_block_pool;
struct anv_block_pool surface_state_block_pool;
struct anv_state_pool surface_state_pool;
struct anv_meta_state meta_state;
struct anv_state border_colors;
struct anv_queue queue;
struct anv_block_pool scratch_block_pool;
struct anv_compiler * compiler;
struct anv_aub_writer * aub_writer;
pthread_mutex_t mutex;
};
void *
anv_device_alloc(struct anv_device * device,
size_t size,
size_t alignment,
VkSystemAllocType allocType);
void
anv_device_free(struct anv_device * device,
void * mem);
void* anv_gem_mmap(struct anv_device *device,
uint32_t gem_handle, uint64_t offset, uint64_t size);
void anv_gem_munmap(void *p, uint64_t size);
uint32_t anv_gem_create(struct anv_device *device, size_t size);
void anv_gem_close(struct anv_device *device, int gem_handle);
int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
int anv_gem_wait(struct anv_device *device, int gem_handle, int64_t *timeout_ns);
int anv_gem_execbuffer(struct anv_device *device,
struct drm_i915_gem_execbuffer2 *execbuf);
int anv_gem_set_tiling(struct anv_device *device, int gem_handle,
uint32_t stride, uint32_t tiling);
int anv_gem_create_context(struct anv_device *device);
int anv_gem_destroy_context(struct anv_device *device, int context);
int anv_gem_get_param(int fd, uint32_t param);
int anv_gem_get_aperture(struct anv_physical_device *physical_dev, uint64_t *size);
int anv_gem_handle_to_fd(struct anv_device *device, int gem_handle);
int anv_gem_fd_to_handle(struct anv_device *device, int fd);
int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size);
struct anv_reloc_list {
size_t num_relocs;
size_t array_length;
struct drm_i915_gem_relocation_entry * relocs;
struct anv_bo ** reloc_bos;
};
VkResult anv_reloc_list_init(struct anv_reloc_list *list,
struct anv_device *device);
void anv_reloc_list_finish(struct anv_reloc_list *list,
struct anv_device *device);
struct anv_batch_bo {
struct anv_bo bo;
/* Bytes actually consumed in this batch BO */
size_t length;
/* These offsets reference the per-batch reloc list */
size_t first_reloc;
size_t num_relocs;
struct anv_batch_bo * prev_batch_bo;
};
struct anv_batch {
struct anv_device * device;
void * start;
void * end;
void * next;
struct anv_reloc_list relocs;
/* This callback is called (with the associated user data) in the event
* that the batch runs out of space.
*/
VkResult (*extend_cb)(struct anv_batch *, void *);
void * user_data;
};
void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords);
void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);
uint64_t anv_batch_emit_reloc(struct anv_batch *batch,
void *location, struct anv_bo *bo, uint32_t offset);
struct anv_address {
struct anv_bo *bo;
uint32_t offset;
};
#define __gen_address_type struct anv_address
#define __gen_user_data struct anv_batch
static inline uint64_t
__gen_combine_address(struct anv_batch *batch, void *location,
const struct anv_address address, uint32_t delta)
{
if (address.bo == NULL) {
return delta;
} else {
assert(batch->start <= location && location < batch->end);
return anv_batch_emit_reloc(batch, location, address.bo, address.offset + delta);
}
}
#include "gen7_pack.h"
#include "gen75_pack.h"
#undef GEN8_3DSTATE_MULTISAMPLE
#include "gen8_pack.h"
#define anv_batch_emit(batch, cmd, ...) do { \
struct cmd __template = { \
cmd ## _header, \
__VA_ARGS__ \
}; \
void *__dst = anv_batch_emit_dwords(batch, cmd ## _length); \
cmd ## _pack(batch, __dst, &__template); \
} while (0)
#define anv_batch_emitn(batch, n, cmd, ...) ({ \
struct cmd __template = { \
cmd ## _header, \
.DwordLength = n - cmd ## _length_bias, \
__VA_ARGS__ \
}; \
void *__dst = anv_batch_emit_dwords(batch, n); \
cmd ## _pack(batch, __dst, &__template); \
__dst; \
})
#define anv_batch_emit_merge(batch, dwords0, dwords1) \
do { \
uint32_t *dw; \
\
assert(ARRAY_SIZE(dwords0) == ARRAY_SIZE(dwords1)); \
dw = anv_batch_emit_dwords((batch), ARRAY_SIZE(dwords0)); \
for (uint32_t i = 0; i < ARRAY_SIZE(dwords0); i++) \
dw[i] = (dwords0)[i] | (dwords1)[i]; \
VG(VALGRIND_CHECK_MEM_IS_DEFINED(dw, ARRAY_SIZE(dwords0) * 4));\
} while (0)
#define GEN8_MOCS { \
.MemoryTypeLLCeLLCCacheabilityControl = WB, \
.TargetCache = L3DefertoPATforLLCeLLCselection, \
.AgeforQUADLRU = 0 \
}
struct anv_device_memory {
struct anv_bo bo;
VkDeviceSize map_size;
void * map;
};
struct anv_dynamic_vp_state {
struct anv_object base;
struct anv_state sf_clip_vp;
struct anv_state cc_vp;
struct anv_state scissor;
};
struct anv_dynamic_rs_state {
uint32_t state_sf[GEN8_3DSTATE_SF_length];
uint32_t state_raster[GEN8_3DSTATE_RASTER_length];
};
struct anv_dynamic_ds_state {
uint32_t state_wm_depth_stencil[GEN8_3DSTATE_WM_DEPTH_STENCIL_length];
uint32_t state_color_calc[GEN8_COLOR_CALC_STATE_length];
};
struct anv_dynamic_cb_state {
uint32_t state_color_calc[GEN8_COLOR_CALC_STATE_length];
};
struct anv_descriptor_slot {
int8_t dynamic_slot;
uint8_t index;
};
struct anv_descriptor_set_layout {
struct {
uint32_t surface_count;
struct anv_descriptor_slot *surface_start;
uint32_t sampler_count;
struct anv_descriptor_slot *sampler_start;
} stage[VK_SHADER_STAGE_NUM];
uint32_t count;
uint32_t num_dynamic_buffers;
uint32_t shader_stages;
struct anv_descriptor_slot entries[0];
};
struct anv_descriptor {
struct anv_sampler *sampler;
struct anv_surface_view *view;
};
struct anv_descriptor_set {
struct anv_descriptor descriptors[0];
};
#define MAX_VBS 32
#define MAX_SETS 8
#define MAX_RTS 8
struct anv_pipeline_layout {
struct {
struct anv_descriptor_set_layout *layout;
uint32_t surface_start[VK_SHADER_STAGE_NUM];
uint32_t sampler_start[VK_SHADER_STAGE_NUM];
} set[MAX_SETS];
uint32_t num_sets;
struct {
uint32_t surface_count;
uint32_t sampler_count;
} stage[VK_SHADER_STAGE_NUM];
};
struct anv_buffer {
struct anv_device * device;
VkDeviceSize size;
/* Set when bound */
struct anv_bo * bo;
VkDeviceSize offset;
};
#define ANV_CMD_BUFFER_PIPELINE_DIRTY (1 << 0)
#define ANV_CMD_BUFFER_RS_DIRTY (1 << 2)
#define ANV_CMD_BUFFER_DS_DIRTY (1 << 3)
#define ANV_CMD_BUFFER_CB_DIRTY (1 << 4)
#define ANV_CMD_BUFFER_VP_DIRTY (1 << 5)
#define ANV_CMD_BUFFER_INDEX_BUFFER_DIRTY (1 << 6)
struct anv_vertex_binding {
struct anv_buffer * buffer;
VkDeviceSize offset;
};
struct anv_descriptor_set_binding {
struct anv_descriptor_set * set;
uint32_t dynamic_offsets[128];
};
struct anv_cmd_buffer {
struct anv_object base;
struct anv_device * device;
struct drm_i915_gem_execbuffer2 execbuf;
struct drm_i915_gem_exec_object2 * exec2_objects;
struct anv_bo ** exec2_bos;
uint32_t exec2_array_length;
bool need_reloc;
uint32_t serial;
uint32_t bo_count;
struct anv_batch batch;
struct anv_batch_bo * last_batch_bo;
struct anv_batch_bo * surface_batch_bo;
uint32_t surface_next;
struct anv_reloc_list surface_relocs;
struct anv_state_stream surface_state_stream;
struct anv_state_stream dynamic_state_stream;
/* State required while building cmd buffer */
uint32_t current_pipeline;
uint32_t vb_dirty;
uint32_t dirty;
uint32_t compute_dirty;
uint32_t descriptors_dirty;
uint32_t scratch_size;
struct anv_pipeline * pipeline;
struct anv_pipeline * compute_pipeline;
struct anv_framebuffer * framebuffer;
struct anv_dynamic_rs_state * rs_state;
struct anv_dynamic_ds_state * ds_state;
struct anv_dynamic_vp_state * vp_state;
struct anv_dynamic_cb_state * cb_state;
uint32_t state_vf[GEN8_3DSTATE_VF_length];
struct anv_vertex_binding vertex_bindings[MAX_VBS];
struct anv_descriptor_set_binding descriptors[MAX_SETS];
};
void anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer);
void anv_aub_writer_destroy(struct anv_aub_writer *writer);
struct anv_fence {
struct anv_object base;
struct anv_bo bo;
struct drm_i915_gem_execbuffer2 execbuf;
struct drm_i915_gem_exec_object2 exec2_objects[1];
bool ready;
};
struct anv_shader_module {
uint32_t size;
char data[0];
};
struct anv_shader {
struct anv_shader_module * module;
char entrypoint[0];
};
struct anv_pipeline {
struct anv_object base;
struct anv_device * device;
struct anv_batch batch;
uint32_t batch_data[256];
struct anv_shader * shaders[VK_SHADER_STAGE_NUM];
struct anv_pipeline_layout * layout;
bool use_repclear;
struct brw_vs_prog_data vs_prog_data;
struct brw_wm_prog_data wm_prog_data;
struct brw_gs_prog_data gs_prog_data;
struct brw_cs_prog_data cs_prog_data;
bool writes_point_size;
struct brw_stage_prog_data * prog_data[VK_SHADER_STAGE_NUM];
uint32_t scratch_start[VK_SHADER_STAGE_NUM];
uint32_t total_scratch;
struct {
uint32_t vs_start;
uint32_t vs_size;
uint32_t nr_vs_entries;
uint32_t gs_start;
uint32_t gs_size;
uint32_t nr_gs_entries;
} urb;
uint32_t active_stages;
struct anv_state_stream program_stream;
struct anv_state blend_state;
uint32_t vs_simd8;
uint32_t ps_simd8;
uint32_t ps_simd16;
uint32_t gs_vec4;
uint32_t gs_vertex_count;
uint32_t cs_simd;
uint32_t vb_used;
uint32_t binding_stride[MAX_VBS];
uint32_t state_sf[GEN8_3DSTATE_SF_length];
uint32_t state_vf[GEN8_3DSTATE_VF_length];
uint32_t state_raster[GEN8_3DSTATE_RASTER_length];
uint32_t state_wm_depth_stencil[GEN8_3DSTATE_WM_DEPTH_STENCIL_length];
uint32_t cs_thread_width_max;
uint32_t cs_right_mask;
};
struct anv_pipeline_create_info {
bool use_repclear;
bool disable_viewport;
bool disable_scissor;
bool disable_vs;
bool use_rectlist;
};
VkResult
anv_pipeline_create(VkDevice device,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const struct anv_pipeline_create_info *extra,
VkPipeline *pPipeline);
struct anv_compiler *anv_compiler_create(struct anv_device *device);
void anv_compiler_destroy(struct anv_compiler *compiler);
int anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline);
void anv_compiler_free(struct anv_pipeline *pipeline);
struct anv_format {
const char *name;
uint16_t surface_format; /**< RENDER_SURFACE_STATE.SurfaceFormat */
uint8_t cpp; /**< Bytes-per-pixel of anv_format::surface_format. */
uint8_t num_channels;
uint8_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */
bool has_stencil;
};
const struct anv_format *
anv_format_for_vk_format(VkFormat format);
/**
* A proxy for the color surfaces, depth surfaces, and stencil surfaces.
*/
struct anv_surface {
/**
* Offset from VkImage's base address, as bound by vkBindImageMemory().
*/
uint32_t offset;
uint32_t stride; /**< RENDER_SURFACE_STATE.SurfacePitch */
uint16_t qpitch; /**< RENDER_SURFACE_STATE.QPitch */
/**
* \name Alignment of miptree images, in units of pixels.
*
* These fields contain the real alignment values, not the values to be
* given to the GPU. For example, if h_align is 4, then program the GPU
* with HALIGN_4.
* \{
*/
uint8_t h_align; /**< RENDER_SURFACE_STATE.SurfaceHorizontalAlignment */
uint8_t v_align; /**< RENDER_SURFACE_STATE.SurfaceVerticalAlignment */
/** \} */
uint8_t tile_mode; /**< RENDER_SURFACE_STATE.TileMode */
};
struct anv_image {
VkImageType type;
VkExtent3D extent;
VkFormat format;
uint32_t levels;
uint32_t array_size;
VkDeviceSize size;
uint32_t alignment;
/* Set when bound */
struct anv_bo *bo;
VkDeviceSize offset;
struct anv_swap_chain *swap_chain;
/** RENDER_SURFACE_STATE.SurfaceType */
uint8_t surf_type;
/** Primary surface is either color or depth. */
struct anv_surface primary_surface;
/** Stencil surface is optional. */
struct anv_surface stencil_surface;
};
struct anv_surface_view {
struct anv_state surface_state;
struct anv_bo * bo;
uint32_t offset;
uint32_t range;
VkExtent3D extent;
VkFormat format;
};
struct anv_image_create_info {
const VkImageCreateInfo *vk_info;
bool force_tile_mode;
uint8_t tile_mode;
};
VkResult anv_image_create(VkDevice _device,
const struct anv_image_create_info *info,
VkImage *pImage);
void anv_image_view_init(struct anv_surface_view *view,
struct anv_device *device,
const VkImageViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer);
void anv_color_attachment_view_init(struct anv_surface_view *view,
struct anv_device *device,
const VkColorAttachmentViewCreateInfo* pCreateInfo,
struct anv_cmd_buffer *cmd_buffer);
void anv_surface_view_destroy(struct anv_device *device,
struct anv_surface_view *view);
struct anv_sampler {
uint32_t state[4];
};
struct anv_depth_stencil_view {
struct anv_bo *bo;
uint32_t depth_offset; /**< Offset into bo. */
uint32_t depth_stride; /**< 3DSTATE_DEPTH_BUFFER.SurfacePitch */
uint32_t depth_format; /**< 3DSTATE_DEPTH_BUFFER.SurfaceFormat */
uint16_t depth_qpitch; /**< 3DSTATE_DEPTH_BUFFER.SurfaceQPitch */
uint32_t stencil_offset; /**< Offset into bo. */
uint32_t stencil_stride; /**< 3DSTATE_STENCIL_BUFFER.SurfacePitch */
uint16_t stencil_qpitch; /**< 3DSTATE_STENCIL_BUFFER.SurfaceQPitch */
};
struct anv_framebuffer {
struct anv_object base;
uint32_t color_attachment_count;
const struct anv_surface_view * color_attachments[MAX_RTS];
const struct anv_depth_stencil_view * depth_stencil;
uint32_t sample_count;
uint32_t width;
uint32_t height;
uint32_t layers;
/* Viewport for clears */
VkDynamicVpState vp_state;
};
struct anv_render_pass_layer {
VkAttachmentLoadOp color_load_op;
VkClearColorValue clear_color;
};
struct anv_render_pass {
VkRect2D render_area;
uint32_t num_clear_layers;
uint32_t num_layers;
struct anv_render_pass_layer layers[0];
};
void anv_device_init_meta(struct anv_device *device);
void anv_device_finish_meta(struct anv_device *device);
void
anv_cmd_buffer_clear(struct anv_cmd_buffer *cmd_buffer,
struct anv_render_pass *pass);
void *
anv_lookup_entrypoint(const char *name);
VkResult anv_DestroyImage(VkDevice device, VkImage image);
VkResult anv_DestroyImageView(VkDevice device, VkImageView imageView);
VkResult anv_DestroyBufferView(VkDevice device, VkBufferView bufferView);
VkResult anv_DestroyColorAttachmentView(VkDevice device,
VkColorAttachmentView view);
VkResult anv_DestroyDepthStencilView(VkDevice device, VkDepthStencilView view);
VkResult anv_DestroyRenderPass(VkDevice device, VkRenderPass renderPass);
#define ANV_DEFINE_CASTS(__anv_type, __VkType) \
static inline struct __anv_type * \
__anv_type ## _from_handle(__VkType _handle) \
{ \
return (struct __anv_type *) _handle; \
} \
\
static inline __VkType \
__anv_type ## _to_handle(struct __anv_type *_obj) \
{ \
return (__VkType) _obj; \
}
ANV_DEFINE_CASTS(anv_physical_device, VkPhysicalDevice)
ANV_DEFINE_CASTS(anv_instance, VkInstance)
ANV_DEFINE_CASTS(anv_queue, VkQueue)
ANV_DEFINE_CASTS(anv_device, VkDevice)
ANV_DEFINE_CASTS(anv_device_memory, VkDeviceMemory)
ANV_DEFINE_CASTS(anv_dynamic_vp_state, VkDynamicVpState)
ANV_DEFINE_CASTS(anv_dynamic_rs_state, VkDynamicRsState)
ANV_DEFINE_CASTS(anv_dynamic_ds_state, VkDynamicDsState)
ANV_DEFINE_CASTS(anv_dynamic_cb_state, VkDynamicCbState)
ANV_DEFINE_CASTS(anv_descriptor_set_layout, VkDescriptorSetLayout)
ANV_DEFINE_CASTS(anv_descriptor_set, VkDescriptorSet)
ANV_DEFINE_CASTS(anv_pipeline_layout, VkPipelineLayout)
ANV_DEFINE_CASTS(anv_buffer, VkBuffer)
ANV_DEFINE_CASTS(anv_cmd_buffer, VkCmdBuffer)
ANV_DEFINE_CASTS(anv_fence, VkFence)
ANV_DEFINE_CASTS(anv_shader_module, VkShaderModule)
ANV_DEFINE_CASTS(anv_shader, VkShader)
ANV_DEFINE_CASTS(anv_pipeline, VkPipeline)
ANV_DEFINE_CASTS(anv_image, VkImage)
ANV_DEFINE_CASTS(anv_sampler, VkSampler)
ANV_DEFINE_CASTS(anv_depth_stencil_view, VkDepthStencilView)
ANV_DEFINE_CASTS(anv_framebuffer, VkFramebuffer)
ANV_DEFINE_CASTS(anv_render_pass, VkRenderPass)
ANV_DEFINE_CASTS(anv_query_pool, VkQueryPool)
#define ANV_FROM_HANDLE(__anv_type, __name, __handle) \
struct __anv_type *__name = __anv_type ## _from_handle(__handle)
#ifdef __cplusplus
}
#endif

356
src/vulkan/query.c Normal file
View File

@@ -0,0 +1,356 @@
/*
* 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 "private.h"
struct anv_query_pool_slot {
uint64_t begin;
uint64_t end;
uint64_t available;
};
struct anv_query_pool {
struct anv_object base;
VkQueryType type;
uint32_t slots;
struct anv_bo bo;
};
static void
anv_query_pool_destroy(struct anv_device *device,
struct anv_object *object,
VkObjectType obj_type)
{
struct anv_query_pool *pool = (struct anv_query_pool *) object;
assert(obj_type == VK_OBJECT_TYPE_QUERY_POOL);
anv_gem_munmap(pool->bo.map, pool->bo.size);
anv_gem_close(device, pool->bo.gem_handle);
anv_device_free(device, pool);
}
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);
pool->base.destructor = anv_query_pool_destroy;
pool->type = pCreateInfo->queryType;
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_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_error(VK_ERROR_UNKNOWN);
}
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;
}
static void
anv_batch_emit_ps_depth_count(struct anv_batch *batch,
struct anv_bo *bo, uint32_t offset)
{
anv_batch_emit(batch, GEN8_PIPE_CONTROL,
.DestinationAddressType = DAT_PPGTT,
.PostSyncOperation = WritePSDepthCount,
.Address = { bo, offset }); /* FIXME: This is only lower 32 bits */
}
void anv_CmdBeginQuery(
VkCmdBuffer cmdBuffer,
VkQueryPool queryPool,
uint32_t slot,
VkQueryControlFlags flags)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
switch (pool->type) {
case VK_QUERY_TYPE_OCCLUSION:
anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
slot * sizeof(struct anv_query_pool_slot));
break;
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
default:
unreachable("");
}
}
void anv_CmdEndQuery(
VkCmdBuffer cmdBuffer,
VkQueryPool queryPool,
uint32_t slot)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
switch (pool->type) {
case VK_QUERY_TYPE_OCCLUSION:
anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
slot * sizeof(struct anv_query_pool_slot) + 8);
break;
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
default:
unreachable("");
}
}
void anv_CmdResetQueryPool(
VkCmdBuffer cmdBuffer,
VkQueryPool queryPool,
uint32_t startQuery,
uint32_t queryCount)
{
stub();
}
#define TIMESTAMP 0x2358
void anv_CmdWriteTimestamp(
VkCmdBuffer cmdBuffer,
VkTimestampType timestampType,
VkBuffer destBuffer,
VkDeviceSize destOffset)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
struct anv_bo *bo = buffer->bo;
switch (timestampType) {
case VK_TIMESTAMP_TYPE_TOP:
anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
.RegisterAddress = TIMESTAMP,
.MemoryAddress = { bo, buffer->offset + destOffset });
anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
.RegisterAddress = TIMESTAMP + 4,
.MemoryAddress = { bo, buffer->offset + destOffset + 4 });
break;
case VK_TIMESTAMP_TYPE_BOTTOM:
anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
.DestinationAddressType = DAT_PPGTT,
.PostSyncOperation = WriteTimestamp,
.Address = /* FIXME: This is only lower 32 bits */
{ bo, buffer->offset + destOffset });
break;
default:
break;
}
}
#define alu_opcode(v) __gen_field((v), 20, 31)
#define alu_operand1(v) __gen_field((v), 10, 19)
#define alu_operand2(v) __gen_field((v), 0, 9)
#define alu(opcode, operand1, operand2) \
alu_opcode(opcode) | alu_operand1(operand1) | alu_operand2(operand2)
#define OPCODE_NOOP 0x000
#define OPCODE_LOAD 0x080
#define OPCODE_LOADINV 0x480
#define OPCODE_LOAD0 0x081
#define OPCODE_LOAD1 0x481
#define OPCODE_ADD 0x100
#define OPCODE_SUB 0x101
#define OPCODE_AND 0x102
#define OPCODE_OR 0x103
#define OPCODE_XOR 0x104
#define OPCODE_STORE 0x180
#define OPCODE_STOREINV 0x580
#define OPERAND_R0 0x00
#define OPERAND_R1 0x01
#define OPERAND_R2 0x02
#define OPERAND_R3 0x03
#define OPERAND_R4 0x04
#define OPERAND_SRCA 0x20
#define OPERAND_SRCB 0x21
#define OPERAND_ACCU 0x31
#define OPERAND_ZF 0x32
#define OPERAND_CF 0x33
#define CS_GPR(n) (0x2600 + (n) * 8)
static void
emit_load_alu_reg_u64(struct anv_batch *batch, uint32_t reg,
struct anv_bo *bo, uint32_t offset)
{
anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
.RegisterAddress = reg,
.MemoryAddress = { bo, offset });
anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
.RegisterAddress = reg + 4,
.MemoryAddress = { bo, offset + 4 });
}
void anv_CmdCopyQueryPoolResults(
VkCmdBuffer cmdBuffer,
VkQueryPool queryPool,
uint32_t startQuery,
uint32_t queryCount,
VkBuffer destBuffer,
VkDeviceSize destOffset,
VkDeviceSize destStride,
VkQueryResultFlags flags)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, cmdBuffer);
ANV_FROM_HANDLE(anv_query_pool, pool, queryPool);
ANV_FROM_HANDLE(anv_buffer, buffer, destBuffer);
uint32_t slot_offset, dst_offset;
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;
}
assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
/* FIXME: If we're not waiting, should we just do this on the CPU? */
if (flags & VK_QUERY_RESULT_WAIT_BIT)
anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
.CommandStreamerStallEnable = true,
.StallAtPixelScoreboard = true);
dst_offset = buffer->offset + destOffset;
for (uint32_t i = 0; i < queryCount; i++) {
slot_offset = (startQuery + i) * sizeof(struct anv_query_pool_slot);
emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(0), &pool->bo, slot_offset);
emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(1), &pool->bo, slot_offset + 8);
/* FIXME: We need to clamp the result for 32 bit. */
uint32_t *dw = anv_batch_emitn(&cmd_buffer->batch, 5, GEN8_MI_MATH);
dw[1] = alu(OPCODE_LOAD, OPERAND_SRCA, OPERAND_R1);
dw[2] = alu(OPCODE_LOAD, OPERAND_SRCB, OPERAND_R0);
dw[3] = alu(OPCODE_SUB, 0, 0);
dw[4] = alu(OPCODE_STORE, OPERAND_R2, OPERAND_ACCU);
anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
.RegisterAddress = CS_GPR(2),
/* FIXME: This is only lower 32 bits */
.MemoryAddress = { buffer->bo, dst_offset });
if (flags & VK_QUERY_RESULT_64_BIT)
anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
.RegisterAddress = CS_GPR(2) + 4,
/* FIXME: This is only lower 32 bits */
.MemoryAddress = { buffer->bo, dst_offset + 4 });
dst_offset += destStride;
}
}

151
src/vulkan/util.c Normal file
View File

@@ -0,0 +1,151 @@
/*
* 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 "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();
}
int
anv_vector_init(struct anv_vector *vector, uint32_t element_size, uint32_t size)
{
assert(is_power_of_two(size));
assert(element_size < size && 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;
}

269
src/vulkan/vk_gen.py Normal file
View File

@@ -0,0 +1,269 @@
# 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:
for type, name, args, num, h in entrypoints:
print "%s anv_%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.
*/
/* This file generated from vk_gen.py, don't edit directly. */
#include "private.h"
struct anv_entrypoint {
uint32_t name;
uint32_t hash;
void *function;
void *validate;
};
/* 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.
*/
"""
for type, name, args, num, h in entrypoints:
print "%s anv_validate_%s%s __attribute__ ((weak));" % (type, name, args)
# 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, anv_%s, anv_validate_%s }," % (offsets[num], h, name, 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 void * __attribute__ ((noinline))
resolve_entrypoint(uint32_t index)
{
if (enable_validate && entrypoints[index].validate)
return entrypoints[index].validate;
return entrypoints[index].function;
}
"""
# 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 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 resolve_entrypoint(i);
}
""" % (prime_factor, prime_step, hash_mask)

294
src/vulkan/x11.c Normal file
View File

@@ -0,0 +1,294 @@
/*
* 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 "private.h"
#include <xcb/xcb.h>
#include <xcb/dri3.h>
#include <xcb/present.h>
static const VkFormat formats[] = {
VK_FORMAT_B5G6R5_UNORM,
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_B8G8R8A8_SRGB,
};
VkResult anv_GetDisplayInfoWSI(
VkDisplayWSI display,
VkDisplayInfoTypeWSI infoType,
size_t* pDataSize,
void* pData)
{
VkDisplayFormatPropertiesWSI *properties = pData;
size_t size;
if (pDataSize == NULL)
return VK_ERROR_INVALID_POINTER;
switch (infoType) {
case VK_DISPLAY_INFO_TYPE_FORMAT_PROPERTIES_WSI:
size = sizeof(properties[0]) * ARRAY_SIZE(formats);
if (pData == NULL) {
*pDataSize = size;
return VK_SUCCESS;
}
if (*pDataSize < size)
return vk_error(VK_ERROR_INVALID_VALUE);
*pDataSize = size;
for (uint32_t i = 0; i < ARRAY_SIZE(formats); i++)
properties[i].swapChainFormat = formats[i];
return VK_SUCCESS;
default:
return VK_UNSUPPORTED;
}
}
struct anv_swap_chain {
struct anv_device * device;
xcb_connection_t * conn;
xcb_window_t window;
xcb_gc_t gc;
VkExtent2D extent;
uint32_t count;
struct {
struct anv_image * image;
struct anv_device_memory * memory;
xcb_pixmap_t pixmap;
} images[0];
};
VkResult anv_CreateSwapChainWSI(
VkDevice _device,
const VkSwapChainCreateInfoWSI* pCreateInfo,
VkSwapChainWSI* pSwapChain)
{
struct anv_device *device = (struct anv_device *) _device;
struct anv_swap_chain *chain;
xcb_void_cookie_t cookie;
VkResult result;
size_t size;
int ret;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI);
size = sizeof(*chain) + pCreateInfo->imageCount * 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->device = device;
chain->conn = (xcb_connection_t *) pCreateInfo->pNativeWindowSystemHandle;
chain->window = (xcb_window_t) (uintptr_t) pCreateInfo->pNativeWindowHandle;
chain->count = pCreateInfo->imageCount;
chain->extent = pCreateInfo->imageExtent;
for (uint32_t i = 0; i < chain->count; i++) {
struct anv_image *image;
struct anv_surface *surface;
struct anv_device_memory *memory;
anv_image_create((VkDevice) device,
&(struct anv_image_create_info) {
.force_tile_mode = true,
.tile_mode = XMAJOR,
.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,
}},
(VkImage *) &image);
surface = &image->primary_surface;
anv_AllocMemory((VkDevice) device,
&(VkMemoryAllocInfo) {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOC_INFO,
.allocationSize = image->size,
.memoryTypeIndex = 0,
},
(VkDeviceMemory *) &memory);
anv_BindObjectMemory(VK_NULL_HANDLE,
VK_OBJECT_TYPE_IMAGE,
(VkImage) image,
(VkDeviceMemory) memory, 0);
ret = anv_gem_set_tiling(device, memory->bo.gem_handle,
surface->stride, I915_TILING_X);
if (ret) {
result = vk_error(VK_ERROR_UNKNOWN);
goto fail;
}
int fd = anv_gem_handle_to_fd(device, memory->bo.gem_handle);
if (fd == -1) {
result = vk_error(VK_ERROR_UNKNOWN);
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;
image->swap_chain = chain;
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);
*pSwapChain = (VkSwapChainWSI) chain;
return VK_SUCCESS;
fail:
return result;
}
VkResult anv_DestroySwapChainWSI(
VkSwapChainWSI swapChain)
{
struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
struct anv_device *device = chain->device;
anv_device_free(device, chain);
return VK_SUCCESS;
}
VkResult anv_GetSwapChainInfoWSI(
VkSwapChainWSI swapChain,
VkSwapChainInfoTypeWSI infoType,
size_t* pDataSize,
void* pData)
{
struct anv_swap_chain *chain = (struct anv_swap_chain *) swapChain;
VkSwapChainImageInfoWSI *images;
size_t size;
switch (infoType) {
case VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI:
size = sizeof(*images) * chain->count;
if (pData && *pDataSize < size)
return VK_ERROR_INVALID_VALUE;
*pDataSize = size;
if (!pData)
return VK_SUCCESS;
images = pData;
for (uint32_t i = 0; i < chain->count; i++) {
images[i].image = (VkImage) chain->images[i].image;
images[i].memory = (VkDeviceMemory) chain->images[i].memory;
}
return VK_SUCCESS;
default:
return VK_UNSUPPORTED;
}
}
VkResult anv_QueuePresentWSI(
VkQueue queue_,
const VkPresentInfoWSI* pPresentInfo)
{
struct anv_image *image = (struct anv_image *) pPresentInfo->image;
struct anv_swap_chain *chain = image->swap_chain;
xcb_void_cookie_t cookie;
xcb_pixmap_t pixmap;
assert(pPresentInfo->sType == VK_STRUCTURE_TYPE_PRESENT_INFO_WSI);
if (chain == NULL)
return vk_error(VK_ERROR_INVALID_VALUE);
pixmap = XCB_NONE;
for (uint32_t i = 0; i < chain->count; i++) {
if ((VkImage) chain->images[i].image == pPresentInfo->image) {
pixmap = chain->images[i].pixmap;
break;
}
}
if (pixmap == XCB_NONE)
return vk_error(VK_ERROR_INVALID_VALUE);
cookie = xcb_copy_area(chain->conn,
pixmap,
chain->window,
chain->gc,
0, 0,
0, 0,
chain->extent.width,
chain->extent.height);
xcb_discard_reply(chain->conn, cookie.sequence);
xcb_flush(chain->conn);
return VK_SUCCESS;
}