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