#include "worker.h"
#include "../wrapper/queue.h"
#include "../wrapper/device.h"
namespace vulkanapi {
	CommandWorker::CommandWorker(const string& name, Device& device, Queue& queue, VkCommandPoolCreateFlags queueFlags)
		:mName(name)
		,mDevice(device)
		,mQueue(queue)
		,mCommandPool(device, queueFlags, queue.QueueFamilyIndex())
		,mWork(name, 64)
		,mImmediateExeCmd(mCommandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)
	{

	}
	void CommandWorker::Invoke(voidFn fn)
	{
		mWork.Invoke(fn);
	}

	void CommandWorker::InvokeBuffer(commandFn fn, voidFn callback)
	{
		mWork.Invoke([=]() {
			CommandBuffer cmd = mCommandPool.Pop();
			Buffer(cmd, fn, callback);
			mCommandPool.Push(cmd);
		});
	}

	void CommandWorker::Buffer(CommandBuffer& cmd, commandFn fn, voidFn callback)
	{
		cmd.Reset();
		cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
		fn(cmd);
		cmd.EndRecord();
		cmd.Submit(mQueue.Ptr());
		cmd.WaitFofFence(mDevice.Ptr());
		callback();
	}

	void CommandWorker::Flush()
	{
		mWork.SyncInvoke([]() {});
	}
	void CommandWorker::Draw(commandFn fn)
	{
		CommandBuffer cmd = mCommandPool.Pop();
		cmd.Reset();
		cmd.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
		fn(cmd);
		cmd.EndRecord();
		cmd.Submit(mQueue.Ptr());
		cmd.WaitFofFence(mDevice.Ptr());
		mCommandPool.Push(cmd);
	}
	bool CommandWorker::Present(VkPresentInfoKHR& presentInfo)
	{
		VkResult result = vkQueuePresentKHR(mQueue.Ptr(), &presentInfo);
		return result == VK_SUCCESS;
	}
}
