text:
/*
 * Basic example for hardware accelerated ray tracing using VK_KHR_ray_tracing_pipeline and VK_KHR_acceleration_structure
  */

#include "raytracing_basic.h"

RaytracingBasic::RaytracingBasic()
{
	title = "Hardware accelerated ray tracing";

	// SPIRV 1.4 requires Vulkan 1.1
	set_api_version(VK_API_VERSION_1_1);

	// Ray tracing related extensions required by this sample
	add_device_extension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME);
	add_device_extension(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);

	// Required by VK_KHR_acceleration_structure
	add_device_extension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
	add_device_extension(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
	add_device_extension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);

	// Required for VK_KHR_ray_tracing_pipeline
	add_device_extension(VK_KHR_SPIRV_1_4_EXTENSION_NAME);

	// Required by VK_KHR_spirv_1_4
	add_device_extension(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME);
}

RaytracingBasic::~RaytracingBasic()
{
	if (device)
	{
		vkDestroyPipeline(get_device().get_handle(), pipeline, nullptr);
		vkDestroyPipelineLayout(get_device().get_handle(), pipeline_layout, nullptr);
		vkDestroyDescriptorSetLayout(get_device().get_handle(), descriptor_set_layout, nullptr);
		vkDestroyImageView(get_device().get_handle(), storage_image.view, nullptr);
		vkDestroyImage(get_device().get_handle(), storage_image.image, nullptr);
		vkFreeMemory(get_device().get_handle(), storage_image.memory, nullptr);
		delete_acceleration_structure(top_level_acceleration_structure);
		delete_acceleration_structure(bottom_level_acceleration_structure);
		vertex_buffer.reset();
		index_buffer.reset();
		ubo.reset();
	}
}

void RaytracingBasic::request_gpu_features(vkb::PhysicalDevice &gpu)
{
	// Enable extension features required by this sample
	// These are passed to device creation via a pNext structure chain
	auto &requested_buffer_device_address_features                  = gpu.request_extension_features<VkPhysicalDeviceBufferDeviceAddressFeatures>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES);
	requested_buffer_device_address_features.bufferDeviceAddress    = VK_TRUE;
	auto &requested_ray_tracing_features                            = gpu.request_extension_features<VkPhysicalDeviceRayTracingPipelineFeaturesKHR>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR);
	requested_ray_tracing_features.rayTracingPipeline               = VK_TRUE;
	auto &requested_acceleration_structure_features                 = gpu.request_extension_features<VkPhysicalDeviceAccelerationStructureFeaturesKHR>(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR);
	requested_acceleration_structure_features.accelerationStructure = VK_TRUE;
}

/*
	Set up a storage image that the ray generation shader will be writing to
*/
void RaytracingBasic::create_storage_image()
{
	storage_image.width  = width;
	storage_image.height = height;

	VkImageCreateInfo image = vkb::initializers::image_create_info();
	image.imageType         = VK_IMAGE_TYPE_2D;
	image.format            = VK_FORMAT_B8G8R8A8_UNORM;
	image.extent.width      = storage_image.width;
	image.extent.height     = storage_image.height;
	image.extent.depth      = 1;
	image.mipLevels         = 1;
	image.arrayLayers       = 1;
	image.samples           = VK_SAMPLE_COUNT_1_BIT;
	image.tiling            = VK_IMAGE_TILING_OPTIMAL;
	image.usage             = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
	image.initialLayout     = VK_IMAGE_LAYOUT_UNDEFINED;
	VK_CHECK(vkCreateImage(get_device().get_handle(), &image, nullptr, &storage_image.image));

	VkMemoryRequirements memory_requirements;
	vkGetImageMemoryRequirements(get_device().get_handle(), storage_image.image, &memory_requirements);
	VkMemoryAllocateInfo memory_allocate_info = vkb::initializers::memory_allocate_info();
	memory_allocate_info.allocationSize       = memory_requirements.size;
	memory_allocate_info.memoryTypeIndex      = get_device().get_memory_type(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
	VK_CHECK(vkAllocateMemory(get_device().get_handle(), &memory_allocate_info, nullptr, &storage_image.memory));
	VK_CHECK(vkBindImageMemory(get_device().get_handle(), storage_image.image, storage_image.memory, 0));

	VkImageViewCreateInfo color_image_view           = vkb::initializers::image_view_create_info();
	color_image_view.viewType                        = VK_IMAGE_VIEW_TYPE_2D;
	color_image_view.format                          = VK_FORMAT_B8G8R8A8_UNORM;
	color_image_view.subresourceRange                = {};
	color_image_view.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
	color_image_view.subresourceRange.baseMipLevel   = 0;
	color_image_view.subresourceRange.levelCount     = 1;
	color_image_view.subresourceRange.baseArrayLayer = 0;
	color_image_view.subresourceRange.layerCount     = 1;
	color_image_view.image                           = storage_image.image;
	VK_CHECK(vkCreateImageView(get_device().get_handle(), &color_image_view, nullptr, &storage_image.view));

	VkCommandBuffer command_buffer = get_device().create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
	vkb::set_image_layout(command_buffer, storage_image.image,
	                      VK_IMAGE_LAYOUT_UNDEFINED,
	                      VK_IMAGE_LAYOUT_GENERAL,
	                      {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1});
	get_device().flush_command_buffer(command_buffer, queue);
}

/*
	Gets the device address from a buffer that's needed in many places during the ray tracing setup
*/
uint64_t RaytracingBasic::get_buffer_device_address(VkBuffer buffer)
{
	VkBufferDeviceAddressInfoKHR buffer_device_address_info{};
	buffer_device_address_info.sType  = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
	buffer_device_address_info.buffer = buffer;
	return vkGetBufferDeviceAddressKHR(device->get_handle(), &buffer_device_address_info);
}

/*
	Create buffer and allocate memory for a temporary scratch buffer
*/
ScratchBuffer RaytracingBasic::create_scratch_buffer(VkDeviceSize size)
{
	ScratchBuffer scratch_buffer{};

	VkBufferCreateInfo buffer_create_info = {};
	buffer_create_info.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
	buffer_create_info.size               = size;
	buffer_create_info.usage              = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
	VK_CHECK(vkCreateBuffer(device->get_handle(), &buffer_create_info, nullptr, &scratch_buffer.handle));

	VkMemoryRequirements memory_requirements = {};
	vkGetBufferMemoryRequirements(device->get_handle(), scratch_buffer.handle, &memory_requirements);

	VkMemoryAllocateFlagsInfo memory_allocate_flags_info = {};
	memory_allocate_flags_info.sType                     = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
	memory_allocate_flags_info.flags                     = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;

	VkMemoryAllocateInfo memory_allocate_info = {};
	memory_allocate_info.sType                = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
	memory_allocate_info.pNext                = &memory_allocate_flags_info;
	memory_allocate_info.allocationSize       = memory_requirements.size;
	memory_allocate_info.memoryTypeIndex      = device->get_memory_type(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
	VK_CHECK(vkAllocateMemory(device->get_handle(), &memory_allocate_info, nullptr, &scratch_buffer.memory));
	VK_CHECK(vkBindBufferMemory(device->get_handle(), scratch_buffer.handle, scratch_buffer.memory, 0));

	VkBufferDeviceAddressInfoKHR buffer_device_address_info{};
	buffer_device_address_info.sType  = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
	buffer_device_address_info.buffer = scratch_buffer.handle;
	scratch_buffer.device_address     = vkGetBufferDeviceAddressKHR(device->get_handle(), &buffer_device_address_info);

	return scratch_buffer;
}

void RaytracingBasic::delete_scratch_buffer(ScratchBuffer &scratch_buffer)
{
	if (scratch_buffer.memory != VK_NULL_HANDLE)
	{
		vkFreeMemory(device->get_handle(), scratch_buffer.memory, nullptr);
	}
	if (scratch_buffer.handle != VK_NULL_HANDLE)
	{
		vkDestroyBuffer(device->get_handle(), scratch_buffer.handle, nullptr);
	}
}

/*
	Create the bottom level acceleration structure that contains the scene's geometry (triangles)
*/
void RaytracingBasic::create_bottom_level_acceleration_structure()
{
	// Setup vertices and indices for a single triangle
	struct Vertex
	{
		float pos[3];
	};
	std::vector<Vertex> vertices = {
	    {{1.0f, 1.0f, 0.0f}},
	    {{-1.0f, 1.0f, 0.0f}},
	    {{0.0f, -1.0f, 0.0f}}};
	std::vector<uint32_t> indices = {0, 1, 2};

	auto vertex_buffer_size = vertices.size() * sizeof(Vertex);
	auto index_buffer_size  = indices.size() * sizeof(uint32_t);

	// Create buffers for the bottom level geometry
	// For the sake of simplicity we won't stage the vertex data to the GPU memory

	// Note that the buffer usage flags for buffers consumed by the bottom level acceleration structure require special flags
	const VkBufferUsageFlags buffer_usage_flags = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;

	vertex_buffer = std::make_unique<vkb::core::Buffer>(get_device(), vertex_buffer_size, buffer_usage_flags, VMA_MEMORY_USAGE_CPU_TO_GPU);
	vertex_buffer->update(vertices.data(), vertex_buffer_size);

	index_buffer = std::make_unique<vkb::core::Buffer>(get_device(), index_buffer_size, buffer_usage_flags, VMA_MEMORY_USAGE_CPU_TO_GPU);
	index_buffer->update(indices.data(), index_buffer_size);

	// Setup a single transformation matrix that can be used to transform the whole geometry for a single bottom level acceleration structure
	VkTransformMatrixKHR transform_matrix = {
	    1.0f, 0.0f, 0.0f, 0.0f,
	    0.0f, 1.0f, 0.0f, 0.0f,
	    0.0f, 0.0f, 1.0f, 0.0f};
	std::unique_ptr<vkb::core::Buffer> transform_matrix_buffer = std::make_unique<vkb::core::Buffer>(get_device(), sizeof(transform_matrix), buffer_usage_flags, VMA_MEMORY_USAGE_CPU_TO_GPU);
	transform_matrix_buffer->update(&transform_matrix, sizeof(transform_matrix));

	VkDeviceOrHostAddressConstKHR vertex_data_device_address{};
	VkDeviceOrHostAddressConstKHR index_data_device_address{};
	VkDeviceOrHostAddressConstKHR transform_matrix_device_address{};

	vertex_data_device_address.deviceAddress      = get_buffer_device_address(vertex_buffer->get_handle());
	index_data_device_address.deviceAddress       = get_buffer_device_address(index_buffer->get_handle());
	transform_matrix_device_address.deviceAddress = get_buffer_device_address(transform_matrix_buffer->get_handle());

	// The bottom level acceleration structure contains one set of triangles as the input geometry
	VkAccelerationStructureGeometryKHR acceleration_structure_geometry{};
	acceleration_structure_geometry.sType                            = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
	acceleration_structure_geometry.geometryType                     = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
	acceleration_structure_geometry.flags                            = VK_GEOMETRY_OPAQUE_BIT_KHR;
	acceleration_structure_geometry.geometry.triangles.sType         = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
	acceleration_structure_geometry.geometry.triangles.vertexFormat  = VK_FORMAT_R32G32B32_SFLOAT;
	acceleration_structure_geometry.geometry.triangles.vertexData    = vertex_data_device_address;
	acceleration_structure_geometry.geometry.triangles.maxVertex     = 3;
	acceleration_structure_geometry.geometry.triangles.vertexStride  = sizeof(Vertex);
	acceleration_structure_geometry.geometry.triangles.indexType     = VK_INDEX_TYPE_UINT32;
	acceleration_structure_geometry.geometry.triangles.indexData     = index_data_device_address;
	acceleration_structure_geometry.geometry.triangles.transformData = transform_matrix_device_address;

	// Get the size requirements for buffers involved in the acceleration structure build process
	VkAccelerationStructureBuildGeometryInfoKHR acceleration_structure_build_geometry_info{};
	acceleration_structure_build_geometry_info.sType         = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
	acceleration_structure_build_geometry_info.type          = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
	acceleration_structure_build_geometry_info.flags         = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
	acceleration_structure_build_geometry_info.geometryCount = 1;
	acceleration_structure_build_geometry_info.pGeometries   = &acceleration_structure_geometry;

	const uint32_t primitive_count = 1;

	VkAccelerationStructureBuildSizesInfoKHR acceleration_structure_build_sizes_info{};
	acceleration_structure_build_sizes_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
	vkGetAccelerationStructureBuildSizesKHR(
	    device->get_handle(),
	    VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
	    &acceleration_structure_build_geometry_info,
	    &primitive_count,
	    &acceleration_structure_build_sizes_info);

	// Create a buffer to hold the acceleration structure
	bottom_level_acceleration_structure.buffer = std::make_unique<vkb::core::Buffer>(
	    get_device(),
	    acceleration_structure_build_sizes_info.accelerationStructureSize,
	    VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR,
	    VMA_MEMORY_USAGE_GPU_ONLY);

	// Create the acceleration structure
	VkAccelerationStructureCreateInfoKHR acceleration_structure_create_info{};
	acceleration_structure_create_info.sType  = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
	acceleration_structure_create_info.buffer = bottom_level_acceleration_structure.buffer->get_handle();
	acceleration_structure_create_info.size   = acceleration_structure_build_sizes_info.accelerationStructureSize;
	acceleration_structure_create_info.type   = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
	vkCreateAccelerationStructureKHR(device->get_handle(), &acceleration_structure_create_info, nullptr, &bottom_level_acceleration_structure.handle);

	// The actual build process starts here

	// Create a scratch buffer as a temporary storage for the acceleration structure build
	ScratchBuffer scratch_buffer = create_scratch_buffer(acceleration_structure_build_sizes_info.buildScratchSize);

	VkAccelerationStructureBuildGeometryInfoKHR acceleration_build_geometry_info{};
	acceleration_build_geometry_info.sType                     = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
	acceleration_build_geometry_info.type                      = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
	acceleration_build_geometry_info.flags                     = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
	acceleration_build_geometry_info.mode                      = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
	acceleration_build_geometry_info.dstAccelerationStructure  = bottom_level_acceleration_structure.handle;
	acceleration_build_geometry_info.geometryCount             = 1;
	acceleration_build_geometry_info.pGeometries               = &acceleration_structure_geometry;
	acceleration_build_geometry_info.scratchData.deviceAddress = scratch_buffer.device_address;

	VkAccelerationStructureBuildRangeInfoKHR acceleration_structure_build_range_info;
	acceleration_structure_build_range_info.primitiveCount                                           = 1;
	acceleration_structure_build_range_info.primitiveOffset                                          = 0;
	acceleration_structure_build_range_info.firstVertex                                              = 0;
	acceleration_structure_build_range_info.transformOffset                                          = 0;
	std::vector<VkAccelerationStructureBuildRangeInfoKHR *> acceleration_build_structure_range_infos = {&acceleration_structure_build_range_info};

	// Build the acceleration structure on the device via a one-time command buffer submission
	// Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds
	VkCommandBuffer command_buffer = get_device().create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
	vkCmdBuildAccelerationStructuresKHR(
	    command_buffer,
	    1,
	    &acceleration_build_geometry_info,
	    acceleration_build_structure_range_infos.data());
	get_device().flush_command_buffer(command_buffer, queue);

	delete_scratch_buffer(scratch_buffer);

	// Get the bottom acceleration structure's handle, which will be used during the top level acceleration build
	VkAccelerationStructureDeviceAddressInfoKHR acceleration_device_address_info{};
	acceleration_device_address_info.sType                 = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
	acceleration_device_address_info.accelerationStructure = bottom_level_acceleration_structure.handle;
	bottom_level_acceleration_structure.device_address     = vkGetAccelerationStructureDeviceAddressKHR(device->get_handle(), &acceleration_device_address_info);
}

/*
	Create the top level acceleration structure containing geometry instances of the bottom level acceleration structure(s)
*/
void RaytracingBasic::create_top_level_acceleration_structure()
{
	VkTransformMatrixKHR transform_matrix = {
	    1.0f, 0.0f, 0.0f, 0.0f,
	    0.0f, 1.0f, 0.0f, 0.0f,
	    0.0f, 0.0f, 1.0f, 0.0f};

	VkAccelerationStructureInstanceKHR acceleration_structure_instance{};
	acceleration_structure_instance.transform                              = transform_matrix;
	acceleration_structure_instance.instanceCustomIndex                    = 0;
	acceleration_structure_instance.mask                                   = 0xFF;
	acceleration_structure_instance.instanceShaderBindingTableRecordOffset = 0;
	acceleration_structure_instance.flags                                  = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
	acceleration_structure_instance.accelerationStructureReference         = bottom_level_acceleration_structure.device_address;

	std::unique_ptr<vkb::core::Buffer> instances_buffer = std::make_unique<vkb::core::Buffer>(get_device(),
	                                                                               sizeof(VkAccelerationStructureInstanceKHR),
	                                                                               VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
	                                                                               VMA_MEMORY_USAGE_CPU_TO_GPU);
	instances_buffer->update(&acceleration_structure_instance, sizeof(VkAccelerationStructureInstanceKHR));

	VkDeviceOrHostAddressConstKHR instance_data_device_address{};
	instance_data_device_address.deviceAddress = get_buffer_device_address(instances_buffer->get_handle());

	// The top level acceleration structure contains (bottom level) instance as the input geometry
	VkAccelerationStructureGeometryKHR acceleration_structure_geometry{};
	acceleration_structure_geometry.sType                              = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
	acceleration_structure_geometry.geometryType                       = VK_GEOMETRY_TYPE_INSTANCES_KHR;
	acceleration_structure_geometry.flags                              = VK_GEOMETRY_OPAQUE_BIT_KHR;
	acceleration_structure_geometry.geometry.instances.sType           = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
	acceleration_structure_geometry.geometry.instances.arrayOfPointers = VK_FALSE;
	acceleration_structure_geometry.geometry.instances.data            = instance_data_device_address;

	// Get the size requirements for buffers involved in the acceleration structure build process
	VkAccelerationStructureBuildGeometryInfoKHR acceleration_structure_build_geometry_info{};
	acceleration_structure_build_geometry_info.sType         = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
	acceleration_structure_build_geometry_info.type          = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
	acceleration_structure_build_geometry_info.flags         = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
	acceleration_structure_build_geometry_info.geometryCount = 1;
	acceleration_structure_build_geometry_info.pGeometries   = &acceleration_structure_geometry;

	const uint32_t primitive_count = 1;

	VkAccelerationStructureBuildSizesInfoKHR acceleration_structure_build_sizes_info{};
	acceleration_structure_build_sizes_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR;
	vkGetAccelerationStructureBuildSizesKHR(
	    device->get_handle(), VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR,
	    &acceleration_structure_build_geometry_info,
	    &primitive_count,
	    &acceleration_structure_build_sizes_info);

	// Create a buffer to hold the acceleration structure
	top_level_acceleration_structure.buffer = std::make_unique<vkb::core::Buffer>(
	    get_device(),
	    acceleration_structure_build_sizes_info.accelerationStructureSize,
	    VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR,
	    VMA_MEMORY_USAGE_GPU_ONLY);

	// Create the acceleration structure
	VkAccelerationStructureCreateInfoKHR acceleration_structure_create_info{};
	acceleration_structure_create_info.sType  = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR;
	acceleration_structure_create_info.buffer = top_level_acceleration_structure.buffer->get_handle();
	acceleration_structure_create_info.size   = acceleration_structure_build_sizes_info.accelerationStructureSize;
	acceleration_structure_create_info.type   = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
	vkCreateAccelerationStructureKHR(device->get_handle(), &acceleration_structure_create_info, nullptr, &top_level_acceleration_structure.handle);

	// The actual build process starts here

	// Create a scratch buffer as a temporary storage for the acceleration structure build
	ScratchBuffer scratch_buffer = create_scratch_buffer(acceleration_structure_build_sizes_info.buildScratchSize);

	VkAccelerationStructureBuildGeometryInfoKHR acceleration_build_geometry_info{};
	acceleration_build_geometry_info.sType                     = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR;
	acceleration_build_geometry_info.type                      = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
	acceleration_build_geometry_info.flags                     = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
	acceleration_build_geometry_info.mode                      = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
	acceleration_build_geometry_info.dstAccelerationStructure  = top_level_acceleration_structure.handle;
	acceleration_build_geometry_info.geometryCount             = 1;
	acceleration_build_geometry_info.pGeometries               = &acceleration_structure_geometry;
	acceleration_build_geometry_info.scratchData.deviceAddress = scratch_buffer.device_address;

	VkAccelerationStructureBuildRangeInfoKHR acceleration_structure_build_range_info;
	acceleration_structure_build_range_info.primitiveCount                                           = 1;
	acceleration_structure_build_range_info.primitiveOffset                                          = 0;
	acceleration_structure_build_range_info.firstVertex                                              = 0;
	acceleration_structure_build_range_info.transformOffset                                          = 0;
	std::vector<VkAccelerationStructureBuildRangeInfoKHR *> acceleration_build_structure_range_infos = {&acceleration_structure_build_range_info};

	// Build the acceleration structure on the device via a one-time command buffer submission
	// Some implementations may support acceleration structure building on the host (VkPhysicalDeviceAccelerationStructureFeaturesKHR->accelerationStructureHostCommands), but we prefer device builds
	VkCommandBuffer command_buffer = get_device().create_command_buffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
	vkCmdBuildAccelerationStructuresKHR(
	    command_buffer,
	    1,
	    &acceleration_build_geometry_info,
	    acceleration_build_structure_range_infos.data());
	get_device().flush_command_buffer(command_buffer, queue);

	delete_scratch_buffer(scratch_buffer);

	// Get the top acceleration structure's handle, which will be used to setup it's descriptor
	VkAccelerationStructureDeviceAddressInfoKHR acceleration_device_address_info{};
	acceleration_device_address_info.sType                 = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR;
	acceleration_device_address_info.accelerationStructure = top_level_acceleration_structure.handle;
	top_level_acceleration_structure.device_address        = vkGetAccelerationStructureDeviceAddressKHR(device->get_handle(), &acceleration_device_address_info);
}

inline uint32_t aligned_size(uint32_t value, uint32_t alignment)
{
	return (value + alignment - 1) & ~(alignment - 1);
}

/*
	Create scene geometry and ray tracing acceleration structures
*/
void RaytracingBasic::create_scene()
{
	create_bottom_level_acceleration_structure();
	create_top_level_acceleration_structure();
}

/*
	Create the Shader Binding Tables that connects the ray tracing pipelines' programs and the  top-level acceleration structure

	SBT Layout used in this sample:

		/-----------\
		| raygen    |
		|-----------|
		| miss      |
		|-----------|
		| hit       |
		\-----------/
*/

void RaytracingBasic::create_shader_binding_tables()
{
	const uint32_t           handle_size             = ray_tracing_pipeline_properties.shaderGroupHandleSize;
	const uint32_t           handle_size_aligned     = aligned_size(ray_tracing_pipeline_properties.shaderGroupHandleSize, ray_tracing_pipeline_properties.shaderGroupHandleAlignment);
	const uint32_t           handle_alignment        = ray_tracing_pipeline_properties.shaderGroupHandleAlignment;
	const uint32_t           group_count             = static_cast<uint32_t>(shader_groups.size());
	const uint32_t           sbt_size                = group_count * handle_size_aligned;
	const VkBufferUsageFlags sbt_buffer_usafge_flags = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
	const VmaMemoryUsage     sbt_memory_usage        = VMA_MEMORY_USAGE_CPU_TO_GPU;

	// Raygen
	// Create binding table buffers for each shader type
	raygen_shader_binding_table = std::make_unique<vkb::core::Buffer>(get_device(), handle_size, sbt_buffer_usafge_flags, sbt_memory_usage, 0);
	miss_shader_binding_table   = std::make_unique<vkb::core::Buffer>(get_device(), handle_size, sbt_buffer_usafge_flags, sbt_memory_usage, 0);
	hit_shader_binding_table    = std::make_unique<vkb::core::Buffer>(get_device(), handle_size, sbt_buffer_usafge_flags, sbt_memory_usage, 0);

	// Copy the pipeline's shader handles into a host buffer
	std::vector<uint8_t> shader_handle_storage(sbt_size);
	VK_CHECK(vkGetRayTracingShaderGroupHandlesKHR(get_device().get_handle(), pipeline, 0, group_count, sbt_size, shader_handle_storage.data()));

	// Copy the shader handles from the host buffer to the binding tables
	uint8_t *data = static_cast<uint8_t *>(raygen_shader_binding_table->map());
	memcpy(data, shader_handle_storage.data(), handle_size);
	data = static_cast<uint8_t *>(miss_shader_binding_table->map());
	memcpy(data, shader_handle_storage.data() + handle_size_aligned, handle_size);
	data = static_cast<uint8_t *>(hit_shader_binding_table->map());
	memcpy(data, shader_handle_storage.data() + handle_size_aligned * 2, handle_size);
	raygen_shader_binding_table->unmap();
	miss_shader_binding_table->unmap();
	hit_shader_binding_table->unmap();
}

/*
	Create the descriptor sets used for the ray tracing dispatch
*/
void RaytracingBasic::create_descriptor_sets()
{
	std::vector<VkDescriptorPoolSize> pool_sizes = {
	    {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1},
	    {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
	    {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1}};
	VkDescriptorPoolCreateInfo descriptor_pool_create_info = vkb::initializers::descriptor_pool_create_info(pool_sizes, 1);
	VK_CHECK(vkCreateDescriptorPool(get_device().get_handle(), &descriptor_pool_create_info, nullptr, &descriptor_pool));

	VkDescriptorSetAllocateInfo descriptor_set_allocate_info = vkb::initializers::descriptor_set_allocate_info(descriptor_pool, &descriptor_set_layout, 1);
	VK_CHECK(vkAllocateDescriptorSets(get_device().get_handle(), &descriptor_set_allocate_info, &descriptor_set));

	// Setup the descriptor for binding our top level acceleration structure to the ray tracing shaders
	VkWriteDescriptorSetAccelerationStructureKHR descriptor_acceleration_structure_info{};
	descriptor_acceleration_structure_info.sType                      = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
	descriptor_acceleration_structure_info.accelerationStructureCount = 1;
	descriptor_acceleration_structure_info.pAccelerationStructures    = &top_level_acceleration_structure.handle;

	VkWriteDescriptorSet acceleration_structure_write{};
	acceleration_structure_write.sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
	acceleration_structure_write.dstSet          = descriptor_set;
	acceleration_structure_write.dstBinding      = 0;
	acceleration_structure_write.descriptorCount = 1;
	acceleration_structure_write.descriptorType  = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
	// The acceleration structure descriptor has to be chained via pNext
	acceleration_structure_write.pNext = &descriptor_acceleration_structure_info;

	VkDescriptorImageInfo image_descriptor{};
	image_descriptor.imageView   = storage_image.view;
	image_descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL;

	VkDescriptorBufferInfo buffer_descriptor = create_descriptor(*ubo);

	VkWriteDescriptorSet result_image_write   = vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &image_descriptor);
	VkWriteDescriptorSet uniform_buffer_write = vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, &buffer_descriptor);

	std::vector<VkWriteDescriptorSet> write_descriptor_sets = {
	    acceleration_structure_write,
	    result_image_write,
	    uniform_buffer_write};
	vkUpdateDescriptorSets(get_device().get_handle(), static_cast<uint32_t>(write_descriptor_sets.size()), write_descriptor_sets.data(), 0, VK_NULL_HANDLE);
}

/*
	Create our ray tracing pipeline
*/
void RaytracingBasic::create_ray_tracing_pipeline()
{
	// Slot for binding top level acceleration structures to the ray generation shader
	VkDescriptorSetLayoutBinding acceleration_structure_layout_binding{};
	acceleration_structure_layout_binding.binding         = 0;
	acceleration_structure_layout_binding.descriptorType  = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
	acceleration_structure_layout_binding.descriptorCount = 1;
	acceleration_structure_layout_binding.stageFlags      = VK_SHADER_STAGE_RAYGEN_BIT_KHR;

	VkDescriptorSetLayoutBinding result_image_layout_binding{};
	result_image_layout_binding.binding         = 1;
	result_image_layout_binding.descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
	result_image_layout_binding.descriptorCount = 1;
	result_image_layout_binding.stageFlags      = VK_SHADER_STAGE_RAYGEN_BIT_KHR;

	VkDescriptorSetLayoutBinding uniform_buffer_binding{};
	uniform_buffer_binding.binding         = 2;
	uniform_buffer_binding.descriptorType  = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
	uniform_buffer_binding.descriptorCount = 1;
	uniform_buffer_binding.stageFlags      = VK_SHADER_STAGE_RAYGEN_BIT_KHR;

	std::vector<VkDescriptorSetLayoutBinding> bindings = {
	    acceleration_structure_layout_binding,
	    result_image_layout_binding,
	    uniform_buffer_binding};

	VkDescriptorSetLayoutCreateInfo layout_info{};
	layout_info.sType        = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
	layout_info.bindingCount = static_cast<uint32_t>(bindings.size());
	layout_info.pBindings    = bindings.data();
	VK_CHECK(vkCreateDescriptorSetLayout(get_device().get_handle(), &layout_info, nullptr, &descriptor_set_layout));

	VkPipelineLayoutCreateInfo pipeline_layout_create_info{};
	pipeline_layout_create_info.sType          = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
	pipeline_layout_create_info.setLayoutCount = 1;
	pipeline_layout_create_info.pSetLayouts    = &descriptor_set_layout;

	VK_CHECK(vkCreatePipelineLayout(get_device().get_handle(), &pipeline_layout_create_info, nullptr, &pipeline_layout));

	// Ray tracing shaders require SPIR-V 1.4, so we need to set the appropriate target envinroment for the glslang compiler
	vkb::GLSLCompiler::set_target_environment(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4);

	/*
		Setup ray tracing shader groups
		Each shader group points at the corresponding shader in the pipeline
	*/
	std::vector<VkPipelineShaderStageCreateInfo> shader_stages;

	// Ray generation group
	{
		shader_stages.push_back(load_shader("khr_ray_tracing_basic/raygen.rgen", VK_SHADER_STAGE_RAYGEN_BIT_KHR));
		VkRayTracingShaderGroupCreateInfoKHR raygen_group_ci{};
		raygen_group_ci.sType              = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
		raygen_group_ci.type               = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
		raygen_group_ci.generalShader      = static_cast<uint32_t>(shader_stages.size()) - 1;
		raygen_group_ci.closestHitShader   = VK_SHADER_UNUSED_KHR;
		raygen_group_ci.anyHitShader       = VK_SHADER_UNUSED_KHR;
		raygen_group_ci.intersectionShader = VK_SHADER_UNUSED_KHR;
		shader_groups.push_back(raygen_group_ci);
	}

	// Ray miss group
	{
		shader_stages.push_back(load_shader("khr_ray_tracing_basic/miss.rmiss", VK_SHADER_STAGE_MISS_BIT_KHR));
		VkRayTracingShaderGroupCreateInfoKHR miss_group_ci{};
		miss_group_ci.sType              = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
		miss_group_ci.type               = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
		miss_group_ci.generalShader      = static_cast<uint32_t>(shader_stages.size()) - 1;
		miss_group_ci.closestHitShader   = VK_SHADER_UNUSED_KHR;
		miss_group_ci.anyHitShader       = VK_SHADER_UNUSED_KHR;
		miss_group_ci.intersectionShader = VK_SHADER_UNUSED_KHR;
		shader_groups.push_back(miss_group_ci);
	}

	// Ray closest hit group
	{
		shader_stages.push_back(load_shader("khr_ray_tracing_basic/closesthit.rchit", VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR));
		VkRayTracingShaderGroupCreateInfoKHR closes_hit_group_ci{};
		closes_hit_group_ci.sType              = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
		closes_hit_group_ci.type               = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
		closes_hit_group_ci.generalShader      = VK_SHADER_UNUSED_KHR;
		closes_hit_group_ci.closestHitShader   = static_cast<uint32_t>(shader_stages.size()) - 1;
		closes_hit_group_ci.anyHitShader       = VK_SHADER_UNUSED_KHR;
		closes_hit_group_ci.intersectionShader = VK_SHADER_UNUSED_KHR;
		shader_groups.push_back(closes_hit_group_ci);
	}

	/*
		Create the ray tracing pipeline
	*/
	VkRayTracingPipelineCreateInfoKHR raytracing_pipeline_create_info{};
	raytracing_pipeline_create_info.sType                        = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;
	raytracing_pipeline_create_info.stageCount                   = static_cast<uint32_t>(shader_stages.size());
	raytracing_pipeline_create_info.pStages                      = shader_stages.data();
	raytracing_pipeline_create_info.groupCount                   = static_cast<uint32_t>(shader_groups.size());
	raytracing_pipeline_create_info.pGroups                      = shader_groups.data();
	raytracing_pipeline_create_info.maxPipelineRayRecursionDepth = 1;
	raytracing_pipeline_create_info.layout                       = pipeline_layout;
	VK_CHECK(vkCreateRayTracingPipelinesKHR(get_device().get_handle(), VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &raytracing_pipeline_create_info, nullptr, &pipeline));
}

/*
	Deletes all ressources acquired by an acceleration structure
*/
void RaytracingBasic::delete_acceleration_structure(AccelerationStructure &acceleration_structure)
{
	if (acceleration_structure.buffer)
	{
		acceleration_structure.buffer.reset();
	}
	if (acceleration_structure.handle)
	{
		vkDestroyAccelerationStructureKHR(device->get_handle(), acceleration_structure.handle, nullptr);
	}
}

/*
	Create the uniform buffer used to pass matrices to the ray tracing ray generation shader
*/
void RaytracingBasic::create_uniform_buffer()
{
	ubo = std::make_unique<vkb::core::Buffer>(get_device(),
	                                          sizeof(uniform_data),
	                                          VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
	                                          VMA_MEMORY_USAGE_CPU_TO_GPU);
	ubo->convert_and_update(uniform_data);

	update_uniform_buffers();
}

/*
	Command buffer generation
*/
void RaytracingBasic::build_command_buffers()
{
	if (width != storage_image.width || height != storage_image.height)
	{
		// If the view port size has changed, we need to recreate the storage image
		vkDestroyImageView(get_device().get_handle(), storage_image.view, nullptr);
		vkDestroyImage(get_device().get_handle(), storage_image.image, nullptr);
		vkFreeMemory(get_device().get_handle(), storage_image.memory, nullptr);
		create_storage_image();
		// The descriptor also needs to be updated to reference the new image
		VkDescriptorImageInfo image_descriptor{};
		image_descriptor.imageView              = storage_image.view;
		image_descriptor.imageLayout            = VK_IMAGE_LAYOUT_GENERAL;
		VkWriteDescriptorSet result_image_write = vkb::initializers::write_descriptor_set(descriptor_set, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, &image_descriptor);
		vkUpdateDescriptorSets(get_device().get_handle(), 1, &result_image_write, 0, VK_NULL_HANDLE);
		build_command_buffers();
	}

	VkCommandBufferBeginInfo command_buffer_begin_info = vkb::initializers::command_buffer_begin_info();

	VkImageSubresourceRange subresource_range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};

	for (int32_t i = 0; i < draw_cmd_buffers.size(); ++i)
	{
		VK_CHECK(vkBeginCommandBuffer(draw_cmd_buffers[i], &command_buffer_begin_info));

		/*
			Setup the strided device address regions pointing at the shader identifiers in the shader binding table
		*/

		const uint32_t handle_size_aligned = aligned_size(ray_tracing_pipeline_properties.shaderGroupHandleSize, ray_tracing_pipeline_properties.shaderGroupHandleAlignment);

		VkStridedDeviceAddressRegionKHR raygen_shader_sbt_entry{};
		raygen_shader_sbt_entry.deviceAddress = get_buffer_device_address(raygen_shader_binding_table->get_handle());
		raygen_shader_sbt_entry.stride        = handle_size_aligned;
		raygen_shader_sbt_entry.size          = handle_size_aligned;

		VkStridedDeviceAddressRegionKHR miss_shader_sbt_entry{};
		miss_shader_sbt_entry.deviceAddress = get_buffer_device_address(miss_shader_binding_table->get_handle());
		miss_shader_sbt_entry.stride        = handle_size_aligned;
		miss_shader_sbt_entry.size          = handle_size_aligned;

		VkStridedDeviceAddressRegionKHR hit_shader_sbt_entry{};
		hit_shader_sbt_entry.deviceAddress = get_buffer_device_address(hit_shader_binding_table->get_handle());
		hit_shader_sbt_entry.stride        = handle_size_aligned;
		hit_shader_sbt_entry.size          = handle_size_aligned;

		VkStridedDeviceAddressRegionKHR callable_shader_sbt_entry{};

		/*
			Dispatch the ray tracing commands
		*/
		vkCmdBindPipeline(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline);
		vkCmdBindDescriptorSets(draw_cmd_buffers[i], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline_layout, 0, 1, &descriptor_set, 0, 0);

		vkCmdTraceRaysKHR(
		    draw_cmd_buffers[i],
		    &raygen_shader_sbt_entry,
		    &miss_shader_sbt_entry,
		    &hit_shader_sbt_entry,
		    &callable_shader_sbt_entry,
		    width,
		    height,
		    1);

		/*
			Copy ray tracing output to swap chain image
		*/

		// Prepare current swap chain image as transfer destination
		vkb::set_image_layout(
		    draw_cmd_buffers[i],
		    get_render_context().get_swapchain().get_images()[i],
		    VK_IMAGE_LAYOUT_UNDEFINED,
		    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
		    subresource_range);

		// Prepare ray tracing output image as transfer source
		vkb::set_image_layout(
		    draw_cmd_buffers[i],
		    storage_image.image,
		    VK_IMAGE_LAYOUT_GENERAL,
		    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
		    subresource_range);

		VkImageCopy copy_region{};
		copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
		copy_region.srcOffset      = {0, 0, 0};
		copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
		copy_region.dstOffset      = {0, 0, 0};
		copy_region.extent         = {width, height, 1};
		vkCmdCopyImage(draw_cmd_buffers[i], storage_image.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
		               get_render_context().get_swapchain().get_images()[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy_region);

		// Transition swap chain image back for presentation
		vkb::set_image_layout(
		    draw_cmd_buffers[i],
		    get_render_context().get_swapchain().get_images()[i],
		    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
		    VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
		    subresource_range);

		// Transition ray tracing output image back to general layout
		vkb::set_image_layout(
		    draw_cmd_buffers[i],
		    storage_image.image,
		    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
		    VK_IMAGE_LAYOUT_GENERAL,
		    subresource_range);

		/*
			Start a new render pass to draw the UI overlay on top of the ray traced image
		*/
		VkClearValue clear_values[2];
		clear_values[0].color        = {{0.0f, 0.0f, 0.033f, 0.0f}};
		clear_values[1].depthStencil = {0.0f, 0};

		VkRenderPassBeginInfo render_pass_begin_info    = vkb::initializers::render_pass_begin_info();
		render_pass_begin_info.renderPass               = render_pass;
		render_pass_begin_info.framebuffer              = framebuffers[i];
		render_pass_begin_info.renderArea.extent.width  = width;
		render_pass_begin_info.renderArea.extent.height = height;
		render_pass_begin_info.clearValueCount          = 2;
		render_pass_begin_info.pClearValues             = clear_values;

		vkCmdBeginRenderPass(draw_cmd_buffers[i], &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
		draw_ui(draw_cmd_buffers[i]);
		vkCmdEndRenderPass(draw_cmd_buffers[i]);

		VK_CHECK(vkEndCommandBuffer(draw_cmd_buffers[i]));
	}
}

void RaytracingBasic::update_uniform_buffers()
{
	uniform_data.proj_inverse = glm::inverse(camera.matrices.perspective);
	uniform_data.view_inverse = glm::inverse(camera.matrices.view);
	ubo->convert_and_update(uniform_data);
}

bool RaytracingBasic::prepare(vkb::Platform &platform)
{
	if (!ApiVulkanSample::prepare(platform))
	{
		return false;
	}

	// This sample copies the ray traced output to the swap chain image, so we need to enable the required image usage flags
	const std::set<VkImageUsageFlagBits> image_usage_flags = {VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT};
	update_swapchain_image_usage_flags(image_usage_flags);

	// This sample renders the UI overlay on top of the ray tracing output, so we need to disable color attachment clears
	update_render_pass_flags(RenderPassCreateFlags::ColorAttachmentLoad);

	// Get the ray tracing pipeline properties, which we'll need later on in the sample
	ray_tracing_pipeline_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
	VkPhysicalDeviceProperties2 device_properties{};
	device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
	device_properties.pNext = &ray_tracing_pipeline_properties;
	vkGetPhysicalDeviceProperties2(get_device().get_gpu().get_handle(), &device_properties);

	// Get the acceleration structure features, which we'll need later on in the sample
	acceleration_structure_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR;
	VkPhysicalDeviceFeatures2 device_features{};
	device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
	device_features.pNext = &acceleration_structure_features;
	vkGetPhysicalDeviceFeatures2(get_device().get_gpu().get_handle(), &device_features);

	camera.type = vkb::CameraType::LookAt;
	camera.set_perspective(60.0f, (float) width / (float) height, 0.1f, 512.0f);
	camera.set_rotation(glm::vec3(0.0f, 0.0f, 0.0f));
	camera.set_translation(glm::vec3(0.0f, 0.0f, -2.5f));

	create_storage_image();
	create_scene();
	create_uniform_buffer();
	create_ray_tracing_pipeline();
	create_shader_binding_tables();
	create_descriptor_sets();
	build_command_buffers();
	prepared = true;
	return true;
}

void RaytracingBasic::draw()
{
	ApiVulkanSample::prepare_frame();
	submit_info.commandBufferCount = 1;
	submit_info.pCommandBuffers    = &draw_cmd_buffers[current_buffer];
	VK_CHECK(vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE));
	ApiVulkanSample::submit_frame();
}

void RaytracingBasic::render(float delta_time)
{
	if (!prepared)
		return;
	draw();
	if (camera.updated)
		update_uniform_buffers();
}

std::unique_ptr<vkb::VulkanSample> create_raytracing_basic()
{
	return std::make_unique<RaytracingBasic>();
}

redpajama_set_name: RedPajamaGithub


text:
Leftist Freak Taken Into Custody for Threats to "Stab as Many Children as Possible" at Florida Elementary School…
TAMPA, Fla.–
A man who apparently planned an attack on a Tampa elementary school was taken into custody for mental health evaluation under the Baker Act. However, a document issued by the Hillsborough County Sheriff's Office appears only to have warned deputies about the alleged threat, raising questions about who should be notified about school threats and in what situations.
The bulletin, labeled "situational awareness" and "law enforcement sensitive," was sent Monday. It described the alleged plot hatched by 22-year-old Andrew Ivan Aman to stab students at Bellamy Elementary School.
The bulletin says Aman concealed a kitchen knife in a handbag and was headed for the school with the intent to "stab as many children as possible."
"If adults get in the way, he planned to stab them as well," the document stated.
However, Aman became sidetracked when he encountered his roommate before leaving their residence. That's when he apparently changed his mind. Aman's roommate told officers about the plot.
The document said Aman targeted the school because he hates the United States and "the school's 'obnoxious pride in America' as illustrated by the large American flag mural on the front of the building."
After Aman was taken into custody, deputies searched his residence. They said no firearms were found.
The bulletin warned, "Law enforcement should use extreme caution in dealing with [the subject.]"
It's unclear what agencies or groups had access to the document. In a section labeled "dissemination," a box is marked next to HCSO, but not "other law enforcement agency" or "public."
After the document was made public, the Hillsborough County Sheriff's Office issued a notice about the incident, verifying details outlined in the bulletin.
HCSO said there is an ongoing investigation and charges could follow, however, there is "currently no safety threat for students, parents or staff of Bellamy Elementary."
Via: FOX13
August 15, 2019 August 15, 2019 Frank and Freeda BluntTR News & PoliticsAndrew Ivan Aman, democrat violence, democrats are evil, Florida, leftist hate, leftist violence, Liberal Hate, Liberal Violence, News, Public Schools, Real News, Stabbing Attack, Truth
2 thoughts on "Leftist Freak Taken Into Custody for Threats to "Stab as Many Children as Possible" at Florida Elementary School…"
Manuel N K
The guy is nuts, but liberalism is a Mental disorder so… Doubly Insane?
Insane squared?
Previous Post What Democrats Have Been Saying About Our Border and Illegal Aliens Simply isn't True…
Next Post Watch: President Trump's "Trouble With Women and Minority Voters" is Another Leftist Lie…

redpajama_set_name: RedPajamaCommonCrawl


text:
schoolofrock
REVIEW: School of Rock
Quick Summary: Young or old, Stick It To The Man, and go and see the feel good, uplifting and energetic School of Rock.
My Dad and I at the end of the show
School of Rock is an adaptation of the 2003 comedy film of the same name starring Jack Black. The musical is written by Andrew Lloyd Webber (composer), Julian Fellowes (playwright) and Glenn Slater (Lyricist), and is currently showing at the Gillian Lynne Theatre in Drury Lane, London.
T H E S H O W
I first saw this show earlier this year, and alongside the ingenious fusion of rock, musical theatre and classical music influences, it was the vivacity and youthfulness of the cast that really stood out to me. I got the opportunity to take my Dad to see the show yesterday, and I knew he would love it simply because of the music; the show is saturated with nods to great rock songs such as Smoke on the Water, Satisfaction, as well as the rock concept album The Myths and Legends of King Arthur and the Knights of the Round Table.
The thought that my Dad actually came away from the show with went beyond noticing the obvious witty and comically written play, and great integration of well-known and loved music into the score. The overriding feeling that you get coming away from this show is one that is relevant at any and every stage of your life: don't get tied down by other people's limiting beliefs. This can be from something as small as whether you read Vogue or Sports Illustrated, as Billy has to choose, or as big as whether you compete in Battle of the Bands or not. The positive message of "You Do You" is woven tightly throughout the whole show.
The only reason I gave this show 4 stars as opposed to 5 was that by the end, I did start to feel quite tired. I was sitting 4 rows from the front (I talk about ticket details later on), and so the noise levels were high throughout. HOWEVER, this is a tiny, tiny point and generally did not detract from the experience.
T H E C A S T
Obviously, if you are going to see School of Rock then you are expecting a bunch of talented kids – and I can tell you, they do not disappoint! With cheesy over-acting thrown out of the window, the child cast of this production provides stellar vocal performances mixed with a convincing awareness of themselves and what they are trying to say. The harmonies in songs such as 'Horace Green Alma Mater' and 'If Only You Would Listen' highlights their cohesion and commitment.
I could not write a review on School of Rock without mentioning the musical talent of the kids in this production that I feel is unmatched on the rest of the West End. As Andrew Lloyd Webber announces over the loudspeaker at the beginning of the show, the children play all of their own rock instruments. The best moment in the show to demonstrate this is in the final song where the pit musicians all stand up and watch the show alongside the audience, as the children in the show alongside their mentor fake-teacher Dewey Finn rock their way through 'Stick It To The Man' and 'Teacher's Pet', full of guitar, keys, drum and bass solos, bringing the audience to its feet. The musicality and finesse in their playing is professional in its standard.
The standout vocal performance came from the shy but brilliant vocalist Tomika, played by Fayth Ifil, who performed a rendition of Amazing Grace full of innocence and killer riffs to prove she can sing, which induced a thunderous applause from the audience. Also highly notable was the bossy and indignant Summer, played by Freya Yates, who was very impressive in her 'Time To Play', hitting a belted Db at the end of the song.
Among the adults, both Craig Gallivan (down-and-out amateur rock star, Dewey Finn) and Rosanna Hyland (music lover turned uptight Headmistress, Rosalie Mullins) had fantastic performances. Rosanna Hyland's 'Where Did The Rock Go?' was full of emotion, bite and effortlessly clear top notes. Her rendition of Queen of the Night was unassuming and highly enjoyable. Craig Gallivan's Dewey Finn was hopeful, uplifting and unfailingly energetic, all matched by his perfect diction and fantastic voice.
Side note, the cast is changing on 22 August. Details can be found here
T H E T H E A T R E
As far as the theatre itself goes, the Gillian Lynne Theatre is modern, spacious and well designed. No matter what seat you go for, you generally won't get a bad one as the stage is so wide that you can see from most angles. From the furthest to the side in the front row, you will see the whole width of the stage, albeit with a few missing spots deeper into the set. The seating at the back of the stalls and the upper circle is well rigged so that you can easily see over the people in front of you, and don't have any of those "back-of-the-head" viewing moments.
T I C K E T S
The prices for this show are fairly reasonable if you are savvy when buying your tickets, and the show is absolutely worth the price. If you buy in advance (and maybe get matinee tickets) then you could easily spend a maximum of £35 a head in the stalls, which for a West End show is pretty good – I was seated 4 rows from the front with excellent views in seat D52, on a Saturday matinee performance for £35 per ticket.
The School of Rock website tells you the best dates with the best prices, so this is a great website to use. Also don't be afraid to be seated slightly to the side of the theatre, as the view is very rarely compromised!
Top tip: if you are over 5'4″, then a great cheaper ticket to get is in the front row of the upper circle. It is advertised as 'restricted view' because of a barrier and lighting rig that hangs over the front of the upper circle, but for anyone over 5'4, this does not obstruct at all, and the leg room is great!
If you've seen School of Rock, share your experience either in the comments or on our Instagram page!
August 19, 2018 April 16, 2019 therosieword Tagged andrewlloydwebber, blog, books, bookstagram, jackblack, music, musicaltheatre, review, schoolofrock, schoolofrockthemusical, songs, theatrekid, write, writer, writing	2 Comments


text:
L'édition 2021 du tournoi de tennis de Linz se déroule du 7 au  sur dur en intérieur. Elle appartient à la catégorie WTA 250.

Faits marquants

Forfaits

Lauréates
L'américaine Alison Riske  remporte son  WTA, le  depuis 2019, en dominant en finale la roumaine Jaqueline Cristian.
La paire russe Natela Dzalamidze / Kamilla Rakhimova remporte le double.

Primes et points

NB : Pour les têtes de série exemptées de , une élimination au  ne rapporte qu'un point WTA.
Source:

Résultats en simple

Parcours

Tableau

Résultats en double

Parcours

Tableau

Notes et références

Notes

Références

Voir aussi

Articles connexes
 Tournoi de tennis de Linz
 Saison 2021 de la WTA

Liens externes
  Site officiel du tournoi

WTA 2021
Linz
Sport en Autriche en 2021
Tennis en novembre 2021

redpajama_set_name: RedPajamaWikipedia


text:
Legendary Ex-Inter Milan President Massimo Moratti: "We Were Close To Signing Pele In 1958 But Santos Fans Refused To Accept Transfer"
Inter had come close to signing legendary former Santos and Brazil forward Pele in 1958, but the opposition of fans of Santos caused the deal to fall through.
This according to former Nerazzurri President Massimo Moratti, who told Italian news outlet Gazzetta.it that his father had a contract with the Brazilian icon ready but that it was the reaction of fans back in Brazil that stopped the transfer.
Pele passed away this evening, depriving football of one of its greatest and most iconic player.
The Brazilian great only ever played for two clubs in his career, namely Santos and New York Cosmos.
The former forward did naturally attract plenty of transfer interest during his career however, given his status as the best player in the world or very close to it.
According to Moratti, the Nerazzurri had made an attempt to sign Pele and come close, although in the end he remained at Santos, where he spent the vast majority of his career.
"When I read that he had been close to joining Milan in the Gazzetta, I was surprised," the former Inter President said.
"Sure, maybe, but Inter were certainly the first European club to have that great player in hand."
"I remember perfectly that we had signed Pele for the 1958-59 season, he was the young kid who astonished the world in Sweden and my father knew that he had to act fast to get ahead of the competition," Moratti continued.
"It was a full contract, signed, and it only needed to be deposited."
"But as soon as they heard about it in Brazil, there was an uproar against the club directors there, so how could we go through with it?"
"When you consider that there were really threats against the President of Santos, and you think you never know what some crazed person might do… it was no longer just a football situation, it was a matter of conscience and so my father tore the contract up."
Moratti explained that "The person who we were hearing on the other end of the phone was someone obviously very concerned for his safety."
"Then, when things calmed down we tried to return to the deal," he added, "but by that point things were closed off for other reasons."
By Toni Weeler
Chelsea's Chalobah, Man Utd's Lindelof & West Ham's Kehrer On Inter Milan's Radar As Nerazzurri Scramble For Skriniar Replacements, Italian Media Report
Inter Milan Could Sell Milan Skriniar To PSG For €15M If Atalanta Loan Merih Demiral As Replacement, Italian Broadcaster Reports
Lille's Djalo, Udinese's Becao & Spurs' Tanganga Among Inter Milan's Targets To Replace Skriniar, Italian Media Report


text:
Karl Ludwig Albrecht, né le  à Leipzig, et mort à une date inconnue, est un sculpteur saxon.

Biographie
Karl Ludwig Albrecht est né le  à Leipzig. Il apprend les rudiments de la sculpture de Knaur. Par la suite, il va à l'académie des arts de Leipzig, plus tard il peaufine ses compétences en étudiant les œuvres de Rietschel et Hanel. Ses deux premières œuvres, un Bacchus et un Gambrinus, connaissent un tel succès que les copies de terre cuite prolifèrent. Il exécute aussi de nombreuses statuettes destinées à être reproduites en argent.

Références

Annexes

Bibliographie

Liens externes

Sculpteur saxon
Naissance en octobre 1834
Naissance à Leipzig
Naissance dans le royaume de Saxe
Date de décès non renseignée (XIXe siècle)


text:
ISU Grand Prix w łyżwiarstwie figurowym 2011/2012 – 17. edycja zawodów w łyżwiarstwie figurowym. Zawodnicy podczas sezonu wystąpili w siedmiu zawodach cyklu rozgrywek. Rywalizacja rozpoczęła się w Ontario 21 października, a zakończyła we francuskiej Québec finałem Grand Prix, który odbył się w dniach 8 – 11 grudnia 2011 roku.

Kalendarium zawodów

Medaliści

Soliści

Solistki

Pary sportowe

Pary taneczne

Klasyfikacje punktowe

Awans do finału Grand Prix zdobywa 6 najlepszych zawodników/par w każdej z konkurencji.

Przypisy

Grand Prix w łyżwiarstwie figurowym
2011 w łyżwiarstwie figurowym
2012 w łyżwiarstwie figurowym


The architecture of a country defines its culture; the efficiency of its transportation systems defines its intellect.
Roads are one of the first indicators of the stability and strength of any country's infrastructure. They are the avenues to social and economic growth, providing access to health centres, financial institutions, supermarkets and most importantly, to family and friends.
Not only does the NRA build and maintain roads, we also collect information on the performance of the existing transportation system; forecast future traffic demand; and identify possible solutions to anticipated issues in system performance and deficiencies.
The National Roads Authority aims to improve lives by improving transportation.


text:
Biden picks diverse team of top economic advisers
30 November 2020 - 18:47 By Jarrett Renshaw
Biden named leading members of an economic team that will have to combat the crushing blows to workers and businesses from the coronavirus pandemic, which has killed more than 266,000 people in the United States in nine months.
Image: Reuters/Kevin Lamarque
President-elect Joe Biden named former Federal Reserve Chair Janet Yellen as his Treasury secretary nominee on Monday, and named three women to other top economic posts, setting the stage for a more diverse White House.
While Biden's transition to the presidency on Jan. 20 appeared to be hitting its stride, he himself was hobbling after fracturing his foot while playing with his dog on Saturday and will wear a protective boot for several weeks, his doctors said.
The incoming administration has been hampered for weeks by Republican President Donald Trump, who has refused to concede to Biden, a Democrat. Trump has said without providing evidence that the Nov. 3 vote was fraudulent, claims that state and federal election officials have dismissed.
In contrast to Trump, who largely picked white men for key positions, Biden's early appointments were shaping up to be highly diverse, including an all-women senior communications team unveiled on Sunday night. He named campaign spokeswoman Kate Bedingfield as White House communications director and veteran Democratic spokeswoman Jen Psaki as press secretary.
"This team looks like America and brings seriousness of purpose, the highest degree of competency, and unwavering belief in the promise of America," Biden said in a statement. "They will be ready on day one to get to work for all Americans."
Biden was expected to formally introduce the new economic team members on Tuesday, the transition team said.
Yellen, 74, chaired the U.S. central bank from 2014 to 2018 and had served as the chair of President Bill Clinton's Council of Economic Advisers.
On Twitter after Biden announced her nomination Yellen underscored the challenges facing the United States. "To recover, we must restore the American dream — a society where each person can rise to their potential and dream even bigger for their children. As Treasury Secretary, I will work every day towards rebuilding that dream for all."
Trump administration gives green light to proceed with Biden transition
After weeks of waiting, President Donald Trump's administration on Monday cleared the way for President-elect Joe Biden to transition to the White ...
PROGRESSIVE PICKS
Biden also said he would nominate Wally Adeyemo as Yellen's deputy. Adeyemo had been a deputy national security adviser under President Barack Obama, then was the president of the Obama Foundation, which is overseeing the planning for the Democratic former president's library.
And Biden said he would nominate Neera Tanden to head the Office of Management and Budget. Tanden helped the Obama administration create the Affordable Care Act, the sweeping healthcare overhaul popularly known as Obamacare that was one of the former president's central accomplishments and whose demolition became a central goal for Republicans.
Tanden, chief executive of the progressive Center for American Progress think tank, would be the first woman of color to lead the OMB if she is confirmed by the Senate.
Biden selected Cecelia Rouse, dean of the Princeton School of Public and International Affairs, to chair the Council of Economic Advisers. She was a member of the council under Obama from 2009 to 2011.
Heather Boushey, an economist focused on economic inequality and the president, chief executive and co-founder of the Washington Center for Equitable Growth, will serve on the council.
Biden and Vice President-elect Kamala Harris were also set to receive their first classified presidential daily briefing on Monday, which the Trump administration had previously refused to provide. The briefing is the first step toward transfer of responsibility for the most sensitive intelligence to a new administration.
Trump, for his part, kept up his unfounded fraud claims in an interview with Fox News on Sunday and with Sunday evening Tweets that the social media service flagged as disputed. Trump, who on Thursday said he would vacate the White House if Biden were formally declared winner by the Electoral College on Dec. 14, appeared to retreat from his combative legal stance, telling Fox that he did not see a path toward making his case to the U.S. Supreme Court.
Separately on Monday, election authorities in Georgia said they have opened investigations into third-party groups trying to sign up new voters in advance of a January special election that will determine control of the U.S. Senate.
As Biden marches forward with Cabinet, Trump hopes likely to fade in key states
US President Donald Trump's increasingly tenuous efforts to reverse his election loss to President-elect Joe Biden could be dealt a lethal blow on ...
Two weeks after Biden named President-elect, Trump faces stinging setbacks
Joe Biden on Saturday reached the two-week mark since becoming president-elect, with President Donald Trump stinging from back-to-back setbacks in ...
Ramaphosa's phone call with US president-elect Joe Biden
President Cyril Ramaphosa had a phone call with US President-elect Joe Biden on Tuesday evening to discuss strengthening US-Africa relations and ...
Coronavirus Command Council recommends that school reopening be postponed by ... News
Forget Twitter, Trump's son just asked Elon Musk to develop an app his dad can ... World
'You can keep him!' - Mzansi reacts to angry 'South African' who stormed US ... South Africa
Man clocks 240km/h on N1 in Limpopo – guess what he was driving South Africa
Education department confirms two-week delay in reopening schools South Africa


text:
ATLUTD: MLS Regular Season
Prekrap: Atlanta United at Philadelphia Union - who are the frauds?
(The answer is, and has been all year, the Union - but they might win anyway and if they do NYCFC will win the East)
By Parker Cleveland@AekprrAcdeellnv Aug 30, 2019, 9:05am EDT
Share All sharing options for: Prekrap: Atlanta United at Philadelphia Union - who are the frauds?
Atlanta United is coming off of its second trophy of 2019 and seventh win in a row in all competitions. It's very impressive and adds to the lore of the team. The match also highlighted an interesting phase of the season for Atlanta United - the opposition is scared. Minnesota United is a good team, they are a strong attacking side with one of the best goal scorers in the league and they got spooked by Atlanta before the game even started. Playing three defensive midfielders and sitting Darwin Quintero sent a strange message from Adrian Heath. Before the match, the talk from Minnesota was about feeling like they should win the game, but the lineup sent a message about not wanting to lose. Perhaps that got into the Loons players heads a bit, but Atlanta dominated the first half, had a few problems when Minnesota opened the game up to start the second, but then locked the result down when Leandro Gonzalez-Pirez got his customary red card.
At this point, teams should have some fear of what Atlanta can do in the attack, but as the Five Stripes have been showing recently, and showed time and again under Tata Martino, teams that play a defensive style and abandon their strengths will more likely be broken down than steal a point or win. That will be very different this week as the Five Stripes travel to Chester, Pennsylvania to take on the Philadelphia Union in a game that may very well determine if Atlanta or NYCFC ends up winning the conference.
The Philadelphia Fading Frauds
MLS has been in a word "weird" in 2019. It seemed like the teams that had more or less hacked (you know, cheated) the league by having innovative roster moves were poised to pull away from the rest of the league that wasn't following suit after last year. But, rather than Atlanta United, LAFC, NYCFC, and NYRB pulling away from the league, only LAFC has managed to dominate week in and week out. There are reasons for that including Frank de Boer needing to learn the league and deal with schedule congestion, NYCFC still playing in a baseball stadium, and the Red Bulls choking on the stench of a nearby landfill while Chris Armas blows it. The result has been what MLS has always wanted - parity.
This year it seems more like that is coming via attrition rather than an improvement by the rest of the league. It has opened up the table though and made it seem like anyone can be a contender to play LAFC in MLS Cup or the Western Conference Finals. There is only three points separating the 2-7th place teams in the West and until recently the East was very close with the Philadelphia Union, of all teams, filling the void left by Atlanta trying to figure out what it was doing, NYRB being NYRB, and NYCFC having a back loaded schedule. As the table stands now, Atlanta, Philly, and NYCFC are separated by a point and the teams in 4-8th place just stand four points apart.
Until recently, Philly had been solid. There were even thoughts that the team would separate from the rest of the conference going into May. Instead, they've looked about like a middle of the road playoff team. Sure, the Union are doing somethings better - the team is pressing more and scoring more, but Philly has let Atlanta and NYCFC reel them back in thanks to inconsistent performances since coming back from the summer international tournament break. In the last 11 games, Philly has lost four games, having only lost two prior to that, with five wins and two draws. It's not bad, it's not great, and Philly has had similar outcomes over the past two seasons where they've been impressive to begin the year only to fade down the stretch. It seems like that's the case once again.
All is not lost for the team though, they can still take the conference, perhaps needing some help, but winning at home against Atlanta United will be key for them to do it. However, for that to happen, they'll have to find a way to replace Alejandro Bedoya's ability to overcome mediocre defenders and maintain possession and push play in transition as he's suspended for the match. In addition, the team will rely on the creative spark of Ilsinho, a journeyman left back who came to the league from Russia and upon figuring out that American college graduates will just watch someone do tricks during a match, has amassed a library of tekkers videos that keep the Daniel Lovitzs of the world distracted from how their 401k is doing.
Anyway, aside from him, Philly has a backline that hasn't come together as well as it has in the past. Perhaps the added emphasis on pressing and attacking means that there is more space when the press is broken, but the team has allowed 41 goals (the third most of any team in the playoff picture in the East) or 1.46 goals a game. It's a lot of goals. The team has a nightmare of a schedule to finish the year as well with games against Atlanta, LAFC, NYRB, San Jose, and NYCFC over their last six. If they are going to make a push for the top spot in the East, they will need to tighten up the defense, and will need to play their best soccer of the season.
Winning the conference will mean winning on the road
The winner of this match will more than likely determine who carries the Eastern Conference - Atlanta United or NYCFC. Luckily, Atlanta is playing their best soccer of the season. It seems like Frank de Boer has taken the defensive shackles off of the team that he had held down his fleet of Ferraris with and Josef Martinez has dragged what was a clump of discarded bicycles out of the canal and the team is back to its old marauding fun to watch self. The talk of fans having high expectations has been replaced by trophies and Josef scoring at will as he excites the fanbase with declarations of love, as he told ProSoccerUSA after the USOC win: "Every time I drive here, I get goosebumps. For me, playing here is the best thing that's happened to me. I have to thank the fans. I love the people here."
What's more, the team is actually winning on the road finally. After not taking three points away from Atlanta since May, United have won their last two away from home and carrying that form will be key with four of the last seven matches coming after a trip on an airplane. On top of that, a win will finally, once and for all, settle the fraud debate about the Union. Are they actually good? A match with Josef, Barco, and Pity looking to exploit a shaky backline is a good test to answer that question.
He's running
I really can't emphasize how bad of a look it is for MLS that the Philadelphia Union were in first place in the East for so long. They made minor adjustments from last year when they barely made the playoffs and lost their best player in the off-season and they had people believing that they'd somehow become the next version of NYRB and not a kind of low-rent facsimile. Their season has been framed as a success story, but it also shows how the playoff set-up and fixture congestion that wore everyone down really disrupted the league. A win keeps Atlanta in first place, and as we all know, if you ain't first, you're last.


This is a tiny adirondack yurt cabin.
It's a 14′ wooden yurt that can be used as a tiny home, guest space, studio, backyard office, meditation space, or anything else you can think of.
Inside, this one is set up as a tiny home with a couch, loft bed, fireplace, and a kitchenette.
You can share this yurt cabin with your friends and family for free using the e-mail and social media re-share buttons below. Thanks.
If you enjoyed this tiny yurt you'll absolutely LOVE our Free Daily Tiny House Newsletter with even more! Thank you!
Not a lot of headroom in that bed…I'd bonk my head on the ceiling just turning over.
Very sweet and quite a nice space, but not really set up as a tiny home, in my opinion.
The bed is a death trap – turn over in the night and I would probably fall out….and the floor is a long way down!
The kitchenette pics aren't clear – is the blue cube a water container? Maybe with a bowl for washing up cups or washing one's self?
Lack of a toilet is the biggest marker that it is not really a home of any sort! I am not a 'going outside in the wild' sort of a lady!! I quite like the shape of a yurt, but to be lived in full time (or even for holidays…or beyond a couple of hours!!!) a toilet would be essential and would need to be screened off even if I was there on my own. This does detract from the beauty of the shape of a yurt, BUT I would not want to share toileting even with my nearest and dearest! This may be too much information, but I have a Kampa Khazi camping toilet now for night time use in our small house in France. The plumbed in toilet is downstairs, the stairs are narrow and steep and I have had a few night time stumbles on the way down to the toilet. The Kampa Khazi is a remove able plastic bucket with a lid, set in a plastic toilet shaped outer with toilet seat and lid. It's lightweight but sturdy. Something like that would work here, provided there is somewhere nearby to empty the bucket.
I have mentioned Clic-Clac sofas in other comments. I don't mean to sound like a broken record, but they are comfortable as both a sofa and a bed and ours has build under storage for bed linen, so they are a boon for tiny/small living. Our 6′ tall son sleeps on one in our small house in France and it seats 3 or 4 adults comfortably as a sofa (or in our case 3 adults and a dog!). It is easy to move to clean under or when we put the table up.
Thank you for putting the info up, Alex. They always make me think!
H-m-m…I thought yurts were canvas over a wooden frame.
Wow! That's some loft bed. I wouldn't want to fall out of that thing.


Do you think we are missing an alternative of google-analytics or a related project?
There are no recommendations yet. Be the first to promote google-analytics!
Have you used google-analytics? Share your experience. Write a short recommendation and google-analytics, you and your project will be promoted on Awesome Go.
Do you know of a usefull tutorial, book or news relevant to google-analytics?


text:
Ripple Finalizes $50 Million Investment in MoneyGram
Published on September 8, 2016 by crypto-profit
Blockchain service provider Ripple Labs has finalized its $50 million investment in MoneyGram International (NASDAQ:MGI). The money transfer company received the final $20 million from the San Francisco-based firm as part of the commitment made in June 2019.
Ripple Completes Investment in MoneyGram
In June, the blockchain provider committed $30 million as part of the investment, and now it has completed the transaction. In the latest transaction, Ripple acquired MoneyGram's newly issued stock at $4.10 per share, which is much higher than MoneyGram's current market valuation. With the investment concluded, Ripple will now hold around 10% of MoneyGram International's outstanding common shares.
According to MoneyGram CEO Alex Holmes, the partnership with Ripple is transformative for the digital asset segments as well as traditional money transfers. Holmes said that for the first time, they can settle currencies in a matter of seconds.
The Dallas-based money transfer firm aims at providing a platform that will enable its users across the globe to transfer and receive money quickly and safely. Customers can now transact effortlessly through the company's mobile or online platforms, or at global agent locations. The money that MoneyGram received will go into supporting its payments product, On-Demand Liquidity, which uses XRP.
On-Demand Liquidity Enhancing the Trading Volume
Since the companies partnered in June, MoneyGram International has used the On-Demand Liquidity platform to transact around 10% of its trading volume of the Mexican peso foreign exchange. It has also expanded cross-border transfers to Australia, Europe, and the Philippines. The amount the company received from Ripple will help it enhance trading volume through the use of the XRP-powered payment platform.
>> Bitfinex and Tether Hit With Another Market Manipulation Suit
Holmes said that partnerships such as the one with Ripple drive innovations and has helped MoneyGram to create enhanced customer experiences. He added that the company expects to enhance its growth into new territories as well as trying new products and services.
Ripple CEO Brad Garlinghouse stated that he was impressed with the progress they had made since they invested in MoneyGram International. He added that blockchain tech and digital assets have significant potential for transforming cross-border transactions.
Featured image: DepositPhotos © BiancoBlue
Ripple Invests in Cybersecurity Startup Funding Round
Elliptic, A Crypto Forensic Startup, Raises $23 Million USD
Elliptic, a British startup firm aimed at tracing suspicious crypto activity, has raised $23 million USD in a funding round
Ripple Shuns Securities Question | Dismisses XRP Lawsuit
Over the past few years, XRP has grown into the third-biggest cryptocurrency by market cap, and much of the credit
Ripple has invested in a $2.2 million USD seed funding round by London-based cybersecurity startup Keyless via its investing division,


text:
De polders Oud- en Nieuw Hongerland  vormden een waterschap in de gemeente Nissewaard (voorheen Hekelingen en daarna Spijkenisse) in de Nederlandse provincie Zuid-Holland. Het waterschap was in 1953 gevormd door:
 polder Nieuw Hongerland
 polder Oud Hongerland

Het waterschap was verantwoordelijk voor de waterhuishouding in de polders.

Polder in Nissewaard
Voormalig waterschap in Zuid-Holland


Glow-in-the-Dark Products stay illuminated for 10 hours.
During power outages or other situations where lights are off, SetonGlo(TM) Photoluminescent Fire and Exit Signs help employees find their way out while avoiding hazardous equipment, situations, and materials. Signs are available in aluminum, plastic, and self-adhesive materials in various sizes. SetonGlo tapes are offered in stripes, solids, and V- and arrow-styles. Glow-in-the-dark aisle marking arrows, dots, and footprints are also available.
Light the Way to Safety with SetonGlo(TM) Ten Hour Plus Glow-In-The-Dark Products!
Branford, CT - A production facility can be a dangerous place when the lights go out. Employees need to find their way out while avoiding potentially hazardous equipment, situations and materials. Seton is helping people stay safe during power outages and other emergencies with its line of SetonGlo(TM) Photoluminescent Fire & Exit Signs.
The SetonGlo(TM) signs are available in aluminum, plastic and self-adhesive materials in a variety of sizes.
In addition to signs, Seton offers other photoluminescent materials that comply with multiple safety standards and glow for ten plus hours. These products include glow-in-the-dark aisle marking arrows, dots and footprints. SetonGlo(TM) tapes are also available in stripes, solids and V- and arrow-styles for low-level marking.
For more information on Seton health and safety signs, as well as a complete online product catalog, visit www.seton.com or call 1-800-243-6624.
Seton is an international manufacturer of over 50,000 safety and facility identification products for manufacturing, construction, healthcare, telecommunication, electrical, and other markets.


text:
Researchers at Kaiser center in Almaden Valley…
Researchers at Kaiser center in Almaden Valley to study the roots of autism
By Stephen Baxter and Bay Area News Group | Santa Cruz Sentinel, Bay Area News Group
December 6, 2007 at 8:02 a.m.
Autism diagnoses continue to rise, and a local group of researchers is trying to understand the disorder's cause through a $5.9 million study funded by the Centers for Disease Control and Prevention.
Roughly 450 children from 2 to 4 years old will be recruited from Santa Clara and Alameda counties, with local testing conducted at Kaiser Permanente's Autism Spectrum Disorder Center in the Almaden Valley.
Families will not be paid to participate in the study, and children must have been born in Santa Clara or Alameda counties between September 2003 and August 2005. Children with neuro-developmental impairments and those with typical developments are being recruited.
Nationwide the study will include 2,700 children from six states. Autism, a brain-based disorder that affects a person's ability to socialize and communicate, can often be detected in a child's first three years. Some symptoms include a lack of eye contact with parents, obsessive behavior and a disinterest in conversation, according to the American Academy of Pediatrics.
The CDC estimates that about one in 150 children born in the United States is affected by autism, whose causes are not fully understood.
"We hope this study will help us learn more about the factors that may lead to autism and other developmental disabilities, and how genes and the environment may affect child development," said Lisa Croen, the principal investigator for the California portion of the study.
Croen said research will be conducted in the next four years and results will likely be available in five years.
The Study to Explore Early Development will be the largest investigation of factors that put children at risk for developmental disabilities such as autism. Researchers will collect data on factors such as medications taken during pregnancy, genetic history and parents' lifestyles and occupations.
Autism was recently in the news, when a 15-year-old San Jose boy became lost while hiking with his family in Uvas Canyon County Park. The boy, who does not speak, spent the night of Nov. 17 in the woods but was found 18 hours after his disappearance.
Some San Jose parents have firsthand experience with the disorder.
Vanessa Wallace has four children with autism spectrum disorders and plans to participate in the study. When Wallace's first child was diagnosed about six years ago, she was overwhelmed by the available information on causes and treatments.
"We're looking forward to the results. Any information we can learn about autism is going to empower parents to make better choices for their kids," Wallace said.
She added that San Jose Unified School District, Kaiser Permanente and other organizations have helped her family deal with autism. There are no known cures for autism spectrum disorders, but experts say children can progress developmentally and learn new skills.
A report from the American Academy of Pediatrics released in November suggested that parents should have children screened for autism twice before age 2.
"We want parents to know that there's life after the diagnosis and there's a lot of resources to help," Wallace said.
For more information, call (510) 620-3700 or (866) 470-6115.


text:
Common Management Errors
(not necessarily in order of importance and with some suggestions for remedial strategies)
"...Generally social and behavioural causes frustrate change initiatives rather than technical problems ... Too much focus on the tip of the iceberg, on the measurable and observable, on the before and after, and not on the complex process of changing..."
Patrick Dawson, 2005
Accepted Change Mantra Under Threat
Why are there so many management models?
"...persistently, organisational reality doesn't fit the idealised reality that the models present......by trying to provide certainty in a changing and ambiguous world, models entirely miss the point..."
Paul Culmsee as quoted by Theo Chapman 2016
Some examples: the idea that "six simple steps" or all the wrongs of the organisation can be put in 4 quadrants on a whiteboard is not appropriate.
Rather than concentrate on finding the right framework, it is better to help people handle the ambiguity of situations in constant flux and its messiness.
Unfortunately people in organisations tend to prefer models/frameworks they are familiar with, ie they are used as security rather than a means to solve a problem.
It is better to understand the behaviours that people revert to in the face of "ambiguity/uncertainty". People like to stay in their "zone of comfort", ie things they are familiar with
"...dealing with ambiguity can be learnt but can't be taught..."
Paul Cumsee as quoted by Theo Chapman 2016
Some warning signs that people are unable to handle ambiguity (called ambiguity intolerance), ie people rush to find solutions without considering all the details. The higher you go up the organisational tree, the more intolerant of ambiguity, ie
"...you have to learn to live with cognitive dissonance and tolerate it. You have to learn to live with contradictions. Sometimes you have to run with contradictions for a while, even though it feels wrong and you desperately want to manage it out and get back to a sense of order and control..."
Need to understand the situation and conditions, ie conditions trump situations or causes
Work conditions are more important than leadership, ie having
"...a really compelling purpose and providing adequate resources for staff to do their work will have better outcomes than for those organisations that don't have these things, regardless of the quality of leaders..."
Paul Cumsee 2016 as quoted by Theo Chapman 2016
People are looking for clear, simple solutions for these complex challenges and, most times, it is not possible.
With most change projects failing, some recent research is challenging some of the accepted mantras of change management. For example, concepts based on detachment from the past, stages and phases are being challenged as most people need to remember the past, build on it, learn from it, etc, not neglect or forget it.
"...staged theories have a certain seductive appeal - they bring a sense of conceptual order to a complex process and offer the emotional promised land of 'recovery' and 'closure'. However they are incapable of capturing the complexity, diversity and idiosynatic quality of the grieving experience. Staged models do not address the multiplicity of physical, psychological, social and spiritual needs experienced by the bereaved, their families and intimate networks..."
Downe-Wamboldt & Tamlyn as quoted by Ivana Crestani, 2016
The letting go of the past ignores the reality that staff are experiencing the past, present and future, now. This "letting go" approach creates resistance.
The need "to let go of the past" and "move on" has been the basis for concepts like the
i) grief cycle (Kubler-Ross, 1969) with it stages, ie shock, denial, anger, bargaining, depression, acceptance & integration (see elsewhere for more detail) is being challenged. We need to build and reflect, ie learn from the past, not neglect or ignore it.
ii) managing transitions (William Bridges, 1991), ie moving zones from "ending via neutral to beginning" (see elsewhere for more detail)
iii) SCARF (David Rock, 2008), ie status, certainty, autonomy, relatedness & fairness; it focuses on threats and rewards
NB the way people view change can depend on their attitude to change, ie is it an opportunity to look forward to or more a threat that needs to be carefully managed or is it inevitable?
- pushing the concept of "get on the bus/train, or get off" encourages group think rather than diversity, differing opinions, etc
- too often we focus on performance when it should be capability
- too often we focus on challenges, issues, etc rather than building on past successes, things we do well, etc
- are change models are too simplistic or too generalised given the complexity and situational elements of change (see more detail on the section covering 70+ change frameworks)
- most frameworks tend to be top-down, rational, linear and assume a single event, yet most organisations experience continuous multiple and frequent change
- the approach is too problem centric, ie a problem to fix rather than people/emotional/behavioural focused
- dominant focus on negative emotions like fear, anxiety, anger, sadness, resistance, etc that are considered to be dysfunctional; with limited research on positive emotions like hope, excitement, happiness, confidence, etc). Emotions are viewed more as a source of resistance than support.
5 levels of emotions (developed by Ashkansy and quoted by Ivana Crestani, 2016), ie
i) within person (emotional reactions, behaviours, etc)
ii) between persons (individual differences, emotional intelligence, etc)
iii) interpersonal (emotional labour, interpersonal relationships, etc)
iv) groups and teams (emotional contagion, leadership, group behaviour, etc)
v) organisation-wide (emotional culture & climate, leadership & organisation performance, etc)
"...employees experience a range of emotions in response to change; some feel calm, some feel excitement, while others feel anxious...... emotions become less intense over time, and a change from anticipatory emotions of hope and fear in the pre-merger stage, to realise emotions of happiness and sorrow post merger..."
Dasborough as quoted by Ivana Crestani, 2016
People are experiencing more change, eg from 2012 to 2015 both the pace and impact of change has increased by 71% and 65% respectively (Ivana Crestani, 2016).
Thus people are experiencing constant and multiple changes and need to be aware of the emotions that people are experiencing as they are in
- several stages of change at once
- accumulating emotional experiences during changes
- past emotional experiences will impact on subsequent change experiences
- how do emotions unfold as change unfold?
Different levels in the organisation have different experiences with change, eg
- senior levels (change is intentional, a conscious decision, designed to solve problems and provide new opportunities like promotional opportunities), ie
"...leaders don't see changes occurring simultaneously across the organisation because of a narrow focus and organisational silos..."
Ivana Crestani, 2016
- lower levels (change is imposed, it is out of one's control, it creates problems and disrupts routines)
"...employees experienced multiple changes simultaneously, but their ability to process these changes has an upper limit..."
NB Change is about people and feelings. Change and emotions are inseparable.
Engaging employees emotionally
This involves
- communicate continuity or connection via the past. This will enhance the sense of belonging, provides meaning to what does not change, gives a sense of control and enhances confidence
- supportive leadership that ensures staff have the capability to perform, capacity to change, enabling employees to change helpfully and with resilience, and using respectful language
"...these participative approaches can contribute to creating a community spirit which is an important role for communications and organisational change to engender commitment, trust in the organisation, its identity and its leaders, and readiness to change..."
Elving as quoted by Ivana Crestani, 2016
More research is required around the emotional experience of change around the following elements
- emotional intelligence (recognising and managing our own and others' emotions)
- emotional contagion (negative and positive emotions spreading like viruses)
- emotional labour (displaying required emotions at work, eg putting on a brave face)
- emotional culture (what emotions are expressed, suppressed and valued, eg culture of fear or trust)
Concept of continuing bond
This challenges a staged approach to grief.
Decades of research suggests that people retain their bonds with departed love ones and this can be a positive experience; this applies at the individual and collective levels. Staff have families, friends (at work and outside), etc with whom they will discuss change and talk about the past in a healthy positive way to help build the future. Linked with this is the notion that all emotions are healthy whether positive, negative or mixed. Negative emotions are not necessarily destructive or dysfunctional; they can help give constructive meaning to the change process. The best way to deal with negative emotions, like anger, is to acknowledge the emotions behind these issues rather than suppressing emotions. Also this means taking staff seriously and moving away from focusing on discrete emotions to understanding the emotional experience.


Axis Bank offers Commodity Power, Commodity Lite and Commodity Quik to provide finance to non-individuals against warehouse receipts or storage receipts. These loans can be taken against approved agri commodities stored in various private, professional or government warehouses. The Commodity Power fees and charges include processing charges for new cases and renewal of existing cases. To learn more about the Commodity Power fees & charges for breach of sanction terms, or in the event of default, please refer to the table below.


When a computer communicates with another computer there are certain rules that they follow. The commands that control computers are called protocols. The connection between devices depends on the protocol. The convention rules ensure that POS software gets all the needed upkeep. The protocols also can enable a computer to connect with other devices like printers and bar scanners.
Using the best POS software will advantage your corporation. Your business will be more efficient when serving customers.They help a person improve the customer services they offer. The POS software is programmed to do some of the tasks automatically. your computer can do work for you when you are out doing your business.
You can get various POS software in the software market. There is a high competition between the POS retail on whose product is the best. The competition between the providers makes it challenging on picking the best POS product that suits your business corporation. Certain features of the software and the provider will enable you to know the best software. The The first thing is to look at the industry which the software operates in. confirm how the current software works, and if it is efficient.
Stable POS software can be used for a long period of time without it crashing.You can ask around from other retailers who might have used the software. check the type of operating system of your computer and if the software you obtain is compatible. The best rated POS software performed well when it was used in windows.There are many POS software today in the market. Over the past ten years the accounting industry of system development has improved fast. The POS software development has also developed rapidly.
look at the company you have and the number of clients you serve and how the software can ensure the financial stability improves. Moreover, you should check the future plans of your business. You should compare the current software you use and the one you are about to acquire and how it will impact on your business in future.
software you pick should be easy to manage.
Having in mind all the above said details and consideration of the software you can make a good decision.


text:
Research Uncovers Desalted Water's Fingerprint
A new study by Avner Vengosh, associate professor of earth and ocean sciences at Duke University's Nicholas School of the Environment, and colleagues in France and Israel provides tools to identify and trace manmade water as it mixes with natural water supplies and, over time, replaces natural waters in areas entirely dependent on desalination.
Manmade water is created by removing salt from seawater and brackish groundwater through reverse osmosis desalination.
"Water that's been desalted through reverse osmosis contains a unique composition which will induce changes in the chemistry and ecology of aquifers and natural water systems it enters," says Vengosh.
The study, published in June in the peer-reviewed journal Environmental Science & Technology, details for the first time the isotope geochemistry – or chemical fingerprints – of the elements boron, lithium, strontium, oxygen, and hydrogen found in reverse osmosis-desalted seawater and brackish groundwater.
Identifying these unique geochemical and isotopic fingerprints gives scientists and water quality managers a new array of tools for tracing the presence and distribution of manmade fresh water in a region's soils, surface waters, and groundwater, Vengosh says.
Being able to trace water back to a desalinated source through its isotopic and geochemical fingerprints will allow local governments and water utilities to zero in on the problem of valuable water loss and correct it more quickly and efficiently. Moreover, because desalted wastewater can be recycled through the environment and reused as a drinking water source – a process already being used in southern California – the new tools would enable water authorities to trace the relative contribution of desalted water in their system and to test the effectiveness of their water treatment processes.
Vengosh co-authored the new study with Wolfram Kloppmann, Catherine Guerrot, and Romain Millot of the Bureau de Recherches Geologiques et Minieres of France, and Irena Pankratov of the National Water Commission of Israel.
Noise-quenching Curtains are Now on the Market
Trojan Launches Drinking Water System Validated for Full Virus Treatment
Idaho Mapping Method Earns Ash Award
Israel's Palmachim Desalination Plant Adds PX Devices
American Water to Find Methods of Optimizing RO
2022 Year in Review: A Look at the Average Monthly Temperatures Across Earth