#pragma once #include #include #include #include #include #include "framework/CDescriptorSet.h" #include "framework/CMemPool.h" #include "framework/CShader.h" #include "framework/CCmdMemRing.h" #include "nanovg.h" // Create flags enum NVGcreateFlags { // Flag indicating if geometry based anti-aliasing is used (may not be needed when using MSAA). NVG_ANTIALIAS = 1<<0, // Flag indicating if strokes should be drawn using stencil buffer. The rendering will be a little // slower, but path overlaps (i.e. self-intersecting or sharp turns) will be drawn just once. NVG_STENCIL_STROKES = 1<<1, // Flag indicating that additional debug checks are done. NVG_DEBUG = 1<<2, }; enum DKNVGuniformLoc { DKNVG_LOC_VIEWSIZE, DKNVG_LOC_TEX, DKNVG_LOC_FRAG, DKNVG_MAX_LOCS }; enum VKNVGshaderType { NSVG_SHADER_FILLGRAD, NSVG_SHADER_FILLIMG, NSVG_SHADER_SIMPLE, NSVG_SHADER_IMG }; struct DKNVGtextureDescriptor { int width, height; int type; int flags; }; struct DKNVGblend { int srcRGB; int dstRGB; int srcAlpha; int dstAlpha; }; enum DKNVGcallType { DKNVG_NONE = 0, DKNVG_FILL, DKNVG_CONVEXFILL, DKNVG_STROKE, DKNVG_TRIANGLES, }; struct DKNVGcall { int type; int image; int pathOffset; int pathCount; int triangleOffset; int triangleCount; int uniformOffset; DKNVGblend blendFunc; }; struct DKNVGpath { int fillOffset; int fillCount; int strokeOffset; int strokeCount; }; struct DKNVGfragUniforms { float scissorMat[12]; // matrices are actually 3 vec4s float paintMat[12]; struct NVGcolor innerCol; struct NVGcolor outerCol; float scissorExt[2]; float scissorScale[2]; float extent[2]; float radius; float feather; float strokeMult; float strokeThr; int texType; int type; }; namespace nvg { class DkRenderer; } struct DKNVGcontext { nvg::DkRenderer *renderer; float view[2]; int fragSize; int flags; // Per frame buffers DKNVGcall* calls; int ccalls; int ncalls; DKNVGpath* paths; int cpaths; int npaths; struct NVGvertex* verts; int cverts; int nverts; unsigned char* uniforms; int cuniforms; int nuniforms; }; namespace nvg { class Texture { private: const int m_id; dk::Image m_image; dk::ImageDescriptor m_image_descriptor; CMemPool::Handle m_image_mem; DKNVGtextureDescriptor m_texture_descriptor; public: Texture(int id); ~Texture(); void Initialize(CMemPool &image_pool, CMemPool &scratch_pool, dk::Device device, dk::Queue transfer_queue, int type, int w, int h, int image_flags, const u8 *data); void Update(CMemPool &image_pool, CMemPool &scratch_pool, dk::Device device, dk::Queue transfer_queue, int type, int w, int h, int image_flags, const u8 *data); int GetId(); const DKNVGtextureDescriptor &GetDescriptor(); dk::Image &GetImage(); dk::ImageDescriptor &GetImageDescriptor(); }; class DkRenderer { private: enum SamplerType : u8 { SamplerType_MipFilter = 1 << 0, SamplerType_Nearest = 1 << 1, SamplerType_RepeatX = 1 << 2, SamplerType_RepeatY = 1 << 3, SamplerType_Total = 0x10, }; private: static constexpr size_t DynamicCmdSize = 0x20000; static constexpr size_t FragmentUniformSize = sizeof(DKNVGfragUniforms) + 4 - sizeof(DKNVGfragUniforms) % 4; static constexpr size_t MaxImages = 0x1000; /* From the application. */ u32 m_view_width; u32 m_view_height; dk::Device m_device; dk::Queue m_queue; CMemPool &m_image_mem_pool; CMemPool &m_code_mem_pool; CMemPool &m_data_mem_pool; /* State. */ dk::UniqueCmdBuf m_dyn_cmd_buf; CCmdMemRing<1> m_dyn_cmd_mem; std::optional m_vertex_buffer; CShader m_vertex_shader; CShader m_fragment_shader; CMemPool::Handle m_view_uniform_buffer; CMemPool::Handle m_frag_uniform_buffer; u32 m_next_texture_id = 1; std::vector> m_textures; CDescriptorSet m_image_descriptor_set; CDescriptorSet m_sampler_descriptor_set; std::array m_image_descriptor_mappings; int m_last_image_descriptor = 0; int AcquireImageDescriptor(std::shared_ptr texture, int image); void FreeImageDescriptor(int image); void SetUniforms(const DKNVGcontext &ctx, int offset, int image); void UpdateVertexBuffer(const void *data, size_t size); void DrawFill(const DKNVGcontext &ctx, const DKNVGcall &call); void DrawConvexFill(const DKNVGcontext &ctx, const DKNVGcall &call); void DrawStroke(const DKNVGcontext &ctx, const DKNVGcall &call); void DrawTriangles(const DKNVGcontext &ctx, const DKNVGcall &call); std::shared_ptr FindTexture(int id); public: DkRenderer(unsigned int view_width, unsigned int view_height, dk::Device device, dk::Queue queue, CMemPool &image_mem_pool, CMemPool &code_mem_pool, CMemPool &data_mem_pool); ~DkRenderer(); int Create(DKNVGcontext &ctx); int CreateTexture(const DKNVGcontext &ctx, int type, int w, int h, int image_flags, const u8 *data); int DeleteTexture(const DKNVGcontext &ctx, int id); int UpdateTexture(const DKNVGcontext &ctx, int id, int x, int y, int w, int h, const u8 *data); int GetTextureSize(const DKNVGcontext &ctx, int id, int *w, int *h); const DKNVGtextureDescriptor *GetTextureDescriptor(const DKNVGcontext &ctx, int id); void Flush(DKNVGcontext &ctx); }; }