void vkeGameRendererDynamic::setNodeData(VkeNodeData::List *inData){
	m_node_data = inData;
	if (m_node_data != NULL){

		uint32_t cnt = m_node_data->count();
		uint32_t transformsSize = 64 * 64;

		uint32_t sz = sizeof(VkeNodeUniform) * 100;
		sz += (transformsSize);

		VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;

		bufferCreate(&m_uniforms_buffer_staging, sz, (VkBufferUsageFlagBits)usageFlags);
		bufferAlloc(&m_uniforms_buffer_staging, &m_uniforms_staging, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);

		bufferCreate(&m_uniforms_buffer, sz, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
		bufferAlloc(&m_uniforms_buffer, &m_uniforms_memory, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);


		m_uniforms_descriptor.buffer = m_uniforms_buffer;
		m_uniforms_descriptor.offset = 0;
		m_uniforms_descriptor.range = sizeof(VkeNodeUniform) * 100;

		m_transforms_descriptor.buffer = m_uniforms_buffer;
		m_transforms_descriptor.offset = sizeof(VkeNodeUniform) * 100;
		m_transforms_descriptor.range = transformsSize; //(4 * 64);
	}
}
Exemplo n.º 2
0
void vkeGameRendererDynamic::setMaterialData(VkeMaterial::List *inData){
	m_materials = inData;

	if (m_materials != NULL){

		uint32_t cnt = m_materials->count();
		uint32_t sz = sizeof(VkeMaterialUniform) * cnt;

		VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;

		bufferCreate(&m_material_buffer_staging, sz, (VkBufferUsageFlagBits)usageFlags);
		bufferAlloc(&m_material_buffer_staging, &m_material_staging, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT);

		VkeMaterialUniform *uniforms = NULL;

		VKA_CHECK_ERROR(vkMapMemory(getDefaultDevice(), m_material_staging, 0, sz, 0, (void **)&uniforms), "Could not map buffer memory.\n");

		for (uint32_t i = 0; i < cnt; ++i){
			VkeMaterial *mat = m_materials->getMaterial(i);
			mat->initVKBufferData(m_material_buffer_staging);
			mat->updateVKBufferData(uniforms);
		}

		vkUnmapMemory(getDefaultDevice(), m_material_staging);
	}

}
Exemplo n.º 3
0
void vkeGameRendererDynamic::setNodeData(VkeNodeData::List *inData){
	m_node_data = inData;
	if (m_node_data != NULL){

		uint32_t cnt = m_node_data->count();
		uint32_t transformsSize = 64 * m_instance_count;

		uint32_t sz = sizeof(VkeNodeUniform) * cnt;
		sz += (transformsSize);

		m_uniforms_local = (float*)malloc( sz);

		bufferCreate(&m_uniforms_buffer, sz, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
		bufferAlloc(&m_uniforms_buffer, &m_uniforms_memory, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);


		m_uniforms_descriptor.buffer = m_uniforms_buffer;
		m_uniforms_descriptor.offset = 0;
		m_uniforms_descriptor.range = sizeof(VkeNodeUniform) * cnt;

		m_transforms_descriptor.buffer = m_uniforms_buffer;
		m_transforms_descriptor.offset = sizeof(VkeNodeUniform) * cnt;
		m_transforms_descriptor.range = transformsSize; 
	}
}
Exemplo n.º 4
0
/**
 * Sends a packet of bytes to a remote peer. Returns 0 on success.
 *
 * Returns -1 if an error occurs. Sets errno to ENOMEM if memory couldn't be
 * allocated. Sets errno to EHOSTDOWN if the peer died recently. Sets errno
 * to EINVAL if pid is the same as the local pid.
 */
int peerSendBytes(pid_t pid, const char* bytes, size_t size) {
	Peer* peer = localPeer;
    assert(peer != NULL);

    OutgoingPacket* packet = calloc(1, sizeof(OutgoingPacket));
    if (packet == NULL) {
        errno = ENOMEM;
        return -1;
    }

    Buffer* copy = bufferCreate(size); 
    if (copy == NULL) {
        free(packet);
        errno = ENOMEM;
        return -1;
    }

    // Copy data.
    memcpy(copy->data, bytes, size);
    copy->size = size;
    
    packet->bytes = copy;
    packet->header.type = BYTES;
    packet->header.size = size;
    packet->free = outgoingPacketFreeBytes;
    bufferPrepareForWrite(packet->bytes);
    
    peerLock(peer);
    
    PeerProxy* peerProxy = peerProxyGetOrCreate(peer, pid, true);
    if (peerProxy == NULL) {
        // The peer is already dead or we couldn't alloc memory. Either way,
        // errno is set.
        peerUnlock(peer);
        packet->free(packet); 
        return -1;
    } else {
        peerProxyEnqueueOutgoingPacket(peerProxy, packet);
        peerUnlock(peer);
        selectorWakeUp(peer->selector);
        return 0; 
    }
}
Exemplo n.º 5
0
static VkBool32 bufferObjectPrepare(IBufferSP& buffer, IDeviceMemorySP& deviceMemory, const IInitialResourcesSP& initialResources, const VkBufferCreateInfo& bufferCreateInfo, const VkMemoryPropertyFlags memoryPropertyFlag)
{
    VkResult result;

    //

    buffer = bufferCreate(initialResources->getDevice()->getDevice(), bufferCreateInfo.flags, bufferCreateInfo.size, bufferCreateInfo.usage, bufferCreateInfo.sharingMode, bufferCreateInfo.queueFamilyIndexCount, bufferCreateInfo.pQueueFamilyIndices);

    if (!buffer.get())
    {
        logPrint(VKTS_LOG_ERROR, "BufferObject: Could not create buffer.");

        return VK_FALSE;
    }

    VkMemoryRequirements memoryRequirements;

    buffer->getBufferMemoryRequirements(memoryRequirements);

    VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
    initialResources->getPhysicalDevice()->getPhysicalDeviceMemoryProperties(physicalDeviceMemoryProperties);

    deviceMemory = deviceMemoryCreate(initialResources->getDevice()->getDevice(), memoryRequirements, physicalDeviceMemoryProperties.memoryTypeCount, physicalDeviceMemoryProperties.memoryTypes, memoryPropertyFlag);

    if (!deviceMemory.get())
    {
        logPrint(VKTS_LOG_ERROR, "BufferObject: Could not allocate memory.");

        return VK_FALSE;
    }

    result = buffer->bindBufferMemory(deviceMemory->getDeviceMemory(), 0);

    if (result != VK_SUCCESS)
    {
        logPrint(VKTS_LOG_ERROR, "BufferObject: Could not bind buffer memory.");

        return VK_FALSE;
    }

    return VK_TRUE;
}
Exemplo n.º 6
0
static PeerProxy* peerProxyCreate(Peer* peer, Credentials credentials) {
    PeerProxy* peerProxy = calloc(1, sizeof(PeerProxy));
    if (peerProxy == NULL) {
        return NULL;
    }
   
    peerProxy->inputBuffer = bufferCreate(sizeof(Header));
    if (peerProxy->inputBuffer == NULL) {
        free(peerProxy);
        return NULL;
    }

    peerProxy->peer = peer;
    peerProxy->credentials = credentials;

    // Initial state == expecting a header.
    peerProxyExpectHeader(peerProxy); 
  
    // Add this proxy to the map. Make sure the key points to the stable memory
    // inside of the peer proxy itself.
    pid_t* pid = &(peerProxy->credentials.pid);
    hashmapPut(peer->peerProxies, pid, peerProxy);
    return peerProxy;
}
Exemplo n.º 7
0
void VkeCubeTexture::loadCubeDDS(const char *inFile){


	std::string searchPaths[] = {
		std::string(PROJECT_NAME),
		NVPWindow::sysExePath() + std::string(PROJECT_RELDIRECTORY),
		std::string(PROJECT_ABSDIRECTORY)
	};

	nv_dds::CDDSImage ddsImage;

	for (uint32_t i = 0; i < 3; ++i){
        std::string separator = "";
        uint32_t strSize = searchPaths[i].size();
        if(searchPaths[i].substr(strSize-1,strSize) != "/") separator = "/";
        std::string filePath = searchPaths[i] + separator + std::string("images/") + std::string(inFile);
        ddsImage.load(filePath, true);
		if (ddsImage.is_valid()) break;
	}

	if (!ddsImage.is_valid()){
		perror("Could not cube load texture image.\n");
		exit(1);
	}

	uint32_t imgW = ddsImage.get_width();
	uint32_t imgH = ddsImage.get_height();
	uint32_t comCount = ddsImage.get_components();
	uint32_t fmt = ddsImage.get_format();

	bool isCube = ddsImage.is_cubemap();
	bool isComp = ddsImage.is_compressed();

	VkFormat vkFmt = VK_FORMAT_R8G8B8A8_UNORM;

	switch (fmt){
	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
		vkFmt = VK_FORMAT_BC1_RGB_SRGB_BLOCK;
		break;

	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
		vkFmt = VK_FORMAT_BC2_UNORM_BLOCK;

		break;

	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
		vkFmt = VK_FORMAT_BC3_UNORM_BLOCK;
		break;
	default:

		break;
	}


	m_width = imgW;
	m_height = imgH;
	m_format = vkFmt;

	VulkanDC::Device::Queue::Name queueName = "DEFAULT_GRAPHICS_QUEUE";
	VulkanDC::Device::Queue::CommandBufferID cmdID = INIT_COMMAND_ID;
	VulkanDC *dc = VulkanDC::Get();
	VulkanDC::Device *device = dc->getDefaultDevice();
	VulkanDC::Device::Queue *queue = device->getQueue(queueName);
	VkCommandBuffer cmd = VK_NULL_HANDLE;

	queue->beginCommandBuffer(cmdID, &cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);

	imageCreateAndBind(
		&m_data.image,
		&m_data.memory,
		m_format, VK_IMAGE_TYPE_2D,
		m_width, m_height, 1, 6,
		VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
		(VkImageUsageFlagBits)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
		VK_IMAGE_TILING_OPTIMAL);

	VkBuffer cubeMapBuffer;
	VkDeviceMemory cubeMapMem;

	bufferCreate(&cubeMapBuffer, m_width*m_height * 3 * 6, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
	bufferAlloc(&cubeMapBuffer, &cubeMapMem, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);


	if (m_memory_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT){
		imageSetLayoutBarrier(cmdID, queueName, m_data.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL);

		for (uint32_t i = 0; i < 6; ++i){

			void *data = NULL;
			VkSubresourceLayout layout;
			VkImageSubresource subres;
			subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			subres.mipLevel = m_mip_level;
			subres.arrayLayer = i;
			vkGetImageSubresourceLayout(getDefaultDevice(), m_data.image, &subres, &layout);


			VKA_CHECK_ERROR(vkMapMemory(getDefaultDevice(), cubeMapMem, layout.offset, layout.size, 0, &data), "Could not map memory for image.\n");

			const nv_dds::CTexture &mipmap = ddsImage.get_cubemap_face(i);

			memcpy(data, (void *)mipmap, layout.size);



			vkUnmapMemory(getDefaultDevice(), cubeMapMem);
		}

		VkBufferImageCopy biCpyRgn[6];


		for (uint32_t k = 0; k < 6; ++k){
			VkSubresourceLayout layout;
			VkImageSubresource subres;
			subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			subres.mipLevel = m_mip_level;
			subres.arrayLayer = k;
			vkGetImageSubresourceLayout(getDefaultDevice(), m_data.image, &subres, &layout);

			biCpyRgn[k].bufferOffset = layout.offset;
			biCpyRgn[k].bufferImageHeight = 0;
			biCpyRgn[k].bufferRowLength = 0;
			biCpyRgn[k].imageExtent.width = m_width;
			biCpyRgn[k].imageExtent.height = m_height;
			biCpyRgn[k].imageExtent.depth = 1;
			biCpyRgn[k].imageOffset.x = 0;
			biCpyRgn[k].imageOffset.y = 0;
			biCpyRgn[k].imageOffset.z = 0;
			biCpyRgn[k].imageSubresource.baseArrayLayer = k;
			biCpyRgn[k].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			biCpyRgn[k].imageSubresource.layerCount = 1;
			biCpyRgn[k].imageSubresource.mipLevel = 0;

		}

		VkFence copyFence;
		VkFenceCreateInfo fenceInfo;
		memset(&fenceInfo, 0, sizeof(fenceInfo));
		fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;


		vkCreateFence(device->getVKDevice(), &fenceInfo, NULL, &copyFence);

		vkCmdCopyBufferToImage(cmd, cubeMapBuffer, m_data.image, m_data.imageLayout, 6, biCpyRgn);
		queue->flushCommandBuffer(cmdID, &copyFence);

		vkWaitForFences(device->getVKDevice(), 1, &copyFence, VK_TRUE, 100000000000);

		vkDestroyBuffer(device->getVKDevice(), cubeMapBuffer, NULL);
		vkFreeMemory(device->getVKDevice(), cubeMapMem, NULL);

	}


	VkSamplerCreateInfo sampler;

	sampler.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
	sampler.pNext = NULL;
	sampler.magFilter = VK_FILTER_NEAREST;
	sampler.minFilter = VK_FILTER_NEAREST;
	sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
	sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
	sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
	sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
	sampler.mipLodBias = 0.0f;
	sampler.maxAnisotropy = 1;
	sampler.compareOp = VK_COMPARE_OP_NEVER;
	sampler.minLod = 0.0f;
	sampler.maxLod = 0.0f;

	sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;

	VkImageViewCreateInfo view;
	view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
	view.pNext = NULL;
	view.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
	view.format = m_format;
	view.components.r = VK_COMPONENT_SWIZZLE_R;
	view.components.g = VK_COMPONENT_SWIZZLE_G;
	view.components.b = VK_COMPONENT_SWIZZLE_B;
	view.components.a = VK_COMPONENT_SWIZZLE_A;

	view.subresourceRange.baseArrayLayer = 0;
	view.subresourceRange.levelCount = 1;
	view.subresourceRange.baseMipLevel = 0;
	view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
	view.subresourceRange.layerCount = 1;

	VKA_CHECK_ERROR(vkCreateSampler(getDefaultDevice(), &sampler, NULL, &m_data.sampler), "Could not create sampler for image texture.\n");

	view.image = m_data.image;

	VKA_CHECK_ERROR(vkCreateImageView(getDefaultDevice(), &view, NULL, &m_data.view), "Could not create image view for texture.\n");





}
Exemplo n.º 8
0
void VkeCubeTexture::loadTextureFiles(const char **inPath){

	bool imagesOK = true;
	VKA_INFO_MSG("Loading Cube Texture.\n");
	for (uint32_t i = 0; i < 6; ++i){
		if (!loadTexture(inPath[i], NULL, NULL, &m_width, &m_height)){
			VKA_ERROR_MSG("Error loading texture image.\n");
			printf("Texture : %d not available (%s).\n", i, inPath[i]);
			return;
		}
	}

	VulkanDC::Device::Queue::Name queueName = "DEFAULT_GRAPHICS_QUEUE";
	VulkanDC::Device::Queue::CommandBufferID cmdID = INIT_COMMAND_ID;
	VulkanDC *dc = VulkanDC::Get();
	VulkanDC::Device *device = dc->getDefaultDevice();
	VulkanDC::Device::Queue *queue = device->getQueue(queueName);
	VkCommandBuffer cmd = VK_NULL_HANDLE;

	queue->beginCommandBuffer(cmdID, &cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);

	imageCreateAndBind(
		&m_data.image,
		&m_data.memory,
		m_format, VK_IMAGE_TYPE_2D,
		m_width, m_height, 1, 6,
		VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
		(VkImageUsageFlagBits)( VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT ),
		VK_IMAGE_TILING_OPTIMAL);

	VkBuffer cubeMapBuffer;
	VkDeviceMemory cubeMapMem;

	bufferCreate(&cubeMapBuffer, m_width*m_height * 4 * 6, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
	bufferAlloc(&cubeMapBuffer, &cubeMapMem, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);

	VkDeviceSize dSize = m_width * m_height * 4;
	uint32_t rowPitch = m_width * 4;

	if (m_memory_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT){
		imageSetLayoutBarrier(cmdID, queueName, m_data.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL);

		for (uint32_t i = 0; i < 6; ++i){

			void *data = NULL;
			VkDeviceSize ofst = dSize*i;

			VKA_CHECK_ERROR(vkMapMemory(getDefaultDevice(),cubeMapMem, ofst, dSize, 0, &data), "Could not map memory for image.\n");

			if (!loadTexture(inPath[i], (uint8_t**)&data, rowPitch, &m_width, &m_height)){
				VKA_ERROR_MSG("Could not load final image.\n");
			}

			vkUnmapMemory(getDefaultDevice(), cubeMapMem);
		}

		VkBufferImageCopy biCpyRgn[6];
			

		for (uint32_t k = 0; k < 6; ++k){
			VkDeviceSize ofst = dSize*k;

			biCpyRgn[k].bufferOffset = ofst;
			biCpyRgn[k].bufferImageHeight = 0;
			biCpyRgn[k].bufferRowLength = 0;
			biCpyRgn[k].imageExtent.width = m_width;
			biCpyRgn[k].imageExtent.height = m_height;
			biCpyRgn[k].imageExtent.depth = 1;
			biCpyRgn[k].imageOffset.x = 0;
			biCpyRgn[k].imageOffset.y = 0;
			biCpyRgn[k].imageOffset.z = 0;
			biCpyRgn[k].imageSubresource.baseArrayLayer = k;
			biCpyRgn[k].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
			biCpyRgn[k].imageSubresource.layerCount = 1;
			biCpyRgn[k].imageSubresource.mipLevel = 0;

		}

		VkFence copyFence;
		VkFenceCreateInfo fenceInfo;
		memset(&fenceInfo, 0, sizeof(fenceInfo));
		fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
		

		vkCreateFence(device->getVKDevice(), &fenceInfo,NULL , &copyFence);

		vkCmdCopyBufferToImage(cmd, cubeMapBuffer, m_data.image, m_data.imageLayout, 6, biCpyRgn);
		queue->flushCommandBuffer(cmdID , &copyFence);

		vkWaitForFences(device->getVKDevice(), 1, &copyFence, VK_TRUE, 100000000000);
		
		vkDestroyBuffer(device->getVKDevice(), cubeMapBuffer, NULL);
		vkFreeMemory(device->getVKDevice(), cubeMapMem, NULL);

	}


	VkSamplerCreateInfo sampler;
	
	sampler.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
	sampler.pNext = NULL;
	sampler.magFilter = VK_FILTER_NEAREST;
	sampler.minFilter = VK_FILTER_NEAREST;
	sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
    sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
	sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
	sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
	sampler.mipLodBias = 0.0f;
	sampler.maxAnisotropy = 1;
	sampler.compareOp = VK_COMPARE_OP_NEVER;
	sampler.minLod = 0.0f;
	sampler.maxLod = 0.0f;

	sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;

	VkImageViewCreateInfo view;
	view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
	view.pNext = NULL;
	view.viewType = VK_IMAGE_VIEW_TYPE_CUBE; 
	view.format = m_format;
	view.components = {
		
		VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A
	};
	
	view.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 0 };
    view.subresourceRange.baseArrayLayer = 0;
	view.subresourceRange.levelCount = 1;
	view.subresourceRange.baseMipLevel = 0;
    view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
	view.subresourceRange.layerCount = 1;

	VKA_CHECK_ERROR(vkCreateSampler(getDefaultDevice(), &sampler,NULL, &m_data.sampler), "Could not create sampler for image texture.\n");

	view.image = m_data.image;

	VKA_CHECK_ERROR(vkCreateImageView(getDefaultDevice(), &view,NULL, &m_data.view), "Could not create image view for texture.\n");


	VKA_INFO_MSG("Created CUBE Image Texture.\n");

}
Exemplo n.º 9
0
void vkeGameRendererDynamic::initIndirectCommands(){

	if (!m_node_data) return;

	VulkanDC *dc = VulkanDC::Get();
	VulkanDC::Device *device = dc->getDefaultDevice();
	VulkanDC::Device::Queue *queue = dc->getDefaultQueue();

	uint32_t cnt = m_node_data->count();
	uint32_t sz = sizeof(VkDrawIndexedIndirectCommand)*cnt;

	VkBuffer sceneIndirectStaging;
	VkDeviceMemory sceneIndirectMemStaging;

	VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;

	bufferCreate(&m_scene_indirect_buffer, sz, (VkBufferUsageFlagBits)usageFlags);
	bufferAlloc(&m_scene_indirect_buffer, &m_scene_indirect_memory, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);

	usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;

	bufferCreate(&sceneIndirectStaging, sz, (VkBufferUsageFlagBits)usageFlags);
	bufferAlloc(&sceneIndirectStaging, &sceneIndirectMemStaging, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);

	VkDrawIndexedIndirectCommand *commands = NULL;

	VKA_CHECK_ERROR(vkMapMemory(device->getVKDevice(), sceneIndirectMemStaging, 0, sz, 0, (void **)&commands), "Could not map indirect buffer memory.\n");

	for (uint32_t i = 0; i < cnt; ++i){
		VkeMesh *mesh = m_node_data->getData(i)->getMesh();
		commands[i].firstIndex = mesh->getFirstIndex();
		commands[i].firstInstance = i*m_instance_count;
		commands[i].vertexOffset = mesh->getFirstVertex();
		commands[i].indexCount = mesh->getIndexCount();
		commands[i].instanceCount = m_instance_count;
	}

	vkUnmapMemory(device->getVKDevice(), sceneIndirectMemStaging);

	VkBufferCopy bufCpy;
	bufCpy.dstOffset = 0;
	bufCpy.srcOffset = 0;
	bufCpy.size = sz;

	VkCommandBuffer copyCmd;
	VkCommandBufferAllocateInfo cmdBufInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO };
	cmdBufInfo.commandBufferCount = 1;
	cmdBufInfo.commandPool = queue->getCommandPool();
	cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;

	VKA_CHECK_ERROR(vkAllocateCommandBuffers(device->getVKDevice(), &cmdBufInfo, &copyCmd), "Could not allocate command buffers.\n");

	VkCommandBufferBeginInfo cmdBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
	cmdBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;

	VKA_CHECK_ERROR(vkBeginCommandBuffer(copyCmd, &cmdBeginInfo), "Could not begin commmand buffer.\n");

	vkCmdCopyBuffer(copyCmd, sceneIndirectStaging, m_scene_indirect_buffer, 1, &bufCpy);

	VKA_CHECK_ERROR(vkEndCommandBuffer(copyCmd), "Could not end command buffer.\n");

	VkSubmitInfo subInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
	subInfo.commandBufferCount = 1;
	subInfo.pCommandBuffers = &copyCmd;

	VkFence theFence;
	VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO };

	VKA_CHECK_ERROR(vkCreateFence(device->getVKDevice(), &fenceInfo, NULL, &theFence), "Could not create fence.\n");
	VKA_CHECK_ERROR(vkQueueSubmit(queue->getVKQueue(), 1, &subInfo, theFence), "Could not submit queue for indirect buffer copy.\n");
	VKA_CHECK_ERROR(vkWaitForFences(device->getVKDevice(), 1, &theFence, VK_TRUE, UINT_MAX), "Could not wait for fence.\n");

	vkFreeCommandBuffers(device->getVKDevice(), queue->getCommandPool(), 1, &copyCmd);
	vkDestroyFence(device->getVKDevice(), theFence, NULL);

}