Harbor

Changelog deb9b627f663

add backend stencil contract

@sky · 1 month ago · parent c4a26f5e2979
0 added 17 modified 0 deleted
backend/backend.odin +36 -0 modified
228 unchanged lines hidden
229 229 Image_Aspect :: enum {
230 230 Color,
231 231 Depth,
232 + Stencil,
232 233 }
233 234 Image_Aspect_Flags :: bit_set[Image_Aspect]
234 235
18 unchanged lines hidden
253 254 Never,
254 255 Less,
255 256 Less_Or_Equal,
257 + Equal,
258 + Greater_Or_Equal,
259 + Greater,
260 + Not_Equal,
256 261 Always,
257 262 }
258 263
264 + Stencil_Op :: enum {
265 + Keep,
266 + Zero,
267 + Replace,
268 + Increment_Clamp,
269 + Decrement_Clamp,
270 + Invert,
271 + }
272 +
273 + Stencil_Face_State :: struct {
274 + fail_op: Stencil_Op,
275 + pass_op: Stencil_Op,
276 + depth_fail_op: Stencil_Op,
277 + compare_op: Compare_Op,
278 + }
279 +
280 + Stencil_State :: struct {
281 + enable: bool,
282 + read_mask: u8,
283 + write_mask: u8,
284 + reference: u8,
285 + front: Stencil_Face_State,
286 + back: Stencil_Face_State,
287 + }
288 +
259 289 Image_Layout :: enum {
260 290 Undefined,
261 291 Color_Attachment,
109 unchanged lines hidden
371 401 blend_mode: Blend_Mode,
372 402 enable_depth_test: bool,
373 403 enable_depth_bias: bool,
404 + depth_format: Format,
405 + stencil: Stencil_State,
374 406 depth_only: bool,
375 407 color_attachment_count: u32,
376 408 color_formats: [MAX_COLOR_TARGETS]Format,
59 unchanged lines hidden
436 468 depth_load_op: Attachment_Load_Op,
437 469 depth_store_op: Attachment_Store_Op,
438 470 depth_final_layout: Image_Layout,
471 + has_stencil: bool,
472 + stencil_load_op: Attachment_Load_Op,
473 + stencil_store_op: Attachment_Store_Op,
439 474 }
440 475
441 476 Framebuffer_Desc :: struct {
16 unchanged lines hidden
458 493 clear_colors: [MAX_COLOR_TARGETS][4]f32,
459 494 clear_color: [4]f32,
460 495 clear_depth: f32,
496 + clear_stencil: u8,
461 497 }
462 498
463 499 // --- Frame context ---
269 unchanged lines hidden
backend/d3d11/d3d11_backend.odin +1 -0 modified
110 unchanged lines hidden
111 111 rasterizer_state: ^d3d11.IRasterizerState,
112 112 blend_state: ^d3d11.IBlendState,
113 113 depth_stencil_state: ^d3d11.IDepthStencilState,
114 + stencil_ref: u32,
114 115 topology: d3d11.PRIMITIVE_TOPOLOGY,
115 116 rasterizer_desc: d3d11.RASTERIZER_DESC,
116 117
482 unchanged lines hidden
backend/d3d11/d3d11_convert.odin +37 -0 modified
132 unchanged lines hidden
133 133 return .LESS
134 134 case .Less_Or_Equal:
135 135 return .LESS_EQUAL
136 + case .Equal:
137 + return .EQUAL
138 + case .Greater_Or_Equal:
139 + return .GREATER_EQUAL
140 + case .Greater:
141 + return .GREATER
142 + case .Not_Equal:
143 + return .NOT_EQUAL
136 144 case .Always:
137 145 return .ALWAYS
138 146 }
139 147 return .ALWAYS
140 148 }
141 149
150 + @(private)
151 + to_d3d11_stencil_op :: proc(op: bk.Stencil_Op) -> d3d11.STENCIL_OP {
152 + switch op {
153 + case .Keep:
154 + return .KEEP
155 + case .Zero:
156 + return .ZERO
157 + case .Replace:
158 + return .REPLACE
159 + case .Increment_Clamp:
160 + return .INCR_SAT
161 + case .Decrement_Clamp:
162 + return .DECR_SAT
163 + case .Invert:
164 + return .INVERT
165 + }
166 + return .KEEP
167 + }
168 +
169 + @(private)
170 + to_d3d11_stencil_face :: proc(face: bk.Stencil_Face_State) -> d3d11.DEPTH_STENCILOP_DESC {
171 + return {
172 + StencilFailOp = to_d3d11_stencil_op(face.fail_op),
173 + StencilDepthFailOp = to_d3d11_stencil_op(face.depth_fail_op),
174 + StencilPassOp = to_d3d11_stencil_op(face.pass_op),
175 + StencilFunc = to_d3d11_compare_func(face.compare_op),
176 + }
177 + }
178 +
142 179 // --- Vertex format conversion ---
143 180
144 181 @(private)
59 unchanged lines hidden
backend/d3d11/d3d11_frame.odin +5 -1 modified
207 unchanged lines hidden
208 208 }
209 209
210 210 if fb_entry.dsv != nil {
211 - g_d3d.ctx->ClearDepthStencilView(fb_entry.dsv, {.DEPTH}, desc.clear_depth, 0)
211 + clear_flags := d3d11.CLEAR_FLAGS{.DEPTH}
212 + if pass, pass_ok := render_pass_entry(desc.pass); pass_ok && pass.desc.has_stencil {
213 + clear_flags += {.STENCIL}
214 + }
215 + g_d3d.ctx->ClearDepthStencilView(fb_entry.dsv, clear_flags, desc.clear_depth, u8(desc.clear_stencil))
212 216 }
213 217
214 218 // Set viewport
111 unchanged lines hidden
backend/d3d11/d3d11_ops.odin modified

Diff hidden because this file has more than 800 lines.

backend/d3d12/d3d12_backend.odin modified

Diff hidden because this file has more than 800 lines.

backend/d3d12/d3d12_convert.odin +37 -0 modified
146 unchanged lines hidden
147 147 return .LESS
148 148 case .Less_Or_Equal:
149 149 return .LESS_EQUAL
150 + case .Equal:
151 + return .EQUAL
152 + case .Greater_Or_Equal:
153 + return .GREATER_EQUAL
154 + case .Greater:
155 + return .GREATER
156 + case .Not_Equal:
157 + return .NOT_EQUAL
150 158 case .Always:
151 159 return .ALWAYS
152 160 }
153 161 return .ALWAYS
154 162 }
155 163
164 + @(private)
165 + to_d3d12_stencil_op :: proc(op: bk.Stencil_Op) -> d3d12.STENCIL_OP {
166 + switch op {
167 + case .Keep:
168 + return .KEEP
169 + case .Zero:
170 + return .ZERO
171 + case .Replace:
172 + return .REPLACE
173 + case .Increment_Clamp:
174 + return .INCR_SAT
175 + case .Decrement_Clamp:
176 + return .DECR_SAT
177 + case .Invert:
178 + return .INVERT
179 + }
180 + return .KEEP
181 + }
182 +
183 + @(private)
184 + to_d3d12_stencil_face :: proc(face: bk.Stencil_Face_State) -> d3d12.DEPTH_STENCILOP_DESC {
185 + return {
186 + StencilFailOp = to_d3d12_stencil_op(face.fail_op),
187 + StencilDepthFailOp = to_d3d12_stencil_op(face.depth_fail_op),
188 + StencilPassOp = to_d3d12_stencil_op(face.pass_op),
189 + StencilFunc = to_d3d12_compare_func(face.compare_op),
190 + }
191 + }
192 +
156 193 // --- Vertex format conversion ---
157 194
158 195 @(private)
58 unchanged lines hidden
backend/d3d12/d3d12_frame.odin +6 -2 modified
267 unchanged lines hidden
268 268 }
269 269
270 270 if has_dsv {
271 + clear_flags := d3d12.CLEAR_FLAGS{.DEPTH}
272 + if pass, pass_ok := render_pass_entry(desc.pass); pass_ok && pass.desc.has_stencil {
273 + clear_flags += {.STENCIL}
274 + }
271 275 g_d3d.command_list->ClearDepthStencilView(
272 276 dsv_handle,
273 - {.DEPTH},
277 + clear_flags,
274 278 desc.clear_depth,
275 - 0,
279 + u8(desc.clear_stencil),
276 280 0,
277 281 nil,
278 282 )
110 unchanged lines hidden
backend/d3d12/d3d12_ops.odin modified

Diff hidden because this file has more than 800 lines.

backend/opengl/gl_backend.odin +1 -0 modified
72 unchanged lines hidden
73 73 blend_mode: bk.Blend_Mode,
74 74 enable_depth_test: bool,
75 75 enable_depth_bias: bool,
76 + stencil: bk.Stencil_State,
76 77 cull_mode: bk.Cull_Mode,
77 78 front_face: bk.Front_Face,
78 79 vertex_stride: u32,
235 unchanged lines hidden
backend/opengl/gl_convert.odin +26 -0 modified
96 unchanged lines hidden
97 97 return gl.LESS
98 98 case .Less_Or_Equal:
99 99 return gl.LEQUAL
100 + case .Equal:
101 + return gl.EQUAL
102 + case .Greater_Or_Equal:
103 + return gl.GEQUAL
104 + case .Greater:
105 + return gl.GREATER
106 + case .Not_Equal:
107 + return gl.NOTEQUAL
100 108 case .Always:
101 109 return gl.ALWAYS
102 110 }
103 111 return gl.ALWAYS
104 112 }
105 113
114 + to_gl_stencil_op :: proc(op: bk.Stencil_Op) -> i32 {
115 + switch op {
116 + case .Keep:
117 + return gl.KEEP
118 + case .Zero:
119 + return gl.ZERO
120 + case .Replace:
121 + return gl.REPLACE
122 + case .Increment_Clamp:
123 + return gl.INCR
124 + case .Decrement_Clamp:
125 + return gl.DECR
126 + case .Invert:
127 + return gl.INVERT
128 + }
129 + return gl.KEEP
130 + }
131 +
106 132 format_pixel_size :: proc(format: bk.Format) -> u32 {
107 133 switch format {
108 134 case .R8G8B8A8_SRGB, .R8G8B8A8_UNORM, .B8G8R8A8_SRGB:
34 unchanged lines hidden
backend/opengl/gl_frame.odin +3 -0 modified
47 unchanged lines hidden
48 48 gl.BindFramebuffer(gl.FRAMEBUFFER, fb.id)
49 49 gl.Viewport(0, 0, i32(desc.width), i32(desc.height))
50 50 gl.ClearDepth(f64(desc.clear_depth))
51 + gl.ClearStencil(i32(desc.clear_stencil))
51 52 mask := u32(0)
52 53 pass, pass_ok := render_pass_entry(desc.pass)
53 54 if pass_ok {
54 55 if pass.desc.has_depth do mask |= gl.DEPTH_BUFFER_BIT
56 + if pass.desc.has_stencil do mask |= gl.STENCIL_BUFFER_BIT
55 57 } else {
56 58 mask = gl.DEPTH_BUFFER_BIT
57 59 }
3 unchanged lines hidden
61 63 gl.ClearBufferfv(gl.COLOR, i32(i), &clear[0])
62 64 }
63 65 }
66 + if mask & gl.STENCIL_BUFFER_BIT != 0 do gl.StencilMask(0xFF)
64 67 if mask != 0 do gl.Clear(mask)
65 68 g_gl.render_pass_active = true
66 69 }
18 unchanged lines hidden
backend/opengl/gl_ops.odin modified

Diff hidden because this file has more than 800 lines.

backend/vulkan/vk_convert.odin +41 -0 modified
139 unchanged lines hidden
140 140 result: vk.ImageAspectFlags
141 141 if .Color in flags {result += {.COLOR}}
142 142 if .Depth in flags {result += {.DEPTH}}
143 + if .Stencil in flags {result += {.STENCIL}}
143 144 return result
144 145 }
145 146
77 unchanged lines hidden
223 224 return .LESS
224 225 case .Less_Or_Equal:
225 226 return .LESS_OR_EQUAL
227 + case .Equal:
228 + return .EQUAL
229 + case .Greater_Or_Equal:
230 + return .GREATER_OR_EQUAL
231 + case .Greater:
232 + return .GREATER
233 + case .Not_Equal:
234 + return .NOT_EQUAL
226 235 case .Always:
227 236 return .ALWAYS
228 237 }
229 238 return .ALWAYS
230 239 }
231 240
241 + @(private)
242 + to_vk_stencil_op :: proc(op: bk.Stencil_Op) -> vk.StencilOp {
243 + switch op {
244 + case .Keep:
245 + return .KEEP
246 + case .Zero:
247 + return .ZERO
248 + case .Replace:
249 + return .REPLACE
250 + case .Increment_Clamp:
251 + return .INCREMENT_AND_CLAMP
252 + case .Decrement_Clamp:
253 + return .DECREMENT_AND_CLAMP
254 + case .Invert:
255 + return .INVERT
256 + }
257 + return .KEEP
258 + }
259 +
260 + @(private)
261 + to_vk_stencil_face :: proc(face: bk.Stencil_Face_State, state: bk.Stencil_State) -> vk.StencilOpState {
262 + return {
263 + failOp = to_vk_stencil_op(face.fail_op),
264 + passOp = to_vk_stencil_op(face.pass_op),
265 + depthFailOp = to_vk_stencil_op(face.depth_fail_op),
266 + compareOp = to_vk_compare_op(face.compare_op),
267 + compareMask = u32(state.read_mask),
268 + writeMask = u32(state.write_mask),
269 + reference = u32(state.reference),
270 + }
271 + }
272 +
232 273 // --- Descriptor conversion ---
233 274
234 275 @(private)
45 unchanged lines hidden
backend/vulkan/vk_ops.odin modified

Diff hidden because this file has more than 800 lines.

compiler/executor.odin modified

Diff hidden because this file has more than 800 lines.

pipeline/graphics.odin +59 -1 modified
21 unchanged lines hidden
22 22 blend_mode: bk.Blend_Mode,
23 23 enable_depth_test: bool,
24 24 enable_depth_bias: bool,
25 + stencil: bk.Stencil_State,
25 26 depth_only: bool, // no color attachment (shadow pass)
26 27 color_attachment_count: u32,
27 28 push_constant_size: u32,
90 unchanged lines hidden
118 119 depthWriteEnable = b32(config.enable_depth_test),
119 120 depthCompareOp = .LESS,
120 121 depthBoundsTestEnable = false,
121 - stencilTestEnable = false,
122 + stencilTestEnable = b32(config.stencil.enable),
123 + front = to_vk_stencil_face(config.stencil.front, config.stencil),
124 + back = to_vk_stencil_face(config.stencil.back, config.stencil),
122 125 }
123 126
124 127 // Color blend attachments
104 unchanged lines hidden
229 232 }
230 233 return .ONE
231 234 }
235 +
236 + @(private)
237 + to_vk_compare_op :: proc(op: bk.Compare_Op) -> vk.CompareOp {
238 + switch op {
239 + case .Never:
240 + return .NEVER
241 + case .Less:
242 + return .LESS
243 + case .Less_Or_Equal:
244 + return .LESS_OR_EQUAL
245 + case .Equal:
246 + return .EQUAL
247 + case .Greater_Or_Equal:
248 + return .GREATER_OR_EQUAL
249 + case .Greater:
250 + return .GREATER
251 + case .Not_Equal:
252 + return .NOT_EQUAL
253 + case .Always:
254 + return .ALWAYS
255 + }
256 + return .ALWAYS
257 + }
258 +
259 + @(private)
260 + to_vk_stencil_op :: proc(op: bk.Stencil_Op) -> vk.StencilOp {
261 + switch op {
262 + case .Keep:
263 + return .KEEP
264 + case .Zero:
265 + return .ZERO
266 + case .Replace:
267 + return .REPLACE
268 + case .Increment_Clamp:
269 + return .INCREMENT_AND_CLAMP
270 + case .Decrement_Clamp:
271 + return .DECREMENT_AND_CLAMP
272 + case .Invert:
273 + return .INVERT
274 + }
275 + return .KEEP
276 + }
277 +
278 + @(private)
279 + to_vk_stencil_face :: proc(face: bk.Stencil_Face_State, state: bk.Stencil_State) -> vk.StencilOpState {
280 + return {
281 + failOp = to_vk_stencil_op(face.fail_op),
282 + passOp = to_vk_stencil_op(face.pass_op),
283 + depthFailOp = to_vk_stencil_op(face.depth_fail_op),
284 + compareOp = to_vk_compare_op(face.compare_op),
285 + compareMask = u32(state.read_mask),
286 + writeMask = u32(state.write_mask),
287 + reference = u32(state.reference),
288 + }
289 + }