ImageView &TransientAllocator::request_attachment(unsigned width, unsigned height, VkFormat format, unsigned index) { Hasher h; h.u32(width); h.u32(height); h.u32(format); h.u32(index); auto hash = h.get(); auto *node = transients.request(hash); if (node) return node->handle->get_view(); auto image_info = ImageCreateInfo::transient_render_target(width, height, format); node = transients.emplace(hash, device->create_image(image_info, nullptr)); return node->handle->get_view(); }
void CommandBuffer::flush_graphics_pipeline() { Hasher h; active_vbos = 0; auto &layout = current_layout->get_resource_layout(); for_each_bit(layout.attribute_mask, [&](uint32_t bit) { h.u32(bit); active_vbos |= 1u << attribs[bit].binding; h.u32(attribs[bit].binding); h.u32(attribs[bit].format); h.u32(attribs[bit].offset); }); for_each_bit(active_vbos, [&](uint32_t bit) { h.u32(vbo_input_rates[bit]); h.u32(vbo_strides[bit]); }); h.u64(render_pass->get_cookie()); h.u64(current_program->get_cookie()); h.data(static_state.words, sizeof(static_state.words)); if (static_state.state.blend_enable) { const auto needs_blend_constant = [](VkBlendFactor factor) { return factor == VK_BLEND_FACTOR_CONSTANT_COLOR || factor == VK_BLEND_FACTOR_CONSTANT_ALPHA; }; bool b0 = needs_blend_constant(static_cast<VkBlendFactor>(static_state.state.src_color_blend)); bool b1 = needs_blend_constant(static_cast<VkBlendFactor>(static_state.state.src_alpha_blend)); bool b2 = needs_blend_constant(static_cast<VkBlendFactor>(static_state.state.dst_color_blend)); bool b3 = needs_blend_constant(static_cast<VkBlendFactor>(static_state.state.dst_alpha_blend)); if (b0 || b1 || b2 || b3) h.data(reinterpret_cast<uint32_t *>(potential_static_state.blend_constants), sizeof(potential_static_state.blend_constants)); } auto hash = h.get(); current_pipeline = current_program->get_graphics_pipeline(hash); if (current_pipeline == VK_NULL_HANDLE) current_pipeline = build_graphics_pipeline(hash); }
void CommandBuffer::flush_descriptor_set(uint32_t set) { auto &layout = current_layout->get_resource_layout(); auto &set_layout = layout.sets[set]; uint32_t num_dynamic_offsets = 0; uint32_t dynamic_offsets[VULKAN_NUM_BINDINGS]; Hasher h; // UBOs for_each_bit(set_layout.uniform_buffer_mask, [&](uint32_t binding) { h.u64(cookies[set][binding]); h.u32(bindings[set][binding].buffer.range); VK_ASSERT(bindings[set][binding].buffer.buffer != VK_NULL_HANDLE); dynamic_offsets[num_dynamic_offsets++] = bindings[set][binding].buffer.offset; }); // SSBOs for_each_bit(set_layout.storage_buffer_mask, [&](uint32_t binding) { h.u64(cookies[set][binding]); h.u32(bindings[set][binding].buffer.offset); h.u32(bindings[set][binding].buffer.range); VK_ASSERT(bindings[set][binding].buffer.buffer != VK_NULL_HANDLE); }); // Sampled buffers for_each_bit(set_layout.sampled_buffer_mask, [&](uint32_t binding) { h.u64(cookies[set][binding]); VK_ASSERT(bindings[set][binding].buffer_view != VK_NULL_HANDLE); }); // Sampled images for_each_bit(set_layout.sampled_image_mask, [&](uint32_t binding) { h.u64(cookies[set][binding]); h.u64(secondary_cookies[set][binding]); h.u32(bindings[set][binding].image.imageLayout); VK_ASSERT(bindings[set][binding].image.imageView != VK_NULL_HANDLE); VK_ASSERT(bindings[set][binding].image.sampler != VK_NULL_HANDLE); }); // Storage images for_each_bit(set_layout.storage_image_mask, [&](uint32_t binding) { h.u64(cookies[set][binding]); h.u32(bindings[set][binding].image.imageLayout); VK_ASSERT(bindings[set][binding].image.imageView != VK_NULL_HANDLE); }); // Input attachments for_each_bit(set_layout.input_attachment_mask, [&](uint32_t binding) { h.u64(cookies[set][binding]); h.u32(bindings[set][binding].image.imageLayout); VK_ASSERT(bindings[set][binding].image.imageView != VK_NULL_HANDLE); }); Hash hash = h.get(); auto allocated = current_layout->get_allocator(set)->find(hash); // The descriptor set was not successfully cached, rebuild. if (!allocated.second) { uint32_t write_count = 0; uint32_t buffer_info_count = 0; VkWriteDescriptorSet writes[VULKAN_NUM_BINDINGS]; VkDescriptorBufferInfo buffer_info[VULKAN_NUM_BINDINGS]; for_each_bit(set_layout.uniform_buffer_mask, [&](uint32_t binding) { auto &write = writes[write_count++]; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.pNext = nullptr; write.descriptorCount = 1; write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; write.dstArrayElement = 0; write.dstBinding = binding; write.dstSet = allocated.first; // Offsets are applied dynamically. auto &buffer = buffer_info[buffer_info_count++]; buffer = bindings[set][binding].buffer; buffer.offset = 0; write.pBufferInfo = &buffer; }); for_each_bit(set_layout.storage_buffer_mask, [&](uint32_t binding) { auto &write = writes[write_count++]; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.pNext = nullptr; write.descriptorCount = 1; write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; write.dstArrayElement = 0; write.dstBinding = binding; write.dstSet = allocated.first; write.pBufferInfo = &bindings[set][binding].buffer; }); for_each_bit(set_layout.sampled_buffer_mask, [&](uint32_t binding) { auto &write = writes[write_count++]; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.pNext = nullptr; write.descriptorCount = 1; write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; write.dstArrayElement = 0; write.dstBinding = binding; write.dstSet = allocated.first; write.pTexelBufferView = &bindings[set][binding].buffer_view; }); for_each_bit(set_layout.sampled_image_mask, [&](uint32_t binding) { auto &write = writes[write_count++]; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.pNext = nullptr; write.descriptorCount = 1; write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write.dstArrayElement = 0; write.dstBinding = binding; write.dstSet = allocated.first; write.pImageInfo = &bindings[set][binding].image; }); for_each_bit(set_layout.storage_image_mask, [&](uint32_t binding) { auto &write = writes[write_count++]; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.pNext = nullptr; write.descriptorCount = 1; write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; write.dstArrayElement = 0; write.dstBinding = binding; write.dstSet = allocated.first; write.pImageInfo = &bindings[set][binding].image; }); for_each_bit(set_layout.input_attachment_mask, [&](uint32_t binding) { auto &write = writes[write_count++]; write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write.pNext = nullptr; write.descriptorCount = 1; write.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; write.dstArrayElement = 0; write.dstBinding = binding; write.dstSet = allocated.first; write.pImageInfo = &bindings[set][binding].image; }); vkUpdateDescriptorSets(device->get_device(), write_count, writes, 0, nullptr); } vkCmdBindDescriptorSets(cmd, render_pass ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE, current_pipeline_layout, set, 1, &allocated.first, num_dynamic_offsets, dynamic_offsets); }