mirror of
https://github.com/love2d/love.git
synced 2026-08-14 10:13:46 +02:00
Add functions for indirect draws and compute dispatches.
Resolves #1879. - Add an 'indirectdraw' boolean field to the graphics feature support table returned by love.graphics.getSupported. This is almost always supported when compute shaders are supported, except on a few older phones. - Add an 'indirectarguments' boolean field to the settings table in love.graphics.newBuffer. - Add love.graphics.dispatchIndirect(shader, argumentsbuffer [, argumentsindex = 1]). The compute dispatch's threadgroup width, height, and depth values are fetched from the buffer (as 3 uints) instead of coming from function parameters. - Add love.graphics.drawIndirect(mesh, argumentsbuffer, argumentsindex, x, y, ....). Vertex or index count, instance count, and other related parameters for drawing the mesh are fetched from the buffer (as 4 or 5 uints depending on whether the mesh has an index buffer) instead of coming from function parameters. It's usually a good idea to keep parameters other than the instance count in sync with what the mesh should be using. - Add love.graphics.drawFromShaderIndirect(drawmode, argumentsbuffer [, argumentsindex = 1] [, maintexture = nil]) and drawFromShaderIndirect(indexbuffer, argumentsbuffer [, argumentsindex] [, maintexture = nil]). Vertex or index count, instance count, and other related parameters are fetched from the buffer as 4 or 5 uints, as above. For the dispatch indirect arguments buffer, it has to have 3 uint32 elements: { uint threadgroupsX, uint threadgroupsY, uint threadgroupsZ }. For non-indexed draws, the arguments buffer has to have 4 uint32 elements: { uint vertexCount, uint instanceCount, uint baseVertex, uint baseInstance }. Note that baseInstance should always be set to 0 as many drivers don't support non-zero values. For draws which use an index buffer, the arguments buffer has to have 5 uint32 elements: { uint indexCount, uint instanceCount, uint firstIndex, uint baseVertex, uint baseInstance }. As above, the baseInstance value should always be 0. A buffer can be created to have an array of those structures, which can be used with the argumentsindex parameter of the Indirect dispatch/draw functions.
This commit is contained in:
@@ -3099,6 +3099,20 @@ int w_drawInstanced(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_drawIndirect(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
Buffer *argsbuffer = luax_checkbuffer(L, 2);
|
||||
int argsindex = (int) luaL_checkinteger(L, 3) - 1;
|
||||
|
||||
luax_checkstandardtransform(L, 4, [&](const Matrix4 &m)
|
||||
{
|
||||
luax_catchexcept(L, [&]() { instance()->drawIndirect(t, m, argsbuffer, argsindex); });
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_drawFromShader(lua_State *L)
|
||||
{
|
||||
if (luax_istype(L, 1, Buffer::type))
|
||||
@@ -3135,6 +3149,40 @@ int w_drawFromShader(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_drawFromShaderIndirect(lua_State *L)
|
||||
{
|
||||
if (luax_istype(L, 1, Buffer::type))
|
||||
{
|
||||
// Indexed drawing.
|
||||
Buffer *t = luax_checkbuffer(L, 1);
|
||||
Buffer *argsbuffer = luax_checkbuffer(L, 2);
|
||||
int argsindex = (int) luaL_optinteger(L, 3, 1) - 1;
|
||||
|
||||
Texture *tex = nullptr;
|
||||
if (!lua_isnoneornil(L, 4))
|
||||
tex = luax_checktexture(L, 4);
|
||||
|
||||
luax_catchexcept(L, [&]() { instance()->drawFromShaderIndirect(t, argsbuffer, argsindex, tex); });
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *primstr = luaL_checkstring(L, 1);
|
||||
PrimitiveType primtype = PRIMITIVE_TRIANGLES;
|
||||
if (!getConstant(primstr, primtype))
|
||||
return luax_enumerror(L, "primitive type", getConstants(primtype), primstr);
|
||||
|
||||
Buffer *argsbuffer = luax_checkbuffer(L, 2);
|
||||
int argsindex = (int) luaL_optinteger(L, 3, 1) - 1;
|
||||
|
||||
Texture *tex = nullptr;
|
||||
if (!lua_isnoneornil(L, 4))
|
||||
tex = luax_checktexture(L, 4);
|
||||
|
||||
luax_catchexcept(L, [&]() { instance()->drawFromShaderIndirect(primtype, argsbuffer, argsindex, tex); });
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_print(lua_State *L)
|
||||
{
|
||||
std::vector<love::font::ColoredString> str;
|
||||
@@ -3529,6 +3577,15 @@ int w_dispatchThreadgroups(lua_State* L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_dispatchIndirect(lua_State *L)
|
||||
{
|
||||
Shader *shader = luax_checkshader(L, 1);
|
||||
Buffer *argsbuffer = luax_checkbuffer(L, 2);
|
||||
int argsindex = (int) luaL_optinteger(L, 3, 1) - 1;
|
||||
luax_catchexcept(L, [&]() { instance()->dispatchIndirect(shader, argsbuffer, argsindex); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_copyBuffer(lua_State *L)
|
||||
{
|
||||
Buffer *source = luax_checkbuffer(L, 1);
|
||||
@@ -3844,12 +3901,15 @@ static const luaL_Reg functions[] =
|
||||
{ "draw", w_draw },
|
||||
{ "drawLayer", w_drawLayer },
|
||||
{ "drawInstanced", w_drawInstanced },
|
||||
{ "drawIndirect", w_drawIndirect },
|
||||
{ "drawFromShader", w_drawFromShader },
|
||||
{ "drawFromShaderIndirect", w_drawFromShaderIndirect },
|
||||
|
||||
{ "print", w_print },
|
||||
{ "printf", w_printf },
|
||||
|
||||
{ "dispatchThreadgroups", w_dispatchThreadgroups },
|
||||
{ "dispatchIndirect", w_dispatchIndirect },
|
||||
|
||||
{ "copyBuffer", w_copyBuffer },
|
||||
{ "copyBufferToTexture", w_copyBufferToTexture },
|
||||
|
||||
Reference in New Issue
Block a user