
#include "sbox/rendertools.h"

native static class RenderTools as NativeEngine.RenderTools
{
	bool SetRenderState( IRenderContext context, CRenderAttributes attributes, IMaterialMode materialMode, VertexLayout layout, SceneSystemPerFrameStats_t stats );
	void Draw( IRenderContext context, RenderPrimitiveType type, VertexLayout layout, void* vertices, int numVertices, CastTo[uint16*] void* indices, int numIndices, SceneSystemPerFrameStats_t stats );

	void ResolveFrameBuffer( IRenderContext renderContext, ITexture texture, NativeRect viewport );
	void ResolveDepthBuffer( IRenderContext renderContext, ITexture texture, NativeRect viewport );
	void DrawSceneObject( IRenderContext renderContext, ISceneLayer sceneLayer, CSceneObject sceneObject, Transform transform, Vector4 color, IMaterial material, CRenderAttributes attributes );
	void DrawModel( IRenderContext renderContext, ISceneLayer sceneLayer, IModel hModel, CastTo[CTransformUnaligned*] void* transforms, int numTransforms, CRenderAttributes attributes );
	void DrawModel( IRenderContext renderContext, ISceneLayer sceneLayer, IModel hModel, RenderBufferHandle_t hDrawArgBuffer, int nBufferOffset, CRenderAttributes attributes );
	
	//
	// Render context can be null and we'll create one
	//
	void Compute( IRenderContext renderContext, CRenderAttributes attributes, IMaterialMode pMode, int tx, int ty, int tz );
	void ComputeIndirect( IRenderContext renderContext, CRenderAttributes attributes, IMaterialMode pMode, RenderBufferHandle_t hIndirectBuffer, uint nIndirectBufferOffset );
	void TraceRays( IRenderContext renderContext, CRenderAttributes attributes, IMaterialMode pMode, uint tx, uint ty, uint tz );
	void TraceRaysIndirect( IRenderContext renderContext, CRenderAttributes attributes, IMaterialMode pMode, RenderBufferHandle_t hIndirectBuffer, uint nIndirectBufferOffset );
	void SetDynamicConstantBufferData( CRenderAttributes attributes, StringToken nTokenID, IRenderContext renderContext, void* data, int dataSize );

	void CopyTexture( IRenderContext renderContext, ITexture sourceTexture, ITexture destTexture, Rect_t pSrcRect, int nDestX, int nDestY, uint nSrcMipSlice, uint nSrcArraySlice, uint nDstMipSlice, uint nDstArraySlice );

	inline void SetGPUBufferData( IRenderContext renderContext, RenderBufferHandle_t hGpuBuffer, void* pData, uint nDataSize, uint nOffset )
	{
		// Create and submit
		if ( renderContext == nullptr )
		{
			CRenderContextPtr pRenderContext( g_pRenderDevice );
			pRenderContext->SetGPUBufferData( hGpuBuffer, pData, nDataSize, nOffset );
			// Not flushing on purpose, no readback needed
		}
		else
		{
			renderContext->SetGPUBufferData( hGpuBuffer, pData, nDataSize, nOffset );
		}
	}

	inline void CopyGPUBufferHiddenStructureCount( IRenderContext renderContext, RenderBufferHandle_t hSrcBuffer, RenderBufferHandle_t hDestBuffer, uint nDestBufferOffset )
	{
		// Create and submit
		if ( renderContext == nullptr )
		{
			CRenderContextPtr pRenderContext( g_pRenderDevice );
			pRenderContext->CopyGPUBufferHiddenStructureCount( hSrcBuffer, hDestBuffer, nDestBufferOffset );
			// Not flushing on purpose, no readback needed
		}
		else
		{
			renderContext->CopyGPUBufferHiddenStructureCount( hSrcBuffer, hDestBuffer, nDestBufferOffset );
		}
	}

	inline void SetGPUBufferHiddenStructureCount( IRenderContext renderContext, RenderBufferHandle_t hBuffer, uint nCounter )
	{
		// Create and submit
		if ( renderContext == nullptr )
		{
			CRenderContextPtr pRenderContext( g_pRenderDevice );
			pRenderContext->SetGPUBufferHiddenStructureCount( hBuffer, nCounter );
			// Not flushing on purpose, no readback needed
		}
		else
		{
			renderContext->SetGPUBufferHiddenStructureCount( hBuffer, nCounter );
		}
	}
}

native class VertexLayout as NativeEngine.VertexLayout
{
	static VertexLayout Create( string name, int size ); [new]
	
	void Destroy(); [delete]
	void Free();

	void Add( string semanticName, int semanticIndex, uint format, int offset );
	void Build();
}