#include <psemek/wgpu/render_bundle_encoder.hpp>
#include <psemek/wgpu/detail/string_view.hpp>
#include <psemek/wgpu/external/webgpu.h>

namespace psemek::wgpu
{

	void render_bundle_encoder::set_pipeline(render_pipeline const & pipeline)
	{
		wgpuRenderBundleEncoderSetPipeline((WGPURenderBundleEncoder)get(), (WGPURenderPipeline)pipeline.get());
	}

	void render_bundle_encoder::set_bind_group(std::uint32_t group_index, bind_group const & group, std::vector<std::uint32_t> const & dynamic_offsets)
	{
		wgpuRenderBundleEncoderSetBindGroup((WGPURenderBundleEncoder)get(), group_index, (WGPUBindGroup)group.get(), dynamic_offsets.size(), dynamic_offsets.data());
	}

	void render_bundle_encoder::set_vertex_buffer(std::uint32_t slot, buffer const & buffer, std::uint64_t offset, std::uint64_t size)
	{
		wgpuRenderBundleEncoderSetVertexBuffer((WGPURenderBundleEncoder)get(), slot, (WGPUBuffer)buffer.get(), offset, size);
	}

	void render_bundle_encoder::set_index_buffer(buffer const & buffer, index_format format, std::uint64_t offset, std::uint64_t size)
	{
		wgpuRenderBundleEncoderSetIndexBuffer((WGPURenderBundleEncoder)get(), (WGPUBuffer)buffer.get(), (WGPUIndexFormat)format, offset, size);
	}

	void render_bundle_encoder::draw(std::uint32_t vertex_count, std::uint32_t instance_count, std::uint32_t first_vertex, std::uint32_t first_instance)
	{
		wgpuRenderBundleEncoderDraw((WGPURenderBundleEncoder)get(), vertex_count, instance_count, first_vertex, first_instance);
	}

	void render_bundle_encoder::draw_indexed(std::uint32_t index_count, std::uint32_t instance_count, std::uint32_t first_index, std::uint32_t base_vertex, std::uint32_t first_instance)
	{
		wgpuRenderBundleEncoderDrawIndexed((WGPURenderBundleEncoder)get(), index_count, instance_count, first_index, base_vertex, first_instance);
	}

	void render_bundle_encoder::draw_indirect(buffer const & indirect_buffer, std::uint64_t offset)
	{
		wgpuRenderBundleEncoderDrawIndirect((WGPURenderBundleEncoder)get(), (WGPUBuffer)indirect_buffer.get(), offset);
	}

	void render_bundle_encoder::draw_indexed_indirect(buffer const & indirect_buffer, std::uint64_t offset)
	{
		wgpuRenderBundleEncoderDrawIndexedIndirect((WGPURenderBundleEncoder)get(), (WGPUBuffer)indirect_buffer.get(), offset);
	}

	void render_bundle_encoder::insert_debug_marker(std::string_view marker_label)
	{
		wgpuRenderBundleEncoderInsertDebugMarker((WGPURenderBundleEncoder)get(), detail::to_string_view(marker_label));
	}

	void render_bundle_encoder::push_debug_group(std::string_view group_label)
	{
		wgpuRenderBundleEncoderPushDebugGroup((WGPURenderBundleEncoder)get(), detail::to_string_view(group_label));
	}

	void render_bundle_encoder::pop_debug_group()
	{
		wgpuRenderBundleEncoderPopDebugGroup((WGPURenderBundleEncoder)get());
	}

	render_bundle render_bundle_encoder::finish(render_bundle::descriptor const & desc)
	{
		WGPURenderBundleDescriptor descriptor = {};
		descriptor.nextInChain = (WGPUChainedStruct const *)detail::fill_chain(desc.chain);
		descriptor.label = detail::to_string_view(desc.label);
		return render_bundle(wgpuRenderBundleEncoderFinish((WGPURenderBundleEncoder)get(), &descriptor));
	}

	void render_bundle_encoder::set_label(std::string const & label)
	{
		wgpuRenderBundleEncoderSetLabel((WGPURenderBundleEncoder)get(), detail::to_string_view(label));
	}

	void render_bundle_encoder::reference(void * ptr)
	{
		wgpuRenderBundleEncoderAddRef((WGPURenderBundleEncoder)ptr);
	}

	void render_bundle_encoder::release(void * ptr)
	{
		wgpuRenderBundleEncoderRelease((WGPURenderBundleEncoder)ptr);
	}

}
