Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Vulkan compute shader development and pipeline configuration. Generate GLSL/HLSL compute shaders, compile to SPIR-V, configure compute pipelines, manage descriptor sets and resource bindings, implement memory barriers and synchronization.
.claude/skills/a5c-ai-vulkan-compute/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 145% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 211% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 535% | 0% |
| case-22 | ✗→✓ | ▲ Improved | 61% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 189% | 0% |
You are vulkan-compute - a specialized skill for Vulkan compute shader development and pipeline configuration. This skill provides expert capabilities for GPU compute using the Vulkan API.
This skill enables AI-powered Vulkan compute operations including:
Generate GLSL compute shaders:
glsl#version 450 // Workgroup size specification layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in; // Buffer bindings layout(set = 0, binding = 0) readonly buffer InputBuffer { float inputData[]; }; layout(set = 0, binding = 1) writeonly buffer OutputBuffer { float outputData[]; }; // Push constants for runtime parameters layout(push_constant) uniform PushConstants { uint dataSize; float multiplier; } pc; void main() { uint gid = gl_GlobalInvocationID.x; if (gid < pc.dataSize) { outputData[gid] = inputData[gid] * pc.multiplier; } }
Compile shaders to SPIR-V:
bash# Using glslangValidator glslangValidator -V compute.glsl -o compute.spv # Using glslc (Google's compiler) glslc -fshader-stage=compute compute.glsl -o compute.spv # With optimization glslc -O compute.glsl -o compute.spv # Generate human-readable SPIR-V spirv-dis compute.spv -o compute.spvasm # Validate SPIR-V spirv-val compute.spv # Optimize SPIR-V spirv-opt -O compute.spv -o compute_opt.spv
Create Vulkan compute pipelines:
c// Load SPIR-V shader VkShaderModuleCreateInfo shaderInfo = { .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .codeSize = spirvSize, .pCode = spirvCode }; VkShaderModule shaderModule; vkCreateShaderModule(device, &shaderInfo, NULL, &shaderModule); // Pipeline layout with descriptor set and push constants VkPushConstantRange pushConstantRange = { .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, .offset = 0, .size = sizeof(PushConstants) }; VkPipelineLayoutCreateInfo layoutInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = 1, .pSetLayouts = &descriptorSetLayout, .pushConstantRangeCount = 1, .pPushConstantRanges = &pushConstantRange }; VkPipelineLayout pipelineLayout; vkCreatePipelineLayout(device, &layoutInfo, NULL, &pipelineLayout); // Create compute pipeline VkComputePipelineCreateInfo pipelineInfo = { .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, .stage = { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .stage = VK_SHADER_STAGE_COMPUTE_BIT, .module = shaderModule, .pName = "main" }, .layout = pipelineLayout }; VkPipeline computePipeline; vkCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &computePipeline);
Configure resource bindings:
c// Descriptor set layout VkDescriptorSetLayoutBinding bindings[] = { { .binding = 0, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT }, { .binding = 1, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 1, .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT } }; VkDescriptorSetLayoutCreateInfo layoutInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, .bindingCount = 2, .pBindings = bindings }; VkDescriptorSetLayout descriptorSetLayout; vkCreateDescriptorSetLayout(device, &layoutInfo, NULL, &descriptorSetLayout); // Allocate and update descriptor set VkDescriptorBufferInfo inputBufferInfo = { .buffer = inputBuffer, .offset = 0, .range = VK_WHOLE_SIZE }; VkDescriptorBufferInfo outputBufferInfo = { .buffer = outputBuffer, .offset = 0, .range = VK_WHOLE_SIZE }; VkWriteDescriptorSet writes[] = { { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .dstSet = descriptorSet, .dstBinding = 0, .descriptorCount = 1, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .pBufferInfo = &inputBufferInfo }, { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .dstSet = descriptorSet, .dstBinding = 1, .descriptorCount = 1, .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .pBufferInfo = &outputBufferInfo } }; vkUpdateDescriptorSets(device, 2, writes, 0, NULL);
Runtime shader customization:
glsl// In shader layout(constant_id = 0) const uint WORKGROUP_SIZE = 256; layout(constant_id = 1) const bool USE_FAST_MATH = false; layout(local_size_x_id = 0) in;
c// In C code VkSpecializationMapEntry entries[] = { {0, 0, sizeof(uint32_t)}, // WORKGROUP_SIZE {1, sizeof(uint32_t), sizeof(VkBool32)} // USE_FAST_MATH }; struct { uint32_t workgroupSize; VkBool32 useFastMath; } specData = {512, VK_TRUE}; VkSpecializationInfo specInfo = { .mapEntryCount = 2, .pMapEntries = entries, .dataSize = sizeof(specData), .pData = &specData }; // Use in pipeline creation pipelineInfo.stage.pSpecializationInfo = &specInfo;
Execute compute work:
c// Record command buffer vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline); vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0, 1, &descriptorSet, 0, NULL); vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(PushConstants), &pushConstants); // Dispatch uint32_t groupCountX = (dataSize + 255) / 256; vkCmdDispatch(commandBuffer, groupCountX, 1, 1); // Indirect dispatch vkCmdDispatchIndirect(commandBuffer, indirectBuffer, 0);
Proper synchronization:
c// Buffer memory barrier VkBufferMemoryBarrier barrier = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .buffer = buffer, .offset = 0, .size = VK_WHOLE_SIZE }; vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 1, &barrier, 0, NULL); // Memory barrier for compute-to-transfer VkMemoryBarrier memoryBarrier = { .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT }; vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0, NULL, 0, NULL);
Debug with validation:
c// Enable validation layers const char* validationLayers[] = { "VK_LAYER_KHRONOS_validation" }; VkInstanceCreateInfo createInfo = { .enabledLayerCount = 1, .ppEnabledLayerNames = validationLayers }; // Debug messenger callback VkDebugUtilsMessengerCreateInfoEXT debugInfo = { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, .pfnUserCallback = debugCallback };
This skill integrates with the following processes:
compute-shader-development.js - Compute shader workflowsjson{ "operation": "compile-shader", "status": "success", "input": "compute.glsl", "output": "compute.spv", "spirv_size": 1024, "workgroup_size": [256, 1, 1], "bindings": [ {"binding": 0, "type": "storage_buffer", "access": "readonly"}, {"binding": 1, "type": "storage_buffer", "access": "writeonly"} ], "push_constants_size": 8, "artifacts": ["compute.spv", "compute.spvasm"] }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 9,532 | 13,041 | +37% | 1 | 1 | 0% | 1,958 | 4,799 | +145% | 0 | 0 | — |
case-02 | pass→pass | 7,386 | 5,736 | -22% | 1 | 1 | 0% | 1,288 | 3,728 | +189% | 0 | 0 | — |
case-03 | pass→pass | 6,522 | 5,115 | -22% | 1 | 1 | 0% | 1,284 | 3,688 | +187% | 0 | 0 | — |
case-04 | pass→pass | 8,202 | 6,100 | -26% | 1 | 1 | 0% | 1,548 | 3,908 | +152% | 0 | 0 | — |
case-05 | pass→pass | 11,617 | 11,678 | +1% | 1 | 1 | 0% | 2,389 | 4,560 | +91% | 0 | 0 | — |
case-06 | pass→pass | 6,167 | 5,414 | -12% | 1 | 1 | 0% | 916 | 3,537 | +286% | 0 | 0 | — |
case-07 | pass→pass | 10,387 | 8,184 | -21% | 1 | 1 | 0% | 1,997 | 4,417 | +121% | 0 | 0 | — |
case-08 | pass→pass | 21,022 | 10,262 | -51% | 1 | 1 | 0% | 4,059 | 4,454 | +10% | 0 | 0 | — |
case-09 | pass→pass | 12,552 | 15,886 | +27% | 1 | 1 | 0% | 2,550 | 5,239 | +105% | 0 | 0 | — |
case-10 | fail→pass | 8,217 | 7,624 | -7% | 1 | 1 | 0% | 1,301 | 4,050 | +211% | 0 | 0 | — |
case-11 | pass→pass | 16,425 | 11,406 | -31% | 1 | 1 | 0% | 2,644 | 5,041 | +91% | 0 | 0 | — |
case-12 | pass→pass | 12,837 | 19,345 | +51% | 1 | 1 | 0% | 2,584 | 5,870 | +127% | 0 | 0 | — |
case-13 | fail→pass | 4,051 | 18,209 | +349% | 1 | 1 | 0% | 521 | 3,310 | +535% | 0 | 0 | — |
case-14 | pass→pass | 11,523 | 10,164 | -12% | 1 | 1 | 0% | 1,978 | 4,750 | +140% | 0 | 0 | — |
case-15 | pass→pass | 13,016 | 11,230 | -14% | 1 | 1 | 0% | 2,563 | 4,475 | +75% | 0 | 0 | — |
case-16 | pass→pass | 11,150 | 9,180 | -18% | 1 | 1 | 0% | 2,161 | 4,534 | +110% | 0 | 0 | — |
case-17 | pass→pass | 9,357 | 6,114 | -35% | 1 | 1 | 0% | 1,839 | 3,781 | +106% | 0 | 0 | — |
case-18 | pass→pass | 16,326 | 10,029 | -39% | 1 | 1 | 0% | 2,498 | 4,867 | +95% | 0 | 0 | — |
case-19 | pass→pass | 3,093 | 5,907 | +91% | 1 | 1 | 0% | 562 | 3,893 | +593% | 0 | 0 | — |
case-20 | fail→fail | 21,168 | 20,170 | -5% | 1 | 1 | 0% | 4,858 | 7,372 | +52% | 0 | 0 | — |
case-21 | pass→pass | 15,117 | 12,059 | -20% | 1 | 1 | 0% | 2,379 | 5,194 | +118% | 0 | 0 | — |
case-22 | fail→pass | 29,032 | 17,912 | -38% | 1 | 1 | 0% | 3,498 | 5,640 | +61% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +18 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.