瀏覽代碼

Add idl codegen

Cloud Wu 6 年之前
父節點
當前提交
e9cd8b5532
共有 5 個文件被更改,包括 1432 次插入0 次删除
  1. 93 0
      scripts/bgfx-idl.lua
  2. 955 0
      scripts/bgfx.idl
  3. 271 0
      scripts/codegen.lua
  4. 8 0
      scripts/genie.lua
  5. 105 0
      scripts/idl.lua

+ 93 - 0
scripts/bgfx-idl.lua

@@ -0,0 +1,93 @@
+-- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved.
+-- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE
+
+local idl     = require "idl"
+local codegen = require "codegen"
+
+assert(loadfile("bgfx.idl" , "t", idl))()
+
+codegen.nameconversion(idl.types, idl.funcs)
+
+local code_temp_include = [[
+/*
+ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ */
+
+/*
+ *
+ * AUTO GENERATED! DO NOT EDIT!
+ *
+ */
+
+$c99decl
+/**/
+typedef struct bgfx_interface_vtbl
+{
+	$interface_struct
+} bgfx_interface_vtbl_t;
+]]
+
+local code_temp_impl = [[
+/*
+ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ */
+
+/*
+ *
+ * AUTO GENERATED! DO NOT EDIT!
+ *
+ */
+
+$c99
+/**/
+BGFX_C_API bgfx_interface_vtbl_t* bgfx_get_interface(uint32_t _version)
+{
+	if (_version == BGFX_API_VERSION)
+	{
+		static bgfx_interface_vtbl_t s_bgfx_interface =
+		{
+			$interface_import
+		};
+
+		return &s_bgfx_interface;
+	}
+
+	return NULL;
+}
+]]
+
+local function codes()
+	local temp = {}
+	local action = {
+		c99 = "\n",
+		c99decl = "\n",
+		interface_struct = "\n\t",
+		interface_import = ",\n\t\t\t",
+	}
+	for k in pairs(action) do
+		temp[k] = {}
+	end
+	for _, f in ipairs(idl.funcs) do
+		for k in pairs(action) do
+			table.insert(temp[k], (codegen["gen_"..k](f)))
+		end
+	end
+
+	for k, ident in pairs(action) do
+		temp[k] = table.concat(temp[k], ident)
+	end
+
+	return temp
+end
+
+local codes_tbl = codes()
+
+for filename, temp in pairs {
+	["../include/bgfx/c99/bgfx.idl.h"] = code_temp_include ,
+	["../src/bgfx.idl.inl"] = code_temp_impl } do
+
+	print ("Generate " .. filename)
+	local out = io.open(filename, "wb")
+	out:write((temp:gsub("$([%l%d_]+)", codes_tbl)))
+	out:close()
+end

+ 955 - 0
scripts/bgfx.idl

@@ -0,0 +1,955 @@
+-- bgfx interface 
+
+typedef "bool"
+typedef "char"
+typedef "float"
+typedef "int32_t"
+typedef "uint8_t"
+typedef "uint16_t"
+typedef "uint32_t"
+typedef "uint64_t"
+typedef "uintptr_t"
+typedef "va_list"
+typedef "void"
+
+typedef "Attachment"
+typedef "Caps"
+typedef "Encoder"
+typedef "Init"
+typedef "InstanceDataBuffer"
+typedef "InternalData"
+typedef "Memory"
+typedef "PlatformData"
+typedef "ReleaseFn"
+typedef "Stats"
+typedef "TextureInfo"
+typedef "Transform"
+typedef "TransientIndexBuffer"
+typedef "TransientVertexBuffer"
+typedef "UniformInfo"
+typedef "VertexDecl"
+typedef "ViewId"
+
+typedef.Access               { enum }
+typedef.Attrib               { enum }
+typedef.AttribType           { enum }
+typedef.BackbufferRatio      { enum }
+typedef.OcclusionQueryResult { enum }
+typedef.RenderFrame          { enum }
+typedef.RendererType         { enum }
+typedef.TextureFormat        { enum }
+typedef.TopologyConvert      { enum }
+typedef.TopologySort         { enum }
+typedef.UniformType          { enum }
+typedef.ViewMode             { enum }
+
+typedef.DynamicIndexBufferHandle  { handle }
+typedef.DynamicVertexBufferHandle { handle }
+typedef.FrameBufferHandle         { handle }
+typedef.IndexBufferHandle         { handle }
+typedef.IndirectBufferHandle      { handle }
+typedef.OcclusionQueryHandle      { handle }
+typedef.ProgramHandle             { handle }
+typedef.ShaderHandle              { handle }
+typedef.TextureHandle             { handle }
+typedef.UniformHandle             { handle }
+typedef.VertexBufferHandle        { handle }
+typedef.VertexDeclHandle          { handle }
+
+func.VertexDecl.begin
+	"void"
+	.renderer        "RendererType::Enum"
+
+func.VertexDecl.add
+	"void"
+	.attrib          "Attrib::Enum"
+	.num             "uint8_t"
+	.type            "AttribType::Enum"
+	.normalized      "bool"
+	.asInt           "bool"
+
+func.VertexDecl.decode { const }
+	"void"
+	.attrib          "Attrib::Enum"
+	.num             "uint8_t &"          { out }
+	.type            "AttribType::Enum &" { out }
+	.normalized      "bool &"             { out }
+	.asInt           "bool &"             { out }
+
+func.VertexDecl.has { const }
+	"bool"
+	.attrib          "Attrib::Enum"
+
+func.VertexDecl.skip
+	"void"
+	.num             "uint8_t"
+
+-- Notice: `end` is a keyword in lua
+func.VertexDecl["end"]
+	"void"
+
+func.vertexPack
+	"void"
+	.input           "const float *"
+	.inputNormalized "bool"
+	.attr            "Attrib::Enum"
+	.decl            "const VertexDecl &"
+	.data            "void *"
+	.index           "uint32_t"
+
+func.vertexUnpack
+	"void"
+	.output          "float *" { out }
+	.attr            "Attrib::Enum"
+	.decl            "const VertexDecl &"
+	.data            "const void *"
+	.index           "uint32_t"
+
+func.vertexConvert
+	"void"
+	.dstDecl "const VertexDecl &"
+	.dstData "void *"
+	.srcDecl "const VertexDecl &"
+	.srcData "const void *"
+	.num     "uint32_t"
+
+func.weldVertices
+	"uint16_t"
+	.output  "uint16_t *"
+	.decl    "const VertexDecl &"
+	.data    "const void *"
+	.num     "uint16_t"
+	.epsilon "float"
+
+func.topologyConvert
+	"uint32_t"
+	.conversion "TopologyConvert::Enum"
+	.dst        "void *" { out }
+	.dstSize    "uint32_t"
+	.indices    "const void *"
+	.numIndices "uint32_t"
+	.index32    "bool"
+
+func.topologySortTriList
+	"void"
+	.sort       "TopologySort::Enum"
+	.dst        "void *" { out }
+	.dstSize    "uint32_t"
+	.dir        "const float *"
+	.pos        "const float *"
+	.vertices   "const void *"
+	.stride     "uint32_t"
+	.indices    "const void *"
+	.numIndices "uint32_t"
+	.index32    "bool"
+
+func.getSupportedRenderers
+	"uint8_t"
+	.max  "uint8_t"
+	.enum "RendererType::Enum *" { out }
+
+func.getRendererName
+	"const char *"
+	.type "RendererType::Enum"
+
+local init_ctor = [[
+	BX_PLACEMENT_NEW(_init, bgfx::Init);
+]]
+func.initCtor { cfunc = init_ctor }
+	"void"
+	.init "Init *"
+
+local init = [[
+	bgfx_init_t init = *_init;
+
+	if (init.callback != NULL)
+	{
+		static bgfx::CallbackC99 s_callback;
+		s_callback.m_interface = init.callback;
+		init.callback = reinterpret_cast<bgfx_callback_interface_t *>(&s_callback);
+	}
+
+	if (init.allocator != NULL)
+	{
+		static bgfx::AllocatorC99 s_allocator;
+		s_allocator.m_interface = init.allocator;
+		init.allocator = reinterpret_cast<bgfx_allocator_interface_t *>(&s_allocator);
+	}
+
+	union { const bgfx_init_t* c; const bgfx::Init* cpp; } in;
+	in.c = &init;
+
+	return bgfx::init(*in.cpp);
+]]
+func.init { cfunc = init }
+	"bool"
+	.init "const Init &"
+
+func.shutdown
+	"void"
+
+func.reset
+	"void"
+	.width  "uint32_t"
+	.height "uint32_t"
+	.flags  "uint32_t"
+	.format "TextureFormat::Enum"
+
+func.frame
+	"uint32_t"
+	.capture "bool"
+
+func.getRendererType
+	"RendererType::Enum"
+
+func.getCaps
+	"const Caps *"
+
+func.getStats
+	"const Stats *"
+
+func.alloc
+	"const Memory *"
+	.size "uint32_t"
+
+func.copy
+	"const Memory *"
+	.data "const void *"
+	.size "uint32_t"
+
+func.makeRef
+	"const Memory *"
+	.data "const void *"
+	.size "uint32_t"
+
+func.makeRef { cname = "make_ref_release" }
+	"const Memory *"
+	.data      "const void *"
+	.size      "uint32_t"
+	.releaseFn "ReleaseFn"
+	.userData  "void *"
+
+func.setDebug
+	"void"
+	.debug "uint32_t"
+
+func.dbgTextClear
+	"void"
+	.attr  "uint8_t"
+	.small "bool"
+
+func.dbgTextPrintf { vararg = "dbgTextPrintfVargs" }
+	"void"
+	.x      "uint16_t"
+	.y      "uint16_t"
+	.attr   "uint8_t"
+	.format "const char *"
+
+func.dbgTextPrintfVargs { cname = "dbg_text_vprintf" }
+	"void"
+	.x       "uint16_t"
+	.y       "uint16_t"
+	.attr    "uint8_t"
+	.format  "const char *"
+	.argList "va_list"
+
+func.dbgTextImage
+	"void"
+	.x       "uint16_t"
+	.y       "uint16_t"
+	.width   "uint16_t"
+	.height  "uint16_t"
+	.data    "const void *"
+	.pitch   "uint16_t"
+
+func.createIndexBuffer
+	"IndexBufferHandle"
+	.mem   "const Memory *"
+	.flags "uint16_t"
+
+func.setName { cname = "set_index_buffer_name" }
+	"void"
+	.handle "IndexBufferHandle"
+	.name   "const char *"
+	.len    "int32_t"
+
+func.destroy { cname = "destroy_index_buffer" }
+	"void"
+	.handle "IndexBufferHandle"
+
+func.createVertexBuffer
+	"VertexBufferHandle"
+	.mem   "const Memory *"
+	.decl  "const VertexDecl &"
+	.flags "uint16_t"
+
+func.setName { cname = "set_vertex_buffer_name" }
+	"void"
+	.handle "VertexBufferHandle"
+	.name   "const char *"
+	.len    "int32_t"
+
+func.destroy { cname = "destroy_vertex_buffer" }
+	"void"
+	.handle "VertexBufferHandle"
+
+func.createDynamicIndexBuffer
+	"DynamicIndexBufferHandle"
+	.num   "uint32_t"
+	.flags "uint16_t"
+
+func.createDynamicIndexBuffer { cname = "create_dynamic_index_buffer_mem" }
+	"DynamicIndexBufferHandle"
+	.mem   "const Memory *"
+	.flags "uint16_t"
+
+func.update { cname = "update_dynamic_index_buffer" }
+	"void"
+	.handle     "DynamicIndexBufferHandle"
+	.startIndex "uint32_t"
+	.mem        "const Memory *"
+
+func.destroy { cname = "destroy_dynamic_index_buffer" }
+	"void"
+	.handle "DynamicIndexBufferHandle"
+
+func.createDynamicVertexBuffer
+	"DynamicVertexBufferHandle"
+	.num   "uint32_t"
+	.decl  "const VertexDecl &"
+	.flags "uint16_t"
+
+func.createDynamicVertexBuffer { cname = "create_dynamic_vertex_buffer_mem" }
+	"DynamicVertexBufferHandle"
+	.mem   "const Memory *"
+	.decl  "const VertexDecl &"
+	.flags "uint16_t"
+
+func.update { cname = "update_dynamic_vertex_buffer" }
+	"void"
+	.handle      "DynamicVertexBufferHandle"
+	.startVertex "uint32_t"
+	.mem         "const Memory *"
+
+func.destroy { cname = "destroy_dynamic_vertex_buffer" }
+	"void"
+	.handle "DynamicVertexBufferHandle"
+
+func.getAvailTransientIndexBuffer
+	"uint32_t"
+	.num "uint32_t"
+
+func.getAvailTransientVertexBuffer
+	"uint32_t"
+	.num "uint32_t"
+	.decl  "const VertexDecl &"
+
+func.getAvailInstanceDataBuffer
+	"uint32_t"
+	.num    "uint32_t"
+	.stride "uint16_t"
+
+func.allocTransientIndexBuffer
+	"void"
+	.tib "TransientIndexBuffer *" { out }
+	.num "uint32_t"
+
+func.allocTransientVertexBuffer
+	"void"
+	.tvb  "TransientVertexBuffer *" { out }
+	.num  "uint32_t"
+	.decl "const VertexDecl &"
+
+func.allocTransientBuffers
+	"bool"
+	.tvb         "TransientVertexBuffer *" { out }
+	.decl        "const VertexDecl &"
+	.numVertices "uint32_t"
+	.tib         "TransientIndexBuffer *" { out }
+	.numIndices  "uint32_t"
+
+func.allocInstanceDataBuffer
+	"void"
+	.idb    "InstanceDataBuffer *" { out }
+	.num    "uint32_t"
+	.stride "uint16_t"
+
+func.createIndirectBuffer
+	"IndirectBufferHandle"
+	.num "uint32_t"
+
+func.destroy { cname = "destroy_indirect_buffer" }
+	"void"
+	.handle "IndirectBufferHandle"
+
+func.createShader
+	"ShaderHandle"
+	.mem "const Memory *"
+
+func.getShaderUniforms
+	"uint16_t"
+	.handle   "ShaderHandle"
+	.uniforms "UniformHandle *" { out }
+	.max      "uint16_t"
+
+func.setName { cname = "set_shader_name" }
+	"void"
+	.handle "ShaderHandle"
+	.name   "const char *"
+	.len    "int32_t"
+
+func.destroy { cname = "destroy_shader" }
+	"void"
+	.handle "ShaderHandle"
+
+func.createProgram
+	"ProgramHandle"
+	.vsh "ShaderHandle"
+	.fsh "ShaderHandle"
+	.destroyShaders "bool"
+
+func.createProgram { cname = "create_compute_program" }
+	"ProgramHandle"
+	.csh "ShaderHandle"
+	.destroyShaders "bool"
+
+func.destroy { cname = "destroy_program" }
+	"void"
+	.handle "ProgramHandle"
+
+func.isTextureValid
+	"bool"
+	.depth     "uint16_t"
+	.cubeMap   "bool"
+	.numLayers "uint16_t"
+	.format    "TextureFormat::Enum"
+	.flags     "uint64_t"
+
+func.calcTextureSize
+	"void"
+	.info      "TextureInfo &" { out }
+	.width     "uint16_t"
+	.height    "uint16_t"
+	.depth     "uint16_t"
+	.cubeMap   "bool"
+	.hasMips   "bool"
+	.numLayers "uint16_t"
+	.format    "TextureFormat::Enum"
+
+func.createTexture
+	"TextureHandle"
+	.mem   "const Memory *"
+	.flags "uint64_t"
+	.skip  "uint8_t"
+	.info  "TextureInfo *" { out }
+
+func.createTexture2D
+	"TextureHandle"
+	.width     "uint16_t"
+	.height    "uint16_t"
+	.hasMips   "bool"
+	.numLayers "uint16_t"
+	.format    "TextureFormat::Enum"
+	.flags     "uint64_t"
+	.mem       "const Memory *"
+
+func.createTexture2D { cname = "create_texture_2d_scaled" }
+	"TextureHandle"
+	.ratio     "BackbufferRatio::Enum"
+	.hasMips   "bool"
+	.numLayers "uint16_t"
+	.format    "TextureFormat::Enum"
+	.flags     "uint64_t"
+
+func.createTexture3D
+	"TextureHandle"
+	.width     "uint16_t"
+	.height    "uint16_t"
+	.depth     "uint16_t"
+	.hasMips   "bool"
+	.format    "TextureFormat::Enum"
+	.flags     "uint64_t"
+	.mem       "const Memory *"
+
+func.createTextureCube
+	"TextureHandle"
+	.size      "uint16_t"
+	.hasMips   "bool"
+	.numLayers "uint16_t"
+	.format    "TextureFormat::Enum"
+	.flags     "uint64_t"
+	.mem       "const Memory *"
+
+func.updateTexture2D
+	"void"
+	.handle "TextureHandle"
+	.layer  "uint16_t"
+	.mip    "uint16_t"
+	.x      "uint16_t"
+	.y      "uint16_t"
+	.width  "uint16_t"
+	.height "uint16_t"
+	.mem    "const Memory *"
+	.pitch  "uint16_t"
+
+func.updateTexture3D
+	"void"
+	.handle "TextureHandle"
+	.mip    "uint16_t"
+	.x      "uint16_t"
+	.y      "uint16_t"
+	.z      "uint16_t"
+	.width  "uint16_t"
+	.height "uint16_t"
+	.depth  "uint16_t"
+	.mem    "const Memory *"
+
+func.updateTextureCube
+	"void"
+	.handle "TextureHandle"
+	.layer  "uint16_t"
+	.side   "uint8_t"
+	.mip    "uint8_t"
+	.x      "uint16_t"
+	.y      "uint16_t"
+	.width  "uint16_t"
+	.height "uint16_t"
+	.mem    "const Memory *"
+	.pitch  "uint16_t"
+
+func.readTexture
+	"uint32_t"
+	.handle "TextureHandle"
+	.data   "void *"
+	.mip    "uint8_t"
+
+func.setName { cname = "set_texture_name" }
+	"void"
+	.handle "TextureHandle"
+	.name   "const char *"
+	.len    "int32_t"
+
+func.getDirectAccessPtr
+	"void *"
+	.handle "TextureHandle"
+
+func.destroy { cname = "destroy_texture" }
+	"void"
+	.handle "TextureHandle"
+
+func.createFrameBuffer
+	"FrameBufferHandle"
+	.width        "uint16_t"
+	.height       "uint16_t"
+	.format       "TextureFormat::Enum"
+	.textureFlags "uint64_t"
+
+func.createFrameBuffer { cname = "create_frame_buffer_scaled" }
+	"FrameBufferHandle"
+	.ratio        "BackbufferRatio::Enum"
+	.format       "TextureFormat::Enum"
+	.textureFlags "uint64_t"
+
+func.createFrameBuffer { cname = "create_frame_buffer_from_handles" }
+	"FrameBufferHandle"
+	.num            "uint8_t"
+	.handles        "const TextureHandle *"
+	.destroyTexture "bool"
+
+func.createFrameBuffer { cname = "create_frame_buffer_from_attachment" }
+	"FrameBufferHandle"
+	.num            "uint8_t"
+	.handles        "const Attachment *"
+	.destroyTexture "bool"
+
+func.createFrameBuffer { cname = "create_frame_buffer_from_nwh" }
+	"FrameBufferHandle"
+	.nwh         "void *"
+	.width       "uint16_t"
+	.height      "uint16_t"
+	.format      "TextureFormat::Enum"
+	.depthFormat "TextureFormat::Enum"
+
+func.setName { cname = "set_frame_buffer_name" }
+	"void"
+	.handle "FrameBufferHandle"
+	.name   "const char *"
+	.len    "int32_t"
+
+func.getTexture
+	"TextureHandle"
+	.handle     "FrameBufferHandle"
+	.attachment "uint8_t"
+
+func.destroy { cname = "destroy_frame_buffer" }
+	"void"
+	.handle "FrameBufferHandle"
+
+func.createUniform
+	"UniformHandle"
+	.name "const char *"
+	.type "UniformType::Enum"
+	.num  "uint16_t"
+
+func.getUniformInfo
+	"void"
+	.handle "UniformHandle"
+	.info   "UniformInfo &" { out }
+
+func.destroy { cname = "destroy_uniform" }
+	"void"
+	.handle "UniformHandle"
+
+func.createOcclusionQuery
+	"OcclusionQueryHandle"
+
+func.getResult
+	"OcclusionQueryResult::Enum"
+	.handle "OcclusionQueryHandle"
+	.result "int32_t *" { out }
+
+func.destroy { cname = "destroy_occlusion_query" }
+	"void"
+	.handle "OcclusionQueryHandle"
+
+func.setPaletteColor
+	"void"
+	.index "uint8_t"
+	.rgba  "const float *"
+
+func.setViewName
+	"void"
+	.id   "ViewId"
+	.name "const char *"
+
+func.setViewRect
+	"void"
+	.id     "ViewId"
+	.x      "uint16_t"
+	.y      "uint16_t"
+	.width  "uint16_t"
+	.height "uint16_t"
+
+func.setViewRect { cname = "set_view_rect_ratio" }
+	"void"
+	.id    "ViewId"
+	.x     "uint16_t"
+	.y     "uint16_t"
+	.ratio "BackbufferRatio::Enum"
+
+func.setViewScissor
+	"void"
+	.id     "ViewId"
+	.x      "uint16_t"
+	.y      "uint16_t"
+	.width  "uint16_t"
+	.height "uint16_t"
+
+func.setViewClear
+	"void"
+	.id      "ViewId"
+	.flags   "uint16_t"
+	.rgba    "uint32_t"
+	.depth   "float"
+	.stencil "uint8_t"
+
+func.setViewClear { cname = "set_view_clear_mrt" }
+	"void"
+	.id      "ViewId"
+	.flags   "uint16_t"
+	.depth   "float"
+	.stencil "uint8_t"
+	.c0      "uint8_t"
+	.c1      "uint8_t"
+	.c2      "uint8_t"
+	.c3      "uint8_t"
+	.c4      "uint8_t"
+	.c5      "uint8_t"
+	.c6      "uint8_t"
+	.c7      "uint8_t"
+
+func.setViewMode
+	"void"
+	.id   "ViewId"
+	.mode "ViewMode::Enum"
+
+func.setViewFrameBuffer
+	"void"
+	.id     "ViewId"
+	.handle "FrameBufferHandle"
+
+func.setViewTransform
+	"void"
+	.id   "ViewId"
+	.view "const void *"
+	.proj "const void *"
+
+func.setViewOrder
+	"void"
+	.id    "ViewId"
+	.num   "uint16_t"
+	.order "const ViewId *"
+
+func.begin { cname = "encoder_begin" }
+	"Encoder *"
+	.forThread "bool"
+
+func["end"] { cname = "encoder_end" }
+	"void"
+	.encoder "Encoder *"
+
+func.Encoder.setMarker
+	"void"
+	.marker "const char *"
+
+func.Encoder.setState
+	"void"
+	.state "uint64_t"
+	.rgba  "uint32_t"
+
+func.Encoder.setCondition
+	"void"
+	.handle  "OcclusionQueryHandle"
+	.visible "bool"
+
+func.Encoder.setStencil
+	"void"
+	.fstencil "uint32_t"
+	.bstencil "uint32_t"
+
+func.Encoder.setScissor
+	"uint16_t"
+	.x      "uint16_t"
+	.y      "uint16_t"
+	.width  "uint16_t"
+	.height "uint16_t"
+
+func.Encoder.setScissor { cname = "set_scissor_cached" }
+	"void"
+	.cache "uint16_t"
+
+func.Encoder.setTransform
+	"uint32_t"
+	.mtx "const void *"
+	.num "uint16_t"
+
+func.Encoder.setTransform { cname = "set_transform_cached" }
+	"void"
+	.cache "uint32_t"
+	.num   "uint16_t"
+
+func.Encoder.allocTransform
+	"uint32_t"
+	.transform "Transform *" { out }
+	.num       "uint16_t"
+
+func.Encoder.setUniform
+	"void"
+	.handle "UniformHandle"
+	.value  "const void *"
+	.num    "uint16_t"
+
+func.Encoder.setIndexBuffer
+	"void"
+	.handle     "IndexBufferHandle"
+	.firstIndex "uint32_t"
+	.numIndices "uint32_t"
+
+func.Encoder.setIndexBuffer { cname = "set_dynamic_index_buffer" }
+	"void"
+	.handle     "DynamicIndexBufferHandle"
+	.firstIndex "uint32_t"
+	.numIndices "uint32_t"
+
+func.Encoder.setIndexBuffer { cname = "set_transient_index_buffer" }
+	"void"
+	.tib        "const TransientIndexBuffer *"
+	.firstIndex "uint32_t"
+	.numIndices "uint32_t"
+
+func.Encoder.setVertexBuffer
+	"void"
+	.stream      "uint8_t"
+	.handle      "VertexBufferHandle"
+	.startVertex "uint32_t"
+	.numVertices "uint32_t"
+
+func.Encoder.setVertexBuffer { cname = "set_dynamic_vertex_buffer" }
+	"void"
+	.stream      "uint8_t"
+	.handle      "DynamicVertexBufferHandle"
+	.startVertex "uint32_t"
+	.numVertices "uint32_t"
+
+func.Encoder.setVertexBuffer { cname = "set_transient_vertex_buffer" }
+	"void"
+	.stream      "uint8_t"
+	.tvb         "const TransientVertexBuffer *"
+	.startVertex "uint32_t"
+	.numVertices "uint32_t"
+
+func.Encoder.setVertexCount
+	"void"
+	.numVertices "uint32_t"
+
+func.Encoder.setInstanceDataBuffer
+	"void"
+	.idb   "const InstanceDataBuffer *"
+	.start "uint32_t"
+	.num   "uint32_t"
+
+func.Encoder.setInstanceDataBuffer { cname = "set_instance_data_from_vertex_buffer" }
+	"void"
+	.handle      "VertexBufferHandle"
+	.startVertex "uint32_t"
+	.num         "uint32_t"
+
+func.Encoder.setInstanceDataBuffer { cname = "set_instance_data_from_dynamic_vertex_buffer" }
+	"void"
+	.handle      "DynamicVertexBufferHandle"
+	.startVertex "uint32_t"
+	.num         "uint32_t"
+
+func.Encoder.setInstanceCount
+	"void"
+	.numInstances "uint32_t"
+
+func.Encoder.setTexture
+	"void"
+	.stage   "uint8_t"
+	.sampler "UniformHandle"
+	.handle  "TextureHandle"
+	.flags   "uint32_t"
+
+func.Encoder.touch
+	"void"
+	.id "ViewId"
+
+func.Encoder.submit
+	"void"
+	.id            "ViewId"
+	.program       "ProgramHandle"
+	.depth         "uint32_t"
+	.preserveState "bool"
+
+func.Encoder.submit { cname = "submit_occlusion_query" }
+	"void"
+	.id             "ViewId"
+	.program        "ProgramHandle"
+	.occlusionQuery "OcclusionQueryHandle"
+	.depth          "uint32_t"
+	.preserveState  "bool"
+
+func.Encoder.submit { cname = "submit_indirect" }
+	"void"
+	.id             "ViewId"
+	.program        "ProgramHandle"
+	.indirectHandle "IndirectBufferHandle"
+	.start          "uint16_t"
+	.num            "uint16_t"
+	.depth          "uint32_t"
+	.preserveState  "bool"
+
+func.Encoder.setBuffer { cname = "set_compute_index_buffer" }
+	"void"
+	.stage  "uint8_t"
+	.handle "IndexBufferHandle"
+	.access "Access::Enum"
+
+func.Encoder.setBuffer { cname = "set_compute_vertex_buffer" }
+	"void"
+	.stage  "uint8_t"
+	.handle "VertexBufferHandle"
+	.access "Access::Enum"
+
+func.Encoder.setBuffer { cname = "set_compute_dynamic_index_buffer" }
+	"void"
+	.stage  "uint8_t"
+	.handle "DynamicIndexBufferHandle"
+	.access "Access::Enum"
+
+func.Encoder.setBuffer { cname = "set_compute_dynamic_vertex_buffer" }
+	"void"
+	.stage  "uint8_t"
+	.handle "DynamicVertexBufferHandle"
+	.access "Access::Enum"
+
+func.Encoder.setBuffer { cname = "set_compute_indirect_buffer" }
+	"void"
+	.stage  "uint8_t"
+	.handle "IndirectBufferHandle"
+	.access "Access::Enum"
+
+func.Encoder.setImage
+	"void"
+	.stage  "uint8_t"
+	.handle "TextureHandle"
+	.mip    "uint8_t"
+	.access "Access::Enum"
+	.format "TextureFormat::Enum"
+
+func.Encoder.dispatch
+	"void"
+	.id      "ViewId"
+	.program "ProgramHandle"
+	.numX    "uint32_t"
+	.numY    "uint32_t"
+	.numZ    "uint32_t"
+
+func.Encoder.dispatch { cname = "dispatch_indirect" }
+	"void"
+	.id             "ViewId"
+	.program        "ProgramHandle"
+	.indirectHandle "IndirectBufferHandle"
+	.start          "uint16_t"
+	.num            "uint16_t"
+
+func.Encoder.discard
+	"void"
+
+func.Encoder.blit
+	"void"
+	.id     "ViewId"
+	.dst    "TextureHandle"
+	.dstMip "uint8_t"
+	.dstX   "uint16_t"
+	.dstY   "uint16_t"
+	.dstZ   "uint16_t"
+	.src    "TextureHandle"
+	.srcMip "uint8_t"
+	.srcX   "uint16_t"
+	.srcY   "uint16_t"
+	.srcZ   "uint16_t"
+	.width  "uint16_t"
+	.height "uint16_t"
+	.depth  "uint16_t"
+
+func.requestScreenShot
+	"void"
+	.handle   "FrameBufferHandle"
+	.filePath "const char *"
+
+func.renderFrame
+	"RenderFrame::Enum"
+	.msecs "int32_t"
+
+func.setPlatformData
+	"void"
+	.data "const PlatformData &"
+
+func.getInternalData
+	"const InternalData *"
+
+func.overrideInternal { cname = "override_internal_texture_ptr" }
+	"uintptr_t"
+	.handle "TextureHandle"
+	.ptr    "uintptr_t"
+
+func.overrideInternal { cname = "override_internal_texture" }
+	"uintptr_t"
+	.handle  "TextureHandle"
+	.width   "uint16_t"
+	.height  "uint16_t"
+	.numMips "uint8_t"
+	.format  "TextureFormat::Enum"
+	.flags   "uint32_t"

+ 271 - 0
scripts/codegen.lua

@@ -0,0 +1,271 @@
+-- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved.
+-- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE
+
+local codegen = {}
+
+local function camelcase_to_underscorecase(name)
+	local tmp = {}
+	for v in name:gmatch "[%u%d]+%l*" do
+		tmp[#tmp+1] = v:lower()
+	end
+	return table.concat(tmp, "_")
+end
+
+local function convert_typename(name)
+	if name:match "^%u" then
+		return "bgfx_" .. camelcase_to_underscorecase(name) .. "_t"
+	else
+		return name
+	end
+end
+
+local function convert_funcname(name)
+	name = name:gsub("^%l", string.upper)	-- Change to upper CamlCase
+	return camelcase_to_underscorecase(name)
+end
+
+local function convert_arg(all_types, arg, what)
+	local t, postfix = arg.fulltype:match "(%a[%a%d_:]*)%s*([*&]+)%s*$"
+	if t then
+		arg.type = t
+		if postfix == "&" then
+			arg.ref = true
+		end
+	else
+		arg.type = arg.fulltype
+	end
+	local ctype = all_types[arg.type]
+	if not ctype then
+		error ("Undefined type " .. arg.fulltype .. " for " .. what)
+	end
+	arg.ctype = arg.fulltype:gsub(arg.type, ctype.cname):gsub("&", "*")
+	if ctype.cname ~= arg.type then
+		arg.cpptype = arg.fulltype:gsub(arg.type, "bgfx::"..arg.type)
+	else
+		arg.cpptype = arg.fulltype
+	end
+	if arg.ref then
+		arg.ptype = arg.cpptype:gsub("&", "*")
+	end
+end
+
+local function alternative_name(name)
+	if name:sub(1,1) == "_" then
+		return name:sub(2)
+	else
+		return name .. "_"
+	end
+end
+
+local function gen_arg_conversion(all_types, arg)
+	if arg.ctype == arg.fulltype then
+		-- do not need conversion
+		arg.aname = arg.name
+		return
+	end
+	local ctype = all_types[arg.type]
+	if ctype.handle and arg.type == arg.fulltype then
+		local aname = alternative_name(arg.name)
+		arg.aname = aname .. ".cpp"
+		arg.conversion = string.format(
+			"union { %s c; bgfx::%s cpp; } %s = { %s };" ,
+			ctype.cname, arg.type, aname, arg.name)
+	elseif arg.ref then
+		if ctype.cname == arg.type then
+			arg.aname = "*" .. arg.name
+		elseif arg.out and ctype.enum then
+			local aname = alternative_name(arg.name)
+			local cpptype = arg.cpptype:match "(.-)%s*&"	-- remove &
+			arg.aname = aname
+			arg.conversion = string.format("%s %s;", cpptype, aname)
+			arg.out_conversion = string.format("*%s = (%s)%s;", arg.name, ctype.cname, aname)
+		else
+			arg.aname = alternative_name(arg.name)
+			arg.conversion = string.format(
+				"%s %s = *(%s)%s;",
+				arg.cpptype, arg.aname, arg.ptype, arg.name)
+		end
+	else
+		arg.aname = string.format(
+			"(%s)%s",
+			arg.cpptype, arg.name)
+	end
+end
+
+local function gen_ret_conversion(all_types, func)
+	local postfix = { func.vararg and "va_end(argList);" }
+	func.ret_postfix = postfix
+
+	for _, arg in ipairs(func.args) do
+		if arg.out_conversion then
+			postfix[#postfix+1] = arg.out_conversion
+		end
+	end
+
+	local ctype = all_types[func.ret.type]
+	if ctype.handle then
+		func.ret_conversion = string.format(
+			"union { %s c; bgfx::%s cpp; } handle_ret;" ,
+			ctype.cname, func.ret.type)
+		func.ret_prefix = "handle_ret.cpp = "
+		postfix[#postfix+1] = "return handle_ret.c;"
+	elseif func.ret.fulltype ~= "void" then
+		local ctype_conversion = func.ret.type == func.ret.ctype and "" or ("(" ..  func.ret.ctype .. ")")
+		if #postfix > 0 then
+			func.ret_prefix = string.format("%s retValue = %s", func.ret.ctype , ctype_conversion)
+			postfix[#postfix+1] = "return retValue;"
+		else
+			func.ret_prefix = string.format("return %s", ctype_conversion)
+		end
+	end
+end
+
+function codegen.nameconversion(all_types, all_funcs)
+	local enums = {}
+	for k,v in pairs(all_types) do
+		if not v.cname then
+			v.cname = convert_typename(k)
+		end
+		if v.enum then
+			enums[#enums+1] = k
+		end
+	end
+	for _, e in ipairs(enums) do
+		local t = all_types[e]
+		all_types[e] = nil
+		all_types[e .. "::Enum"] = t
+	end
+
+	for _,v in ipairs(all_funcs) do
+		if v.cname == nil then
+			v.cname = convert_funcname(v.name)
+		end
+		if v.class then
+			v.cname = convert_funcname(v.class) .. "_" .. v.cname
+		end
+		for _, arg in ipairs(v.args) do
+			convert_arg(all_types, arg, v.name)
+			gen_arg_conversion(all_types, arg)
+		end
+		if v.vararg then
+			local args = v.args
+			local vararg = {
+				name = "",
+				ctype = "...",
+				aname = "argList",
+				conversion = string.format(
+					"va_list argList;\n\tva_start(argList, %s);",
+					args[#args].name),
+			}
+			args[#args + 1] = vararg
+			v.implname = v.vararg
+		else
+			v.implname = v.name
+		end
+		convert_arg(all_types, v.ret, v.name .. "@rettype")
+		gen_ret_conversion(all_types, v)
+		if v.class then
+			local classname = v.class
+			if v.const then
+				classname = "const " .. classname
+			end
+			local classtype = { fulltype = classname .. "*" }
+			convert_arg(all_types, classtype, "class member " .. v.name)
+			v.this = classtype.ctype .. " _this"
+			v.this_conversion = string.format( "%s This = (%s)_this;", classtype.cpptype, classtype.cpptype)
+		end
+	end
+end
+
+local function lines(tbl)
+	if #tbl == 0 then
+		return "//EMPTYLINE"
+	else
+		return table.concat(tbl, "\n\t")
+	end
+end
+
+local function remove_emptylines(txt)
+	return (txt:gsub("\t//EMPTYLINE\n", ""))
+end
+
+local function codetemp(func)
+	local conversion = {}
+	local args = {}
+	local callargs = {}
+	local cppfunc
+	if func.class then
+		-- It's a member function
+		args[1] = func.this
+		conversion[1] = func.this_conversion
+		cppfunc = "This->" .. func.name
+	else
+		cppfunc = "bgfx::" .. func.implname
+	end
+	for _, arg in ipairs(func.args) do
+		conversion[#conversion+1] = arg.conversion
+		args[#args+1] = arg.ctype .. " " .. arg.name
+		callargs[#callargs+1] = arg.aname
+	end
+	conversion[#conversion+1] = func.ret_conversion
+
+	return {
+		RET = func.ret.ctype,
+		FUNCNAME = func.cname,
+		ARGS = table.concat(args, ", "),
+		CONVERSION = lines(conversion),
+		PRERET = func.ret_prefix or "",
+		CPPFUNC = cppfunc,
+		CALLARGS = table.concat(callargs, ", "),
+		POSTRET = lines(func.ret_postfix),
+		CODE = func.cfunc,
+	}
+end
+
+local function apply_template(func, temp)
+	func.codetemp = func.codetemp or codetemp(func)
+	return (temp:gsub("$(%u+)", func.codetemp))
+end
+
+local c99temp = [[
+BGFX_C_API $RET bgfx_$FUNCNAME($ARGS)
+{
+	$CONVERSION
+	$PRERET$CPPFUNC($CALLARGS);
+	$POSTRET
+}
+]]
+
+local c99usertemp = [[
+BGFX_C_API $RET bgfx_$FUNCNAME($ARGS)
+{
+$CODE
+}
+]]
+
+function codegen.gen_c99(func)
+	if func.cfunc then
+		return apply_template(func, c99usertemp)
+	else
+		return remove_emptylines(apply_template(func, c99temp))
+	end
+end
+
+local template_function_declaration = [[
+/**/
+BGFX_C_API $RET bgfx_$FUNCNAME($ARGS);
+]]
+
+function codegen.gen_c99decl(func)
+	return apply_template(func, template_function_declaration)
+end
+
+function codegen.gen_interface_struct(func)
+	return apply_template(func, "$RET (*$FUNCNAME)($ARGS);")
+end
+
+function codegen.gen_interface_import(func)
+	return "bgfx_" .. func.cname
+end
+
+return codegen

+ 8 - 0
scripts/genie.lua

@@ -48,6 +48,14 @@ newoption {
 	description = "Enable building examples.",
 }
 
+dofile "bgfx-idl.lua"
+
+newaction {
+	trigger = "idl",
+	description = "Generate bgfx interface source code",
+	execute = doidl
+}
+
 solution "bgfx"
 	configurations {
 		"Debug",

+ 105 - 0
scripts/idl.lua

@@ -0,0 +1,105 @@
+-- Copyright 2019 云风 https://github.com/cloudwu . All rights reserved.
+-- License (the same with bgfx) : https://github.com/bkaradzic/bgfx/blob/master/LICENSE
+
+local idl = {}
+
+local all_types = {}
+
+local function typedef(_, typename)
+	assert(all_types[typename] == nil, "Duplicate type")
+	local t = {}
+	all_types[typename] = t
+	local function type_attrib(attrib)
+		assert(type(attrib) == "table", "type attrib should be a table")
+		for _, a in ipairs(attrib) do
+			t[a] = true
+		end
+	end
+	return function(cname)
+		local typ = type(cname)
+		if typ == "table" then
+			type_attrib(cname)
+			return
+		end
+		assert(typ == "string" , "type should be a string")
+		t.cname = cname
+		return type_attrib
+	end
+end
+
+idl.typedef = setmetatable({} , { __index = typedef, __call = typedef })
+idl.types = all_types
+
+local all_funcs = {}
+
+local function duplicate_arg_name(name)
+	error ("Duplicate arg name " .. name)
+end
+
+local function funcdef(_, funcname)
+	local f = { name = funcname , args = {} }
+	all_funcs[#all_funcs+1] = f
+	local args
+	local function args_desc(obj, args_name)
+		obj[args_name] = duplicate_arg_name
+		return function (fulltype)
+			local arg = {
+				name = "_" .. args_name,
+				fulltype = fulltype,
+			}
+			f.args[#f.args+1] = arg
+			local function arg_attrib(_, attrib )
+				assert(type(attrib) == "table", "Arg attributes should be a table")
+				for _, a in ipairs(attrib) do
+					arg[a] = true
+				end
+				return args
+			end
+			return setmetatable( {} , {
+				__index = function(_, name)
+					return args_desc(obj, name)
+				end
+				, __call = arg_attrib } )
+		end
+	end
+	args = setmetatable({}, { __index = args_desc })
+	local function rettype(value)
+		assert(type(value) == "string", "Need return type")
+		f.ret = { fulltype = value }
+		return args
+	end
+
+	local function funcdef(value)
+		if type(value) == "table" then
+			for k,v in pairs(value) do
+				if type(k) == "number" then
+					f[v] = true
+				else
+					f[k] = v
+				end
+			end
+			return rettype
+		end
+		return rettype(value)
+	end
+
+	local function classfunc(_, methodname)
+		f.class = f.name
+		f.name = methodname
+		return funcdef
+	end
+
+	return setmetatable({} , { __index = classfunc, __call = function(_, value) return funcdef(value) end })
+end
+
+idl.func = setmetatable({}, { __index = funcdef })
+idl.funcs = all_funcs
+
+idl.handle = "handle"
+idl.enum = "enum"
+idl.out = "out"
+idl.const = "const"
+
+return setmetatable(idl , { __index = function (_, keyword)
+	error (tostring(keyword) .. " is invalid")
+	end})