Skip to content

Commit 04ab171

Browse files
committed
Add slang shaders for headless samples
1 parent a442bdd commit 04ab171

4 files changed

Lines changed: 104 additions & 9 deletions

File tree

examples/computeheadless/computeheadless.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class VulkanExample
8282

8383
VkDebugReportCallbackEXT debugReportCallback{};
8484

85+
std::string shaderDir = "glsl";
86+
8587
VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkBuffer *buffer, VkDeviceMemory *memory, VkDeviceSize size, void *data = nullptr)
8688
{
8789
// Create the buffer handle
@@ -132,11 +134,19 @@ class VulkanExample
132134
vks::android::loadVulkanLibrary();
133135
#endif
134136

137+
if (commandLineParser.isSet("shaders")) {
138+
shaderDir = commandLineParser.getValueAsString("shaders", "glsl");
139+
}
140+
135141
VkApplicationInfo appInfo = {};
136142
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
137143
appInfo.pApplicationName = "Vulkan headless example";
138144
appInfo.pEngineName = "VulkanExample";
139145
appInfo.apiVersion = VK_API_VERSION_1_0;
146+
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
147+
if (shaderDir == "slang") {
148+
appInfo.apiVersion = VK_API_VERSION_1_1;
149+
}
140150

141151
/*
142152
Vulkan instance creation (without surface extensions)
@@ -159,7 +169,7 @@ class VulkanExample
159169
bool layersAvailable = true;
160170
for (auto layerName : validationLayers) {
161171
bool layerAvailable = false;
162-
for (auto instanceLayer : instanceLayers) {
172+
for (auto& instanceLayer : instanceLayers) {
163173
if (strcmp(instanceLayer.layerName, layerName) == 0) {
164174
layerAvailable = true;
165175
break;
@@ -260,8 +270,15 @@ class VulkanExample
260270
deviceCreateInfo.queueCreateInfoCount = 1;
261271
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
262272
std::vector<const char*> deviceExtensions = {};
273+
274+
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
275+
if (shaderDir == "slang") {
276+
deviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
277+
deviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
278+
}
279+
263280
#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset)
264-
// SRS - When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
281+
// When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
265282
uint32_t deviceExtCount = 0;
266283
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr);
267284
if (deviceExtCount > 0)
@@ -410,10 +427,6 @@ class VulkanExample
410427
VkSpecializationMapEntry specializationMapEntry = vks::initializers::specializationMapEntry(0, 0, sizeof(uint32_t));
411428
VkSpecializationInfo specializationInfo = vks::initializers::specializationInfo(1, &specializationMapEntry, sizeof(SpecializationData), &specializationData);
412429

413-
std::string shaderDir = "glsl";
414-
if (commandLineParser.isSet("shaders")) {
415-
shaderDir = commandLineParser.getValueAsString("shaders", "glsl");
416-
}
417430
const std::string shadersPath = getShaderBasePath() + shaderDir + "/computeheadless/";
418431

419432
VkPipelineShaderStageCreateInfo shaderStage = {};

examples/renderheadless/renderheadless.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ class VulkanExample
9797

9898
VkDebugReportCallbackEXT debugReportCallback{};
9999

100+
std::string shaderDir = "glsl";
101+
100102
uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) {
101103
VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
102104
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
@@ -163,11 +165,19 @@ class VulkanExample
163165
vks::android::loadVulkanLibrary();
164166
#endif
165167

168+
if (commandLineParser.isSet("shaders")) {
169+
shaderDir = commandLineParser.getValueAsString("shaders", "glsl");
170+
}
171+
166172
VkApplicationInfo appInfo = {};
167173
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
168174
appInfo.pApplicationName = "Vulkan headless example";
169175
appInfo.pEngineName = "VulkanExample";
170176
appInfo.apiVersion = VK_API_VERSION_1_0;
177+
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
178+
if (shaderDir == "slang") {
179+
appInfo.apiVersion = VK_API_VERSION_1_1;
180+
}
171181

172182
/*
173183
Vulkan instance creation (without surface extensions)
@@ -190,7 +200,7 @@ class VulkanExample
190200
bool layersAvailable = true;
191201
for (auto layerName : validationLayers) {
192202
bool layerAvailable = false;
193-
for (auto instanceLayer : instanceLayers) {
203+
for (auto& instanceLayer : instanceLayers) {
194204
if (strcmp(instanceLayer.layerName, layerName) == 0) {
195205
layerAvailable = true;
196206
break;
@@ -290,8 +300,15 @@ class VulkanExample
290300
deviceCreateInfo.queueCreateInfoCount = 1;
291301
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
292302
std::vector<const char*> deviceExtensions = {};
303+
304+
// Shaders generated by Slang require a certain SPIR-V environment that can't be satisfied by Vulkan 1.0, so we need to expliclity up that to at least 1.1 and enable some required extensions
305+
if (shaderDir == "slang") {
306+
deviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME);
307+
deviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
308+
}
309+
293310
#if (defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT)) && defined(VK_KHR_portability_subset)
294-
// SRS - When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
311+
// When running on macOS with MoltenVK and VK_KHR_portability_subset is defined and supported by the device, enable the extension
295312
uint32_t deviceExtCount = 0;
296313
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &deviceExtCount, nullptr);
297314
if (deviceExtCount > 0)
@@ -643,7 +660,6 @@ class VulkanExample
643660

644661
pipelineCreateInfo.pVertexInputState = &vertexInputState;
645662

646-
std::string shaderDir = "glsl";
647663
if (commandLineParser.isSet("shaders")) {
648664
shaderDir = commandLineParser.getValueAsString("shaders", "glsl");
649665
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
RWStructuredBuffer<uint> values;
8+
9+
[[SpecializationConstant]] const uint BUFFER_ELEMENTS = 32;
10+
11+
uint fibonacci(uint n) {
12+
if(n <= 1){
13+
return n;
14+
}
15+
uint curr = 1;
16+
uint prev = 1;
17+
for(uint i = 2; i < n; ++i) {
18+
uint temp = curr;
19+
curr += prev;
20+
prev = temp;
21+
}
22+
return curr;
23+
}
24+
25+
[numthreads(1, 1, 1)]
26+
[shader("compute")]
27+
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
28+
{
29+
uint index = GlobalInvocationID.x;
30+
if (index >= BUFFER_ELEMENTS)
31+
return;
32+
values[index] = fibonacci(values[index]);
33+
}
34+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
struct VSInput
8+
{
9+
float3 Pos;
10+
float3 Color;
11+
};
12+
13+
struct VSOutput
14+
{
15+
float4 Pos : SV_POSITION;
16+
float3 Color;
17+
};
18+
19+
[shader("vertex")]
20+
VSOutput vertexMain(VSInput input, uniform float4x4 mvp)
21+
{
22+
VSOutput output;
23+
output.Color = input.Color;
24+
output.Pos = mul(mvp, float4(input.Pos.xyz, 1.0));
25+
return output;
26+
}
27+
28+
[shader("fragment")]
29+
float4 fragmentMain(VSOutput input)
30+
{
31+
return float4(input.Color, 1.0);
32+
}

0 commit comments

Comments
 (0)