#pragma once

#include <psemek/wgpu/detail/object.hpp>
#include <psemek/wgpu/query_set.hpp>
#include <psemek/wgpu/buffer.hpp>
#include <psemek/wgpu/bind_group.hpp>
#include <psemek/wgpu/compute_pipeline.hpp>
#include <psemek/wgpu/timestamp_writes.hpp>
#include <psemek/math/vector.hpp>

#include <string>
#include <vector>
#include <optional>

namespace psemek::wgpu
{

	struct compute_pass_encoder
		: detail::object<compute_pass_encoder>
	{
		using detail::object<compute_pass_encoder>::object;

		struct descriptor
		{
			std::vector<chained_struct> chain = {};
			std::string label = {};
			std::optional<struct timestamp_writes> timestamp_writes = {};
		};

		void set_bind_group(std::uint32_t group_index, bind_group const & group, std::vector<std::uint32_t> const & dynamic_offsets);
		void set_pipeline(compute_pipeline const & pipeline);
		void dispatch_workgroups(math::vector<std::uint32_t, 3> const & workgroup_count);
		void dispatch_workgroups_indirect(buffer const & indirect_buffer, std::uint64_t offset);
		void set_push_constants(std::uint32_t offset, util::span<char const> data);
		void write_timestamp(query_set const & query_set, std::uint32_t query_index);
		void insert_debug_marker(std::string const & marker_label);
		void push_debug_group(std::string const & group_label);
		void pop_debug_group();
		void end();
		void set_label(std::string const & label);

		static void reference(void * ptr);
		static void release(void * ptr);

	private:
		explicit compute_pass_encoder(void * ptr)
			: detail::object<compute_pass_encoder>(ptr)
		{}

		friend struct command_encoder;
	};

}
