| 1 | /**************************************************************************/ |
| 2 | /* cluster_builder_rd.cpp */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 10 | /* */ |
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
| 12 | /* a copy of this software and associated documentation files (the */ |
| 13 | /* "Software"), to deal in the Software without restriction, including */ |
| 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
| 16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
| 17 | /* the following conditions: */ |
| 18 | /* */ |
| 19 | /* The above copyright notice and this permission notice shall be */ |
| 20 | /* included in all copies or substantial portions of the Software. */ |
| 21 | /* */ |
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 29 | /**************************************************************************/ |
| 30 | |
| 31 | #include "cluster_builder_rd.h" |
| 32 | #include "servers/rendering/rendering_device.h" |
| 33 | #include "servers/rendering/rendering_server_globals.h" |
| 34 | |
| 35 | ClusterBuilderSharedDataRD::ClusterBuilderSharedDataRD() { |
| 36 | RD::VertexFormatID vertex_format; |
| 37 | |
| 38 | { |
| 39 | Vector<RD::VertexAttribute> attributes; |
| 40 | { |
| 41 | RD::VertexAttribute va; |
| 42 | va.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; |
| 43 | va.stride = sizeof(float) * 3; |
| 44 | attributes.push_back(va); |
| 45 | } |
| 46 | vertex_format = RD::get_singleton()->vertex_format_create(attributes); |
| 47 | } |
| 48 | |
| 49 | { |
| 50 | RD::FramebufferFormatID fb_format; |
| 51 | RD::PipelineColorBlendState blend_state; |
| 52 | String defines; |
| 53 | if (RD::get_singleton()->has_feature(RD::SUPPORTS_FRAGMENT_SHADER_WITH_ONLY_SIDE_EFFECTS)) { |
| 54 | fb_format = RD::get_singleton()->framebuffer_format_create_empty(); |
| 55 | blend_state = RD::PipelineColorBlendState::create_disabled(); |
| 56 | } else { |
| 57 | Vector<RD::AttachmentFormat> afs; |
| 58 | afs.push_back(RD::AttachmentFormat()); |
| 59 | afs.write[0].usage_flags = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; |
| 60 | fb_format = RD::get_singleton()->framebuffer_format_create(afs); |
| 61 | blend_state = RD::PipelineColorBlendState::create_blend(); |
| 62 | defines = "\n#define USE_ATTACHMENT\n" ; |
| 63 | } |
| 64 | |
| 65 | Vector<String> versions; |
| 66 | versions.push_back("" ); |
| 67 | cluster_render.cluster_render_shader.initialize(versions, defines); |
| 68 | cluster_render.shader_version = cluster_render.cluster_render_shader.version_create(); |
| 69 | cluster_render.shader = cluster_render.cluster_render_shader.version_get_shader(cluster_render.shader_version, 0); |
| 70 | cluster_render.shader_pipelines[ClusterRender::PIPELINE_NORMAL] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); |
| 71 | RD::PipelineMultisampleState ms; |
| 72 | ms.sample_count = RD::TEXTURE_SAMPLES_4; |
| 73 | cluster_render.shader_pipelines[ClusterRender::PIPELINE_MSAA] = RD::get_singleton()->render_pipeline_create(cluster_render.shader, fb_format, vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), ms, RD::PipelineDepthStencilState(), blend_state, 0); |
| 74 | } |
| 75 | { |
| 76 | Vector<String> versions; |
| 77 | versions.push_back("" ); |
| 78 | cluster_store.cluster_store_shader.initialize(versions); |
| 79 | cluster_store.shader_version = cluster_store.cluster_store_shader.version_create(); |
| 80 | cluster_store.shader = cluster_store.cluster_store_shader.version_get_shader(cluster_store.shader_version, 0); |
| 81 | cluster_store.shader_pipeline = RD::get_singleton()->compute_pipeline_create(cluster_store.shader); |
| 82 | } |
| 83 | { |
| 84 | Vector<String> versions; |
| 85 | versions.push_back("" ); |
| 86 | cluster_debug.cluster_debug_shader.initialize(versions); |
| 87 | cluster_debug.shader_version = cluster_debug.cluster_debug_shader.version_create(); |
| 88 | cluster_debug.shader = cluster_debug.cluster_debug_shader.version_get_shader(cluster_debug.shader_version, 0); |
| 89 | cluster_debug.shader_pipeline = RD::get_singleton()->compute_pipeline_create(cluster_debug.shader); |
| 90 | } |
| 91 | |
| 92 | { // Sphere mesh data. |
| 93 | static const uint32_t icosphere_vertex_count = 42; |
| 94 | static const float icosphere_vertices[icosphere_vertex_count * 3] = { |
| 95 | 0, 0, -1, 0.7236073, -0.5257253, -0.4472195, -0.276388, -0.8506492, -0.4472199, -0.8944262, 0, -0.4472156, -0.276388, 0.8506492, -0.4472199, 0.7236073, 0.5257253, -0.4472195, 0.276388, -0.8506492, 0.4472199, -0.7236073, -0.5257253, 0.4472195, -0.7236073, 0.5257253, 0.4472195, 0.276388, 0.8506492, 0.4472199, 0.8944262, 0, 0.4472156, 0, 0, 1, -0.1624555, -0.4999952, -0.8506544, 0.4253227, -0.3090114, -0.8506542, 0.2628688, -0.8090116, -0.5257377, 0.8506479, 0, -0.5257359, 0.4253227, 0.3090114, -0.8506542, -0.5257298, 0, -0.8506517, -0.6881894, -0.4999969, -0.5257362, -0.1624555, 0.4999952, -0.8506544, -0.6881894, 0.4999969, -0.5257362, 0.2628688, 0.8090116, -0.5257377, 0.9510579, -0.3090126, 0, 0.9510579, 0.3090126, 0, 0, -1, 0, 0.5877856, -0.8090167, 0, -0.9510579, -0.3090126, 0, -0.5877856, -0.8090167, 0, -0.5877856, 0.8090167, 0, -0.9510579, 0.3090126, 0, 0.5877856, 0.8090167, 0, 0, 1, 0, 0.6881894, -0.4999969, 0.5257362, -0.2628688, -0.8090116, 0.5257377, -0.8506479, 0, 0.5257359, -0.2628688, 0.8090116, 0.5257377, 0.6881894, 0.4999969, 0.5257362, 0.1624555, -0.4999952, 0.8506544, 0.5257298, 0, 0.8506517, -0.4253227, -0.3090114, 0.8506542, -0.4253227, 0.3090114, 0.8506542, 0.1624555, 0.4999952, 0.8506544 |
| 96 | }; |
| 97 | static const uint32_t icosphere_triangle_count = 80; |
| 98 | static const uint16_t icosphere_triangle_indices[icosphere_triangle_count * 3] = { |
| 99 | 0, 13, 12, 1, 13, 15, 0, 12, 17, 0, 17, 19, 0, 19, 16, 1, 15, 22, 2, 14, 24, 3, 18, 26, 4, 20, 28, 5, 21, 30, 1, 22, 25, 2, 24, 27, 3, 26, 29, 4, 28, 31, 5, 30, 23, 6, 32, 37, 7, 33, 39, 8, 34, 40, 9, 35, 41, 10, 36, 38, 38, 41, 11, 38, 36, 41, 36, 9, 41, 41, 40, 11, 41, 35, 40, 35, 8, 40, 40, 39, 11, 40, 34, 39, 34, 7, 39, 39, 37, 11, 39, 33, 37, 33, 6, 37, 37, 38, 11, 37, 32, 38, 32, 10, 38, 23, 36, 10, 23, 30, 36, 30, 9, 36, 31, 35, 9, 31, 28, 35, 28, 8, 35, 29, 34, 8, 29, 26, 34, 26, 7, 34, 27, 33, 7, 27, 24, 33, 24, 6, 33, 25, 32, 6, 25, 22, 32, 22, 10, 32, 30, 31, 9, 30, 21, 31, 21, 4, 31, 28, 29, 8, 28, 20, 29, 20, 3, 29, 26, 27, 7, 26, 18, 27, 18, 2, 27, 24, 25, 6, 24, 14, 25, 14, 1, 25, 22, 23, 10, 22, 15, 23, 15, 5, 23, 16, 21, 5, 16, 19, 21, 19, 4, 21, 19, 20, 4, 19, 17, 20, 17, 3, 20, 17, 18, 3, 17, 12, 18, 12, 2, 18, 15, 16, 5, 15, 13, 16, 13, 0, 16, 12, 14, 2, 12, 13, 14, 13, 1, 14 |
| 100 | }; |
| 101 | |
| 102 | Vector<uint8_t> vertex_data; |
| 103 | vertex_data.resize(sizeof(float) * icosphere_vertex_count * 3); |
| 104 | memcpy(vertex_data.ptrw(), icosphere_vertices, vertex_data.size()); |
| 105 | |
| 106 | sphere_vertex_buffer = RD::get_singleton()->vertex_buffer_create(vertex_data.size(), vertex_data); |
| 107 | |
| 108 | Vector<uint8_t> index_data; |
| 109 | index_data.resize(sizeof(uint16_t) * icosphere_triangle_count * 3); |
| 110 | memcpy(index_data.ptrw(), icosphere_triangle_indices, index_data.size()); |
| 111 | |
| 112 | sphere_index_buffer = RD::get_singleton()->index_buffer_create(icosphere_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT16, index_data); |
| 113 | |
| 114 | Vector<RID> buffers; |
| 115 | buffers.push_back(sphere_vertex_buffer); |
| 116 | |
| 117 | sphere_vertex_array = RD::get_singleton()->vertex_array_create(icosphere_vertex_count, vertex_format, buffers); |
| 118 | |
| 119 | sphere_index_array = RD::get_singleton()->index_array_create(sphere_index_buffer, 0, icosphere_triangle_count * 3); |
| 120 | |
| 121 | float min_d = 1e20; |
| 122 | for (uint32_t i = 0; i < icosphere_triangle_count; i++) { |
| 123 | Vector3 vertices[3]; |
| 124 | for (uint32_t j = 0; j < 3; j++) { |
| 125 | uint32_t index = icosphere_triangle_indices[i * 3 + j]; |
| 126 | for (uint32_t k = 0; k < 3; k++) { |
| 127 | vertices[j][k] = icosphere_vertices[index * 3 + k]; |
| 128 | } |
| 129 | } |
| 130 | Plane p(vertices[0], vertices[1], vertices[2]); |
| 131 | min_d = MIN(Math::abs(p.d), min_d); |
| 132 | } |
| 133 | sphere_overfit = 1.0 / min_d; |
| 134 | } |
| 135 | |
| 136 | { // Cone mesh data. |
| 137 | static const uint32_t cone_vertex_count = 99; |
| 138 | static const float cone_vertices[cone_vertex_count * 3] = { |
| 139 | 0, 1, -1, 0.1950903, 0.9807853, -1, 0.3826835, 0.9238795, -1, 0.5555703, 0.8314696, -1, 0.7071068, 0.7071068, -1, 0.8314697, 0.5555702, -1, 0.9238795, 0.3826834, -1, 0.9807853, 0.1950903, -1, 1, 0, -1, 0.9807853, -0.1950902, -1, 0.9238796, -0.3826833, -1, 0.8314697, -0.5555702, -1, 0.7071068, -0.7071068, -1, 0.5555702, -0.8314697, -1, 0.3826833, -0.9238796, -1, 0.1950901, -0.9807853, -1, -3.25841e-7, -1, -1, -0.1950907, -0.9807852, -1, -0.3826839, -0.9238793, -1, -0.5555707, -0.8314693, -1, -0.7071073, -0.7071063, -1, -0.83147, -0.5555697, -1, -0.9238799, -0.3826827, -1, 0, 0, 0, -0.9807854, -0.1950894, -1, -1, 9.65599e-7, -1, -0.9807851, 0.1950913, -1, -0.9238791, 0.3826845, -1, -0.8314689, 0.5555713, -1, -0.7071059, 0.7071077, -1, -0.5555691, 0.8314704, -1, -0.3826821, 0.9238801, -1, -0.1950888, 0.9807856, -1 |
| 140 | }; |
| 141 | static const uint32_t cone_triangle_count = 62; |
| 142 | static const uint16_t cone_triangle_indices[cone_triangle_count * 3] = { |
| 143 | 0, 23, 1, 1, 23, 2, 2, 23, 3, 3, 23, 4, 4, 23, 5, 5, 23, 6, 6, 23, 7, 7, 23, 8, 8, 23, 9, 9, 23, 10, 10, 23, 11, 11, 23, 12, 12, 23, 13, 13, 23, 14, 14, 23, 15, 15, 23, 16, 16, 23, 17, 17, 23, 18, 18, 23, 19, 19, 23, 20, 20, 23, 21, 21, 23, 22, 22, 23, 24, 24, 23, 25, 25, 23, 26, 26, 23, 27, 27, 23, 28, 28, 23, 29, 29, 23, 30, 30, 23, 31, 31, 23, 32, 32, 23, 0, 7, 15, 24, 32, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 3, 6, 7, 3, 7, 8, 9, 9, 10, 7, 10, 11, 7, 11, 12, 15, 12, 13, 15, 13, 14, 15, 15, 16, 17, 17, 18, 19, 19, 20, 24, 20, 21, 24, 21, 22, 24, 24, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 1, 3, 15, 17, 24, 17, 19, 24, 24, 26, 32, 26, 28, 32, 28, 30, 32, 32, 3, 7, 7, 11, 15, 32, 7, 24 |
| 144 | }; |
| 145 | |
| 146 | Vector<uint8_t> vertex_data; |
| 147 | vertex_data.resize(sizeof(float) * cone_vertex_count * 3); |
| 148 | memcpy(vertex_data.ptrw(), cone_vertices, vertex_data.size()); |
| 149 | |
| 150 | cone_vertex_buffer = RD::get_singleton()->vertex_buffer_create(vertex_data.size(), vertex_data); |
| 151 | |
| 152 | Vector<uint8_t> index_data; |
| 153 | index_data.resize(sizeof(uint16_t) * cone_triangle_count * 3); |
| 154 | memcpy(index_data.ptrw(), cone_triangle_indices, index_data.size()); |
| 155 | |
| 156 | cone_index_buffer = RD::get_singleton()->index_buffer_create(cone_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT16, index_data); |
| 157 | |
| 158 | Vector<RID> buffers; |
| 159 | buffers.push_back(cone_vertex_buffer); |
| 160 | |
| 161 | cone_vertex_array = RD::get_singleton()->vertex_array_create(cone_vertex_count, vertex_format, buffers); |
| 162 | |
| 163 | cone_index_array = RD::get_singleton()->index_array_create(cone_index_buffer, 0, cone_triangle_count * 3); |
| 164 | |
| 165 | float min_d = 1e20; |
| 166 | for (uint32_t i = 0; i < cone_triangle_count; i++) { |
| 167 | Vector3 vertices[3]; |
| 168 | int32_t zero_index = -1; |
| 169 | for (uint32_t j = 0; j < 3; j++) { |
| 170 | uint32_t index = cone_triangle_indices[i * 3 + j]; |
| 171 | for (uint32_t k = 0; k < 3; k++) { |
| 172 | vertices[j][k] = cone_vertices[index * 3 + k]; |
| 173 | } |
| 174 | if (vertices[j] == Vector3()) { |
| 175 | zero_index = j; |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | if (zero_index != -1) { |
| 180 | Vector3 a = vertices[(zero_index + 1) % 3]; |
| 181 | Vector3 b = vertices[(zero_index + 2) % 3]; |
| 182 | Vector3 c = a + Vector3(0, 0, 1); |
| 183 | Plane p(a, b, c); |
| 184 | min_d = MIN(Math::abs(p.d), min_d); |
| 185 | } |
| 186 | } |
| 187 | cone_overfit = 1.0 / min_d; |
| 188 | } |
| 189 | |
| 190 | { // Box mesh data. |
| 191 | static const uint32_t box_vertex_count = 8; |
| 192 | static const float box_vertices[box_vertex_count * 3] = { |
| 193 | -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1 |
| 194 | }; |
| 195 | static const uint32_t box_triangle_count = 12; |
| 196 | static const uint16_t box_triangle_indices[box_triangle_count * 3] = { |
| 197 | 1, 2, 0, 3, 6, 2, 7, 4, 6, 5, 0, 4, 6, 0, 2, 3, 5, 7, 1, 3, 2, 3, 7, 6, 7, 5, 4, 5, 1, 0, 6, 4, 0, 3, 1, 5 |
| 198 | }; |
| 199 | |
| 200 | Vector<uint8_t> vertex_data; |
| 201 | vertex_data.resize(sizeof(float) * box_vertex_count * 3); |
| 202 | memcpy(vertex_data.ptrw(), box_vertices, vertex_data.size()); |
| 203 | |
| 204 | box_vertex_buffer = RD::get_singleton()->vertex_buffer_create(vertex_data.size(), vertex_data); |
| 205 | |
| 206 | Vector<uint8_t> index_data; |
| 207 | index_data.resize(sizeof(uint16_t) * box_triangle_count * 3); |
| 208 | memcpy(index_data.ptrw(), box_triangle_indices, index_data.size()); |
| 209 | |
| 210 | box_index_buffer = RD::get_singleton()->index_buffer_create(box_triangle_count * 3, RD::INDEX_BUFFER_FORMAT_UINT16, index_data); |
| 211 | |
| 212 | Vector<RID> buffers; |
| 213 | buffers.push_back(box_vertex_buffer); |
| 214 | |
| 215 | box_vertex_array = RD::get_singleton()->vertex_array_create(box_vertex_count, vertex_format, buffers); |
| 216 | |
| 217 | box_index_array = RD::get_singleton()->index_array_create(box_index_buffer, 0, box_triangle_count * 3); |
| 218 | } |
| 219 | } |
| 220 | ClusterBuilderSharedDataRD::~ClusterBuilderSharedDataRD() { |
| 221 | RD::get_singleton()->free(sphere_vertex_buffer); |
| 222 | RD::get_singleton()->free(sphere_index_buffer); |
| 223 | RD::get_singleton()->free(cone_vertex_buffer); |
| 224 | RD::get_singleton()->free(cone_index_buffer); |
| 225 | RD::get_singleton()->free(box_vertex_buffer); |
| 226 | RD::get_singleton()->free(box_index_buffer); |
| 227 | |
| 228 | cluster_render.cluster_render_shader.version_free(cluster_render.shader_version); |
| 229 | cluster_store.cluster_store_shader.version_free(cluster_store.shader_version); |
| 230 | cluster_debug.cluster_debug_shader.version_free(cluster_debug.shader_version); |
| 231 | } |
| 232 | |
| 233 | ///////////////////////////// |
| 234 | |
| 235 | void ClusterBuilderRD::_clear() { |
| 236 | if (cluster_buffer.is_null()) { |
| 237 | return; |
| 238 | } |
| 239 | |
| 240 | RD::get_singleton()->free(cluster_buffer); |
| 241 | RD::get_singleton()->free(cluster_render_buffer); |
| 242 | RD::get_singleton()->free(element_buffer); |
| 243 | cluster_buffer = RID(); |
| 244 | cluster_render_buffer = RID(); |
| 245 | element_buffer = RID(); |
| 246 | |
| 247 | memfree(render_elements); |
| 248 | |
| 249 | render_elements = nullptr; |
| 250 | render_element_max = 0; |
| 251 | render_element_count = 0; |
| 252 | |
| 253 | RD::get_singleton()->free(framebuffer); |
| 254 | framebuffer = RID(); |
| 255 | |
| 256 | cluster_render_uniform_set = RID(); |
| 257 | cluster_store_uniform_set = RID(); |
| 258 | } |
| 259 | |
| 260 | void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer) { |
| 261 | ERR_FAIL_COND(p_max_elements == 0); |
| 262 | ERR_FAIL_COND(p_screen_size.x < 1); |
| 263 | ERR_FAIL_COND(p_screen_size.y < 1); |
| 264 | |
| 265 | _clear(); |
| 266 | |
| 267 | screen_size = p_screen_size; |
| 268 | |
| 269 | cluster_screen_size.width = (p_screen_size.width - 1) / cluster_size + 1; |
| 270 | cluster_screen_size.height = (p_screen_size.height - 1) / cluster_size + 1; |
| 271 | |
| 272 | max_elements_by_type = p_max_elements; |
| 273 | if (max_elements_by_type % 32) { // Needs to be aligned to 32. |
| 274 | max_elements_by_type += 32 - (max_elements_by_type % 32); |
| 275 | } |
| 276 | |
| 277 | cluster_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (max_elements_by_type / 32 + 32) * ELEMENT_TYPE_MAX * 4; |
| 278 | |
| 279 | render_element_max = max_elements_by_type * ELEMENT_TYPE_MAX; |
| 280 | |
| 281 | uint32_t element_tag_bits_size = render_element_max / 32; |
| 282 | uint32_t element_tag_depth_bits_size = render_element_max; |
| 283 | |
| 284 | cluster_render_buffer_size = cluster_screen_size.x * cluster_screen_size.y * (element_tag_bits_size + element_tag_depth_bits_size) * 4; // Tag bits (element was used) and tag depth (depth range in which it was used). |
| 285 | |
| 286 | cluster_render_buffer = RD::get_singleton()->storage_buffer_create(cluster_render_buffer_size); |
| 287 | cluster_buffer = RD::get_singleton()->storage_buffer_create(cluster_buffer_size); |
| 288 | |
| 289 | render_elements = static_cast<RenderElementData *>(memalloc(sizeof(RenderElementData) * render_element_max)); |
| 290 | render_element_count = 0; |
| 291 | |
| 292 | element_buffer = RD::get_singleton()->storage_buffer_create(sizeof(RenderElementData) * render_element_max); |
| 293 | |
| 294 | uint32_t div_value = 1 << divisor; |
| 295 | if (use_msaa) { |
| 296 | framebuffer = RD::get_singleton()->framebuffer_create_empty(p_screen_size / div_value, RD::TEXTURE_SAMPLES_4); |
| 297 | } else { |
| 298 | framebuffer = RD::get_singleton()->framebuffer_create_empty(p_screen_size / div_value); |
| 299 | } |
| 300 | |
| 301 | { |
| 302 | Vector<RD::Uniform> uniforms; |
| 303 | { |
| 304 | RD::Uniform u; |
| 305 | u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; |
| 306 | u.binding = 1; |
| 307 | u.append_id(state_uniform); |
| 308 | uniforms.push_back(u); |
| 309 | } |
| 310 | { |
| 311 | RD::Uniform u; |
| 312 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
| 313 | u.binding = 2; |
| 314 | u.append_id(element_buffer); |
| 315 | uniforms.push_back(u); |
| 316 | } |
| 317 | { |
| 318 | RD::Uniform u; |
| 319 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
| 320 | u.binding = 3; |
| 321 | u.append_id(cluster_render_buffer); |
| 322 | uniforms.push_back(u); |
| 323 | } |
| 324 | |
| 325 | cluster_render_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shared->cluster_render.shader, 0); |
| 326 | } |
| 327 | |
| 328 | { |
| 329 | Vector<RD::Uniform> uniforms; |
| 330 | { |
| 331 | RD::Uniform u; |
| 332 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
| 333 | u.binding = 1; |
| 334 | u.append_id(cluster_render_buffer); |
| 335 | uniforms.push_back(u); |
| 336 | } |
| 337 | { |
| 338 | RD::Uniform u; |
| 339 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
| 340 | u.binding = 2; |
| 341 | u.append_id(cluster_buffer); |
| 342 | uniforms.push_back(u); |
| 343 | } |
| 344 | |
| 345 | { |
| 346 | RD::Uniform u; |
| 347 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
| 348 | u.binding = 3; |
| 349 | u.append_id(element_buffer); |
| 350 | uniforms.push_back(u); |
| 351 | } |
| 352 | |
| 353 | cluster_store_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shared->cluster_store.shader, 0); |
| 354 | } |
| 355 | |
| 356 | if (p_color_buffer.is_valid()) { |
| 357 | Vector<RD::Uniform> uniforms; |
| 358 | { |
| 359 | RD::Uniform u; |
| 360 | u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; |
| 361 | u.binding = 1; |
| 362 | u.append_id(cluster_buffer); |
| 363 | uniforms.push_back(u); |
| 364 | } |
| 365 | { |
| 366 | RD::Uniform u; |
| 367 | u.uniform_type = RD::UNIFORM_TYPE_IMAGE; |
| 368 | u.binding = 2; |
| 369 | u.append_id(p_color_buffer); |
| 370 | uniforms.push_back(u); |
| 371 | } |
| 372 | |
| 373 | { |
| 374 | RD::Uniform u; |
| 375 | u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; |
| 376 | u.binding = 3; |
| 377 | u.append_id(p_depth_buffer); |
| 378 | uniforms.push_back(u); |
| 379 | } |
| 380 | { |
| 381 | RD::Uniform u; |
| 382 | u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; |
| 383 | u.binding = 4; |
| 384 | u.append_id(p_depth_buffer_sampler); |
| 385 | uniforms.push_back(u); |
| 386 | } |
| 387 | |
| 388 | debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shared->cluster_debug.shader, 0); |
| 389 | } else { |
| 390 | debug_uniform_set = RID(); |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y) { |
| 395 | view_xform = p_view_transform.affine_inverse(); |
| 396 | projection = p_cam_projection; |
| 397 | z_near = projection.get_z_near(); |
| 398 | z_far = projection.get_z_far(); |
| 399 | camera_orthogonal = p_cam_projection.is_orthogonal(); |
| 400 | adjusted_projection = projection; |
| 401 | if (!camera_orthogonal) { |
| 402 | adjusted_projection.adjust_perspective_znear(0.0001); |
| 403 | } |
| 404 | |
| 405 | Projection correction; |
| 406 | correction.set_depth_correction(p_flip_y); |
| 407 | projection = correction * projection; |
| 408 | adjusted_projection = correction * adjusted_projection; |
| 409 | |
| 410 | // Reset counts. |
| 411 | render_element_count = 0; |
| 412 | for (uint32_t i = 0; i < ELEMENT_TYPE_MAX; i++) { |
| 413 | cluster_count_by_type[i] = 0; |
| 414 | } |
| 415 | } |
| 416 | |
| 417 | void ClusterBuilderRD::bake_cluster() { |
| 418 | RENDER_TIMESTAMP("> Bake 3D Cluster" ); |
| 419 | |
| 420 | RD::get_singleton()->draw_command_begin_label("Bake Light Cluster" ); |
| 421 | |
| 422 | // Clear cluster buffer. |
| 423 | RD::get_singleton()->buffer_clear(cluster_buffer, 0, cluster_buffer_size, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); |
| 424 | |
| 425 | if (render_element_count > 0) { |
| 426 | // Clear render buffer. |
| 427 | RD::get_singleton()->buffer_clear(cluster_render_buffer, 0, cluster_render_buffer_size, RD::BARRIER_MASK_RASTER); |
| 428 | |
| 429 | { // Fill state uniform. |
| 430 | |
| 431 | StateUniform state; |
| 432 | |
| 433 | RendererRD::MaterialStorage::store_camera(adjusted_projection, state.projection); |
| 434 | state.inv_z_far = 1.0 / z_far; |
| 435 | state.screen_to_clusters_shift = get_shift_from_power_of_2(cluster_size); |
| 436 | state.screen_to_clusters_shift -= divisor; //screen is smaller, shift one less |
| 437 | |
| 438 | state.cluster_screen_width = cluster_screen_size.x; |
| 439 | state.cluster_depth_offset = (render_element_max / 32); |
| 440 | state.cluster_data_size = state.cluster_depth_offset + render_element_max; |
| 441 | |
| 442 | RD::get_singleton()->buffer_update(state_uniform, 0, sizeof(StateUniform), &state, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); |
| 443 | } |
| 444 | |
| 445 | // Update instances. |
| 446 | |
| 447 | RD::get_singleton()->buffer_update(element_buffer, 0, sizeof(RenderElementData) * render_element_count, render_elements, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); |
| 448 | |
| 449 | RENDER_TIMESTAMP("Render 3D Cluster Elements" ); |
| 450 | |
| 451 | // Render elements. |
| 452 | { |
| 453 | RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD); |
| 454 | ClusterBuilderSharedDataRD::ClusterRender::PushConstant push_constant = {}; |
| 455 | |
| 456 | RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shared->cluster_render.shader_pipelines[use_msaa ? ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_MSAA : ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_NORMAL]); |
| 457 | RD::get_singleton()->draw_list_bind_uniform_set(draw_list, cluster_render_uniform_set, 0); |
| 458 | |
| 459 | for (uint32_t i = 0; i < render_element_count;) { |
| 460 | push_constant.base_index = i; |
| 461 | switch (render_elements[i].type) { |
| 462 | case ELEMENT_TYPE_OMNI_LIGHT: { |
| 463 | RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->sphere_vertex_array); |
| 464 | RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->sphere_index_array); |
| 465 | } break; |
| 466 | case ELEMENT_TYPE_SPOT_LIGHT: { |
| 467 | // If the spot angle is above a certain threshold, use a sphere instead of a cone for building the clusters |
| 468 | // since the cone gets too flat/large (spot angle close to 90 degrees) or |
| 469 | // can't even cover the affected area of the light (spot angle above 90 degrees). |
| 470 | if (render_elements[i].has_wide_spot_angle) { |
| 471 | RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->sphere_vertex_array); |
| 472 | RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->sphere_index_array); |
| 473 | } else { |
| 474 | RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->cone_vertex_array); |
| 475 | RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->cone_index_array); |
| 476 | } |
| 477 | } break; |
| 478 | case ELEMENT_TYPE_DECAL: |
| 479 | case ELEMENT_TYPE_REFLECTION_PROBE: { |
| 480 | RD::get_singleton()->draw_list_bind_vertex_array(draw_list, shared->box_vertex_array); |
| 481 | RD::get_singleton()->draw_list_bind_index_array(draw_list, shared->box_index_array); |
| 482 | } break; |
| 483 | } |
| 484 | |
| 485 | RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterRender::PushConstant)); |
| 486 | |
| 487 | uint32_t instances = 1; |
| 488 | RD::get_singleton()->draw_list_draw(draw_list, true, instances); |
| 489 | i += instances; |
| 490 | } |
| 491 | RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_COMPUTE); |
| 492 | } |
| 493 | // Store elements. |
| 494 | RENDER_TIMESTAMP("Pack 3D Cluster Elements" ); |
| 495 | |
| 496 | { |
| 497 | RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); |
| 498 | RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shared->cluster_store.shader_pipeline); |
| 499 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cluster_store_uniform_set, 0); |
| 500 | |
| 501 | ClusterBuilderSharedDataRD::ClusterStore::PushConstant push_constant; |
| 502 | push_constant.cluster_render_data_size = render_element_max / 32 + render_element_max; |
| 503 | push_constant.max_render_element_count_div_32 = render_element_max / 32; |
| 504 | push_constant.cluster_screen_size[0] = cluster_screen_size.x; |
| 505 | push_constant.cluster_screen_size[1] = cluster_screen_size.y; |
| 506 | push_constant.render_element_count_div_32 = render_element_count > 0 ? (render_element_count - 1) / 32 + 1 : 0; |
| 507 | push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32; |
| 508 | push_constant.pad1 = 0; |
| 509 | push_constant.pad2 = 0; |
| 510 | |
| 511 | RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterStore::PushConstant)); |
| 512 | |
| 513 | RD::get_singleton()->compute_list_dispatch_threads(compute_list, cluster_screen_size.x, cluster_screen_size.y, 1); |
| 514 | |
| 515 | RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); |
| 516 | } |
| 517 | } else { |
| 518 | RD::get_singleton()->barrier(RD::BARRIER_MASK_TRANSFER, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE); |
| 519 | } |
| 520 | RENDER_TIMESTAMP("< Bake 3D Cluster" ); |
| 521 | RD::get_singleton()->draw_command_end_label(); |
| 522 | } |
| 523 | |
| 524 | void ClusterBuilderRD::debug(ElementType p_element) { |
| 525 | ERR_FAIL_COND(debug_uniform_set.is_null()); |
| 526 | RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); |
| 527 | RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shared->cluster_debug.shader_pipeline); |
| 528 | RD::get_singleton()->compute_list_bind_uniform_set(compute_list, debug_uniform_set, 0); |
| 529 | |
| 530 | ClusterBuilderSharedDataRD::ClusterDebug::PushConstant push_constant; |
| 531 | push_constant.screen_size[0] = screen_size.x; |
| 532 | push_constant.screen_size[1] = screen_size.y; |
| 533 | push_constant.cluster_screen_size[0] = cluster_screen_size.x; |
| 534 | push_constant.cluster_screen_size[1] = cluster_screen_size.y; |
| 535 | push_constant.cluster_shift = get_shift_from_power_of_2(cluster_size); |
| 536 | push_constant.cluster_type = p_element; |
| 537 | push_constant.orthogonal = camera_orthogonal; |
| 538 | push_constant.z_far = z_far; |
| 539 | push_constant.z_near = z_near; |
| 540 | push_constant.max_cluster_element_count_div_32 = max_elements_by_type / 32; |
| 541 | |
| 542 | RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ClusterBuilderSharedDataRD::ClusterDebug::PushConstant)); |
| 543 | |
| 544 | RD::get_singleton()->compute_list_dispatch_threads(compute_list, screen_size.x, screen_size.y, 1); |
| 545 | |
| 546 | RD::get_singleton()->compute_list_end(); |
| 547 | } |
| 548 | |
| 549 | RID ClusterBuilderRD::get_cluster_buffer() const { |
| 550 | return cluster_buffer; |
| 551 | } |
| 552 | |
| 553 | uint32_t ClusterBuilderRD::get_cluster_size() const { |
| 554 | return cluster_size; |
| 555 | } |
| 556 | |
| 557 | uint32_t ClusterBuilderRD::get_max_cluster_elements() const { |
| 558 | return max_elements_by_type; |
| 559 | } |
| 560 | |
| 561 | void ClusterBuilderRD::set_shared(ClusterBuilderSharedDataRD *p_shared) { |
| 562 | shared = p_shared; |
| 563 | } |
| 564 | |
| 565 | ClusterBuilderRD::ClusterBuilderRD() { |
| 566 | state_uniform = RD::get_singleton()->uniform_buffer_create(sizeof(StateUniform)); |
| 567 | } |
| 568 | |
| 569 | ClusterBuilderRD::~ClusterBuilderRD() { |
| 570 | _clear(); |
| 571 | RD::get_singleton()->free(state_uniform); |
| 572 | } |
| 573 | |