#include "commandbuffer.h"
#include "commandpool.h"
#include "device.h"
namespace vulkanapi {
	CommandBuffer::CommandBuffer(CommandPool& commandPool, VkCommandBufferLevel level)
		:mPool(commandPool)
		,mPtr(commandPool.AllocateBuffer(level))
		,mFence(commandPool.AllocateFence())
	{
       
	}
	CommandBuffer::~CommandBuffer()
	{
		//zlog::info("CommandBuffer Destruct {:#x} isNull = {}", (uint64_t)this, mPtr == nullptr || mFence == nullptr);
		if (mPtr) {
			mPool.FreeBuffer(mPtr);
		}
		if (mFence) {
			mPool.FreeFence(mFence);
		}
	}
	CommandBuffer::CommandBuffer(CommandBuffer&& other)noexcept
		: mPtr(other.mPtr)
		, mFence(other.mFence)
		, mPool(other.mPool)
	{
		other.mPtr = nullptr;
		other.mFence = nullptr;
		//zlog::info("CommandBuffer MoveConstruct {:#x} => {:#x}", (uint64_t)&other, (uint64_t)this);
	}
	void CommandBuffer::Reset()
	{
		vkResetCommandBuffer(mPtr, VkCommandBufferResetFlagBits::VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
		mPool.ResetFence(mFence);
	}
	void CommandBuffer::BeginRecord(VkCommandBufferUsageFlags flag)
	{
		VkCommandBufferBeginInfo beginInfo{
			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,//sType
			nullptr,									//pNext
			flag									    //flags
		};
		vkBeginCommandBuffer(mPtr, &beginInfo);
	}
	void CommandBuffer::EndRecord()
	{
		vkEndCommandBuffer(mPtr);
	}
	void CommandBuffer::CmdCopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
	{
		VkBufferCopy copy = {};
		copy.dstOffset = 0;
		copy.srcOffset = 0;
		copy.size = size;
		vkCmdCopyBuffer(mPtr, srcBuffer, dstBuffer, 1, &copy);
	}
	void CommandBuffer::Submit(VkQueue& queue)
	{
		VkSubmitInfo submitInfo{};
		submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
		submitInfo.commandBufferCount = 1;
		submitInfo.pCommandBuffers = &mPtr;
		vkQueueSubmit(queue, 1, &submitInfo, mFence);
	}
	void CommandBuffer::WaitFofFence(VkDevice& device)
	{
		vkWaitForFences(device, 1, &mFence, VK_TRUE, UINT64_MAX);
	}
	void CommandBuffer::BindVertexBuffer(VkBuffer buffer, uint32_t offset)
	{
		VkDeviceSize offsets[] = { offset };
		vkCmdBindVertexBuffers(mPtr, 0, 1, &buffer, offsets);
	}
	void CommandBuffer::BindIndexBuffers(VkBuffer buffer, uint32_t offset, VkIndexType type)
	{
		vkCmdBindIndexBuffer(mPtr, buffer, offset, type);
	}
}

