Skip to content

Commit 49eecab

Browse files
jdolanCopilot
andcommitted
Thread RenderDevice through CommandBuffer; drop window param from swapchain methods
CommandBuffer now holds a weak reference to its RenderDevice instead of a raw SDL_GPUDevice pointer. This gives it access to both device and window without callers having to pass SDL_Window everywhere. - acquireSwapchainTexture(self, &sc) — window implicit - waitAndAcquireSwapchainTexture(self, &sc) — window implicit - initWithCommandBuffer now takes (self, device, cmd) - beginCopyPass uses self->device->device for SDL_GPUDevice Hello.c refactored: Scene struct + drawScene(), Vertex type with named fields, offsetof for vertex attribute offsets. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a17ae73 commit 49eecab

6 files changed

Lines changed: 107 additions & 91 deletions

File tree

Examples/Hello-iOS/Hello-iOS.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ static const char *fragment_shader_msl =
6969
typedef struct {
7070
float x, y, z;
7171
float r, g, b;
72-
} VertexData;
72+
} Vertex;
7373

74-
static const VertexData vertex_data[] = {
74+
static const Vertex vertex_data[] = {
7575
{ -0.5f, 0.5f, -0.5f, 1, 0, 0 }, { 0.5f, -0.5f, -0.5f, 0, 0, 1 }, { -0.5f, -0.5f, -0.5f, 0, 1, 0 },
7676
{ -0.5f, 0.5f, -0.5f, 1, 0, 0 }, { 0.5f, 0.5f, -0.5f, 1, 1, 0 }, { 0.5f, -0.5f, -0.5f, 0, 0, 1 },
7777
{ -0.5f, 0.5f, 0.5f, 1, 1, 1 }, { -0.5f, -0.5f, -0.5f, 0, 1, 0 }, { -0.5f, -0.5f, 0.5f, 0, 1, 1 },
@@ -218,7 +218,7 @@ SDL_AppResult SDL_AppInit(void **unused, int argc, char *argv[]) {
218218
};
219219
SDL_GPUVertexBufferDescription vbDesc = {
220220
.slot = 0,
221-
.pitch = sizeof(VertexData),
221+
.pitch = sizeof(Vertex),
222222
.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX,
223223
};
224224
SDL_GPUVertexAttribute vertexAttribs[] = {

Examples/Hello.c

Lines changed: 80 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,18 @@
3131
#endif
3232

3333
typedef struct {
34-
float x, y, z;
35-
float r, g, b;
36-
} VertexData;
34+
RenderDevice *renderDevice;
35+
Framebuffer *framebuffer;
36+
SDL_GPUGraphicsPipeline *pipeline;
37+
SDL_GPUBuffer *vertexBuffer;
38+
} Scene;
3739

38-
static const VertexData vertex_data[] = {
40+
typedef struct {
41+
float3 position;
42+
float3 color;
43+
} Vertex;
44+
45+
static const Vertex vertexes[] = {
3946
{ -0.5f, 0.5f, -0.5f, 1, 0, 0 }, { 0.5f, -0.5f, -0.5f, 0, 0, 1 }, { -0.5f, -0.5f, -0.5f, 0, 1, 0 },
4047
{ -0.5f, 0.5f, -0.5f, 1, 0, 0 }, { 0.5f, 0.5f, -0.5f, 1, 1, 0 }, { 0.5f, -0.5f, -0.5f, 0, 0, 1 },
4148
{ -0.5f, 0.5f, 0.5f, 1, 1, 1 }, { -0.5f, -0.5f, -0.5f, 0, 1, 0 }, { -0.5f, -0.5f, 0.5f, 0, 1, 1 },
@@ -50,26 +57,77 @@ static const VertexData vertex_data[] = {
5057
{ -0.5f, -0.5f, -0.5f, 0, 1, 0 }, { 0.5f, -0.5f, -0.5f, 0, 0, 1 }, { 0.5f, -0.5f, 0.5f, 1, 0, 1 },
5158
};
5259

60+
/**
61+
* @brief
62+
*/
63+
static void drawScene(Scene *scene) {
64+
static float2 angles;
65+
static Uint64 lastTicks;
66+
67+
Uint64 ticks = SDL_GetTicks();
68+
float dt = (float) (ticks - lastTicks) / 1000.0f;
69+
lastTicks = ticks;
70+
71+
angles.x += dt * 30.0f;
72+
angles.y += dt * 60.0f;
73+
74+
while (angles.x >= 360.0f) {
75+
angles.x -= 360.0f;
76+
}
77+
while (angles.y >= 360.0f) {
78+
angles.y -= 360.0f;
79+
}
80+
81+
CommandBuffer *cmd = $(scene->renderDevice, acquireCommandBuffer);
82+
83+
SwapchainTexture swapchain = { 0 };
84+
$(cmd, waitAndAcquireSwapchainTexture, &swapchain);
85+
86+
float4x4 modelView = float4x4_rotation(angles.x, float3_new(1.f, 0.f, 0.f));
87+
modelView = float4x4_mul(float4x4_rotation(angles.y, float3_new(0.f, 1.f, 0.f)), modelView);
88+
modelView = float4x4_mul(float4x4_translation(float3_new(0.f, 0.f, -2.5f)), modelView);
89+
const float4x4 projection = float4x4_perspective(45.f, (float) swapchain.size.w / (float) swapchain.size.h, 0.01f, 100.f);
90+
const float4x4 modelViewProjection = float4x4_mul(projection, modelView);
91+
92+
SDL_GPUColorTargetInfo colorTarget = {
93+
.texture = swapchain.texture,
94+
.clear_color = { 0.1f, 0.1f, 0.2f, 1.0f },
95+
.load_op = SDL_GPU_LOADOP_CLEAR,
96+
.store_op = SDL_GPU_STOREOP_STORE,
97+
};
98+
99+
SDL_GPUDepthStencilTargetInfo depthTarget = $(scene->framebuffer, depthTargetInfo, SDL_GPU_LOADOP_CLEAR, SDL_GPU_STOREOP_DONT_CARE, 1.f);
100+
101+
RenderPass *renderPass = $(cmd, beginRenderPass, &colorTarget, 1, &depthTarget);
102+
$(renderPass, bindPipeline, scene->pipeline);
103+
$(renderPass, bindVertexBuffers, 0, &(SDL_GPUBufferBinding) {
104+
.buffer = scene->vertexBuffer,
105+
.offset = 0,
106+
}, 1);
107+
$(cmd, pushVertexUniformData, 0, modelViewProjection.f, sizeof(modelViewProjection));
108+
$(renderPass, drawPrimitives, (Uint32) SDL_arraysize(vertexes), 1, 0, 0);
109+
release(renderPass);
110+
111+
$(cmd, submit);
112+
release(cmd);
113+
}
114+
53115
/**
54116
* @brief
55117
*/
56118
int main(int argc, char **argv) {
57119

120+
$$(Resource, addResourcePath, EXAMPLES);
121+
58122
GPU_Assert(SDL_Init(SDL_INIT_VIDEO), "SDL_Init");
59123

60124
SDL_Window *window = SDL_CreateWindow("ObjectivelyGPU Hello", 800, 600, SDL_WINDOW_HIGH_PIXEL_DENSITY);
61125
GPU_Assert(window, "SDL_CreateWindow");
62126

63-
$$(Resource, addResourcePath, EXAMPLES);
64-
65127
RenderDevice *renderDevice = $(alloc(RenderDevice), initWithWindow, window);
66128
GPU_Assert(renderDevice, "RenderDevice init");
67129

68-
SDL_GPUBuffer *vertexBuffer = $(renderDevice, createBufferWithConstMem,
69-
SDL_GPU_BUFFERUSAGE_VERTEX, vertex_data, sizeof(vertex_data));
70-
71-
int w = 0;
72-
int h = 0;
130+
int w, h;
73131
SDL_GetWindowSizeInPixels(window, &w, &h);
74132

75133
Framebuffer *framebuffer = $(alloc(Framebuffer), initWithDevice, renderDevice,
@@ -94,7 +152,7 @@ int main(int argc, char **argv) {
94152

95153
SDL_GPUVertexBufferDescription vertexBufferDescription = {
96154
.slot = 0,
97-
.pitch = sizeof(VertexData),
155+
.pitch = sizeof(Vertex),
98156
.input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX,
99157
.instance_step_rate = 0,
100158
};
@@ -104,13 +162,13 @@ int main(int argc, char **argv) {
104162
.location = 0,
105163
.buffer_slot = 0,
106164
.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3,
107-
.offset = 0,
165+
.offset = offsetof(Vertex, position),
108166
},
109167
{
110168
.location = 1,
111169
.buffer_slot = 0,
112170
.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3,
113-
.offset = 12,
171+
.offset = offsetof(Vertex, color),
114172
},
115173
};
116174

@@ -149,11 +207,9 @@ int main(int argc, char **argv) {
149207
$(renderDevice, releaseShader, vertexShader);
150208
$(renderDevice, releaseShader, fragmentShader);
151209

152-
bool running = true;
153-
float angleX = 0.0f;
154-
float angleY = 0.0f;
155-
Uint64 lastTicks = SDL_GetTicks();
210+
SDL_GPUBuffer *vertexBuffer = $(renderDevice, createBufferWithConstMem, SDL_GPU_BUFFERUSAGE_VERTEX, vertexes, sizeof(vertexes));
156211

212+
bool running = true;
157213
while (running) {
158214
SDL_Event event;
159215
while (SDL_PollEvent(&event)) {
@@ -167,52 +223,12 @@ int main(int argc, char **argv) {
167223
}
168224
}
169225

170-
Uint64 ticks = SDL_GetTicks();
171-
float dt = (float) (ticks - lastTicks) / 1000.0f;
172-
lastTicks = ticks;
173-
174-
angleX += dt * 30.0f;
175-
angleY += dt * 60.0f;
176-
177-
while (angleX >= 360.0f) {
178-
angleX -= 360.0f;
179-
}
180-
while (angleY >= 360.0f) {
181-
angleY -= 360.0f;
182-
}
183-
184-
CommandBuffer *cmd = $(renderDevice, acquireCommandBuffer);
185-
186-
SwapchainTexture swapchain = { 0 };
187-
$(cmd, waitAndAcquireSwapchainTexture, window, &swapchain);
188-
189-
float4x4 modelView = float4x4_rotation(angleX, float3_new(1.f, 0.f, 0.f));
190-
modelView = float4x4_mul(float4x4_rotation(angleY, float3_new(0.f, 1.f, 0.f)), modelView);
191-
modelView = float4x4_mul(float4x4_translation(float3_new(0.f, 0.f, -2.5f)), modelView);
192-
const float4x4 projection = float4x4_perspective(45.f, (float) swapchain.size.w / (float) swapchain.size.h, 0.01f, 100.f);
193-
const float4x4 modelViewProjection = float4x4_mul(projection, modelView);
194-
195-
SDL_GPUColorTargetInfo colorTarget = {
196-
.texture = swapchain.texture,
197-
.clear_color = { 0.1f, 0.1f, 0.2f, 1.0f },
198-
.load_op = SDL_GPU_LOADOP_CLEAR,
199-
.store_op = SDL_GPU_STOREOP_STORE,
200-
};
201-
202-
SDL_GPUDepthStencilTargetInfo depthTarget = $(framebuffer, depthTargetInfo, SDL_GPU_LOADOP_CLEAR, SDL_GPU_STOREOP_DONT_CARE, 1.f);
203-
204-
RenderPass *renderPass = $(cmd, beginRenderPass, &colorTarget, 1, &depthTarget);
205-
$(renderPass, bindPipeline, pipeline);
206-
$(renderPass, bindVertexBuffers, 0, &(SDL_GPUBufferBinding) {
207-
.buffer = vertexBuffer,
208-
.offset = 0,
209-
}, 1);
210-
$(cmd, pushVertexUniformData, 0, modelViewProjection.f, sizeof(modelViewProjection));
211-
$(renderPass, drawPrimitives, (Uint32) SDL_arraysize(vertex_data), 1, 0, 0);
212-
release(renderPass);
213-
214-
$(cmd, submit);
215-
release(cmd);
226+
drawScene(&(Scene) {
227+
.renderDevice = renderDevice,
228+
.framebuffer = framebuffer,
229+
.pipeline = pipeline,
230+
.vertexBuffer = vertexBuffer
231+
});
216232
}
217233

218234
$(renderDevice, waitForIdle);

Examples/HelloCompute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ int main(int argc, char **argv) {
144144

145145
CommandBuffer *cmd = $(renderDevice, acquireCommandBuffer);
146146
SwapchainTexture swapchain = { 0 };
147-
$(cmd, waitAndAcquireSwapchainTexture, window, &swapchain);
147+
$(cmd, waitAndAcquireSwapchainTexture, &swapchain);
148148

149149
float time = (float) (SDL_GetTicks() - startTicks) / 1000.0f;
150150
$(cmd, pushComputeUniformData, 0, &time, sizeof(time));

Sources/ObjectivelyGPU/CommandBuffer.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,23 @@
2626
#include "CommandBuffer.h"
2727
#include "ComputePass.h"
2828
#include "CopyPass.h"
29+
#include "RenderDevice.h"
2930
#include "RenderPass.h"
3031

3132
#define _Class _CommandBuffer
3233

3334
#pragma mark - CommandBuffer
3435

3536
/**
36-
* @fn bool CommandBuffer::acquireSwapchainTexture(const CommandBuffer *self, SDL_Window *window, SwapchainTexture *swapchain)
37+
* @fn bool CommandBuffer::acquireSwapchainTexture(const CommandBuffer *self, SwapchainTexture *swapchain)
3738
* @memberof CommandBuffer
3839
*/
39-
static bool acquireSwapchainTexture(const CommandBuffer *self, SDL_Window *window, SwapchainTexture *swapchain) {
40+
static bool acquireSwapchainTexture(const CommandBuffer *self, SwapchainTexture *swapchain) {
4041

4142
assert(swapchain);
4243

4344
return SDL_AcquireGPUSwapchainTexture(self->cmd,
44-
window,
45+
self->device->window,
4546
&swapchain->texture,
4647
(Uint32 *) &swapchain->size.w,
4748
(Uint32 *) &swapchain->size.h);
@@ -68,7 +69,7 @@ static CopyPass *beginCopyPass(const CommandBuffer *self) {
6869
SDL_GPUCopyPass *pass = SDL_BeginGPUCopyPass(self->cmd);
6970
GPU_Assert(pass, "SDL_BeginGPUCopyPass");
7071

71-
return $(alloc(CopyPass), init, pass, self->device);
72+
return $(alloc(CopyPass), init, pass, self->device->device);
7273
}
7374

7475
/**
@@ -114,13 +115,15 @@ static void generateMipmaps(const CommandBuffer *self, SDL_GPUTexture *texture)
114115
}
115116

116117
/**
117-
* @fn CommandBuffer *CommandBuffer::initWithCommandBuffer(CommandBuffer *self, SDL_GPUCommandBuffer *cmd)
118+
* @fn CommandBuffer *CommandBuffer::initWithCommandBuffer(CommandBuffer *self, const RenderDevice *device, SDL_GPUCommandBuffer *cmd)
118119
* @memberof CommandBuffer
119120
*/
120-
static CommandBuffer *initWithCommandBuffer(CommandBuffer *self, SDL_GPUCommandBuffer *cmd) {
121+
static CommandBuffer *initWithCommandBuffer(CommandBuffer *self, const RenderDevice *device, SDL_GPUCommandBuffer *cmd) {
121122

122123
self = (CommandBuffer *) super(Object, self, init);
123124
if (self) {
125+
assert(device);
126+
self->device = (RenderDevice *) device;
124127
self->cmd = cmd;
125128
assert(self->cmd);
126129
}
@@ -201,15 +204,15 @@ static SDL_GPUFence *submitAndFence(const CommandBuffer *self) {
201204
}
202205

203206
/**
204-
* @fn bool CommandBuffer::waitAndAcquireSwapchainTexture(const CommandBuffer *self, SDL_Window *window, SwapchainTexture *swapchain)
207+
* @fn bool CommandBuffer::waitAndAcquireSwapchainTexture(const CommandBuffer *self, SwapchainTexture *swapchain)
205208
* @memberof CommandBuffer
206209
*/
207-
static bool waitAndAcquireSwapchainTexture(const CommandBuffer *self, SDL_Window *window, SwapchainTexture *swapchain) {
210+
static bool waitAndAcquireSwapchainTexture(const CommandBuffer *self, SwapchainTexture *swapchain) {
208211

209212
assert(swapchain);
210213

211214
return SDL_WaitAndAcquireGPUSwapchainTexture(self->cmd,
212-
window,
215+
self->device->window,
213216
&swapchain->texture,
214217
(Uint32 *) &swapchain->size.w,
215218
(Uint32 *) &swapchain->size.h);

Sources/ObjectivelyGPU/CommandBuffer.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
typedef struct ComputePass ComputePass;
3636
typedef struct CopyPass CopyPass;
3737
typedef struct RenderPass RenderPass;
38+
typedef struct RenderDevice RenderDevice;
3839
typedef struct CommandBuffer CommandBuffer;
3940
typedef struct CommandBufferInterface CommandBufferInterface;
4041
typedef struct SwapchainTexture SwapchainTexture;
@@ -89,10 +90,9 @@ struct CommandBuffer {
8990
SDL_GPUCommandBuffer *cmd;
9091

9192
/**
92-
* @brief The GPU device, threaded through to pass objects that need it.
93-
* @private
93+
* @brief The RenderDevice that this CommandBuffer belongs to.
9494
*/
95-
SDL_GPUDevice *device;
95+
RenderDevice *device;
9696
};
9797

9898
/**
@@ -106,18 +106,17 @@ struct CommandBufferInterface {
106106
ObjectInterface objectInterface;
107107

108108
/**
109-
* @fn bool CommandBuffer::acquireSwapchainTexture(const CommandBuffer *self, SDL_Window *window, SwapchainTexture *swapchain)
109+
* @fn bool CommandBuffer::acquireSwapchainTexture(const CommandBuffer *self, SwapchainTexture *swapchain)
110110
* @brief Acquires the next swapchain texture for rendering.
111111
* @details Returns `false` (without asserting) when the window is minimised
112112
* or the swapchain is temporarily unavailable. The caller should skip
113113
* rendering for that frame.
114114
* @param self The CommandBuffer.
115-
* @param window The window whose swapchain to acquire.
116115
* @param swapchain Output structure populated with the texture and dimensions.
117116
* @return True on success, false when the swapchain is unavailable this frame.
118117
* @memberof CommandBuffer
119118
*/
120-
bool (*acquireSwapchainTexture)(const CommandBuffer *self, SDL_Window *window, SwapchainTexture *swapchain);
119+
bool (*acquireSwapchainTexture)(const CommandBuffer *self, SwapchainTexture *swapchain);
121120

122121
/**
123122
* @fn ComputePass *CommandBuffer::beginComputePass(const CommandBuffer *self, ...)
@@ -185,14 +184,15 @@ struct CommandBufferInterface {
185184
void (*generateMipmaps)(const CommandBuffer *self, SDL_GPUTexture *texture);
186185

187186
/**
188-
* @fn CommandBuffer *CommandBuffer::initWithCommandBuffer(CommandBuffer *self, SDL_GPUCommandBuffer *cmd)
187+
* @fn CommandBuffer *CommandBuffer::initWithCommandBuffer(CommandBuffer *self, const RenderDevice *device, *SDL_GPUCommandBuffer *cmd)
189188
* @brief Initializes this CommandBuffer wrapping the given SDL command buffer.
190189
* @param self The CommandBuffer.
190+
* @param device The RenderDevice that created this CommandBuffer.
191191
* @param cmd The SDL command buffer to wrap. Must not be NULL.
192192
* @return The initialized CommandBuffer, or NULL on failure.
193193
* @memberof CommandBuffer
194194
*/
195-
CommandBuffer *(*initWithCommandBuffer)(CommandBuffer *self, SDL_GPUCommandBuffer *cmd);
195+
CommandBuffer *(*initWithCommandBuffer)(CommandBuffer *self, const RenderDevice *device, SDL_GPUCommandBuffer *cmd);
196196

197197
/**
198198
* @fn void CommandBuffer::insertDebugLabel(const CommandBuffer *self, const char *text)
@@ -259,17 +259,16 @@ struct CommandBufferInterface {
259259
SDL_GPUFence *(*submitAndFence)(const CommandBuffer *self);
260260

261261
/**
262-
* @fn bool CommandBuffer::waitAndAcquireSwapchainTexture(const CommandBuffer *self, SDL_Window *window, SwapchainTexture *swapchain)
262+
* @fn bool CommandBuffer::waitAndAcquireSwapchainTexture(const CommandBuffer *self, SwapchainTexture *swapchain)
263263
* @brief Blocks until a swapchain texture is available, then acquires it.
264264
* @details Prefer `acquireSwapchainTexture` unless you must guarantee a
265265
* texture this frame (e.g. during resize).
266266
* @param self The CommandBuffer.
267-
* @param window The window whose swapchain to acquire.
268267
* @param swapchain Output structure populated with the texture and dimensions.
269268
* @return True on success, false on error.
270269
* @memberof CommandBuffer
271270
*/
272-
bool (*waitAndAcquireSwapchainTexture)(const CommandBuffer *self, SDL_Window *window, SwapchainTexture *swapchain);
271+
bool (*waitAndAcquireSwapchainTexture)(const CommandBuffer *self, SwapchainTexture *swapchain);
273272
};
274273

275274
/**

Sources/ObjectivelyGPU/RenderDevice.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ static CommandBuffer *acquireCommandBuffer(const RenderDevice *self) {
7373
SDL_GPUCommandBuffer *cmd = SDL_AcquireGPUCommandBuffer(self->device);
7474
GPU_Assert(cmd, "SDL_AcquireGPUCommandBuffer");
7575

76-
CommandBuffer *buffer = $(alloc(CommandBuffer), initWithCommandBuffer, cmd);
77-
buffer->device = self->device;
78-
return buffer;
76+
return $(alloc(CommandBuffer), initWithCommandBuffer, self, cmd);
7977
}
8078

8179
/**

0 commit comments

Comments
 (0)