• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright (c) 2015-2016 The Khronos Group Inc.
4  * Copyright (c) 2015-2016 Valve Corporation
5  * Copyright (c) 2015-2016 LunarG, Inc.
6  * Copyright (C) 2016 Google Inc.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and/or associated documentation files (the "Materials"), to
10  * deal in the Materials without restriction, including without limitation the
11  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12  * sell copies of the Materials, and to permit persons to whom the Materials are
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice(s) and this permission notice shall be included in
16  * all copies or substantial portions of the Materials.
17  *
18  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  *
22  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
23  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
25  * USE OR OTHER DEALINGS IN THE MATERIALS.
26  *
27  * Author: Courtney Goeltzenleuchter <courtney@lunarg.com>
28  * Author: Jon Ashburn <jon@lunarg.com>
29  * Author: Ian Elliott <ian@LunarG.com>
30  * Author: Tony Barbour <tony@LunarG.com>
31  */
32 
33 #include <vulkan/vulkan.h>
34 #include <vulkan/vk_layer.h>
35 #include <string.h>
36 #include "loader.h"
37 #include "vk_loader_platform.h"
38 
vkDevExtError(VkDevice dev)39 static VkResult vkDevExtError(VkDevice dev) {
40     struct loader_device *found_dev;
41     struct loader_icd *icd = loader_get_icd_and_device(dev, &found_dev);
42 
43     if (icd)
44         loader_log(icd->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
45                    "Bad destination in loader trampoline dispatch,"
46                    "Are layers and extensions that you are calling enabled?");
47     return VK_ERROR_EXTENSION_NOT_PRESENT;
48 }
49 
50 static inline void
loader_init_device_dispatch_table(struct loader_dev_dispatch_table * dev_table,PFN_vkGetDeviceProcAddr gpa,VkDevice dev)51 loader_init_device_dispatch_table(struct loader_dev_dispatch_table *dev_table,
52                                   PFN_vkGetDeviceProcAddr gpa, VkDevice dev) {
53     VkLayerDispatchTable *table = &dev_table->core_dispatch;
54     for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++)
55         dev_table->ext_dispatch.DevExt[i] = (PFN_vkDevExt)vkDevExtError;
56 
57     table->GetDeviceProcAddr =
58         (PFN_vkGetDeviceProcAddr)gpa(dev, "vkGetDeviceProcAddr");
59     table->DestroyDevice = (PFN_vkDestroyDevice)gpa(dev, "vkDestroyDevice");
60     table->GetDeviceQueue = (PFN_vkGetDeviceQueue)gpa(dev, "vkGetDeviceQueue");
61     table->QueueSubmit = (PFN_vkQueueSubmit)gpa(dev, "vkQueueSubmit");
62     table->QueueWaitIdle = (PFN_vkQueueWaitIdle)gpa(dev, "vkQueueWaitIdle");
63     table->DeviceWaitIdle = (PFN_vkDeviceWaitIdle)gpa(dev, "vkDeviceWaitIdle");
64     table->AllocateMemory = (PFN_vkAllocateMemory)gpa(dev, "vkAllocateMemory");
65     table->FreeMemory = (PFN_vkFreeMemory)gpa(dev, "vkFreeMemory");
66     table->MapMemory = (PFN_vkMapMemory)gpa(dev, "vkMapMemory");
67     table->UnmapMemory = (PFN_vkUnmapMemory)gpa(dev, "vkUnmapMemory");
68     table->FlushMappedMemoryRanges =
69         (PFN_vkFlushMappedMemoryRanges)gpa(dev, "vkFlushMappedMemoryRanges");
70     table->InvalidateMappedMemoryRanges =
71         (PFN_vkInvalidateMappedMemoryRanges)gpa(
72             dev, "vkInvalidateMappedMemoryRanges");
73     table->GetDeviceMemoryCommitment = (PFN_vkGetDeviceMemoryCommitment)gpa(
74         dev, "vkGetDeviceMemoryCommitment");
75     table->GetImageSparseMemoryRequirements =
76         (PFN_vkGetImageSparseMemoryRequirements)gpa(
77             dev, "vkGetImageSparseMemoryRequirements");
78     table->GetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)gpa(
79         dev, "vkGetBufferMemoryRequirements");
80     table->GetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)gpa(
81         dev, "vkGetImageMemoryRequirements");
82     table->BindBufferMemory =
83         (PFN_vkBindBufferMemory)gpa(dev, "vkBindBufferMemory");
84     table->BindImageMemory =
85         (PFN_vkBindImageMemory)gpa(dev, "vkBindImageMemory");
86     table->QueueBindSparse =
87         (PFN_vkQueueBindSparse)gpa(dev, "vkQueueBindSparse");
88     table->CreateFence = (PFN_vkCreateFence)gpa(dev, "vkCreateFence");
89     table->DestroyFence = (PFN_vkDestroyFence)gpa(dev, "vkDestroyFence");
90     table->ResetFences = (PFN_vkResetFences)gpa(dev, "vkResetFences");
91     table->GetFenceStatus = (PFN_vkGetFenceStatus)gpa(dev, "vkGetFenceStatus");
92     table->WaitForFences = (PFN_vkWaitForFences)gpa(dev, "vkWaitForFences");
93     table->CreateSemaphore =
94         (PFN_vkCreateSemaphore)gpa(dev, "vkCreateSemaphore");
95     table->DestroySemaphore =
96         (PFN_vkDestroySemaphore)gpa(dev, "vkDestroySemaphore");
97     table->CreateEvent = (PFN_vkCreateEvent)gpa(dev, "vkCreateEvent");
98     table->DestroyEvent = (PFN_vkDestroyEvent)gpa(dev, "vkDestroyEvent");
99     table->GetEventStatus = (PFN_vkGetEventStatus)gpa(dev, "vkGetEventStatus");
100     table->SetEvent = (PFN_vkSetEvent)gpa(dev, "vkSetEvent");
101     table->ResetEvent = (PFN_vkResetEvent)gpa(dev, "vkResetEvent");
102     table->CreateQueryPool =
103         (PFN_vkCreateQueryPool)gpa(dev, "vkCreateQueryPool");
104     table->DestroyQueryPool =
105         (PFN_vkDestroyQueryPool)gpa(dev, "vkDestroyQueryPool");
106     table->GetQueryPoolResults =
107         (PFN_vkGetQueryPoolResults)gpa(dev, "vkGetQueryPoolResults");
108     table->CreateBuffer = (PFN_vkCreateBuffer)gpa(dev, "vkCreateBuffer");
109     table->DestroyBuffer = (PFN_vkDestroyBuffer)gpa(dev, "vkDestroyBuffer");
110     table->CreateBufferView =
111         (PFN_vkCreateBufferView)gpa(dev, "vkCreateBufferView");
112     table->DestroyBufferView =
113         (PFN_vkDestroyBufferView)gpa(dev, "vkDestroyBufferView");
114     table->CreateImage = (PFN_vkCreateImage)gpa(dev, "vkCreateImage");
115     table->DestroyImage = (PFN_vkDestroyImage)gpa(dev, "vkDestroyImage");
116     table->GetImageSubresourceLayout = (PFN_vkGetImageSubresourceLayout)gpa(
117         dev, "vkGetImageSubresourceLayout");
118     table->CreateImageView =
119         (PFN_vkCreateImageView)gpa(dev, "vkCreateImageView");
120     table->DestroyImageView =
121         (PFN_vkDestroyImageView)gpa(dev, "vkDestroyImageView");
122     table->CreateShaderModule =
123         (PFN_vkCreateShaderModule)gpa(dev, "vkCreateShaderModule");
124     table->DestroyShaderModule =
125         (PFN_vkDestroyShaderModule)gpa(dev, "vkDestroyShaderModule");
126     table->CreatePipelineCache =
127         (PFN_vkCreatePipelineCache)gpa(dev, "vkCreatePipelineCache");
128     table->DestroyPipelineCache =
129         (PFN_vkDestroyPipelineCache)gpa(dev, "vkDestroyPipelineCache");
130     table->GetPipelineCacheData =
131         (PFN_vkGetPipelineCacheData)gpa(dev, "vkGetPipelineCacheData");
132     table->MergePipelineCaches =
133         (PFN_vkMergePipelineCaches)gpa(dev, "vkMergePipelineCaches");
134     table->CreateGraphicsPipelines =
135         (PFN_vkCreateGraphicsPipelines)gpa(dev, "vkCreateGraphicsPipelines");
136     table->CreateComputePipelines =
137         (PFN_vkCreateComputePipelines)gpa(dev, "vkCreateComputePipelines");
138     table->DestroyPipeline =
139         (PFN_vkDestroyPipeline)gpa(dev, "vkDestroyPipeline");
140     table->CreatePipelineLayout =
141         (PFN_vkCreatePipelineLayout)gpa(dev, "vkCreatePipelineLayout");
142     table->DestroyPipelineLayout =
143         (PFN_vkDestroyPipelineLayout)gpa(dev, "vkDestroyPipelineLayout");
144     table->CreateSampler = (PFN_vkCreateSampler)gpa(dev, "vkCreateSampler");
145     table->DestroySampler = (PFN_vkDestroySampler)gpa(dev, "vkDestroySampler");
146     table->CreateDescriptorSetLayout = (PFN_vkCreateDescriptorSetLayout)gpa(
147         dev, "vkCreateDescriptorSetLayout");
148     table->DestroyDescriptorSetLayout = (PFN_vkDestroyDescriptorSetLayout)gpa(
149         dev, "vkDestroyDescriptorSetLayout");
150     table->CreateDescriptorPool =
151         (PFN_vkCreateDescriptorPool)gpa(dev, "vkCreateDescriptorPool");
152     table->DestroyDescriptorPool =
153         (PFN_vkDestroyDescriptorPool)gpa(dev, "vkDestroyDescriptorPool");
154     table->ResetDescriptorPool =
155         (PFN_vkResetDescriptorPool)gpa(dev, "vkResetDescriptorPool");
156     table->AllocateDescriptorSets =
157         (PFN_vkAllocateDescriptorSets)gpa(dev, "vkAllocateDescriptorSets");
158     table->FreeDescriptorSets =
159         (PFN_vkFreeDescriptorSets)gpa(dev, "vkFreeDescriptorSets");
160     table->UpdateDescriptorSets =
161         (PFN_vkUpdateDescriptorSets)gpa(dev, "vkUpdateDescriptorSets");
162     table->CreateFramebuffer =
163         (PFN_vkCreateFramebuffer)gpa(dev, "vkCreateFramebuffer");
164     table->DestroyFramebuffer =
165         (PFN_vkDestroyFramebuffer)gpa(dev, "vkDestroyFramebuffer");
166     table->CreateRenderPass =
167         (PFN_vkCreateRenderPass)gpa(dev, "vkCreateRenderPass");
168     table->DestroyRenderPass =
169         (PFN_vkDestroyRenderPass)gpa(dev, "vkDestroyRenderPass");
170     table->GetRenderAreaGranularity =
171         (PFN_vkGetRenderAreaGranularity)gpa(dev, "vkGetRenderAreaGranularity");
172     table->CreateCommandPool =
173         (PFN_vkCreateCommandPool)gpa(dev, "vkCreateCommandPool");
174     table->DestroyCommandPool =
175         (PFN_vkDestroyCommandPool)gpa(dev, "vkDestroyCommandPool");
176     table->ResetCommandPool =
177         (PFN_vkResetCommandPool)gpa(dev, "vkResetCommandPool");
178     table->AllocateCommandBuffers =
179         (PFN_vkAllocateCommandBuffers)gpa(dev, "vkAllocateCommandBuffers");
180     table->FreeCommandBuffers =
181         (PFN_vkFreeCommandBuffers)gpa(dev, "vkFreeCommandBuffers");
182     table->BeginCommandBuffer =
183         (PFN_vkBeginCommandBuffer)gpa(dev, "vkBeginCommandBuffer");
184     table->EndCommandBuffer =
185         (PFN_vkEndCommandBuffer)gpa(dev, "vkEndCommandBuffer");
186     table->ResetCommandBuffer =
187         (PFN_vkResetCommandBuffer)gpa(dev, "vkResetCommandBuffer");
188     table->CmdBindPipeline =
189         (PFN_vkCmdBindPipeline)gpa(dev, "vkCmdBindPipeline");
190     table->CmdSetViewport = (PFN_vkCmdSetViewport)gpa(dev, "vkCmdSetViewport");
191     table->CmdSetScissor = (PFN_vkCmdSetScissor)gpa(dev, "vkCmdSetScissor");
192     table->CmdSetLineWidth =
193         (PFN_vkCmdSetLineWidth)gpa(dev, "vkCmdSetLineWidth");
194     table->CmdSetDepthBias =
195         (PFN_vkCmdSetDepthBias)gpa(dev, "vkCmdSetDepthBias");
196     table->CmdSetBlendConstants =
197         (PFN_vkCmdSetBlendConstants)gpa(dev, "vkCmdSetBlendConstants");
198     table->CmdSetDepthBounds =
199         (PFN_vkCmdSetDepthBounds)gpa(dev, "vkCmdSetDepthBounds");
200     table->CmdSetStencilCompareMask =
201         (PFN_vkCmdSetStencilCompareMask)gpa(dev, "vkCmdSetStencilCompareMask");
202     table->CmdSetStencilWriteMask =
203         (PFN_vkCmdSetStencilWriteMask)gpa(dev, "vkCmdSetStencilWriteMask");
204     table->CmdSetStencilReference =
205         (PFN_vkCmdSetStencilReference)gpa(dev, "vkCmdSetStencilReference");
206     table->CmdBindDescriptorSets =
207         (PFN_vkCmdBindDescriptorSets)gpa(dev, "vkCmdBindDescriptorSets");
208     table->CmdBindVertexBuffers =
209         (PFN_vkCmdBindVertexBuffers)gpa(dev, "vkCmdBindVertexBuffers");
210     table->CmdBindIndexBuffer =
211         (PFN_vkCmdBindIndexBuffer)gpa(dev, "vkCmdBindIndexBuffer");
212     table->CmdDraw = (PFN_vkCmdDraw)gpa(dev, "vkCmdDraw");
213     table->CmdDrawIndexed = (PFN_vkCmdDrawIndexed)gpa(dev, "vkCmdDrawIndexed");
214     table->CmdDrawIndirect =
215         (PFN_vkCmdDrawIndirect)gpa(dev, "vkCmdDrawIndirect");
216     table->CmdDrawIndexedIndirect =
217         (PFN_vkCmdDrawIndexedIndirect)gpa(dev, "vkCmdDrawIndexedIndirect");
218     table->CmdDispatch = (PFN_vkCmdDispatch)gpa(dev, "vkCmdDispatch");
219     table->CmdDispatchIndirect =
220         (PFN_vkCmdDispatchIndirect)gpa(dev, "vkCmdDispatchIndirect");
221     table->CmdCopyBuffer = (PFN_vkCmdCopyBuffer)gpa(dev, "vkCmdCopyBuffer");
222     table->CmdCopyImage = (PFN_vkCmdCopyImage)gpa(dev, "vkCmdCopyImage");
223     table->CmdBlitImage = (PFN_vkCmdBlitImage)gpa(dev, "vkCmdBlitImage");
224     table->CmdCopyBufferToImage =
225         (PFN_vkCmdCopyBufferToImage)gpa(dev, "vkCmdCopyBufferToImage");
226     table->CmdCopyImageToBuffer =
227         (PFN_vkCmdCopyImageToBuffer)gpa(dev, "vkCmdCopyImageToBuffer");
228     table->CmdUpdateBuffer =
229         (PFN_vkCmdUpdateBuffer)gpa(dev, "vkCmdUpdateBuffer");
230     table->CmdFillBuffer = (PFN_vkCmdFillBuffer)gpa(dev, "vkCmdFillBuffer");
231     table->CmdClearColorImage =
232         (PFN_vkCmdClearColorImage)gpa(dev, "vkCmdClearColorImage");
233     table->CmdClearDepthStencilImage = (PFN_vkCmdClearDepthStencilImage)gpa(
234         dev, "vkCmdClearDepthStencilImage");
235     table->CmdClearAttachments =
236         (PFN_vkCmdClearAttachments)gpa(dev, "vkCmdClearAttachments");
237     table->CmdResolveImage =
238         (PFN_vkCmdResolveImage)gpa(dev, "vkCmdResolveImage");
239     table->CmdSetEvent = (PFN_vkCmdSetEvent)gpa(dev, "vkCmdSetEvent");
240     table->CmdResetEvent = (PFN_vkCmdResetEvent)gpa(dev, "vkCmdResetEvent");
241     table->CmdWaitEvents = (PFN_vkCmdWaitEvents)gpa(dev, "vkCmdWaitEvents");
242     table->CmdPipelineBarrier =
243         (PFN_vkCmdPipelineBarrier)gpa(dev, "vkCmdPipelineBarrier");
244     table->CmdBeginQuery = (PFN_vkCmdBeginQuery)gpa(dev, "vkCmdBeginQuery");
245     table->CmdEndQuery = (PFN_vkCmdEndQuery)gpa(dev, "vkCmdEndQuery");
246     table->CmdResetQueryPool =
247         (PFN_vkCmdResetQueryPool)gpa(dev, "vkCmdResetQueryPool");
248     table->CmdWriteTimestamp =
249         (PFN_vkCmdWriteTimestamp)gpa(dev, "vkCmdWriteTimestamp");
250     table->CmdCopyQueryPoolResults =
251         (PFN_vkCmdCopyQueryPoolResults)gpa(dev, "vkCmdCopyQueryPoolResults");
252     table->CmdPushConstants =
253         (PFN_vkCmdPushConstants)gpa(dev, "vkCmdPushConstants");
254     table->CmdBeginRenderPass =
255         (PFN_vkCmdBeginRenderPass)gpa(dev, "vkCmdBeginRenderPass");
256     table->CmdNextSubpass = (PFN_vkCmdNextSubpass)gpa(dev, "vkCmdNextSubpass");
257     table->CmdEndRenderPass =
258         (PFN_vkCmdEndRenderPass)gpa(dev, "vkCmdEndRenderPass");
259     table->CmdExecuteCommands =
260         (PFN_vkCmdExecuteCommands)gpa(dev, "vkCmdExecuteCommands");
261 }
262 
loader_init_device_extension_dispatch_table(struct loader_dev_dispatch_table * dev_table,PFN_vkGetDeviceProcAddr gpa,VkDevice dev)263 static inline void loader_init_device_extension_dispatch_table(
264     struct loader_dev_dispatch_table *dev_table, PFN_vkGetDeviceProcAddr gpa,
265     VkDevice dev) {
266     VkLayerDispatchTable *table = &dev_table->core_dispatch;
267     table->AcquireNextImageKHR =
268         (PFN_vkAcquireNextImageKHR)gpa(dev, "vkAcquireNextImageKHR");
269     table->CreateSwapchainKHR =
270         (PFN_vkCreateSwapchainKHR)gpa(dev, "vkCreateSwapchainKHR");
271     table->DestroySwapchainKHR =
272         (PFN_vkDestroySwapchainKHR)gpa(dev, "vkDestroySwapchainKHR");
273     table->GetSwapchainImagesKHR =
274         (PFN_vkGetSwapchainImagesKHR)gpa(dev, "vkGetSwapchainImagesKHR");
275     table->QueuePresentKHR =
276         (PFN_vkQueuePresentKHR)gpa(dev, "vkQueuePresentKHR");
277 }
278 
279 static inline void *
loader_lookup_device_dispatch_table(const VkLayerDispatchTable * table,const char * name)280 loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table,
281                                     const char *name) {
282     if (!name || name[0] != 'v' || name[1] != 'k')
283         return NULL;
284 
285     name += 2;
286     if (!strcmp(name, "GetDeviceProcAddr"))
287         return (void *)table->GetDeviceProcAddr;
288     if (!strcmp(name, "DestroyDevice"))
289         return (void *)table->DestroyDevice;
290     if (!strcmp(name, "GetDeviceQueue"))
291         return (void *)table->GetDeviceQueue;
292     if (!strcmp(name, "QueueSubmit"))
293         return (void *)table->QueueSubmit;
294     if (!strcmp(name, "QueueWaitIdle"))
295         return (void *)table->QueueWaitIdle;
296     if (!strcmp(name, "DeviceWaitIdle"))
297         return (void *)table->DeviceWaitIdle;
298     if (!strcmp(name, "AllocateMemory"))
299         return (void *)table->AllocateMemory;
300     if (!strcmp(name, "FreeMemory"))
301         return (void *)table->FreeMemory;
302     if (!strcmp(name, "MapMemory"))
303         return (void *)table->MapMemory;
304     if (!strcmp(name, "UnmapMemory"))
305         return (void *)table->UnmapMemory;
306     if (!strcmp(name, "FlushMappedMemoryRanges"))
307         return (void *)table->FlushMappedMemoryRanges;
308     if (!strcmp(name, "InvalidateMappedMemoryRanges"))
309         return (void *)table->InvalidateMappedMemoryRanges;
310     if (!strcmp(name, "GetDeviceMemoryCommitment"))
311         return (void *)table->GetDeviceMemoryCommitment;
312     if (!strcmp(name, "GetImageSparseMemoryRequirements"))
313         return (void *)table->GetImageSparseMemoryRequirements;
314     if (!strcmp(name, "GetBufferMemoryRequirements"))
315         return (void *)table->GetBufferMemoryRequirements;
316     if (!strcmp(name, "GetImageMemoryRequirements"))
317         return (void *)table->GetImageMemoryRequirements;
318     if (!strcmp(name, "BindBufferMemory"))
319         return (void *)table->BindBufferMemory;
320     if (!strcmp(name, "BindImageMemory"))
321         return (void *)table->BindImageMemory;
322     if (!strcmp(name, "QueueBindSparse"))
323         return (void *)table->QueueBindSparse;
324     if (!strcmp(name, "CreateFence"))
325         return (void *)table->CreateFence;
326     if (!strcmp(name, "DestroyFence"))
327         return (void *)table->DestroyFence;
328     if (!strcmp(name, "ResetFences"))
329         return (void *)table->ResetFences;
330     if (!strcmp(name, "GetFenceStatus"))
331         return (void *)table->GetFenceStatus;
332     if (!strcmp(name, "WaitForFences"))
333         return (void *)table->WaitForFences;
334     if (!strcmp(name, "CreateSemaphore"))
335         return (void *)table->CreateSemaphore;
336     if (!strcmp(name, "DestroySemaphore"))
337         return (void *)table->DestroySemaphore;
338     if (!strcmp(name, "CreateEvent"))
339         return (void *)table->CreateEvent;
340     if (!strcmp(name, "DestroyEvent"))
341         return (void *)table->DestroyEvent;
342     if (!strcmp(name, "GetEventStatus"))
343         return (void *)table->GetEventStatus;
344     if (!strcmp(name, "SetEvent"))
345         return (void *)table->SetEvent;
346     if (!strcmp(name, "ResetEvent"))
347         return (void *)table->ResetEvent;
348     if (!strcmp(name, "CreateQueryPool"))
349         return (void *)table->CreateQueryPool;
350     if (!strcmp(name, "DestroyQueryPool"))
351         return (void *)table->DestroyQueryPool;
352     if (!strcmp(name, "GetQueryPoolResults"))
353         return (void *)table->GetQueryPoolResults;
354     if (!strcmp(name, "CreateBuffer"))
355         return (void *)table->CreateBuffer;
356     if (!strcmp(name, "DestroyBuffer"))
357         return (void *)table->DestroyBuffer;
358     if (!strcmp(name, "CreateBufferView"))
359         return (void *)table->CreateBufferView;
360     if (!strcmp(name, "DestroyBufferView"))
361         return (void *)table->DestroyBufferView;
362     if (!strcmp(name, "CreateImage"))
363         return (void *)table->CreateImage;
364     if (!strcmp(name, "DestroyImage"))
365         return (void *)table->DestroyImage;
366     if (!strcmp(name, "GetImageSubresourceLayout"))
367         return (void *)table->GetImageSubresourceLayout;
368     if (!strcmp(name, "CreateImageView"))
369         return (void *)table->CreateImageView;
370     if (!strcmp(name, "DestroyImageView"))
371         return (void *)table->DestroyImageView;
372     if (!strcmp(name, "CreateShaderModule"))
373         return (void *)table->CreateShaderModule;
374     if (!strcmp(name, "DestroyShaderModule"))
375         return (void *)table->DestroyShaderModule;
376     if (!strcmp(name, "CreatePipelineCache"))
377         return (void *)vkCreatePipelineCache;
378     if (!strcmp(name, "DestroyPipelineCache"))
379         return (void *)vkDestroyPipelineCache;
380     if (!strcmp(name, "GetPipelineCacheData"))
381         return (void *)vkGetPipelineCacheData;
382     if (!strcmp(name, "MergePipelineCaches"))
383         return (void *)vkMergePipelineCaches;
384     if (!strcmp(name, "CreateGraphicsPipelines"))
385         return (void *)vkCreateGraphicsPipelines;
386     if (!strcmp(name, "CreateComputePipelines"))
387         return (void *)vkCreateComputePipelines;
388     if (!strcmp(name, "DestroyPipeline"))
389         return (void *)table->DestroyPipeline;
390     if (!strcmp(name, "CreatePipelineLayout"))
391         return (void *)table->CreatePipelineLayout;
392     if (!strcmp(name, "DestroyPipelineLayout"))
393         return (void *)table->DestroyPipelineLayout;
394     if (!strcmp(name, "CreateSampler"))
395         return (void *)table->CreateSampler;
396     if (!strcmp(name, "DestroySampler"))
397         return (void *)table->DestroySampler;
398     if (!strcmp(name, "CreateDescriptorSetLayout"))
399         return (void *)table->CreateDescriptorSetLayout;
400     if (!strcmp(name, "DestroyDescriptorSetLayout"))
401         return (void *)table->DestroyDescriptorSetLayout;
402     if (!strcmp(name, "CreateDescriptorPool"))
403         return (void *)table->CreateDescriptorPool;
404     if (!strcmp(name, "DestroyDescriptorPool"))
405         return (void *)table->DestroyDescriptorPool;
406     if (!strcmp(name, "ResetDescriptorPool"))
407         return (void *)table->ResetDescriptorPool;
408     if (!strcmp(name, "AllocateDescriptorSets"))
409         return (void *)table->AllocateDescriptorSets;
410     if (!strcmp(name, "FreeDescriptorSets"))
411         return (void *)table->FreeDescriptorSets;
412     if (!strcmp(name, "UpdateDescriptorSets"))
413         return (void *)table->UpdateDescriptorSets;
414     if (!strcmp(name, "CreateFramebuffer"))
415         return (void *)table->CreateFramebuffer;
416     if (!strcmp(name, "DestroyFramebuffer"))
417         return (void *)table->DestroyFramebuffer;
418     if (!strcmp(name, "CreateRenderPass"))
419         return (void *)table->CreateRenderPass;
420     if (!strcmp(name, "DestroyRenderPass"))
421         return (void *)table->DestroyRenderPass;
422     if (!strcmp(name, "GetRenderAreaGranularity"))
423         return (void *)table->GetRenderAreaGranularity;
424     if (!strcmp(name, "CreateCommandPool"))
425         return (void *)table->CreateCommandPool;
426     if (!strcmp(name, "DestroyCommandPool"))
427         return (void *)table->DestroyCommandPool;
428     if (!strcmp(name, "ResetCommandPool"))
429         return (void *)table->ResetCommandPool;
430     if (!strcmp(name, "AllocateCommandBuffers"))
431         return (void *)table->AllocateCommandBuffers;
432     if (!strcmp(name, "FreeCommandBuffers"))
433         return (void *)table->FreeCommandBuffers;
434     if (!strcmp(name, "BeginCommandBuffer"))
435         return (void *)table->BeginCommandBuffer;
436     if (!strcmp(name, "EndCommandBuffer"))
437         return (void *)table->EndCommandBuffer;
438     if (!strcmp(name, "ResetCommandBuffer"))
439         return (void *)table->ResetCommandBuffer;
440     if (!strcmp(name, "CmdBindPipeline"))
441         return (void *)table->CmdBindPipeline;
442     if (!strcmp(name, "CmdSetViewport"))
443         return (void *)table->CmdSetViewport;
444     if (!strcmp(name, "CmdSetScissor"))
445         return (void *)table->CmdSetScissor;
446     if (!strcmp(name, "CmdSetLineWidth"))
447         return (void *)table->CmdSetLineWidth;
448     if (!strcmp(name, "CmdSetDepthBias"))
449         return (void *)table->CmdSetDepthBias;
450     if (!strcmp(name, "CmdSetBlendConstants"))
451         return (void *)table->CmdSetBlendConstants;
452     if (!strcmp(name, "CmdSetDepthBounds"))
453         return (void *)table->CmdSetDepthBounds;
454     if (!strcmp(name, "CmdSetStencilCompareMask"))
455         return (void *)table->CmdSetStencilCompareMask;
456     if (!strcmp(name, "CmdSetStencilwriteMask"))
457         return (void *)table->CmdSetStencilWriteMask;
458     if (!strcmp(name, "CmdSetStencilReference"))
459         return (void *)table->CmdSetStencilReference;
460     if (!strcmp(name, "CmdBindDescriptorSets"))
461         return (void *)table->CmdBindDescriptorSets;
462     if (!strcmp(name, "CmdBindVertexBuffers"))
463         return (void *)table->CmdBindVertexBuffers;
464     if (!strcmp(name, "CmdBindIndexBuffer"))
465         return (void *)table->CmdBindIndexBuffer;
466     if (!strcmp(name, "CmdDraw"))
467         return (void *)table->CmdDraw;
468     if (!strcmp(name, "CmdDrawIndexed"))
469         return (void *)table->CmdDrawIndexed;
470     if (!strcmp(name, "CmdDrawIndirect"))
471         return (void *)table->CmdDrawIndirect;
472     if (!strcmp(name, "CmdDrawIndexedIndirect"))
473         return (void *)table->CmdDrawIndexedIndirect;
474     if (!strcmp(name, "CmdDispatch"))
475         return (void *)table->CmdDispatch;
476     if (!strcmp(name, "CmdDispatchIndirect"))
477         return (void *)table->CmdDispatchIndirect;
478     if (!strcmp(name, "CmdCopyBuffer"))
479         return (void *)table->CmdCopyBuffer;
480     if (!strcmp(name, "CmdCopyImage"))
481         return (void *)table->CmdCopyImage;
482     if (!strcmp(name, "CmdBlitImage"))
483         return (void *)table->CmdBlitImage;
484     if (!strcmp(name, "CmdCopyBufferToImage"))
485         return (void *)table->CmdCopyBufferToImage;
486     if (!strcmp(name, "CmdCopyImageToBuffer"))
487         return (void *)table->CmdCopyImageToBuffer;
488     if (!strcmp(name, "CmdUpdateBuffer"))
489         return (void *)table->CmdUpdateBuffer;
490     if (!strcmp(name, "CmdFillBuffer"))
491         return (void *)table->CmdFillBuffer;
492     if (!strcmp(name, "CmdClearColorImage"))
493         return (void *)table->CmdClearColorImage;
494     if (!strcmp(name, "CmdClearDepthStencilImage"))
495         return (void *)table->CmdClearDepthStencilImage;
496     if (!strcmp(name, "CmdClearAttachments"))
497         return (void *)table->CmdClearAttachments;
498     if (!strcmp(name, "CmdResolveImage"))
499         return (void *)table->CmdResolveImage;
500     if (!strcmp(name, "CmdSetEvent"))
501         return (void *)table->CmdSetEvent;
502     if (!strcmp(name, "CmdResetEvent"))
503         return (void *)table->CmdResetEvent;
504     if (!strcmp(name, "CmdWaitEvents"))
505         return (void *)table->CmdWaitEvents;
506     if (!strcmp(name, "CmdPipelineBarrier"))
507         return (void *)table->CmdPipelineBarrier;
508     if (!strcmp(name, "CmdBeginQuery"))
509         return (void *)table->CmdBeginQuery;
510     if (!strcmp(name, "CmdEndQuery"))
511         return (void *)table->CmdEndQuery;
512     if (!strcmp(name, "CmdResetQueryPool"))
513         return (void *)table->CmdResetQueryPool;
514     if (!strcmp(name, "CmdWriteTimestamp"))
515         return (void *)table->CmdWriteTimestamp;
516     if (!strcmp(name, "CmdCopyQueryPoolResults"))
517         return (void *)table->CmdCopyQueryPoolResults;
518     if (!strcmp(name, "CmdPushConstants"))
519         return (void *)table->CmdPushConstants;
520     if (!strcmp(name, "CmdBeginRenderPass"))
521         return (void *)table->CmdBeginRenderPass;
522     if (!strcmp(name, "CmdNextSubpass"))
523         return (void *)table->CmdNextSubpass;
524     if (!strcmp(name, "CmdEndRenderPass"))
525         return (void *)table->CmdEndRenderPass;
526     if (!strcmp(name, "CmdExecuteCommands"))
527         return (void *)table->CmdExecuteCommands;
528 
529     return NULL;
530 }
531 
532 static inline void
loader_init_instance_core_dispatch_table(VkLayerInstanceDispatchTable * table,PFN_vkGetInstanceProcAddr gpa,VkInstance inst)533 loader_init_instance_core_dispatch_table(VkLayerInstanceDispatchTable *table,
534                                          PFN_vkGetInstanceProcAddr gpa,
535                                          VkInstance inst) {
536     table->GetInstanceProcAddr =
537         (PFN_vkGetInstanceProcAddr)gpa(inst, "vkGetInstanceProcAddr");
538     table->DestroyInstance =
539         (PFN_vkDestroyInstance)gpa(inst, "vkDestroyInstance");
540     table->EnumeratePhysicalDevices =
541         (PFN_vkEnumeratePhysicalDevices)gpa(inst, "vkEnumeratePhysicalDevices");
542     table->GetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures)gpa(
543         inst, "vkGetPhysicalDeviceFeatures");
544     table->GetPhysicalDeviceImageFormatProperties =
545         (PFN_vkGetPhysicalDeviceImageFormatProperties)gpa(
546             inst, "vkGetPhysicalDeviceImageFormatProperties");
547     table->GetPhysicalDeviceFormatProperties =
548         (PFN_vkGetPhysicalDeviceFormatProperties)gpa(
549             inst, "vkGetPhysicalDeviceFormatProperties");
550     table->GetPhysicalDeviceSparseImageFormatProperties =
551         (PFN_vkGetPhysicalDeviceSparseImageFormatProperties)gpa(
552             inst, "vkGetPhysicalDeviceSparseImageFormatProperties");
553     table->GetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)gpa(
554         inst, "vkGetPhysicalDeviceProperties");
555     table->GetPhysicalDeviceQueueFamilyProperties =
556         (PFN_vkGetPhysicalDeviceQueueFamilyProperties)gpa(
557             inst, "vkGetPhysicalDeviceQueueFamilyProperties");
558     table->GetPhysicalDeviceMemoryProperties =
559         (PFN_vkGetPhysicalDeviceMemoryProperties)gpa(
560             inst, "vkGetPhysicalDeviceMemoryProperties");
561     table->EnumerateDeviceExtensionProperties =
562         (PFN_vkEnumerateDeviceExtensionProperties)gpa(
563             inst, "vkEnumerateDeviceExtensionProperties");
564     table->EnumerateDeviceLayerProperties =
565         (PFN_vkEnumerateDeviceLayerProperties)gpa(
566             inst, "vkEnumerateDeviceLayerProperties");
567 }
568 
loader_init_instance_extension_dispatch_table(VkLayerInstanceDispatchTable * table,PFN_vkGetInstanceProcAddr gpa,VkInstance inst)569 static inline void loader_init_instance_extension_dispatch_table(
570     VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,
571     VkInstance inst) {
572     table->DestroySurfaceKHR =
573         (PFN_vkDestroySurfaceKHR)gpa(inst, "vkDestroySurfaceKHR");
574     table->CreateDebugReportCallbackEXT =
575         (PFN_vkCreateDebugReportCallbackEXT)gpa(
576             inst, "vkCreateDebugReportCallbackEXT");
577     table->DestroyDebugReportCallbackEXT =
578         (PFN_vkDestroyDebugReportCallbackEXT)gpa(
579             inst, "vkDestroyDebugReportCallbackEXT");
580     table->DebugReportMessageEXT =
581         (PFN_vkDebugReportMessageEXT)gpa(inst, "vkDebugReportMessageEXT");
582     table->GetPhysicalDeviceSurfaceSupportKHR =
583         (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(
584             inst, "vkGetPhysicalDeviceSurfaceSupportKHR");
585     table->GetPhysicalDeviceSurfaceCapabilitiesKHR =
586         (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)gpa(
587             inst, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
588     table->GetPhysicalDeviceSurfaceFormatsKHR =
589         (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(
590             inst, "vkGetPhysicalDeviceSurfaceFormatsKHR");
591     table->GetPhysicalDeviceSurfacePresentModesKHR =
592         (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(
593             inst, "vkGetPhysicalDeviceSurfacePresentModesKHR");
594 #ifdef VK_USE_PLATFORM_MIR_KHR
595     table->CreateMirSurfaceKHR =
596         (PFN_vkCreateMirSurfaceKHR)gpa(inst, "vkCreateMirSurfaceKHR");
597     table->GetPhysicalDeviceMirPresentationSupportKHR =
598         (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)gpa(
599             inst, "vkGetPhysicalDeviceMirPresentationSupportKHR");
600 #endif
601 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
602     table->CreateWaylandSurfaceKHR =
603         (PFN_vkCreateWaylandSurfaceKHR)gpa(inst, "vkCreateWaylandSurfaceKHR");
604     table->GetPhysicalDeviceWaylandPresentationSupportKHR =
605         (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)gpa(
606             inst, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
607 #endif
608 #ifdef VK_USE_PLATFORM_WIN32_KHR
609     table->CreateWin32SurfaceKHR =
610         (PFN_vkCreateWin32SurfaceKHR)gpa(inst, "vkCreateWin32SurfaceKHR");
611     table->GetPhysicalDeviceWin32PresentationSupportKHR =
612         (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)gpa(
613             inst, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
614 #endif
615 #ifdef VK_USE_PLATFORM_XCB_KHR
616     table->CreateXcbSurfaceKHR =
617         (PFN_vkCreateXcbSurfaceKHR)gpa(inst, "vkCreateXcbSurfaceKHR");
618     table->GetPhysicalDeviceXcbPresentationSupportKHR =
619         (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)gpa(
620             inst, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
621 #endif
622 #ifdef VK_USE_PLATFORM_XLIB_KHR
623     table->CreateXlibSurfaceKHR =
624         (PFN_vkCreateXlibSurfaceKHR)gpa(inst, "vkCreateXlibSurfaceKHR");
625     table->GetPhysicalDeviceXlibPresentationSupportKHR =
626         (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)gpa(
627             inst, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
628 #endif
629     table->GetPhysicalDeviceDisplayPropertiesKHR =
630         (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR) gpa(inst,
631         "vkGetPhysicalDeviceDisplayPropertiesKHR");
632     table->GetPhysicalDeviceDisplayPlanePropertiesKHR =
633         (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR) gpa(inst,
634         "vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
635     table->GetDisplayPlaneSupportedDisplaysKHR =
636         (PFN_vkGetDisplayPlaneSupportedDisplaysKHR) gpa(inst,
637         "vkGetDisplayPlaneSupportedDisplaysKHR");
638     table->GetDisplayModePropertiesKHR =
639         (PFN_vkGetDisplayModePropertiesKHR) gpa(inst,
640         "vkGetDisplayModePropertiesKHR");
641     table->CreateDisplayModeKHR =
642         (PFN_vkCreateDisplayModeKHR) gpa(inst,
643         "vkCreateDisplayModeKHR");
644     table->GetDisplayPlaneCapabilitiesKHR =
645         (PFN_vkGetDisplayPlaneCapabilitiesKHR) gpa(inst,
646         "vkGetDisplayPlaneCapabilitiesKHR");
647     table->CreateDisplayPlaneSurfaceKHR =
648         (PFN_vkCreateDisplayPlaneSurfaceKHR) gpa(inst,
649         "vkCreateDisplayPlaneSurfaceKHR");
650 }
651 
652 static inline void *
loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable * table,const char * name,bool * found_name)653 loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table,
654                                       const char *name, bool *found_name) {
655     if (!name || name[0] != 'v' || name[1] != 'k') {
656         *found_name = false;
657         return NULL;
658     }
659 
660     *found_name = true;
661     name += 2;
662     if (!strcmp(name, "DestroyInstance"))
663         return (void *)table->DestroyInstance;
664     if (!strcmp(name, "EnumeratePhysicalDevices"))
665         return (void *)table->EnumeratePhysicalDevices;
666     if (!strcmp(name, "GetPhysicalDeviceFeatures"))
667         return (void *)table->GetPhysicalDeviceFeatures;
668     if (!strcmp(name, "GetPhysicalDeviceImageFormatProperties"))
669         return (void *)table->GetPhysicalDeviceImageFormatProperties;
670     if (!strcmp(name, "GetPhysicalDeviceFormatProperties"))
671         return (void *)table->GetPhysicalDeviceFormatProperties;
672     if (!strcmp(name, "GetPhysicalDeviceSparseImageFormatProperties"))
673         return (void *)table->GetPhysicalDeviceSparseImageFormatProperties;
674     if (!strcmp(name, "GetPhysicalDeviceProperties"))
675         return (void *)table->GetPhysicalDeviceProperties;
676     if (!strcmp(name, "GetPhysicalDeviceQueueFamilyProperties"))
677         return (void *)table->GetPhysicalDeviceQueueFamilyProperties;
678     if (!strcmp(name, "GetPhysicalDeviceMemoryProperties"))
679         return (void *)table->GetPhysicalDeviceMemoryProperties;
680     if (!strcmp(name, "GetInstanceProcAddr"))
681         return (void *)table->GetInstanceProcAddr;
682     if (!strcmp(name, "EnumerateDeviceExtensionProperties"))
683         return (void *)table->EnumerateDeviceExtensionProperties;
684     if (!strcmp(name, "EnumerateDeviceLayerProperties"))
685         return (void *)table->EnumerateDeviceLayerProperties;
686     if (!strcmp(name, "DestroySurfaceKHR"))
687         return (void *)table->DestroySurfaceKHR;
688     if (!strcmp(name, "GetPhysicalDeviceSurfaceSupportKHR"))
689         return (void *)table->GetPhysicalDeviceSurfaceSupportKHR;
690     if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilitiesKHR"))
691         return (void *)table->GetPhysicalDeviceSurfaceCapabilitiesKHR;
692     if (!strcmp(name, "GetPhysicalDeviceSurfaceFormatsKHR"))
693         return (void *)table->GetPhysicalDeviceSurfaceFormatsKHR;
694     if (!strcmp(name, "GetPhysicalDeviceSurfacePresentModesKHR"))
695         return (void *)table->GetPhysicalDeviceSurfacePresentModesKHR;
696 #ifdef VK_USE_PLATFORM_MIR_KHR
697     if (!strcmp(name, "CreateMirSurfaceKHR"))
698         return (void *)table->CreateMirSurfaceKHR;
699     if (!strcmp(name, "GetPhysicalDeviceMirPresentationSupportKHR"))
700         return (void *)table->GetPhysicalDeviceMirPresentationSupportKHR;
701 #endif
702 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
703     if (!strcmp(name, "CreateWaylandSurfaceKHR"))
704         return (void *)table->CreateWaylandSurfaceKHR;
705     if (!strcmp(name, "GetPhysicalDeviceWaylandPresentationSupportKHR"))
706         return (void *)table->GetPhysicalDeviceWaylandPresentationSupportKHR;
707 #endif
708 #ifdef VK_USE_PLATFORM_WIN32_KHR
709     if (!strcmp(name, "CreateWin32SurfaceKHR"))
710         return (void *)table->CreateWin32SurfaceKHR;
711     if (!strcmp(name, "GetPhysicalDeviceWin32PresentationSupportKHR"))
712         return (void *)table->GetPhysicalDeviceWin32PresentationSupportKHR;
713 #endif
714 #ifdef VK_USE_PLATFORM_XCB_KHR
715     if (!strcmp(name, "CreateXcbSurfaceKHR"))
716         return (void *)table->CreateXcbSurfaceKHR;
717     if (!strcmp(name, "GetPhysicalDeviceXcbPresentationSupportKHR"))
718         return (void *)table->GetPhysicalDeviceXcbPresentationSupportKHR;
719 #endif
720 #ifdef VK_USE_PLATFORM_XLIB_KHR
721     if (!strcmp(name, "CreateXlibSurfaceKHR"))
722         return (void *)table->CreateXlibSurfaceKHR;
723     if (!strcmp(name, "GetPhysicalDeviceXlibPresentationSupportKHR"))
724         return (void *)table->GetPhysicalDeviceXlibPresentationSupportKHR;
725 #endif
726     if (!strcmp(name, "GetPhysicalDeviceDisplayPropertiesKHR"))
727         return (void *)table->GetPhysicalDeviceDisplayPropertiesKHR;
728     if (!strcmp(name, "GetPhysicalDeviceDisplayPlanePropertiesKHR"))
729         return (void *)table->GetPhysicalDeviceDisplayPlanePropertiesKHR;
730     if (!strcmp(name, "GetDisplayPlaneSupportedDisplaysKHR"))
731         return (void *)table->GetDisplayPlaneSupportedDisplaysKHR;
732     if (!strcmp(name, "GetDisplayModePropertiesKHR"))
733         return (void *)table->GetDisplayModePropertiesKHR;
734     if (!strcmp(name, "CreateDisplayModeKHR"))
735         return (void *)table->CreateDisplayModeKHR;
736     if (!strcmp(name, "GetDisplayPlaneCapabilitiesKHR"))
737         return (void *)table->GetDisplayPlaneCapabilitiesKHR;
738     if (!strcmp(name, "CreateDisplayPlaneSurfaceKHR"))
739         return (void *)table->CreateDisplayPlaneSurfaceKHR;
740 
741     if (!strcmp(name, "CreateDebugReportCallbackEXT"))
742         return (void *)table->CreateDebugReportCallbackEXT;
743     if (!strcmp(name, "DestroyDebugReportCallbackEXT"))
744         return (void *)table->DestroyDebugReportCallbackEXT;
745     if (!strcmp(name, "DebugReportMessageEXT"))
746         return (void *)table->DebugReportMessageEXT;
747 
748     *found_name = false;
749     return NULL;
750 }
751