1+ //! This software blitter is highly inspired by SwiftShaders one
2+
13const std = @import ("std" );
24const vk = @import ("vulkan" );
35const base = @import ("base" );
@@ -13,15 +15,90 @@ pub const init: Self = .{
1315 .blit_mutex = .{},
1416};
1517
16- pub fn clear (self : * Self , pixel : * const anyopaque , format : vk.Format , dest : * SoftImage , view_format : vk.Format , range : vk.ImageSubresourceRange , area : ? vk.Rect2D ) void {
18+ pub fn clear (self : * Self , pixel : vk.ClearValue , format : vk.Format , dest : * SoftImage , view_format : vk.Format , range : vk.ImageSubresourceRange , area : ? vk.Rect2D ) void {
1719 const dst_format = base .Image .formatFromAspect (view_format , range .aspect_mask );
1820 if (dst_format == .undefined ) {
1921 return ;
2022 }
2123
24+ const view_format_value : c_uint = @intCast (@intFromEnum (view_format ));
25+
26+ var clamped_pixel : vk.ClearValue = pixel ;
27+ if (base .vku .vkuFormatIsSINT (view_format_value ) or base .vku .vkuFormatIsUINT (view_format_value )) {
28+ const min_value : f32 = if (base .vku .vkuFormatIsSNORM (view_format_value )) -1.0 else 0.0 ;
29+
30+ if (range .aspect_mask .color_bit ) {
31+ clamped_pixel .color .float_32 [0 ] = std .math .clamp (pixel .color .float_32 [0 ], min_value , 1.0 );
32+ clamped_pixel .color .float_32 [1 ] = std .math .clamp (pixel .color .float_32 [1 ], min_value , 1.0 );
33+ clamped_pixel .color .float_32 [2 ] = std .math .clamp (pixel .color .float_32 [2 ], min_value , 1.0 );
34+ clamped_pixel .color .float_32 [3 ] = std .math .clamp (pixel .color .float_32 [3 ], min_value , 1.0 );
35+ }
36+
37+ // Stencil never requires clamping, so we can check for Depth only
38+ if (range .aspect_mask .depth_bit ) {
39+ clamped_pixel .depth_stencil .depth = std .math .clamp (pixel .depth_stencil .depth , min_value , 1.0 );
40+ }
41+ }
42+
43+ if (self .fastClear (clamped_pixel , format , dest , dst_format , range , area )) {
44+ return ;
45+ }
46+ base .logger .fixme ("implement slow clear" , .{});
47+ }
48+
49+ fn fastClear (self : * Self , clear_value : vk.ClearValue , clear_format : vk.Format , dest : * SoftImage , view_format : vk.Format , range : vk.ImageSubresourceRange , render_area : ? vk.Rect2D ) bool {
2250 _ = self ;
23- _ = pixel ;
24- _ = format ;
25- _ = dest ;
26- _ = area ;
51+ _ = render_area ;
52+ _ = range ;
53+
54+ if (clear_format != .r32g32b32a32_sfloat and clear_format != .d32_sfloat and clear_format != .s8_uint ) {
55+ return false ;
56+ }
57+
58+ const ClearValue = union {
59+ rgba : struct { r : f32 , g : f32 , b : f32 , a : f32 },
60+ rgb : [3 ]f32 ,
61+ d : f32 ,
62+ d_as_u32 : u32 ,
63+ s : u32 ,
64+ };
65+
66+ const c : * const ClearValue = @ptrCast (& clear_value );
67+
68+ var pack : u32 = 0 ;
69+ switch (view_format ) {
70+ .r5g6b5_unorm_pack16 = > pack = @as (u16 , @intFromFloat (31.0 * c .rgba .b + 0.5 )) | (@as (u16 , @intFromFloat (63.0 * c .rgba .g + 0.5 )) << 5 ) | (@as (u16 , @intFromFloat (31.0 * c .rgba .r + 0.5 )) << 11 ),
71+ .b5g6r5_unorm_pack16 = > pack = @as (u16 , @intFromFloat (31.0 * c .rgba .r + 0.5 )) | (@as (u16 , @intFromFloat (63.0 * c .rgba .g + 0.5 )) << 5 ) | (@as (u16 , @intFromFloat (31.0 * c .rgba .b + 0.5 )) << 11 ),
72+
73+ .a8b8g8r8_uint_pack32 ,
74+ .a8b8g8r8_unorm_pack32 ,
75+ .r8g8b8a8_unorm ,
76+ = > pack = (@as (u32 , @intFromFloat (255.0 * c .rgba .a + 0.5 )) << 24 ) | (@as (u32 , @intFromFloat (255.0 * c .rgba .b + 0.5 )) << 16 ) | (@as (u32 , @intFromFloat (255.0 * c .rgba .g + 0.5 )) << 8 ) | @as (u32 , @intFromFloat (255.0 * c .rgba .r + 0.5 )),
77+
78+ .b8g8r8a8_unorm = > pack = (@as (u32 , @intFromFloat (255.0 * c .rgba .a + 0.5 )) << 24 ) | (@as (u32 , @intFromFloat (255.0 * c .rgba .r + 0.5 )) << 16 ) | (@as (u32 , @intFromFloat (255.0 * c .rgba .g + 0.5 )) << 8 ) | @as (u32 , @intFromFloat (255.0 * c .rgba .b + 0.5 )),
79+ //.b10g11r11_ufloat_pack32 => pack = R11G11B10F(c.rgb),
80+ //.e5b9g9r9_ufloat_pack32 => pack = RGB9E5(c.rgb),
81+ .d32_sfloat = > {
82+ std .debug .assert (clear_format == .d32_sfloat );
83+ pack = c .d_as_u32 ; // float reinterpreted as uint32
84+ },
85+ .s8_uint = > {
86+ std .debug .assert (clear_format == .s8_uint );
87+ pack = @as (u8 , @intCast (c .s ));
88+ },
89+ else = > return false ,
90+ }
91+
92+ if (dest .interface .memory ) | memory | {
93+ const image_size = dest .interface .getTotalSize ();
94+ const memory_map = memory .map (dest .interface .memory_offset , image_size ) catch return false ;
95+ defer memory .unmap ();
96+
97+ const memory_map_as_u32 : []u32 = @as ([* ]u32 , @ptrCast (@alignCast (memory_map )))[0.. @divExact (image_size , 4 )];
98+
99+ @memset (memory_map_as_u32 , pack );
100+
101+ return true ;
102+ }
103+ return false ;
27104}
0 commit comments