| 1935 | } |
| 1936 | |
| 1937 | void TaskGraph::complete(TaskCompleteInfo const & /*unused*/) |
| 1938 | { |
| 1939 | ImplTaskGraph & impl = *r_cast<ImplTaskGraph *>(this->object); |
| 1940 | u32 required_tmp_size = 1u << 23u; /* 8MB */ |
| 1941 | MemoryArena tmp_memory = MemoryArena{"TaskGraph::complete tmp memory", required_tmp_size}; |
| 1942 | |
| 1943 | /// ================================ |
| 1944 | /// ==== EARLY INPUT VALIDATION ==== |
| 1945 | /// ================================ |
| 1946 | |
| 1947 | DAXA_DBG_ASSERT_TRUE_M(impl.submits.size() > 0, "ERROR: All task graphs must have at least one submission!"); |
| 1948 | DAXA_DBG_ASSERT_TRUE_M(!impl.compiled, "ERROR: TaskGraph was already completed!"); |
| 1949 | if (impl.present.has_value()) |
| 1950 | { |
| 1951 | DAXA_DBG_ASSERT_TRUE_M(impl.swapchain_image != nullptr, "ERROR: No swapchain image registered but a present was recorded!"); |
| 1952 | } |
| 1953 | |
| 1954 | // Validate that all attachments of each task refer to unique resources. |
| 1955 | // Validate that all image attachment mips and layers are within bounds the transient image. |
| 1956 | for (u32 task_i = 0; task_i < impl.tasks.size(); ++task_i) |
| 1957 | { |
| 1958 | ImplTask & task = impl.tasks.at(task_i); |
| 1959 | for (u32 attach_i = 0; attach_i < task.attachments.size(); ++attach_i) |
| 1960 | { |
| 1961 | TaskAttachmentInfo const & attachment = task.attachments[attach_i]; |
| 1962 | |
| 1963 | if (attachment.type == TaskAttachmentType::IMAGE) |
| 1964 | { |
| 1965 | u32 const resource_index = attachment.value.image.translated_view.index; |
| 1966 | |
| 1967 | if (resource_index != ~0u) |
| 1968 | { |
| 1969 | ImplTaskResource const & resource = impl.resources[resource_index]; |
| 1970 | if (resource.external == nullptr) |
| 1971 | { |
| 1972 | bool const mips_in_bounds = attachment.value.image.translated_view.slice.base_mip_level + attachment.value.image.translated_view.slice.level_count <= resource.info.image.mip_level_count; |
| 1973 | bool const layers_in_bounds = attachment.value.image.translated_view.slice.base_array_layer + attachment.value.image.translated_view.slice.layer_count <= resource.info.image.array_layer_count; |
| 1974 | DAXA_DBG_ASSERT_TRUE_M( |
| 1975 | mips_in_bounds && layers_in_bounds, |
| 1976 | std::format( |
| 1977 | "ERROR: Attachment \"{}\" of task \"{}\" is assigned a image view for resource \"{}\" exceeding the images mips/layers!\n" |
| 1978 | "\"{}\" mip levels: {}, array layers: {}. Attachment view mips: [{},{}], layers: [{},{}].", |
| 1979 | attachment.value.common.name, task.name, resource.name, |
| 1980 | resource.name, resource.info.image.mip_level_count, resource.info.image.array_layer_count, |
| 1981 | attachment.value.image.translated_view.slice.base_mip_level, attachment.value.image.translated_view.slice.base_mip_level + attachment.value.image.translated_view.slice.level_count - 1, |
| 1982 | attachment.value.image.translated_view.slice.base_array_layer, attachment.value.image.translated_view.slice.base_array_layer + attachment.value.image.translated_view.slice.layer_count - 1) |
| 1983 | .c_str()); |
| 1984 | } |
| 1985 | } |
| 1986 | } |
| 1987 | |
| 1988 | // Validate that all attachments of each task refer to unique resources. |
| 1989 | for (u32 other_i = attach_i + 1; other_i < task.attachments.size(); ++other_i) |
| 1990 | { |
| 1991 | TaskAttachmentInfo const & other_attachment = task.attachments[other_i]; |
| 1992 | |
| 1993 | if (attachment.type == other_attachment.type) |
| 1994 | { |