Harbor

Changelog ac3743d2ae7e

pin gpu mrt descriptor arrays

@sky · 1 month ago · parent b756a91c2399
0 added 14 modified 0 deleted
gpu/backend/backend.odin +14 -0 modified
22 unchanged lines hidden
23 23 NULL_SAMPLER :: Sampler_Handle(0)
24 24
25 25 MAX_FRAMES_IN_FLIGHT :: 2
26 + MAX_COLOR_TARGETS :: 8
27 + COLOR_WRITE_MASK_ALL :: u8(0x0F)
26 28
27 29 Capability :: enum {
28 30 Compute_Dispatch,
302 unchanged lines hidden
331 333 enable_depth_test: bool,
332 334 enable_depth_bias: bool,
333 335 depth_only: bool,
336 + color_attachment_count: u32,
337 + color_formats: [MAX_COLOR_TARGETS]Format,
338 + color_write_masks: [MAX_COLOR_TARGETS]u8,
334 339 push_constant_size: u32,
335 340 push_constant_stages: Shader_Stage_Flags,
336 341 descriptor_layouts: []Descriptor_Handle,
35 unchanged lines hidden
372 377 Render_Pass_Desc :: struct {
373 378 has_color: bool,
374 379 has_depth: bool,
380 + color_count: u32,
381 + color_formats: [MAX_COLOR_TARGETS]Format,
382 + color_load_ops: [MAX_COLOR_TARGETS]Attachment_Load_Op,
383 + color_store_ops: [MAX_COLOR_TARGETS]Attachment_Store_Op,
384 + color_final_layouts: [MAX_COLOR_TARGETS]Image_Layout,
375 385 color_format: Format,
376 386 depth_format: Format,
377 387 depth_only: bool, // depth-only pass (shadows)
7 unchanged lines hidden
385 395
386 396 Framebuffer_Desc :: struct {
387 397 pass: Render_Pass_Handle,
398 + color_count: u32,
399 + color_views: [MAX_COLOR_TARGETS]Texture_Handle,
388 400 color_view: Texture_Handle,
389 401 depth_view: Texture_Handle,
390 402 width: u32,
6 unchanged lines hidden
397 409 framebuffer: Framebuffer_Handle,
398 410 width: u32,
399 411 height: u32,
412 + color_count: u32,
413 + clear_colors: [MAX_COLOR_TARGETS][4]f32,
400 414 clear_color: [4]f32,
401 415 clear_depth: f32,
402 416 }
246 unchanged lines hidden
gpu/backend/d3d11/d3d11_backend.odin +10 -7 modified
165 unchanged lines hidden
166 166 }
167 167
168 168 D3D11_Framebuffer_Entry :: struct {
169 - rtv: ^d3d11.IRenderTargetView,
170 - dsv: ^d3d11.IDepthStencilView,
171 - color_tex: bk.Texture_Handle,
172 - depth_tex: bk.Texture_Handle,
173 - width: u32,
174 - height: u32,
175 - active: bool,
169 + rtv: ^d3d11.IRenderTargetView,
170 + rtvs: [bk.MAX_COLOR_TARGETS]^d3d11.IRenderTargetView,
171 + rtv_count: u32,
172 + dsv: ^d3d11.IDepthStencilView,
173 + color_tex: bk.Texture_Handle,
174 + color_texs: [bk.MAX_COLOR_TARGETS]bk.Texture_Handle,
175 + depth_tex: bk.Texture_Handle,
176 + width: u32,
177 + height: u32,
178 + active: bool,
176 179 }
177 180
178 181 D3D11_Sampler_Entry :: struct {
413 unchanged lines hidden
gpu/backend/d3d11/d3d11_frame.odin +6 -4 modified
196 unchanged lines hidden
197 197 if !fb_ok {return}
198 198
199 199 // Set render targets
200 - if fb_entry.rtv != nil {
201 - g_d3d.ctx->OMSetRenderTargets(1, &fb_entry.rtv, fb_entry.dsv)
202 - cc := desc.clear_color
203 - g_d3d.ctx->ClearRenderTargetView(fb_entry.rtv, &cc)
200 + if fb_entry.rtv_count > 0 {
201 + g_d3d.ctx->OMSetRenderTargets(fb_entry.rtv_count, &fb_entry.rtvs[0], fb_entry.dsv)
202 + for i in 0..<fb_entry.rtv_count {
203 + cc := desc.clear_colors[i] if desc.color_count > 0 else desc.clear_color
204 + g_d3d.ctx->ClearRenderTargetView(fb_entry.rtvs[i], &cc)
205 + }
204 206 } else {
205 207 g_d3d.ctx->OMSetRenderTargets(0, nil, fb_entry.dsv)
206 208 }
117 unchanged lines hidden
gpu/backend/d3d11/d3d11_ops.odin modified

Diff hidden because this file has more than 800 lines.

gpu/backend/d3d12/d3d12_backend.odin modified

Diff hidden because this file has more than 800 lines.

gpu/backend/d3d12/d3d12_frame.odin +17 -11 modified
224 unchanged lines hidden
225 225 pass_entry, pass_ok := render_pass_entry(desc.pass)
226 226 is_depth_only := pass_ok && pass_entry.desc.depth_only
227 227
228 - rtv_handle: d3d12.CPU_DESCRIPTOR_HANDLE
229 - has_rtv := false
230 - if fb_entry.color_tex != bk.NULL_TEXTURE {
231 - if tex_entry, tex_ok := texture_entry(fb_entry.color_tex); tex_ok && tex_entry.has_rtv {
228 + rtv_handles: [bk.MAX_COLOR_TARGETS]d3d12.CPU_DESCRIPTOR_HANDLE
229 + rtv_count: u32
230 + for i in 0..<fb_entry.color_count {
231 + color_tex := fb_entry.color_texs[i]
232 + if color_tex == bk.NULL_TEXTURE {
233 + continue
234 + }
235 + if tex_entry, tex_ok := texture_entry(color_tex); tex_ok && tex_entry.has_rtv {
232 236 if tex_entry.state != {.RENDER_TARGET} {
233 237 transition_resource(tex_entry.resource, tex_entry.state, {.RENDER_TARGET})
234 238 tex_entry.state = {.RENDER_TARGET}
235 239 }
236 - rtv_handle = get_rtv_cpu_handle(tex_entry.rtv_index)
237 - has_rtv = true
240 + rtv_handles[rtv_count] = get_rtv_cpu_handle(tex_entry.rtv_index)
241 + rtv_count += 1
238 242 }
239 243 }
240 244
12 unchanged lines hidden
253 257 }
254 258 }
255 259
256 - if is_depth_only || !has_rtv {
260 + if is_depth_only || rtv_count == 0 {
257 261 g_d3d.command_list->OMSetRenderTargets(0, nil, false, &dsv_handle if has_dsv else nil)
258 262 } else {
259 263 g_d3d.command_list->OMSetRenderTargets(
260 - 1,
261 - &rtv_handle,
264 + rtv_count,
265 + &rtv_handles[0],
262 266 false,
263 267 &dsv_handle if has_dsv else nil,
264 268 )
265 - cc := desc.clear_color
266 - g_d3d.command_list->ClearRenderTargetView(rtv_handle, &cc, 0, nil)
269 + for i in 0..<rtv_count {
270 + cc := desc.clear_colors[i] if desc.color_count > 0 else desc.clear_color
271 + g_d3d.command_list->ClearRenderTargetView(rtv_handles[i], &cc, 0, nil)
272 + }
267 273 }
268 274
269 275 if has_dsv {
118 unchanged lines hidden
gpu/backend/d3d12/d3d12_ops.odin modified

Diff hidden because this file has more than 800 lines.

gpu/backend/opengl/gl_backend.odin +8 -6 modified
110 unchanged lines hidden
111 111 }
112 112
113 113 GL_Framebuffer_Entry :: struct {
114 - id: u32,
115 - color_tex: bk.Texture_Handle,
116 - depth_tex: bk.Texture_Handle,
117 - width: u32,
118 - height: u32,
119 - active: bool,
114 + id: u32,
115 + color_tex: bk.Texture_Handle,
116 + color_texs: [bk.MAX_COLOR_TARGETS]bk.Texture_Handle,
117 + color_count: u32,
118 + depth_tex: bk.Texture_Handle,
119 + width: u32,
120 + height: u32,
121 + active: bool,
120 122 }
121 123
122 124 GL_Sampler_Entry :: struct {
183 unchanged lines hidden
gpu/backend/opengl/gl_frame.odin +7 -8 modified
46 unchanged lines hidden
47 47 }
48 48 gl.BindFramebuffer(gl.FRAMEBUFFER, fb.id)
49 49 gl.Viewport(0, 0, i32(desc.width), i32(desc.height))
50 - gl.ClearColor(
51 - desc.clear_color[0],
52 - desc.clear_color[1],
53 - desc.clear_color[2],
54 - desc.clear_color[3],
55 - )
56 50 gl.ClearDepth(f64(desc.clear_depth))
57 51 mask := u32(0)
58 52 pass, pass_ok := render_pass_entry(desc.pass)
59 53 if pass_ok {
60 - if pass.desc.has_color do mask |= gl.COLOR_BUFFER_BIT
61 54 if pass.desc.has_depth do mask |= gl.DEPTH_BUFFER_BIT
62 55 } else {
63 - mask = gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT
56 + mask = gl.DEPTH_BUFFER_BIT
64 57 }
58 + if fb.color_count > 0 {
59 + for i in 0..<fb.color_count {
60 + clear := desc.clear_colors[i] if desc.color_count > 0 else desc.clear_color
61 + gl.ClearBufferfv(gl.COLOR, i32(i), &clear[0])
62 + }
63 + }
65 64 if mask != 0 do gl.Clear(mask)
66 65 g_gl.render_pass_active = true
67 66 }
18 unchanged lines hidden
gpu/backend/opengl/gl_ops.odin modified

Diff hidden because this file has more than 800 lines.

gpu/backend/vulkan/vk_ops.odin modified

Diff hidden because this file has more than 800 lines.

gpu/compiler/executor.odin modified

Diff hidden because this file has more than 800 lines.

gpu/pipeline/graphics.odin +22 -12 modified
22 unchanged lines hidden
23 23 enable_depth_test: bool,
24 24 enable_depth_bias: bool,
25 25 depth_only: bool, // no color attachment (shadow pass)
26 + color_attachment_count: u32,
26 27 push_constant_size: u32,
27 28 push_constant_stages: vk.ShaderStageFlags,
28 29 descriptor_set_layouts: []vk.DescriptorSetLayout,
91 unchanged lines hidden
120 121 stencilTestEnable = false,
121 122 }
122 123
123 - // Color blend attachment
124 - blend_attachment := vk.PipelineColorBlendAttachmentState {
125 - colorWriteMask = {.R, .G, .B, .A},
124 + // Color blend attachments
125 + blend_attachments: [bk.MAX_COLOR_TARGETS]vk.PipelineColorBlendAttachmentState
126 + attachment_count := config.color_attachment_count
127 + if !config.depth_only && attachment_count == 0 {
128 + attachment_count = 1
126 129 }
130 + for i in 0..<attachment_count {
131 + blend_attachments[i] = vk.PipelineColorBlendAttachmentState {
132 + colorWriteMask = {.R, .G, .B, .A},
133 + }
134 + }
127 135 if config.enable_blending {
128 136 factors := bk.blend_factors(config.blend_mode)
129 - blend_attachment.blendEnable = true
130 - blend_attachment.colorBlendOp = .ADD
131 - blend_attachment.srcColorBlendFactor = to_vk_blend_factor(factors.src_color)
132 - blend_attachment.dstColorBlendFactor = to_vk_blend_factor(factors.dst_color)
133 - blend_attachment.srcAlphaBlendFactor = to_vk_blend_factor(factors.src_alpha)
134 - blend_attachment.dstAlphaBlendFactor = to_vk_blend_factor(factors.dst_alpha)
135 - blend_attachment.alphaBlendOp = .ADD
137 + for i in 0..<attachment_count {
138 + blend_attachments[i].blendEnable = true
139 + blend_attachments[i].colorBlendOp = .ADD
140 + blend_attachments[i].srcColorBlendFactor = to_vk_blend_factor(factors.src_color)
141 + blend_attachments[i].dstColorBlendFactor = to_vk_blend_factor(factors.dst_color)
142 + blend_attachments[i].srcAlphaBlendFactor = to_vk_blend_factor(factors.src_alpha)
143 + blend_attachments[i].dstAlphaBlendFactor = to_vk_blend_factor(factors.dst_alpha)
144 + blend_attachments[i].alphaBlendOp = .ADD
145 + }
136 146 }
137 147
138 148 color_blend := vk.PipelineColorBlendStateCreateInfo {
139 149 sType = .PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
140 150 logicOpEnable = false,
141 - attachmentCount = config.depth_only ? 0 : 1,
142 - pAttachments = config.depth_only ? nil : &blend_attachment,
151 + attachmentCount = config.depth_only ? 0 : attachment_count,
152 + pAttachments = config.depth_only ? nil : &blend_attachments[0],
143 153 }
144 154
145 155 // Pipeline layout with optional push constants
76 unchanged lines hidden
gpu/tests/recording_backend.odin +16 -4 modified
45 unchanged lines hidden
46 46 descriptor: bk.Descriptor_Handle,
47 47 descriptor_index: u32,
48 48 buffer: bk.Buffer_Handle,
49 + color_count: u32,
50 + color_formats: [bk.MAX_COLOR_TARGETS]bk.Format,
51 + color_views: [bk.MAX_COLOR_TARGETS]bk.Texture_Handle,
52 + clear_colors: [bk.MAX_COLOR_TARGETS][4]f32,
49 53
50 54 push_constant_size: u32,
51 55 push_constant_bytes: [compiler.IMPORTED_PUSH_CONSTANT_CAP]u8,
177 unchanged lines hidden
229 233 }
230 234
231 235 recording_begin_render_pass :: proc(ctx: bk.Frame_Context, desc: bk.Render_Pass_Begin_Desc) {
232 - _ = desc
233 236 if recording_active != nil {
234 237 recording_active.begin_pass_count += 1
235 238 }
236 - recording_record({kind = .Begin_Render_Pass, frame_index = ctx.frame_index})
239 + recording_record({
240 + kind = .Begin_Render_Pass,
241 + frame_index = ctx.frame_index,
242 + color_count = desc.color_count,
243 + clear_colors = desc.clear_colors,
244 + })
237 245 }
238 246
239 247 recording_begin_default_pass :: proc(ctx: bk.Frame_Context, clear_color: [4]f32) {
115 unchanged lines hidden
355 363 }
356 364
357 365 recording_create_graphics_pipeline :: proc(desc: bk.Pipeline_Desc) -> (bk.Pipeline_Handle, bool) {
358 - _ = desc
359 366 rec := recording_active
360 367 if rec == nil {
361 368 return bk.NULL_PIPELINE, false
362 369 }
363 370 handle := bk.Pipeline_Handle(rec.next_pipeline)
364 371 rec.next_pipeline += 1
365 - recording_record({kind = .Create_Graphics_Pipeline, pipeline = handle})
372 + recording_record({
373 + kind = .Create_Graphics_Pipeline,
374 + pipeline = handle,
375 + color_count = desc.color_attachment_count,
376 + color_formats = desc.color_formats,
377 + })
366 378 return handle, true
367 379 }
368 380
135 unchanged lines hidden