Skip to content

Commit d58967c

Browse files
jdolanCopilotCopilot
authored
Add shader cross-compilation pipeline for Hello examples (#2)
* Add shader cross-compilation pipeline for Hello examples - Add Examples/Shaders/ subdirectory with HLSL sources and pre-compiled blobs (.msl, .spv) for Hello and HelloCompute examples (DXIL stubs pending DXC-enabled shadercross) - Add Examples/Shaders/Makefile.am with 'make shadercross' target that regenerates all blobs via glslc (HLSL→SPIR-V) + shadercross (SPIR-V→MSL) and shadercross (HLSL→DXIL); blobs are versioned so consumers do not need shadercross installed - Add ObjectivelyGPU-shadercross Xcode aggregate target with Compile Shaders run-script build phase; input/output paths declared for incremental rebuilds - Add ObjectivelyGPU-shadercross VS utility project with CustomBuild items per HLSL file; add to ObjectivelyGPU.sln - Add RenderDevice::loadComputePipeline(), parallel to loadShader() for compute stages; selects MSL/DXIL/SPIR-V blob by supported format - Rewrite Hello.c and HelloCompute.c to load shaders via RenderDevice::loadShader / loadComputePipeline with a resource path of SDL_GetBasePath() + "Shaders"; remove all inline MSL constants - Add Examples/Shaders/Makefile to configure.ac AC_CONFIG_FILES - Add SUBDIRS = Shaders to Examples/Makefile.am Entry-point convention: vs_main / fs_main / cs_main in HLSL. SPIR-V and MSL preserve these names verbatim (only a literal 'main' would be renamed to 'main0' by SPIRV-Cross). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 7f825a2 commit d58967c

30 files changed

Lines changed: 654 additions & 112 deletions

Examples/Hello.c

Lines changed: 17 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -28,43 +28,6 @@
2828
#include <Objectively.h>
2929
#include <ObjectivelyGPU.h>
3030

31-
static const char *vertex_shader_msl =
32-
"#include <metal_stdlib>\n"
33-
"using namespace metal;\n"
34-
"\n"
35-
"struct type_UBO {\n"
36-
" float4x4 ModelViewProj;\n"
37-
"};\n"
38-
"\n"
39-
"struct main0_out {\n"
40-
" float4 out_color [[user(locn0)]];\n"
41-
" float4 gl_Position [[position]];\n"
42-
"};\n"
43-
"\n"
44-
"struct main0_in {\n"
45-
" float3 in_position [[attribute(0)]];\n"
46-
" float3 in_color [[attribute(1)]];\n"
47-
"};\n"
48-
"\n"
49-
"vertex main0_out main0(main0_in in [[stage_in]], constant type_UBO& UBO [[buffer(0)]]) {\n"
50-
" main0_out out = {};\n"
51-
" out.out_color = float4(in.in_color, 1.0);\n"
52-
" out.gl_Position = UBO.ModelViewProj * float4(in.in_position, 1.0);\n"
53-
" return out;\n"
54-
"}\n";
55-
56-
static const char *fragment_shader_msl =
57-
"#include <metal_stdlib>\n"
58-
"using namespace metal;\n"
59-
"\n"
60-
"struct main0_in {\n"
61-
" float4 in_color [[user(locn0)]];\n"
62-
"};\n"
63-
"\n"
64-
"fragment float4 main0(main0_in in [[stage_in]]) {\n"
65-
" return in.in_color;\n"
66-
"}\n";
67-
6831
typedef struct {
6932
float x, y, z;
7033
float r, g, b;
@@ -89,17 +52,6 @@ static void log_sdl_error(const char *what) {
8952
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "%s: %s", what, SDL_GetError());
9053
}
9154

92-
static SDL_GPUShader *create_shader(const RenderDevice *renderDevice, const char *source, SDL_GPUShaderStage stage, Uint32 numUniformBuffers) {
93-
return $(renderDevice, createShader, &(SDL_GPUShaderCreateInfo) {
94-
.code_size = SDL_strlen(source),
95-
.code = (const Uint8 *) source,
96-
.entrypoint = "main0",
97-
.format = SDL_GPU_SHADERFORMAT_MSL,
98-
.stage = stage,
99-
.num_uniform_buffers = numUniformBuffers,
100-
});
101-
}
102-
10355
static SDL_GPUTexture *create_depth_texture(const RenderDevice *renderDevice, SDL_Size size) {
10456
if (size.w <= 0 || size.h <= 0) {
10557
return NULL;
@@ -169,6 +121,14 @@ int main(int argc, char **argv) {
169121
return status;
170122
}
171123

124+
char *basePath = SDL_GetBasePath();
125+
if (basePath) {
126+
char shaderDir[512];
127+
SDL_snprintf(shaderDir, sizeof(shaderDir), "%sShaders", basePath);
128+
$$(Resource, addResourcePath, shaderDir);
129+
SDL_free(basePath);
130+
}
131+
172132
window = SDL_CreateWindow("ObjectivelyGPU Hello", 800, 600, SDL_WINDOW_HIGH_PIXEL_DENSITY);
173133
if (!window) {
174134
log_sdl_error("SDL_CreateWindow");
@@ -193,8 +153,15 @@ int main(int argc, char **argv) {
193153
depthSize = MakeSize(drawableWidth, drawableHeight);
194154
depthTexture = create_depth_texture(renderDevice, depthSize);
195155

196-
vertexShader = create_shader(renderDevice, vertex_shader_msl, SDL_GPU_SHADERSTAGE_VERTEX, 1);
197-
fragmentShader = create_shader(renderDevice, fragment_shader_msl, SDL_GPU_SHADERSTAGE_FRAGMENT, 0);
156+
vertexShader = $(renderDevice, loadShader, "Hello.vert", &(SDL_GPUShaderCreateInfo) {
157+
.entrypoint = "vs_main",
158+
.stage = SDL_GPU_SHADERSTAGE_VERTEX,
159+
.num_uniform_buffers = 1,
160+
});
161+
fragmentShader = $(renderDevice, loadShader, "Hello.frag", &(SDL_GPUShaderCreateInfo) {
162+
.entrypoint = "fs_main",
163+
.stage = SDL_GPU_SHADERSTAGE_FRAGMENT,
164+
});
198165

199166
SDL_GPUColorTargetDescription colorTargetDescription = {
200167
.format = $(renderDevice, getSwapchainTextureFormat, window),

Examples/HelloCompute.c

Lines changed: 19 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -34,64 +34,10 @@ typedef struct {
3434
float x, y;
3535
} Particle;
3636

37-
static const char *compute_shader_msl =
38-
"#include <metal_stdlib>\n"
39-
"using namespace metal;\n"
40-
"\n"
41-
"struct Particle {\n"
42-
" float2 position;\n"
43-
"};\n"
44-
"\n"
45-
"kernel void main0(uint id [[thread_position_in_grid]], constant float& time [[buffer(0)]], device Particle *particles [[buffer(1)]]) {\n"
46-
" float angle = (float(id) / 256.0) * 6.28318 + time;\n"
47-
" float r = 0.1 + 0.6 * float(id % 64) / 64.0;\n"
48-
" particles[id].position = float2(cos(angle) * r, sin(angle) * r);\n"
49-
"}\n";
50-
51-
static const char *vertex_shader_msl =
52-
"#include <metal_stdlib>\n"
53-
"using namespace metal;\n"
54-
"\n"
55-
"struct Particle {\n"
56-
" float2 position;\n"
57-
"};\n"
58-
"\n"
59-
"struct main0_out {\n"
60-
" float4 gl_Position [[position]];\n"
61-
" float point_size [[point_size]];\n"
62-
"};\n"
63-
"\n"
64-
"vertex main0_out main0(uint id [[vertex_id]], const device Particle *particles [[buffer(0)]]) {\n"
65-
" main0_out out = {};\n"
66-
" out.gl_Position = float4(particles[id].position, 0.0, 1.0);\n"
67-
" out.point_size = 4.0;\n"
68-
" return out;\n"
69-
"}\n";
70-
71-
static const char *fragment_shader_msl =
72-
"#include <metal_stdlib>\n"
73-
"using namespace metal;\n"
74-
"\n"
75-
"fragment float4 main0() {\n"
76-
" return float4(0.8, 0.5, 1.0, 1.0);\n"
77-
"}\n";
78-
7937
static void log_sdl_error(const char *what) {
8038
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "%s: %s", what, SDL_GetError());
8139
}
8240

83-
static SDL_GPUShader *create_shader(const RenderDevice *renderDevice, const char *source, SDL_GPUShaderStage stage, Uint32 numStorageBuffers, Uint32 numUniformBuffers) {
84-
return $(renderDevice, createShader, &(SDL_GPUShaderCreateInfo) {
85-
.code_size = SDL_strlen(source),
86-
.code = (const Uint8 *) source,
87-
.entrypoint = "main0",
88-
.format = SDL_GPU_SHADERFORMAT_MSL,
89-
.stage = stage,
90-
.num_storage_buffers = numStorageBuffers,
91-
.num_uniform_buffers = numUniformBuffers,
92-
});
93-
}
94-
9541
int main(int argc, char **argv) {
9642
(void) argc;
9743
(void) argv;
@@ -110,6 +56,14 @@ int main(int argc, char **argv) {
11056
return status;
11157
}
11258

59+
char *basePath = SDL_GetBasePath();
60+
if (basePath) {
61+
char shaderDir[512];
62+
SDL_snprintf(shaderDir, sizeof(shaderDir), "%sShaders", basePath);
63+
$$(Resource, addResourcePath, shaderDir);
64+
SDL_free(basePath);
65+
}
66+
11367
window = SDL_CreateWindow("ObjectivelyGPU HelloCompute", 800, 600, SDL_WINDOW_HIGH_PIXEL_DENSITY);
11468
if (!window) {
11569
log_sdl_error("SDL_CreateWindow");
@@ -123,20 +77,24 @@ int main(int argc, char **argv) {
12377
.size = NUM_PARTICLES * sizeof(Particle),
12478
});
12579

126-
computePipeline = $(renderDevice, createComputePipeline, &(SDL_GPUComputePipelineCreateInfo) {
127-
.code_size = SDL_strlen(compute_shader_msl),
128-
.code = (const Uint8 *) compute_shader_msl,
129-
.entrypoint = "main0",
130-
.format = SDL_GPU_SHADERFORMAT_MSL,
80+
computePipeline = $(renderDevice, loadComputePipeline, "HelloCompute.comp", &(SDL_GPUComputePipelineCreateInfo) {
81+
.entrypoint = "cs_main",
13182
.num_readwrite_storage_buffers = 1,
13283
.num_uniform_buffers = 1,
13384
.threadcount_x = NUM_PARTICLES,
13485
.threadcount_y = 1,
13586
.threadcount_z = 1,
13687
});
13788

138-
vertexShader = create_shader(renderDevice, vertex_shader_msl, SDL_GPU_SHADERSTAGE_VERTEX, 1, 0);
139-
fragmentShader = create_shader(renderDevice, fragment_shader_msl, SDL_GPU_SHADERSTAGE_FRAGMENT, 0, 0);
89+
vertexShader = $(renderDevice, loadShader, "HelloCompute.vert", &(SDL_GPUShaderCreateInfo) {
90+
.entrypoint = "vs_main",
91+
.stage = SDL_GPU_SHADERSTAGE_VERTEX,
92+
.num_storage_buffers = 1,
93+
});
94+
fragmentShader = $(renderDevice, loadShader, "HelloCompute.frag", &(SDL_GPUShaderCreateInfo) {
95+
.entrypoint = "fs_main",
96+
.stage = SDL_GPU_SHADERSTAGE_FRAGMENT,
97+
});
14098

14199
SDL_GPUColorTargetDescription colorTargetDescription = {
142100
.format = $(renderDevice, getSwapchainTextureFormat, window),

Examples/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
SUBDIRS = Shaders
2+
13
noinst_PROGRAMS = \
24
Hello \
35
HelloCompute

Examples/Shaders/Hello.frag.dxil

Whitespace-only changes.

Examples/Shaders/Hello.frag.hlsl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Hello example fragment shader.
3+
*
4+
* Inputs (TEXCOORD0): float4 color from vertex stage
5+
* Output : float4 RGBA
6+
*/
7+
8+
struct PSInput {
9+
float4 color : TEXCOORD0;
10+
};
11+
12+
float4 fs_main(PSInput input) : SV_Target {
13+
return input.color;
14+
}

Examples/Shaders/Hello.frag.msl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <metal_stdlib>
2+
#include <simd/simd.h>
3+
4+
using namespace metal;
5+
6+
struct fs_main_out
7+
{
8+
float4 _entryPointOutput [[color(0)]];
9+
};
10+
11+
struct fs_main_in
12+
{
13+
float4 input_color [[user(locn0)]];
14+
};
15+
16+
fragment fs_main_out fs_main(fs_main_in in [[stage_in]])
17+
{
18+
fs_main_out out = {};
19+
out._entryPointOutput = in.input_color;
20+
return out;
21+
}
22+

Examples/Shaders/Hello.frag.spv

460 Bytes
Binary file not shown.

Examples/Shaders/Hello.vert.dxil

Whitespace-only changes.

Examples/Shaders/Hello.vert.hlsl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Hello example vertex shader.
3+
*
4+
* Inputs (location 0): float3 position
5+
* (location 1): float3 color
6+
* Uniform (b0, space1): float4x4 ModelViewProj
7+
* Outputs : float4 color (passed through), SV_Position
8+
*/
9+
10+
cbuffer UBO : register(b0, space1) {
11+
float4x4 ModelViewProj;
12+
};
13+
14+
struct VSInput {
15+
float3 position : TEXCOORD0;
16+
float3 color : TEXCOORD1;
17+
};
18+
19+
struct VSOutput {
20+
float4 color : TEXCOORD0;
21+
float4 position : SV_Position;
22+
};
23+
24+
VSOutput vs_main(VSInput input) {
25+
VSOutput output;
26+
output.color = float4(input.color, 1.0);
27+
output.position = mul(ModelViewProj, float4(input.position, 1.0));
28+
return output;
29+
}

Examples/Shaders/Hello.vert.msl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <metal_stdlib>
2+
#include <simd/simd.h>
3+
4+
using namespace metal;
5+
6+
struct UBO
7+
{
8+
float4x4 ModelViewProj;
9+
};
10+
11+
struct vs_main_out
12+
{
13+
float4 _entryPointOutput_color [[user(locn0)]];
14+
float4 gl_Position [[position]];
15+
};
16+
17+
struct vs_main_in
18+
{
19+
float3 input_position [[attribute(0)]];
20+
float3 input_color [[attribute(1)]];
21+
};
22+
23+
vertex vs_main_out vs_main(vs_main_in in [[stage_in]], constant UBO& _40 [[buffer(0)]])
24+
{
25+
vs_main_out out = {};
26+
out._entryPointOutput_color = float4(in.input_color, 1.0);
27+
out.gl_Position = _40.ModelViewProj * float4(in.input_position, 1.0);
28+
return out;
29+
}
30+

0 commit comments

Comments
 (0)