Exemplo n.º 1
0
void VkApp::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size){
	VkCommandBuffer commandBuffer = beginSingleTimeCommands();

	VkBufferCopy copyRegion = {};
	copyRegion.size = size;
	vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);

	endSingleTimeCommands(commandBuffer);
}
Exemplo n.º 2
0
void op3d::Engine::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
{
    VkCommandBuffer commandBuffer = commandBufferManager.beginSingleTimeCommands();

    VkBufferCopy copyRegion = {};
    copyRegion.size = size;
    vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);

    commandBufferManager.endSingleTimeCommands(commandBuffer, graphicsQueue);
}
Exemplo n.º 3
0
    void CopyContext::copyBufferRegion(const Buffer* pDst, uint64_t dstOffset, const Buffer* pSrc, uint64_t srcOffset, uint64_t numBytes)
    {
        resourceBarrier(pDst, Resource::State::CopyDest);
        resourceBarrier(pSrc, Resource::State::CopySource);
        VkBufferCopy region;
        region.srcOffset = pSrc->getGpuAddressOffset() + srcOffset;
        region.dstOffset = pDst->getGpuAddressOffset() + dstOffset;
        region.size = numBytes;

        vkCmdCopyBuffer(mpLowLevelData->getCommandList(), pSrc->getApiHandle(), pDst->getApiHandle(), 1, &region);
        mCommandsPending = true;
    }
Exemplo n.º 4
0
void Renderer::copyBuffer(VkCommandPool commandPool, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
	VkCommandBuffer command_buffer = _BeginSingleTimeCommands(commandPool);

	VkBufferCopy copy_region = {};
	copy_region.srcOffset = 0;
	copy_region.dstOffset = 0;
	copy_region.size = size;

	vkCmdCopyBuffer(command_buffer, srcBuffer, dstBuffer, 1, &copy_region);
	
	_EndSingleTimeCommands(commandPool, command_buffer);
}
Exemplo n.º 5
0
void VkHelper::copyBuffer(VkDevice device, VkCommandPool cmdPool, VkQueue queue, VkBuffer srcBufferId, VkBuffer dstBufferId, VkDeviceSize size)
{
	VkCommandBuffer cmdBuffer = beginSingleTimeCommandBufffer(device, cmdPool);

	VkBufferCopy copyRegion{};
	copyRegion.srcOffset = 0;
	copyRegion.dstOffset = 0;
	copyRegion.size = size;
	vkCmdCopyBuffer(cmdBuffer, srcBufferId, dstBufferId, 1, &copyRegion);

	endSingleTimeCommandBuffer(device, cmdPool, queue, cmdBuffer);
}
Exemplo n.º 6
0
		/**
		* Copy buffer data from src to dst using VkCmdCopyBuffer
		* 
		* @param src Pointer to the source buffer to copy from
		* @param dst Pointer to the destination buffer to copy tp
		* @param queue Pointer
		* @param copyRegion (Optional) Pointer to a copy region, if NULL, the whole buffer is copied
		*
		* @note Source and destionation pointers must have the approriate transfer usage flags set (TRANSFER_SRC / TRANSFER_DST)
		*/
		void copyBuffer(vk::Buffer *src, vk::Buffer *dst, VkQueue queue, VkBufferCopy *copyRegion = nullptr)
		{
			assert(dst->size <= src->size);
			assert(src->buffer && src->buffer);
			VkCommandBuffer copyCmd = createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
			VkBufferCopy bufferCopy{};
			if (copyRegion == nullptr)
			{
				bufferCopy.size = src->size;
			}
			else
			{
				bufferCopy = *copyRegion;
			}

			vkCmdCopyBuffer(copyCmd, src->buffer, dst->buffer, 1, &bufferCopy);

			flushCommandBuffer(copyCmd, queue);
		}
Exemplo n.º 7
0
/*
================
GLMesh_LoadVertexBuffer

Upload the given alias model's mesh to a VBO

Original code by MH from RMQEngine
================
*/
static void GLMesh_LoadVertexBuffer (qmodel_t *m, const aliashdr_t *hdr)
{
	int totalvbosize = 0;
	int remaining_size;
	int copy_offset;
	const aliasmesh_t *desc;
	const short *indexes;
	const trivertx_t *trivertexes;
	byte *vbodata;
	int f;
	VkResult err;

// count the sizes we need
	
	// ericw -- RMQEngine stored these vbo*ofs values in aliashdr_t, but we must not
	// mutate Mod_Extradata since it might be reloaded from disk, so I moved them to qmodel_t
	// (test case: roman1.bsp from arwop, 64mb heap)
	m->vboindexofs = 0;
	
	m->vboxyzofs = 0;
	totalvbosize += (hdr->numposes * hdr->numverts_vbo * sizeof (meshxyz_t)); // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
	
	m->vbostofs = totalvbosize;
	totalvbosize += (hdr->numverts_vbo * sizeof (meshst_t));
	
	if (!hdr->numindexes) return;
	if (!totalvbosize) return;
	
// grab the pointers to data in the extradata

	desc = (aliasmesh_t *) ((byte *) hdr + hdr->meshdesc);
	indexes = (short *) ((byte *) hdr + hdr->indexes);
	trivertexes = (trivertx_t *) ((byte *)hdr + hdr->vertexes);

	{
		const int totalindexsize = hdr->numindexes * sizeof (unsigned short);

		// Allocate index buffer & upload to GPU
		VkBufferCreateInfo buffer_create_info;
		memset(&buffer_create_info, 0, sizeof(buffer_create_info));
		buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
		buffer_create_info.size = totalindexsize;
		buffer_create_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
		err = vkCreateBuffer(vulkan_globals.device, &buffer_create_info, NULL, &m->index_buffer);
		if (err != VK_SUCCESS)
			Sys_Error("vkCreateBuffer failed");

		GL_SetObjectName((uint64_t)m->index_buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, m->name);

		VkMemoryRequirements memory_requirements;
		vkGetBufferMemoryRequirements(vulkan_globals.device, m->index_buffer, &memory_requirements);

		uint32_t memory_type_index = GL_MemoryTypeFromProperties(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
		VkDeviceSize heap_size = INDEX_HEAP_SIZE_MB * (VkDeviceSize)1024 * (VkDeviceSize)1024;
		VkDeviceSize aligned_offset = GL_AllocateFromHeaps(GEOMETRY_MAX_HEAPS, index_buffer_heaps, heap_size, memory_type_index, memory_requirements.size,
			memory_requirements.alignment, &m->index_heap, &m->index_heap_node, &num_vulkan_mesh_allocations, "Index Buffers");
		err = vkBindBufferMemory(vulkan_globals.device, m->index_buffer, m->index_heap->memory, aligned_offset);
		if (err != VK_SUCCESS)
			Sys_Error("vkBindBufferMemory failed");

		remaining_size = totalindexsize;
		copy_offset = 0;

		while (remaining_size > 0)
		{
			const int size_to_copy = q_min(remaining_size, STAGING_BUFFER_SIZE_KB * 1024);
			VkBuffer staging_buffer;
			VkCommandBuffer command_buffer;
			int staging_offset;
			unsigned char * staging_memory = R_StagingAllocate(size_to_copy, 1, &command_buffer, &staging_buffer, &staging_offset);

			memcpy(staging_memory, (byte*)indexes + copy_offset, size_to_copy);

			VkBufferCopy region;
			region.srcOffset = staging_offset;
			region.dstOffset = copy_offset;
			region.size = size_to_copy;
			vkCmdCopyBuffer(command_buffer, staging_buffer, m->index_buffer, 1, &region);

			copy_offset += size_to_copy;
			remaining_size -= size_to_copy;
		}
	}

// create the vertex buffer (empty)

	vbodata = (byte *) malloc(totalvbosize);
	memset(vbodata, 0, totalvbosize);

// fill in the vertices at the start of the buffer
	for (f = 0; f < hdr->numposes; f++) // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
	{
		int v;
		meshxyz_t *xyz = (meshxyz_t *) (vbodata + (f * hdr->numverts_vbo * sizeof (meshxyz_t)));
		const trivertx_t *tv = trivertexes + (hdr->numverts * f);

		for (v = 0; v < hdr->numverts_vbo; v++)
		{
			trivertx_t trivert = tv[desc[v].vertindex];

			xyz[v].xyz[0] = trivert.v[0];
			xyz[v].xyz[1] = trivert.v[1];
			xyz[v].xyz[2] = trivert.v[2];
			xyz[v].xyz[3] = 1;	// need w 1 for 4 byte vertex compression

			// map the normal coordinates in [-1..1] to [-127..127] and store in an unsigned char.
			// this introduces some error (less than 0.004), but the normals were very coarse
			// to begin with
			xyz[v].normal[0] = 127 * r_avertexnormals[trivert.lightnormalindex][0];
			xyz[v].normal[1] = 127 * r_avertexnormals[trivert.lightnormalindex][1];
			xyz[v].normal[2] = 127 * r_avertexnormals[trivert.lightnormalindex][2];
			xyz[v].normal[3] = 0;	// unused; for 4-byte alignment
		}
	}

// fill in the ST coords at the end of the buffer
	{
		meshst_t *st;
		float hscale, vscale;

		//johnfitz -- padded skins
		hscale = (float)hdr->skinwidth/(float)TexMgr_PadConditional(hdr->skinwidth);
		vscale = (float)hdr->skinheight/(float)TexMgr_PadConditional(hdr->skinheight);
		//johnfitz

		st = (meshst_t *) (vbodata + m->vbostofs);
		for (f = 0; f < hdr->numverts_vbo; f++)
		{
			st[f].st[0] = hscale * ((float) desc[f].st[0] + 0.5f) / (float) hdr->skinwidth;
			st[f].st[1] = vscale * ((float) desc[f].st[1] + 0.5f) / (float) hdr->skinheight;
		}
	}

	// Allocate vertex buffer & upload to GPU
	{
		VkBufferCreateInfo buffer_create_info;
		memset(&buffer_create_info, 0, sizeof(buffer_create_info));
		buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
		buffer_create_info.size = totalvbosize;
		buffer_create_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
		err = vkCreateBuffer(vulkan_globals.device, &buffer_create_info, NULL, &m->vertex_buffer);
		if (err != VK_SUCCESS)
			Sys_Error("vkCreateBuffer failed");

		GL_SetObjectName((uint64_t)m->vertex_buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, m->name);

		VkMemoryRequirements memory_requirements;
		vkGetBufferMemoryRequirements(vulkan_globals.device, m->vertex_buffer, &memory_requirements);

		uint32_t memory_type_index = GL_MemoryTypeFromProperties(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
		VkDeviceSize heap_size = VERTEX_HEAP_SIZE_MB * (VkDeviceSize)1024 * (VkDeviceSize)1024;
		VkDeviceSize aligned_offset = GL_AllocateFromHeaps(GEOMETRY_MAX_HEAPS, vertex_buffer_heaps, heap_size, memory_type_index, memory_requirements.size,
			memory_requirements.alignment, &m->vertex_heap, &m->vertex_heap_node, &num_vulkan_mesh_allocations, "Vertex Buffers");
		err = vkBindBufferMemory(vulkan_globals.device, m->vertex_buffer, m->vertex_heap->memory, aligned_offset);
		if (err != VK_SUCCESS)
			Sys_Error("vkBindBufferMemory failed");

		remaining_size = totalvbosize;
		copy_offset = 0;

		while (remaining_size > 0)
		{
			const int size_to_copy = q_min(remaining_size, STAGING_BUFFER_SIZE_KB * 1024);
			VkBuffer staging_buffer;
			VkCommandBuffer command_buffer;
			int staging_offset;
			unsigned char * staging_memory = R_StagingAllocate(size_to_copy, 1, &command_buffer, &staging_buffer, &staging_offset);

			memcpy(staging_memory, (byte*)vbodata + copy_offset, size_to_copy);

			VkBufferCopy region;
			region.srcOffset = staging_offset;
			region.dstOffset = copy_offset;
			region.size = size_to_copy;
			vkCmdCopyBuffer(command_buffer, staging_buffer, m->vertex_buffer, 1, &region);

			copy_offset += size_to_copy;
			remaining_size -= size_to_copy;
		}
	}

	free (vbodata);
}
Exemplo n.º 8
0
	// Setup and fill the compute shader storage buffers for
	// vertex positions and velocities
	void prepareStorageBuffers()
	{

		std::mt19937 rGenerator;
		std::uniform_real_distribution<float> rDistribution(-1.0f, 1.0f);

		// Initial particle positions
		std::vector<Particle> particleBuffer(PARTICLE_COUNT);
		for (auto& particle : particleBuffer)
		{
			particle.pos = glm::vec2(rDistribution(rGenerator), rDistribution(rGenerator));
			particle.vel = glm::vec2(0.0f);
			particle.gradientPos.x = particle.pos.x / 2.0f;
		}

		uint32_t storageBufferSize = particleBuffer.size() * sizeof(Particle);

		// Staging
		// SSBO is static, copy to device local memory 
		// This results in better performance

		struct {
			VkDeviceMemory memory;
			VkBuffer buffer;
		} stagingBuffer;

		VulkanExampleBase::createBuffer(
			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
			VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
			storageBufferSize,
			particleBuffer.data(),
			&stagingBuffer.buffer,
			&stagingBuffer.memory);

		VulkanExampleBase::createBuffer(
			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
			VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
			storageBufferSize,
			nullptr,
			&computeStorageBuffer.buffer,
			&computeStorageBuffer.memory);

		// Copy to staging buffer
		VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);

		VkBufferCopy copyRegion = {};
		copyRegion.size = storageBufferSize;
		vkCmdCopyBuffer(
			copyCmd,
			stagingBuffer.buffer,
			computeStorageBuffer.buffer,
			1,
			&copyRegion);

		VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);

		vkFreeMemory(device, stagingBuffer.memory, nullptr);
		vkDestroyBuffer(device, stagingBuffer.buffer, nullptr);

		computeStorageBuffer.descriptor.range = storageBufferSize;
		computeStorageBuffer.descriptor.buffer = computeStorageBuffer.buffer;
		computeStorageBuffer.descriptor.offset = 0;

		// Binding description
		vertices.bindingDescriptions.resize(1);
		vertices.bindingDescriptions[0] =
			vkTools::initializers::vertexInputBindingDescription(
				VERTEX_BUFFER_BIND_ID,
				sizeof(Particle),
				VK_VERTEX_INPUT_RATE_VERTEX);

		// Attribute descriptions
		// Describes memory layout and shader positions
		vertices.attributeDescriptions.resize(2);
		// Location 0 : Position
		vertices.attributeDescriptions[0] =
			vkTools::initializers::vertexInputAttributeDescription(
				VERTEX_BUFFER_BIND_ID,
				0,
				VK_FORMAT_R32G32_SFLOAT,
				0);
		// Location 1 : Gradient position
		vertices.attributeDescriptions[1] =
			vkTools::initializers::vertexInputAttributeDescription(
				VERTEX_BUFFER_BIND_ID,
				1,
				VK_FORMAT_R32G32B32A32_SFLOAT,
				4 * sizeof(float));

		// Assign to vertex buffer
		vertices.inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo();
		vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size();
		vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data();
		vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size();
		vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data();
	}
Exemplo n.º 9
0
	// Setup and fill the compute shader storage buffers for
	// vertex positions and velocities
	void prepareStorageBuffers()
	{
		float destPosX = 0.0f;
		float destPosY = 0.0f;

		// Initial particle positions
		std::vector<Particle> particleBuffer;
		for (int i = 0; i < PARTICLE_COUNT; ++i)
		{
			// Position
			float aspectRatio = (float)height / (float)width;
			float rndVal = (float)rand() / (float)(RAND_MAX / (360.0f * 3.14f * 2.0f));
			float rndRad = (float)rand() / (float)(RAND_MAX) * 0.5f;
			Particle p;
			p.pos = glm::vec4(
				destPosX + cos(rndVal) * rndRad * aspectRatio,
				destPosY + sin(rndVal) * rndRad,
				0.0f,
				1.0f);
			p.col = glm::vec4(
				(float)(rand() % 255) / 255.0f,
				(float)(rand() % 255) / 255.0f,
				(float)(rand() % 255) / 255.0f,
				1.0f);
			p.vel = glm::vec4(0.0f);
			particleBuffer.push_back(p);
		}

		// Buffer size is the same for all storage buffers
		uint32_t storageBufferSize = particleBuffer.size() * sizeof(Particle);

		VkMemoryAllocateInfo memAlloc = vkTools::initializers::memoryAllocateInfo();
		VkMemoryRequirements memReqs;

		VkResult err;
		void *data;

		struct StagingBuffer {
			VkDeviceMemory memory;
			VkBuffer buffer;
		} stagingBuffer;

		// Allocate and fill host-visible staging storage buffer object

		// Allocate and fill storage buffer object
		VkBufferCreateInfo vBufferInfo = 
			vkTools::initializers::bufferCreateInfo(
				VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 
				storageBufferSize);
		vkTools::checkResult(vkCreateBuffer(device, &vBufferInfo, nullptr, &stagingBuffer.buffer));
		vkGetBufferMemoryRequirements(device, stagingBuffer.buffer, &memReqs);
		memAlloc.allocationSize = memReqs.size;
		getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex);
		vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffer.memory));
		vkTools::checkResult(vkMapMemory(device, stagingBuffer.memory, 0, storageBufferSize, 0, &data));
		memcpy(data, particleBuffer.data(), storageBufferSize);
		vkUnmapMemory(device, stagingBuffer.memory);
		vkTools::checkResult(vkBindBufferMemory(device, stagingBuffer.buffer, stagingBuffer.memory, 0));

		// Allocate device local storage buffer ojbect
		vBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
		vkTools::checkResult(vkCreateBuffer(device, &vBufferInfo, nullptr, &computeStorageBuffer.buffer));
		vkGetBufferMemoryRequirements(device, computeStorageBuffer.buffer, &memReqs);
		memAlloc.allocationSize = memReqs.size;
		getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAlloc.memoryTypeIndex);
		vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &computeStorageBuffer.memory));
		vkTools::checkResult(vkBindBufferMemory(device, computeStorageBuffer.buffer, computeStorageBuffer.memory, 0));

		// Copy from host to device
		createSetupCommandBuffer();

		VkBufferCopy copyRegion = {};
		copyRegion.size = storageBufferSize;
		vkCmdCopyBuffer(
			setupCmdBuffer,
			stagingBuffer.buffer,
			computeStorageBuffer.buffer,
			1,
			&copyRegion);

		flushSetupCommandBuffer();

		// Destroy staging buffer
		vkDestroyBuffer(device, stagingBuffer.buffer, nullptr);
		vkFreeMemory(device, stagingBuffer.memory, nullptr);

		computeStorageBuffer.descriptor.buffer = computeStorageBuffer.buffer;
		computeStorageBuffer.descriptor.offset = 0;
		computeStorageBuffer.descriptor.range = storageBufferSize;

		// Binding description
		vertices.bindingDescriptions.resize(1);
		vertices.bindingDescriptions[0] =
			vkTools::initializers::vertexInputBindingDescription(
				VERTEX_BUFFER_BIND_ID,
				sizeof(Particle),
				VK_VERTEX_INPUT_RATE_VERTEX);

		// Attribute descriptions
		// Describes memory layout and shader positions
		vertices.attributeDescriptions.resize(2);
		// Location 0 : Position
		vertices.attributeDescriptions[0] =
			vkTools::initializers::vertexInputAttributeDescription(
				VERTEX_BUFFER_BIND_ID,
				0,
				VK_FORMAT_R32G32B32A32_SFLOAT,
				0);
		// Location 1 : Color
		vertices.attributeDescriptions[1] =
			vkTools::initializers::vertexInputAttributeDescription(
				VERTEX_BUFFER_BIND_ID,
				1,
				VK_FORMAT_R32G32B32A32_SFLOAT,
				sizeof(float) * 4);

		// Assign to vertex buffer
		vertices.inputState = vkTools::initializers::pipelineVertexInputStateCreateInfo();
		vertices.inputState.vertexBindingDescriptionCount = vertices.bindingDescriptions.size();
		vertices.inputState.pVertexBindingDescriptions = vertices.bindingDescriptions.data();
		vertices.inputState.vertexAttributeDescriptionCount = vertices.attributeDescriptions.size();
		vertices.inputState.pVertexAttributeDescriptions = vertices.attributeDescriptions.data();
	}
void VulkanTexturedQuad::CreateMeshBuffers(VkCommandBuffer uploadCommandBuffer)
{
    struct Vertex
    {
        float position[3];
        float uv[2];
    };

    static const Vertex vertices[4] =
    {
        // Upper Left
        { { -1.0f,  1.0f, 0 }, { 0, 1 } },
        // Upper Right
        { {  1.0f,  1.0f, 0 }, { 1, 1 } },
        // Bottom right
        { {  1.0f, -1.0f, 0 }, { 1, 0 } },
        // Bottom left
        { { -1.0f, -1.0f, 0 }, { 0, 0 } }
    };

    static const int indices[6] =
    {
        0, 1, 2, 2, 3, 0
    };

    auto memoryHeaps = EnumerateHeaps(physicalDevice_);

    indexBuffer_ = AllocateBuffer(device_, sizeof(indices),
        VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
    vertexBuffer_ = AllocateBuffer(device_, sizeof(vertices),
        VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);

    VkMemoryRequirements vertexBufferMemoryRequirements = {};
    vkGetBufferMemoryRequirements(device_, vertexBuffer_,
        &vertexBufferMemoryRequirements);
    VkMemoryRequirements indexBufferMemoryRequirements = {};
    vkGetBufferMemoryRequirements(device_, indexBuffer_,
        &indexBufferMemoryRequirements);

    VkDeviceSize bufferSize = vertexBufferMemoryRequirements.size;
    // We want to place the index buffer behind the vertex buffer. Need to take
    // the alignment into account to find the next suitable location
    VkDeviceSize indexBufferOffset = RoundToNextMultiple(bufferSize,
        indexBufferMemoryRequirements.alignment);

    bufferSize = indexBufferOffset + indexBufferMemoryRequirements.size;
    deviceBufferMemory_ = AllocateMemory(memoryHeaps, device_,
        static_cast<int>(bufferSize),
        vertexBufferMemoryRequirements.memoryTypeBits & indexBufferMemoryRequirements.memoryTypeBits,
        MT_DeviceLocal);

    vkBindBufferMemory(device_, vertexBuffer_, deviceBufferMemory_, 0);
    vkBindBufferMemory(device_, indexBuffer_, deviceBufferMemory_,
        indexBufferOffset);

    uploadBufferBuffer_ = AllocateBuffer (device_, static_cast<int> (bufferSize),
        VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
    VkMemoryRequirements uploadBufferMemoryRequirements = {};
    vkGetBufferMemoryRequirements (device_, uploadBufferBuffer_,
        &uploadBufferMemoryRequirements);

    bool memoryIsHostCoherent = false;
    uploadBufferMemory_ = AllocateMemory(memoryHeaps, device_,
        static_cast<int>(uploadBufferMemoryRequirements.size),
        vertexBufferMemoryRequirements.memoryTypeBits & indexBufferMemoryRequirements.memoryTypeBits,
        MT_HostVisible, &memoryIsHostCoherent);

    vkBindBufferMemory (device_, uploadBufferBuffer_, uploadBufferMemory_, 0);

    void* mapping = nullptr;
    vkMapMemory(device_, uploadBufferMemory_, 0, VK_WHOLE_SIZE,
        0, &mapping);
    ::memcpy(mapping, vertices, sizeof(vertices));

    ::memcpy(static_cast<uint8_t*> (mapping) + indexBufferOffset,
        indices, sizeof(indices));

    if (!memoryIsHostCoherent) 
    {
        VkMappedMemoryRange mappedMemoryRange = {};
        mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
        mappedMemoryRange.memory = uploadBufferMemory_;
        mappedMemoryRange.offset = 0;
        mappedMemoryRange.size = VK_WHOLE_SIZE;

        vkFlushMappedMemoryRanges (device_, 1, &mappedMemoryRange);
    }

    vkUnmapMemory(device_, uploadBufferMemory_);

    VkBufferCopy vertexCopy = {};
    vertexCopy.size = sizeof (vertices);

    VkBufferCopy indexCopy = {};
    indexCopy.size = sizeof (indices);
    indexCopy.srcOffset = indexBufferOffset;

    vkCmdCopyBuffer (uploadCommandBuffer, uploadBufferBuffer_, vertexBuffer_,
        1, &vertexCopy);
    vkCmdCopyBuffer (uploadCommandBuffer, uploadBufferBuffer_, indexBuffer_,
        1, &indexCopy);

    VkBufferMemoryBarrier uploadBarriers[2] = {};
    uploadBarriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
    uploadBarriers[0].buffer = vertexBuffer_;
    uploadBarriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    uploadBarriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    uploadBarriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
    uploadBarriers[0].dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
    uploadBarriers[0].size = VK_WHOLE_SIZE;

    uploadBarriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
    uploadBarriers[1].buffer = indexBuffer_;
    uploadBarriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    uploadBarriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    uploadBarriers[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
    uploadBarriers[1].dstAccessMask = VK_ACCESS_INDEX_READ_BIT;
    uploadBarriers[1].size = VK_WHOLE_SIZE;

    vkCmdPipelineBarrier (uploadCommandBuffer,
        VK_PIPELINE_STAGE_TRANSFER_BIT,
        VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
        0, 0, nullptr, 2, uploadBarriers,
        0, nullptr);
}
Exemplo n.º 11
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);

}
void vkeGameRendererDynamic::generateDrawCommands(){

	//Start generating draw commands.

	VulkanDC *dc = VulkanDC::Get();
	VulkanDC::Device *device = dc->getDefaultDevice();
	VkClearValue clearValues[3];


	/*
	Dispatch threads to create the secondary
	command buffers.
	*/
	m_calls_generated = 0;
	for (uint32_t i = 0; i < m_max_draw_calls; ++i){
		m_draw_calls[i]->initDrawCommands(m_node_data->count(), m_current_buffer_index);
	}

	/*
	Begin setting up the primary command buffer.
	*/
	VkCommandBufferBeginInfo cmdBeginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
	cmdBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;

	vkResetCommandBuffer(m_primary_commands[m_current_buffer_index], 0);
	vkResetCommandBuffer(m_update_commands[m_current_buffer_index], 0);


	VKA_CHECK_ERROR(vkBeginCommandBuffer(m_update_commands[m_current_buffer_index], &cmdBeginInfo), "Could not begin primary command buffer.\n");

	VkBufferMemoryBarrier bufBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
	bufBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
	bufBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
	bufBarrier.dstQueueFamilyIndex = 0;
	bufBarrier.offset = 0;
	bufBarrier.buffer = m_uniforms_buffer;
	bufBarrier.srcQueueFamilyIndex = 0;

	colorClearValues(&clearValues[0], 1.0, 1.0, 1.0);
	depthStencilClearValues(&clearValues[1]);//default#
	colorClearValues(&clearValues[2], 0.0, 0.0, 0.0);

	uint32_t sz = (sizeof(VkeNodeUniform) * 100) + (64 * 64);
	VkBufferCopy bufCopy;
	bufCopy.dstOffset = 0;
	bufCopy.srcOffset = 0;
	bufCopy.size = sz;

	vkCmdCopyBuffer(m_update_commands[m_current_buffer_index], m_uniforms_buffer_staging, m_uniforms_buffer, 1, &bufCopy);

	vkCmdPipelineBarrier(
		m_update_commands[m_current_buffer_index],
		VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
		VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
		0,
		0,
		NULL,
		1,
		&bufBarrier,
		0,
		NULL);

	VKA_CHECK_ERROR(vkEndCommandBuffer(m_update_commands[m_current_buffer_index]), "Could not end command buffer for draw command.\n");


	VKA_CHECK_ERROR(vkBeginCommandBuffer(m_primary_commands[m_current_buffer_index], &cmdBeginInfo), "Could not begin primary command buffer.\n");



	renderPassBegin(&m_primary_commands[m_current_buffer_index], m_render_pass, m_framebuffers[m_current_buffer_index], 0, 0, m_width, m_height, clearValues, 3, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);


	VkViewport vp;
	VkRect2D sc;
	vp.x = 0;
	vp.y = 0;
	vp.height = (float)(m_height);
	vp.width = (float)(m_width);
	vp.minDepth = 0.0f;
	vp.maxDepth = 1.0f;

	sc.offset.x = 0;
	sc.offset.y = 0;
	sc.extent.width = vp.width;
	sc.extent.height = vp.height;

	vkCmdSetViewport(m_primary_commands[m_current_buffer_index], 0, 1, &vp);
	vkCmdSetScissor(m_primary_commands[m_current_buffer_index], 0, 1, &sc);

	/*
	Wait here until the secondary commands are ready.
	*/

	VkCommandBuffer secondaryCommands[11];
	secondaryCommands[0] = m_terrain_command[m_current_buffer_index];
	for (uint32_t i = 0; i < m_max_draw_calls; ++i){
		secondaryCommands[i + 1] = m_draw_calls[i]->getDrawCommand(m_current_buffer_index);
	}

	vkCmdExecuteCommands(m_primary_commands[m_current_buffer_index], 1 + m_max_draw_calls, secondaryCommands);

	vkCmdEndRenderPass(m_primary_commands[m_current_buffer_index]);

	VkImageResolve blitInfo;
    blitInfo.srcOffset.x = 0;
	blitInfo.srcOffset.y = 0;
	blitInfo.srcOffset.z = 0;
	blitInfo.dstOffset.x = 0;
	blitInfo.dstOffset.y = 0;
	blitInfo.dstOffset.z = 0;
    blitInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    blitInfo.srcSubresource.mipLevel = 0;
    blitInfo.srcSubresource.baseArrayLayer = 0;
    blitInfo.srcSubresource.layerCount = 1;
    blitInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    blitInfo.dstSubresource.mipLevel = 0;
    blitInfo.dstSubresource.baseArrayLayer = 0;
    blitInfo.dstSubresource.layerCount = 1;
    blitInfo.extent.width = m_width;
    blitInfo.extent.height = m_height;
    blitInfo.extent.depth = 1;

	vkCmdResolveImage(
		m_primary_commands[m_current_buffer_index],
		m_color_attachment.image,
		VK_IMAGE_LAYOUT_GENERAL,
		m_resolve_attachment[m_current_buffer_index].image,
		VK_IMAGE_LAYOUT_GENERAL,
		1,
		&blitInfo);


	VKA_CHECK_ERROR(vkEndCommandBuffer(m_primary_commands[m_current_buffer_index]), "Could not end command buffer for draw command.\n");

}
Exemplo n.º 13
0
	/**
	* Create Vulkan buffers for the index and vertex buffer using a vertex layout
	*
	* @note Only does staging if a valid command buffer and transfer queue are passed
	*
	* @param meshBuffer Pointer to the mesh buffer containing buffer handles and memory
	* @param layout Vertex layout for the vertex buffer
	* @param createInfo Structure containing information for mesh creation time (center, scaling, etc.)
	* @param useStaging If true, buffers are staged to device local memory
	* @param copyCmd (Required for staging) Command buffer to put the copy commands into
	* @param copyQueue (Required for staging) Queue to put copys into
	*/
	void createBuffers(
		vkMeshLoader::MeshBuffer *meshBuffer,
		std::vector<vkMeshLoader::VertexLayout> layout,
		vkMeshLoader::MeshCreateInfo *createInfo,
		bool useStaging,
		VkCommandBuffer copyCmd,
		VkQueue copyQueue)
	{
		glm::vec3 scale;
		glm::vec2 uvscale;
		glm::vec3 center;
		if (createInfo == nullptr)
		{
			scale = glm::vec3(1.0f);
			uvscale = glm::vec2(1.0f);
			center = glm::vec3(0.0f);
		}
		else
		{
			scale = createInfo->scale;
			uvscale = createInfo->uvscale;
			center = createInfo->center;
		}

		std::vector<float> vertexBuffer;
		for (size_t m = 0; m < m_Entries.size(); m++)
		{
			for (size_t i = 0; i < m_Entries[m].Vertices.size(); i++)
			{
				// Push vertex data depending on layout
				for (auto& layoutDetail : layout)
				{
					// Position
					if (layoutDetail == vkMeshLoader::VERTEX_LAYOUT_POSITION)
					{
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_pos.x * scale.x + center.x);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_pos.y * scale.y + center.y);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_pos.z * scale.z + center.z);
					}
					// Normal
					if (layoutDetail == vkMeshLoader::VERTEX_LAYOUT_NORMAL)
					{
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_normal.x);
						vertexBuffer.push_back(-m_Entries[m].Vertices[i].m_normal.y);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_normal.z);
					}
					// Texture coordinates
					if (layoutDetail == vkMeshLoader::VERTEX_LAYOUT_UV)
					{
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_tex.s * uvscale.s);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_tex.t * uvscale.t);
					}
					// Color
					if (layoutDetail == vkMeshLoader::VERTEX_LAYOUT_COLOR)
					{
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_color.r);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_color.g);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_color.b);
					}
					// Tangent
					if (layoutDetail == vkMeshLoader::VERTEX_LAYOUT_TANGENT)
					{
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_tangent.x);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_tangent.y);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_tangent.z);
					}
					// Bitangent
					if (layoutDetail == vkMeshLoader::VERTEX_LAYOUT_BITANGENT)
					{
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_binormal.x);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_binormal.y);
						vertexBuffer.push_back(m_Entries[m].Vertices[i].m_binormal.z);
					}
					// Dummy layout components for padding
					if (layoutDetail == vkMeshLoader::VERTEX_LAYOUT_DUMMY_FLOAT)
					{
						vertexBuffer.push_back(0.0f);
					}
					if (layoutDetail == vkMeshLoader::VERTEX_LAYOUT_DUMMY_VEC4)
					{
						vertexBuffer.push_back(0.0f);
						vertexBuffer.push_back(0.0f);
						vertexBuffer.push_back(0.0f);
						vertexBuffer.push_back(0.0f);
					}
				}
			}
		}
		meshBuffer->vertices.size = vertexBuffer.size() * sizeof(float);

		dim.min *= scale;
		dim.max *= scale;
		dim.size *= scale;

		std::vector<uint32_t> indexBuffer;
		for (uint32_t m = 0; m < m_Entries.size(); m++)
		{
			uint32_t indexBase = static_cast<uint32_t>(indexBuffer.size());
			for (uint32_t i = 0; i < m_Entries[m].Indices.size(); i++)
			{
				indexBuffer.push_back(m_Entries[m].Indices[i] + indexBase);
			}
			vkMeshLoader::MeshDescriptor descriptor{};
			descriptor.indexBase = indexBase;
			descriptor.indexCount = static_cast<uint32_t>(m_Entries[m].Indices.size());
			descriptor.vertexCount = static_cast<uint32_t>(m_Entries[m].Vertices.size());
			meshBuffer->meshDescriptors.push_back(descriptor);
		}
		meshBuffer->indices.size = indexBuffer.size() * sizeof(uint32_t);
		meshBuffer->indexCount = static_cast<uint32_t>(indexBuffer.size());

		// Use staging buffer to move vertex and index buffer to device local memory
		if (useStaging && copyQueue != VK_NULL_HANDLE && copyCmd != VK_NULL_HANDLE)
		{
			// Create staging buffers
			struct {
				VkBuffer buffer;
				VkDeviceMemory memory;
			} vertexStaging, indexStaging;

			// Vertex buffer
			vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
				meshBuffer->vertices.size,
				&vertexStaging.buffer,
				&vertexStaging.memory,
				vertexBuffer.data());

			// Index buffer
			vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
				meshBuffer->indices.size,
				&indexStaging.buffer,
				&indexStaging.memory,
				indexBuffer.data());

			// Create device local target buffers
			// Vertex buffer
			vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
				VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
				meshBuffer->vertices.size,
				&meshBuffer->vertices.buf,
				&meshBuffer->vertices.mem);

			// Index buffer
			vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
				VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
				meshBuffer->indices.size,
				&meshBuffer->indices.buf,
				&meshBuffer->indices.mem);

			// Copy from staging buffers
			VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
			VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo));

			VkBufferCopy copyRegion = {};

			copyRegion.size = meshBuffer->vertices.size;
			vkCmdCopyBuffer(
				copyCmd,
				vertexStaging.buffer,
				meshBuffer->vertices.buf,
				1,
				&copyRegion);

			copyRegion.size = meshBuffer->indices.size;
			vkCmdCopyBuffer(
				copyCmd,
				indexStaging.buffer,
				meshBuffer->indices.buf,
				1,
				&copyRegion);

			VK_CHECK_RESULT(vkEndCommandBuffer(copyCmd));

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

			VK_CHECK_RESULT(vkQueueSubmit(copyQueue, 1, &submitInfo, VK_NULL_HANDLE));
			VK_CHECK_RESULT(vkQueueWaitIdle(copyQueue));

			vkDestroyBuffer(vulkanDevice->logicalDevice, vertexStaging.buffer, nullptr);
			vkFreeMemory(vulkanDevice->logicalDevice, vertexStaging.memory, nullptr);
			vkDestroyBuffer(vulkanDevice->logicalDevice, indexStaging.buffer, nullptr);
			vkFreeMemory(vulkanDevice->logicalDevice, indexStaging.memory, nullptr);
		}
		else
		{
			// Generate vertex buffer
			vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
				meshBuffer->vertices.size,
				&meshBuffer->vertices.buf,
				&meshBuffer->vertices.mem,
				vertexBuffer.data());

			// Generate index buffer
			vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
				meshBuffer->indices.size,
				&meshBuffer->indices.buf,
				&meshBuffer->indices.mem,
				indexBuffer.data());
		}
	}
Exemplo n.º 14
0
void VulkanGear::generate(GearInfo *gearinfo, VkQueue queue)
{
	this->color = gearinfo->color;
	this->pos = gearinfo->pos;
	this->rotOffset = gearinfo->rotOffset;
	this->rotSpeed = gearinfo->rotSpeed;

	std::vector<Vertex> vBuffer;
	std::vector<uint32_t> iBuffer;

	int i, j;
	float r0, r1, r2;
	float ta, da;
	float u1, v1, u2, v2, len;
	float cos_ta, cos_ta_1da, cos_ta_2da, cos_ta_3da, cos_ta_4da;
	float sin_ta, sin_ta_1da, sin_ta_2da, sin_ta_3da, sin_ta_4da;
	int32_t ix0, ix1, ix2, ix3, ix4, ix5;

	r0 = gearinfo->innerRadius;
	r1 = gearinfo->outerRadius - gearinfo->toothDepth / 2.0;
	r2 = gearinfo->outerRadius + gearinfo->toothDepth / 2.0;
	da = 2.0 * M_PI / gearinfo->numTeeth / 4.0;

	glm::vec3 normal;

	for (i = 0; i < gearinfo->numTeeth; i++)
	{
		ta = i * 2.0 * M_PI / gearinfo->numTeeth;

		cos_ta = cos(ta);
		cos_ta_1da = cos(ta + da);
		cos_ta_2da = cos(ta + 2 * da);
		cos_ta_3da = cos(ta + 3 * da);
		cos_ta_4da = cos(ta + 4 * da);
		sin_ta = sin(ta);
		sin_ta_1da = sin(ta + da);
		sin_ta_2da = sin(ta + 2 * da);
		sin_ta_3da = sin(ta + 3 * da);
		sin_ta_4da = sin(ta + 4 * da);

		u1 = r2 * cos_ta_1da - r1 * cos_ta;
		v1 = r2 * sin_ta_1da - r1 * sin_ta;
		len = sqrt(u1 * u1 + v1 * v1);
		u1 /= len;
		v1 /= len;
		u2 = r1 * cos_ta_3da - r2 * cos_ta_2da;
		v2 = r1 * sin_ta_3da - r2 * sin_ta_2da;

		// front face
		normal = glm::vec3(0.0, 0.0, 1.0);
		ix0 = newVertex(&vBuffer, r0 * cos_ta, r0 * sin_ta, gearinfo->width * 0.5, normal);
		ix1 = newVertex(&vBuffer, r1 * cos_ta, r1 * sin_ta, gearinfo->width * 0.5, normal);
		ix2 = newVertex(&vBuffer, r0 * cos_ta, r0 * sin_ta, gearinfo->width * 0.5, normal);
		ix3 = newVertex(&vBuffer, r1 * cos_ta_3da, r1 * sin_ta_3da, gearinfo->width * 0.5, normal);
		ix4 = newVertex(&vBuffer, r0 * cos_ta_4da, r0 * sin_ta_4da, gearinfo->width * 0.5, normal);
		ix5 = newVertex(&vBuffer, r1 * cos_ta_4da, r1 * sin_ta_4da, gearinfo->width * 0.5, normal);
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);
		newFace(&iBuffer, ix2, ix3, ix4);
		newFace(&iBuffer, ix3, ix5, ix4);

		// front sides of teeth
		normal = glm::vec3(0.0, 0.0, 1.0);
		ix0 = newVertex(&vBuffer, r1 * cos_ta, r1 * sin_ta, gearinfo->width * 0.5, normal);
		ix1 = newVertex(&vBuffer, r2 * cos_ta_1da, r2 * sin_ta_1da, gearinfo->width * 0.5, normal);
		ix2 = newVertex(&vBuffer, r1 * cos_ta_3da, r1 * sin_ta_3da, gearinfo->width * 0.5, normal);
		ix3 = newVertex(&vBuffer, r2 * cos_ta_2da, r2 * sin_ta_2da, gearinfo->width * 0.5, normal);
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);

		// back face 
		normal = glm::vec3(0.0, 0.0, -1.0);
		ix0 = newVertex(&vBuffer, r1 * cos_ta, r1 * sin_ta, -gearinfo->width * 0.5, normal);
		ix1 = newVertex(&vBuffer, r0 * cos_ta, r0 * sin_ta, -gearinfo->width * 0.5, normal);
		ix2 = newVertex(&vBuffer, r1 * cos_ta_3da, r1 * sin_ta_3da, -gearinfo->width * 0.5, normal);
		ix3 = newVertex(&vBuffer, r0 * cos_ta, r0 * sin_ta, -gearinfo->width * 0.5, normal);
		ix4 = newVertex(&vBuffer, r1 * cos_ta_4da, r1 * sin_ta_4da, -gearinfo->width * 0.5, normal);
		ix5 = newVertex(&vBuffer, r0 * cos_ta_4da, r0 * sin_ta_4da, -gearinfo->width * 0.5, normal);
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);
		newFace(&iBuffer, ix2, ix3, ix4);
		newFace(&iBuffer, ix3, ix5, ix4);

		// back sides of teeth 
		normal = glm::vec3(0.0, 0.0, -1.0);
		ix0 = newVertex(&vBuffer, r1 * cos_ta_3da, r1 * sin_ta_3da, -gearinfo->width * 0.5, normal);
		ix1 = newVertex(&vBuffer, r2 * cos_ta_2da, r2 * sin_ta_2da, -gearinfo->width * 0.5, normal);
		ix2 = newVertex(&vBuffer, r1 * cos_ta, r1 * sin_ta, -gearinfo->width * 0.5, normal);
		ix3 = newVertex(&vBuffer, r2 * cos_ta_1da, r2 * sin_ta_1da, -gearinfo->width * 0.5, normal);
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);

		// draw outward faces of teeth 
		normal = glm::vec3(v1, -u1, 0.0);
		ix0 = newVertex(&vBuffer, r1 * cos_ta, r1 * sin_ta, gearinfo->width * 0.5, normal);
		ix1 = newVertex(&vBuffer, r1 * cos_ta, r1 * sin_ta, -gearinfo->width * 0.5, normal);
		ix2 = newVertex(&vBuffer, r2 * cos_ta_1da, r2 * sin_ta_1da, gearinfo->width * 0.5, normal);
		ix3 = newVertex(&vBuffer, r2 * cos_ta_1da, r2 * sin_ta_1da, -gearinfo->width * 0.5, normal);
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);

		normal = glm::vec3(cos_ta, sin_ta, 0.0);
		ix0 = newVertex(&vBuffer, r2 * cos_ta_1da, r2 * sin_ta_1da, gearinfo->width * 0.5, normal);
		ix1 = newVertex(&vBuffer, r2 * cos_ta_1da, r2 * sin_ta_1da, -gearinfo->width * 0.5, normal);
		ix2 = newVertex(&vBuffer, r2 * cos_ta_2da, r2 * sin_ta_2da, gearinfo->width * 0.5, normal);
		ix3 = newVertex(&vBuffer, r2 * cos_ta_2da, r2 * sin_ta_2da, -gearinfo->width * 0.5, normal);
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);

		normal = glm::vec3(v2, -u2, 0.0);
		ix0 = newVertex(&vBuffer, r2 * cos_ta_2da, r2 * sin_ta_2da, gearinfo->width * 0.5, normal);
		ix1 = newVertex(&vBuffer, r2 * cos_ta_2da, r2 * sin_ta_2da, -gearinfo->width * 0.5, normal);
		ix2 = newVertex(&vBuffer, r1 * cos_ta_3da, r1 * sin_ta_3da, gearinfo->width * 0.5, normal);
		ix3 = newVertex(&vBuffer, r1 * cos_ta_3da, r1 * sin_ta_3da, -gearinfo->width * 0.5, normal);
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);

		normal = glm::vec3(cos_ta, sin_ta, 0.0);
		ix0 = newVertex(&vBuffer, r1 * cos_ta_3da, r1 * sin_ta_3da, gearinfo->width * 0.5, normal);
		ix1 = newVertex(&vBuffer, r1 * cos_ta_3da, r1 * sin_ta_3da, -gearinfo->width * 0.5, normal);
		ix2 = newVertex(&vBuffer, r1 * cos_ta_4da, r1 * sin_ta_4da, gearinfo->width * 0.5, normal);
		ix3 = newVertex(&vBuffer, r1 * cos_ta_4da, r1 * sin_ta_4da, -gearinfo->width * 0.5, normal);
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);

		// draw inside radius cylinder 
		ix0 = newVertex(&vBuffer, r0 * cos_ta, r0 * sin_ta, -gearinfo->width * 0.5, glm::vec3(-cos_ta, -sin_ta, 0.0));
		ix1 = newVertex(&vBuffer, r0 * cos_ta, r0 * sin_ta, gearinfo->width * 0.5, glm::vec3(-cos_ta, -sin_ta, 0.0));
		ix2 = newVertex(&vBuffer, r0 * cos_ta_4da, r0 * sin_ta_4da, -gearinfo->width * 0.5, glm::vec3(-cos_ta_4da, -sin_ta_4da, 0.0));
		ix3 = newVertex(&vBuffer, r0 * cos_ta_4da, r0 * sin_ta_4da, gearinfo->width * 0.5, glm::vec3(-cos_ta_4da, -sin_ta_4da, 0.0));
		newFace(&iBuffer, ix0, ix1, ix2);
		newFace(&iBuffer, ix1, ix3, ix2);
	}

	int vertexBufferSize = vBuffer.size() * sizeof(Vertex);
	int indexBufferSize = iBuffer.size() * sizeof(uint32_t);

	bool useStaging = true;

	if (useStaging)
	{
		struct {
			VkBuffer buffer;
			VkDeviceMemory memory;
		} vertexStaging, indexStaging;

		// Create staging buffers
		// Vertex data
		exampleBase->createBuffer(
			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
			VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
			vertexBufferSize,
			vBuffer.data(),
			&vertexStaging.buffer,
			&vertexStaging.memory);
		// Index data
		exampleBase->createBuffer(
			VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
			VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
			indexBufferSize,
			iBuffer.data(),
			&indexStaging.buffer,
			&indexStaging.memory);

		// Create device local buffers
		// Vertex buffer
		exampleBase->createBuffer(
			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
			VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
			vertexBufferSize,
			nullptr,
			&vertexBuffer.buf,
			&vertexBuffer.mem);
		// Index buffer
		exampleBase->createBuffer(
			VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
			VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
			indexBufferSize,
			nullptr,
			&indexBuffer.buf,
			&indexBuffer.mem);

		// Copy from staging buffers
		VkCommandBuffer copyCmd = exampleBase->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);

		VkBufferCopy copyRegion = {};

		copyRegion.size = vertexBufferSize;
		vkCmdCopyBuffer(
			copyCmd,
			vertexStaging.buffer,
			vertexBuffer.buf,
			1,
			&copyRegion);

		copyRegion.size = indexBufferSize;
		vkCmdCopyBuffer(
			copyCmd,
			indexStaging.buffer,
			indexBuffer.buf,
			1,
			&copyRegion);

		exampleBase->flushCommandBuffer(copyCmd, queue, true);

		vkDestroyBuffer(device, vertexStaging.buffer, nullptr);
		vkFreeMemory(device, vertexStaging.memory, nullptr);
		vkDestroyBuffer(device, indexStaging.buffer, nullptr);
		vkFreeMemory(device, indexStaging.memory, nullptr);
	}
	else
	{
		// Vertex buffer
		exampleBase->createBuffer(
			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
			VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
			vertexBufferSize,
			vBuffer.data(),
			&vertexBuffer.buf,
			&vertexBuffer.mem);
		// Index buffer
		exampleBase->createBuffer(
			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
			VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
			indexBufferSize,
			iBuffer.data(),
			&indexBuffer.buf,
			&indexBuffer.mem);
	}

	indexBuffer.count = iBuffer.size();

	prepareUniformBuffer();
}
Exemplo n.º 15
0
	void prepareVertices(bool useStagingBuffers)
	{
		struct Vertex 
		{
			float position[3];
			float color[3];
		};

		std::vector<Vertex> vertexBuffer = 
		{
			{ {  1.0f,  1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f } },
			{ { -1.0f,  1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } },
			{ {  0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }
		};
		uint32_t vertexBufferSize = static_cast<uint32_t>(vertexBuffer.size()) * sizeof(Vertex);

		std::vector<uint32_t> indexBuffer = { 0, 1, 2 };
		indices.count = static_cast<uint32_t>(indexBuffer.size());
		uint32_t indexBufferSize = indices.count * sizeof(uint32_t);

		VkMemoryAllocateInfo memAlloc = {};
		memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
		VkMemoryRequirements memReqs;

		void *data;

		if (useStagingBuffers)
		{
			struct StagingBuffer
			{
				VkDeviceMemory memory;
				VkBuffer buffer;
			};

			struct
			{
				StagingBuffer vertices;
				StagingBuffer indices;
			} stagingBuffers;

			VkBufferCreateInfo vertexBufferInfo = {};
			vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
			vertexBufferInfo.size = vertexBufferSize;
			vertexBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;

			VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &stagingBuffers.vertices.buffer));
			vkGetBufferMemoryRequirements(device, stagingBuffers.vertices.buffer, &memReqs);
			memAlloc.allocationSize = memReqs.size;
			memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
			VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.vertices.memory));

			VK_CHECK_RESULT(vkMapMemory(device, stagingBuffers.vertices.memory, 0, memAlloc.allocationSize, 0, &data));
			memcpy(data, vertexBuffer.data(), vertexBufferSize);
			vkUnmapMemory(device, stagingBuffers.vertices.memory);
			VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffers.vertices.buffer, stagingBuffers.vertices.memory, 0));

			vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
			VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &vertices.buffer));
			vkGetBufferMemoryRequirements(device, vertices.buffer, &memReqs);
			memAlloc.allocationSize = memReqs.size;
			memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
			VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.memory));
			VK_CHECK_RESULT(vkBindBufferMemory(device, vertices.buffer, vertices.memory, 0));

			VkBufferCreateInfo indexbufferInfo = {};
			indexbufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
			indexbufferInfo.size = indexBufferSize;
			indexbufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;

			VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &stagingBuffers.indices.buffer));
			vkGetBufferMemoryRequirements(device, stagingBuffers.indices.buffer, &memReqs);
			memAlloc.allocationSize = memReqs.size;
			memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
			VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.indices.memory));
			VK_CHECK_RESULT(vkMapMemory(device, stagingBuffers.indices.memory, 0, indexBufferSize, 0, &data));
			memcpy(data, indexBuffer.data(), indexBufferSize);
			vkUnmapMemory(device, stagingBuffers.indices.memory);
			VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffers.indices.buffer, stagingBuffers.indices.memory, 0));

			indexbufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
			VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &indices.buffer));
			vkGetBufferMemoryRequirements(device, indices.buffer, &memReqs);
			memAlloc.allocationSize = memReqs.size;
			memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
			VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &indices.memory));
			VK_CHECK_RESULT(vkBindBufferMemory(device, indices.buffer, indices.memory, 0));

			VkCommandBufferBeginInfo cmdBufferBeginInfo = {};
			cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
			cmdBufferBeginInfo.pNext = nullptr;

			VkCommandBuffer copyCmd = getCommandBuffer(true);

			VkBufferCopy copyRegion = {};

			copyRegion.size = vertexBufferSize;
			vkCmdCopyBuffer(copyCmd, stagingBuffers.vertices.buffer, vertices.buffer, 1, &copyRegion);
			copyRegion.size = indexBufferSize;
			vkCmdCopyBuffer(copyCmd, stagingBuffers.indices.buffer, indices.buffer,	1, &copyRegion);

			flushCommandBuffer(copyCmd);

			vkDestroyBuffer(device, stagingBuffers.vertices.buffer, nullptr);
			vkFreeMemory(device, stagingBuffers.vertices.memory, nullptr);
			vkDestroyBuffer(device, stagingBuffers.indices.buffer, nullptr);
			vkFreeMemory(device, stagingBuffers.indices.memory, nullptr);
		}
		else
		{
			VkBufferCreateInfo vertexBufferInfo = {};
			vertexBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
			vertexBufferInfo.size = vertexBufferSize;
			vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;

			VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &vertices.buffer));
			vkGetBufferMemoryRequirements(device, vertices.buffer, &memReqs);
			memAlloc.allocationSize = memReqs.size;
			memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
			VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.memory));
			VK_CHECK_RESULT(vkMapMemory(device, vertices.memory, 0, memAlloc.allocationSize, 0, &data));
			memcpy(data, vertexBuffer.data(), vertexBufferSize);
			vkUnmapMemory(device, vertices.memory);
			VK_CHECK_RESULT(vkBindBufferMemory(device, vertices.buffer, vertices.memory, 0));

			VkBufferCreateInfo indexbufferInfo = {};
			indexbufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
			indexbufferInfo.size = indexBufferSize;
			indexbufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT;

			VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &indices.buffer));
			vkGetBufferMemoryRequirements(device, indices.buffer, &memReqs);
			memAlloc.allocationSize = memReqs.size;
			memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
			VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &indices.memory));
			VK_CHECK_RESULT(vkMapMemory(device, indices.memory, 0, indexBufferSize, 0, &data));
			memcpy(data, indexBuffer.data(), indexBufferSize);
			vkUnmapMemory(device, indices.memory);
			VK_CHECK_RESULT(vkBindBufferMemory(device, indices.buffer, indices.memory, 0));
		}

		vertices.inputBinding.binding = VERTEX_BUFFER_BIND_ID;				
		vertices.inputBinding.stride = sizeof(Vertex);
		vertices.inputBinding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

		vertices.inputAttributes.resize(2);

		vertices.inputAttributes[0].binding = VERTEX_BUFFER_BIND_ID;
		vertices.inputAttributes[0].location = 0;
		vertices.inputAttributes[0].format = VK_FORMAT_R32G32B32_SFLOAT;
		vertices.inputAttributes[0].offset = offsetof(Vertex, position);

		vertices.inputAttributes[1].binding = VERTEX_BUFFER_BIND_ID;
		vertices.inputAttributes[1].location = 1;
		vertices.inputAttributes[1].format = VK_FORMAT_R32G32B32_SFLOAT;
		vertices.inputAttributes[1].offset = offsetof(Vertex, color);

		vertices.inputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
		vertices.inputState.pNext = nullptr;
		vertices.inputState.flags = VK_FLAGS_NONE;
		vertices.inputState.vertexBindingDescriptionCount = 1;
		vertices.inputState.pVertexBindingDescriptions = &vertices.inputBinding;
		vertices.inputState.vertexAttributeDescriptionCount = static_cast<uint32_t>(vertices.inputAttributes.size());
		vertices.inputState.pVertexAttributeDescriptions = vertices.inputAttributes.data();
	}
Exemplo n.º 16
0
	// Load a model from file using the ASSIMP model loader and generate all resources required to render the model
	void loadModel(std::string filename)
	{
		// Load the model from file using ASSIMP

		const aiScene* scene;
		Assimp::Importer Importer;		

		// Flags for loading the mesh
		static const int assimpFlags = aiProcess_FlipWindingOrder | aiProcess_Triangulate | aiProcess_PreTransformVertices;

#if defined(__ANDROID__)
		// Meshes are stored inside the apk on Android (compressed)
		// So they need to be loaded via the asset manager

		AAsset* asset = AAssetManager_open(androidApp->activity->assetManager, filename.c_str(), AASSET_MODE_STREAMING);
		assert(asset);
		size_t size = AAsset_getLength(asset);

		assert(size > 0);

		void *meshData = malloc(size);
		AAsset_read(asset, meshData, size);
		AAsset_close(asset);

		scene = Importer.ReadFileFromMemory(meshData, size, assimpFlags);

		free(meshData);
#else
		scene = Importer.ReadFile(filename.c_str(), assimpFlags);
#endif

		// Generate vertex buffer from ASSIMP scene data
		float scale = 1.0f;
		std::vector<Vertex> vertexBuffer;

		// Iterate through all meshes in the file and extract the vertex components
		for (uint32_t m = 0; m < scene->mNumMeshes; m++)
		{
			for (uint32_t v = 0; v < scene->mMeshes[m]->mNumVertices; v++)
			{
				Vertex vertex;

				// Use glm make_* functions to convert ASSIMP vectors to glm vectors
				vertex.pos = glm::make_vec3(&scene->mMeshes[m]->mVertices[v].x) * scale;
				vertex.normal = glm::make_vec3(&scene->mMeshes[m]->mNormals[v].x);
				// Texture coordinates and colors may have multiple channels, we only use the first [0] one
				vertex.uv = glm::make_vec2(&scene->mMeshes[m]->mTextureCoords[0][v].x);
				// Mesh may not have vertex colors
				vertex.color = (scene->mMeshes[m]->HasVertexColors(0)) ? glm::make_vec3(&scene->mMeshes[m]->mColors[0][v].r) : glm::vec3(1.0f);

				// Vulkan uses a right-handed NDC (contrary to OpenGL), so simply flip Y-Axis
				vertex.pos.y *= -1.0f;

				vertexBuffer.push_back(vertex);
			}
		}
		size_t vertexBufferSize = vertexBuffer.size() * sizeof(Vertex);

		// Generate index buffer from ASSIMP scene data
		std::vector<uint32_t> indexBuffer;
		for (uint32_t m = 0; m < scene->mNumMeshes; m++)
		{
			uint32_t indexBase = static_cast<uint32_t>(indexBuffer.size());
			for (uint32_t f = 0; f < scene->mMeshes[m]->mNumFaces; f++)
			{
				// We assume that all faces are triangulated
				for (uint32_t i = 0; i < 3; i++)
				{
					indexBuffer.push_back(scene->mMeshes[m]->mFaces[f].mIndices[i] + indexBase);
				}
			}
		}
		size_t indexBufferSize = indexBuffer.size() * sizeof(uint32_t);
		model.indices.count = static_cast<uint32_t>(indexBuffer.size());

		// Static mesh should always be device local

		bool useStaging = true;

		if (useStaging)
		{
			struct {
				VkBuffer buffer;
				VkDeviceMemory memory;
			} vertexStaging, indexStaging;

			// Create staging buffers
			// Vertex data
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
				vertexBufferSize,
				&vertexStaging.buffer,
				&vertexStaging.memory,
				vertexBuffer.data()));
			// Index data
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
				indexBufferSize,
				&indexStaging.buffer,
				&indexStaging.memory,
				indexBuffer.data()));

			// Create device local buffers
			// Vertex buffer
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
				VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
				vertexBufferSize,
				&model.vertices.buffer,
				&model.vertices.memory));
			// Index buffer
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
				VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
				indexBufferSize,
				&model.indices.buffer,
				&model.indices.memory));

			// Copy from staging buffers
			VkCommandBuffer copyCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);

			VkBufferCopy copyRegion = {};

			copyRegion.size = vertexBufferSize;
			vkCmdCopyBuffer(
				copyCmd,
				vertexStaging.buffer,
				model.vertices.buffer,
				1,
				&copyRegion);

			copyRegion.size = indexBufferSize;
			vkCmdCopyBuffer(
				copyCmd,
				indexStaging.buffer,
				model.indices.buffer,
				1,
				&copyRegion);

			VulkanExampleBase::flushCommandBuffer(copyCmd, queue, true);

			vkDestroyBuffer(device, vertexStaging.buffer, nullptr);
			vkFreeMemory(device, vertexStaging.memory, nullptr);
			vkDestroyBuffer(device, indexStaging.buffer, nullptr);
			vkFreeMemory(device, indexStaging.memory, nullptr);
		}
		else
		{
			// Vertex buffer
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
				vertexBufferSize,
				&model.vertices.buffer,
				&model.vertices.memory,
				vertexBuffer.data()));
			// Index buffer
			VK_CHECK_RESULT(vulkanDevice->createBuffer(
				VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
				VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
				indexBufferSize,
				&model.indices.buffer,
				&model.indices.memory,
				indexBuffer.data()));
		}
	}