1 type DrawPushConstant = struct 2 object_index : u32 3 4 type Renderer 5 let render (objects : Slice<Object> 6 scene_descriptor_set : DescriptorSet 7 framebuffer : Framebuffer 8 color_load_op : EnterOp 9 color_store_op : ExitOp 10 depth_load_op : EnterOp 11 depth_store_op : ExitOp 12 clear_colors : Slice<Vector4>) = 13 let render_pass = draw/begin framebuffer color_load_op color_store_op 14 depth_load_op depth_store_op clear_colors 15 16 if lighting.descriptor_set <> null then 17 draw/bind_descriptor_set lighting.descriptor_set Renderer.lighting_set 18 19 draw/bind_descriptor_set scene_descriptor_set Renderer.scene_set 20 21 let is_depth = framebuffer.format.attachments 22 |> all { is_depth_format _.format } 23 24 let mut previous_material_descriptor_set = null 25 let mut previous_pipeline = null 26 27 for i = 0 until objects.size do 28 let object = objects[i] 29 let mesh = object.mesh 30 let vertex_format = mesh.format 31 if mesh.index_count == 0 32 || object.material.vertex_shader == "" 33 || object.material.fragment_shader == "" 34 then 35 continue 36 37 do 38 let scissor = vulkan.framebuffer_scissor.intersect object.scissor 39 vulkan.command_buffer.scissor scissor 40 41 let (vertex_shader, fragment_shader) = if is_depth then 42 if vertex_format == VertexFormat.regular then 43 vulkan.depth_shader 44 else 45 assert vertex_format == VertexFormat.skinned 46 vulkan.depth_skinned_shader 47 else 48 (vulkan.get_shader object.material.vertex_shader as VertexShader 49 vulkan.get_shader object.material.fragment_shader as FragmentShader) 50 51 draw/bind_vertex_buffer mesh.vertex_buffer 52 draw/bind_index_buffer mesh.index_buffer 0 mesh.index_count 53 54 let pipeline_cache = 55 let settings = PipelineSettings =vertex_shader =fragment_shader 56 =cull_mode 57 vulkan.pipeline_cache settings 58 59 let pipeline = pipeline_cache.get vertex_format render_pass 60 let material_descriptor_set = if 61 is_depth 62 || pipeline_cache.pipeline_layout.descriptor_set_layouts.size 63 <= Renderer.material_set 64 then 65 null 66 else 67 if object.material.pipeline_layout <> pipeline_cache.pipeline_layout 68 && object.material.descriptor_set <> null 69 then 70 object.material.descriptor_set.discard 71 object.material.descriptor_set = null 72 73 if object.material.descriptor_set == null then 74 if vulkan.material_images.contains object.material then 75 vulkan.material_images.remove_all object.material 76 77 object.material.descriptor_set = DescriptorSet.create 78 object.material.resources.as_slice 79 pipeline_cache.pipeline_layout[Renderer.material_set] 80 81 object.material.pipeline_layout = pipeline_cache.pipeline_layout 82 83 for _, items in object.material.resources do 84 let add (name : String) = 85 vulkan.material_images.add object.material name 86 87 let add_resource (resource : Resource) = case resource of 88 Resource/ImageName name -> add name 89 Resource/ImageNameSampler name _ -> add name 90 else -> () 91 92 case items of 93 OneMany/One resource -> add_resource resource 94 OneMany/Many resources -> 95 for resource in resources do 96 add_resource resource 97 98 object.material.descriptor_set 99 100 if pipeline <> previous_pipeline then 101 draw/bind_pipeline pipeline 102 previous_pipeline = pipeline 103 104 if material_descriptor_set <> previous_material_descriptor_set then 105 if material_descriptor_set <> null then 106 draw/bind_descriptor_set material_descriptor_set 107 Renderer.material_set 108 109 previous_material_descriptor_set = material_descriptor_set 110 111 let push_constant = DrawPushConstant object_index = i 112 draw/set_push_constant push_constant@ptr 113 draw/draw 114 115 vulkan.command_buffer.scissor vulkan.framebuffer_scissor 116 draw/end 117 118 def render = 119 begin_label "Render Setup" 120 121 for i = 0 until cameras.size do 122 let c = cameras[i] 123 let view = c.view 124 let projection = c.projection size.value.width size.value.height 125 scene_ubo.cameras[i].view = view.transpose 126 view_inverse = view.inverse.transpose 127 projection = projection.transpose 128 projection_inverse = projection.inverse.transpose 129 130 scene_ubo.time = vulkan.time as f32 131 scene_buffer.update_single scene_ubo@ptr BarrierFlags/Raster 132 133 if skin_buffer == null 134 || skin_buffer_size < skin_matrices.size * sizeof Matrix4 135 then 136 if skin_buffer <> null then 137 vulkan.unused_buffers.add skin_buffer 138 139 let s = skin_matrices.size * sizeof Matrix4 140 |> max Renderer.skin_buffer_min_size 141 |> ceil_to_power_of_2 142 143 skin_buffer = StorageBuffer.create s 144 skin_buffer_size = s 145 146 if skin_matrices.size > 0 then 147 skin_buffer.update skin_matrices.as_slice BarrierFlags/Raster 148 149 for i = 0 until passes.size do 150 update_pass i 151 152 end_label 153 154 let clear_colors = List<Vector4>.new 155 for node in nodes do 156 case node of 157 is Node/Render -> 158 begin_label "Render Node" 159 160 render passes[node.pass].objects.as_slice 161 passes[node.pass].descriptor_set node.framebuffer 162 node.ops.color_enter_op node.ops.color_exit_op 163 node.ops.depth_enter_op node.ops.depth_exit_op 164 clear_colors.as_slice 165 166 end_label 167 168 if clear_colors.size > 0 then 169 clear_colors.clear 170 171 is Node/ResolveDepth -> 172 begin_label "Resolve Depth Node" 173 174 compute/resolve_depth node.from node.to size.value 175 node.samples.as<i32> BarrierFlags@all 176 end_label 177 178 is Node/ResolveMultisample -> 179 begin_label "Resolve Multisample Node" 180 resolve_multisample node.from node.to BarrierFlags@all 181 end_label 182 183 Node/Barrier -> barrier vulkan.command_buffer.object 184 BarrierFlags@all BarrierFlags@all 185 Node/ClearColor color -> 186 let main_light_intensity = if lighting.lights.is_empty 187 then 1 188 else lighting.lights[0].intensity 189 190 clear_colors.add (color * main_light_intensity) 191 192 is Node/Tonemap -> 193 draw/draw_tonemap node.framebuffer node.descriptor_set 194 node.size.value node.max_size 195 196 def render (renderers : List<Renderer>) (delta_time : f32) = 197 let vulkan : Vulkan @auto 198 199 vulkan.time = (vulkan.time + delta_time as f64) % Renderer.max_time 200 let blit_images = List.new 201 202 for renderer in renderers do 203 if renderer.size.value.width <> 0 && renderer.size.value.height <> 0 then 204 renderer.render 205 if renderer.maybe_blit_image ? Some blit_image then 206 blit_images.add blit_image 207 208 vulkan.acquire_next_image 209 draw/draw_blit blit_images 210 211 assert vulkan.gpu_state.is_none 212 213 vulkan.command_buffer.end 214 submit vulkan.sync vulkan.swapchain.image_index 215 vulkan.present 216 next_frame 217 218 end@ renderer 219