| … | 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 | ||
| … | 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 | ||
| … | 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 | ||
| … | 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 | ||
Diff hidden because this file has more than 800 lines.
Diff hidden because this file has more than 800 lines.
| … | 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 | ||
| … | 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 | ||
Diff hidden because this file has more than 800 lines.
| … | 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 | ||
| … | 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 | ||
| … | 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 | ||
Diff hidden because this file has more than 800 lines.
| … | 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 | ||
Diff hidden because this file has more than 800 lines.
Diff hidden because this file has more than 800 lines.
| … | 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 | + | } | |