mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-12-28 00:54:35 +00:00
Implemented render batching for D3D11, D3D12, Metal, and Vulkan
Fixes https://github.com/libsdl-org/SDL/issues/7534
This commit is contained in:
@@ -2623,26 +2623,58 @@ static bool D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
{
|
||||
const size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(D3D11_VertexPositionColor);
|
||||
D3D11_SetDrawState(renderer, cmd, NULL, 0, NULL, 0, NULL, NULL);
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start, count);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_LINES:
|
||||
{
|
||||
const size_t count = cmd->data.draw.count;
|
||||
size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(D3D11_VertexPositionColor);
|
||||
const D3D11_VertexPositionColor *verts = (D3D11_VertexPositionColor *)(((Uint8 *)vertices) + first);
|
||||
|
||||
D3D11_SetDrawState(renderer, cmd, NULL, 0, NULL, 0, NULL, NULL);
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count);
|
||||
if (verts[0].pos.x != verts[count - 1].pos.x || verts[0].pos.y != verts[count - 1].pos.y) {
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start + (count - 1), 1);
|
||||
|
||||
// Add the final point in the line
|
||||
size_t line_start = 0;
|
||||
size_t line_end = line_start + count - 1;
|
||||
if (verts[line_start].pos.x != verts[line_end].pos.x || verts[line_start].pos.y != verts[line_end].pos.y) {
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start + line_end, 1);
|
||||
}
|
||||
|
||||
if (count > 2) {
|
||||
// joined lines cannot be grouped
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count);
|
||||
} else {
|
||||
// let's group non joined lines
|
||||
SDL_RenderCommand *finalcmd = cmd;
|
||||
SDL_RenderCommand *nextcmd;
|
||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||
|
||||
for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
|
||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||
if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
|
||||
if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
|
||||
// The vertex data has the draw color built in, ignore this
|
||||
continue;
|
||||
}
|
||||
break; // can't go any further on this draw call, different render command up next.
|
||||
} else if (nextcmd->data.draw.count != 2) {
|
||||
break; // can't go any further on this draw call, those are joined lines
|
||||
} else if (nextcmd->data.draw.blend != thisblend) {
|
||||
break; // can't go any further on this draw call, different blendmode copy up next.
|
||||
} else {
|
||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||
|
||||
// Add the final point in the line
|
||||
line_start = count;
|
||||
line_end = line_start + nextcmd->data.draw.count - 1;
|
||||
if (verts[line_start].pos.x != verts[line_end].pos.x || verts[line_start].pos.y != verts[line_end].pos.y) {
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start + line_end, 1);
|
||||
}
|
||||
count += nextcmd->data.draw.count;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_LINELIST, start, count);
|
||||
cmd = finalcmd; // skip any copy commands we just combined in here.
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2656,20 +2688,54 @@ static bool D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
||||
case SDL_RENDERCMD_COPY_EX: // unused
|
||||
break;
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
case SDL_RENDERCMD_GEOMETRY:
|
||||
{
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
const size_t count = cmd->data.draw.count;
|
||||
/* as long as we have the same copy command in a row, with the
|
||||
same texture, we can combine them all into a single draw call. */
|
||||
SDL_Texture *thistexture = cmd->data.draw.texture;
|
||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
|
||||
SDL_TextureAddressMode thisaddressmode_u = cmd->data.draw.texture_address_mode_u;
|
||||
SDL_TextureAddressMode thisaddressmode_v = cmd->data.draw.texture_address_mode_v;
|
||||
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
||||
SDL_RenderCommand *finalcmd = cmd;
|
||||
SDL_RenderCommand *nextcmd;
|
||||
size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(D3D11_VertexPositionColor);
|
||||
for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
|
||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||
if (nextcmdtype != thiscmdtype) {
|
||||
if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
|
||||
// The vertex data has the draw color built in, ignore this
|
||||
continue;
|
||||
}
|
||||
break; // can't go any further on this draw call, different render command up next.
|
||||
} else if (nextcmd->data.draw.texture != thistexture ||
|
||||
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
|
||||
nextcmd->data.draw.texture_address_mode_u != thisaddressmode_u ||
|
||||
nextcmd->data.draw.texture_address_mode_v != thisaddressmode_v ||
|
||||
nextcmd->data.draw.blend != thisblend) {
|
||||
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
||||
} else {
|
||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||
count += nextcmd->data.draw.count;
|
||||
}
|
||||
}
|
||||
|
||||
if (texture) {
|
||||
if (thistexture) {
|
||||
D3D11_SetCopyState(renderer, cmd, NULL);
|
||||
} else {
|
||||
D3D11_SetDrawState(renderer, cmd, NULL, 0, NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, start, count);
|
||||
if (thiscmdtype == SDL_RENDERCMD_GEOMETRY) {
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, start, count);
|
||||
} else {
|
||||
D3D11_DrawPrimitives(renderer, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, start, count);
|
||||
}
|
||||
cmd = finalcmd; // skip any copy commands we just combined in here.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -3084,26 +3084,65 @@ static bool D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
{
|
||||
const size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(D3D12_VertexPositionColor);
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT, 0, NULL, 0, NULL);
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_POINTLIST, start, count);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_LINES:
|
||||
{
|
||||
const size_t count = cmd->data.draw.count;
|
||||
size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(D3D12_VertexPositionColor);
|
||||
const D3D12_VertexPositionColor *verts = (D3D12_VertexPositionColor *)(((Uint8 *)vertices) + first);
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE, 0, NULL, 0, NULL);
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count);
|
||||
if (verts[0].pos.x != verts[count - 1].pos.x || verts[0].pos.y != verts[count - 1].pos.y) {
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_POINTLIST, start + (count - 1), 1);
|
||||
bool have_point_draw_state = false;
|
||||
|
||||
// Add the final point in the line
|
||||
size_t line_start = 0;
|
||||
size_t line_end = line_start + count - 1;
|
||||
if (verts[line_start].pos.x != verts[line_end].pos.x || verts[line_start].pos.y != verts[line_end].pos.y) {
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT, 0, NULL, 0, NULL);
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_POINTLIST, start + line_end, 1);
|
||||
have_point_draw_state = true;
|
||||
}
|
||||
|
||||
if (count > 2) {
|
||||
// joined lines cannot be grouped
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE, 0, NULL, 0, NULL);
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, start, count);
|
||||
} else {
|
||||
// let's group non joined lines
|
||||
SDL_RenderCommand *finalcmd = cmd;
|
||||
SDL_RenderCommand *nextcmd;
|
||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||
|
||||
for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
|
||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||
if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
|
||||
if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
|
||||
// The vertex data has the draw color built in, ignore this
|
||||
continue;
|
||||
}
|
||||
break; // can't go any further on this draw call, different render command up next.
|
||||
} else if (nextcmd->data.draw.count != 2) {
|
||||
break; // can't go any further on this draw call, those are joined lines
|
||||
} else if (nextcmd->data.draw.blend != thisblend) {
|
||||
break; // can't go any further on this draw call, different blendmode copy up next.
|
||||
} else {
|
||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||
|
||||
// Add the final point in the line
|
||||
line_start = count;
|
||||
line_end = line_start + nextcmd->data.draw.count - 1;
|
||||
if (verts[line_start].pos.x != verts[line_end].pos.x || verts[line_start].pos.y != verts[line_end].pos.y) {
|
||||
if (!have_point_draw_state) {
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT, 0, NULL, 0, NULL);
|
||||
have_point_draw_state = true;
|
||||
}
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_POINTLIST, start + line_end, 1);
|
||||
}
|
||||
count += nextcmd->data.draw.count;
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE, 0, NULL, 0, NULL);
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_LINELIST, start, count);
|
||||
cmd = finalcmd; // skip any copy commands we just combined in here.
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3117,20 +3156,54 @@ static bool D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
||||
case SDL_RENDERCMD_COPY_EX: // unused
|
||||
break;
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
case SDL_RENDERCMD_GEOMETRY:
|
||||
{
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
const size_t count = cmd->data.draw.count;
|
||||
/* as long as we have the same copy command in a row, with the
|
||||
same texture, we can combine them all into a single draw call. */
|
||||
SDL_Texture *thistexture = cmd->data.draw.texture;
|
||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
|
||||
SDL_TextureAddressMode thisaddressmode_u = cmd->data.draw.texture_address_mode_u;
|
||||
SDL_TextureAddressMode thisaddressmode_v = cmd->data.draw.texture_address_mode_v;
|
||||
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
||||
SDL_RenderCommand *finalcmd = cmd;
|
||||
SDL_RenderCommand *nextcmd;
|
||||
size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(D3D12_VertexPositionColor);
|
||||
|
||||
if (texture) {
|
||||
D3D12_SetCopyState(renderer, cmd);
|
||||
} else {
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, 0, NULL, 0, NULL);
|
||||
for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
|
||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||
if (nextcmdtype != thiscmdtype) {
|
||||
if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
|
||||
// The vertex data has the draw color built in, ignore this
|
||||
continue;
|
||||
}
|
||||
break; // can't go any further on this draw call, different render command up next.
|
||||
} else if (nextcmd->data.draw.texture != thistexture ||
|
||||
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
|
||||
nextcmd->data.draw.texture_address_mode_u != thisaddressmode_u ||
|
||||
nextcmd->data.draw.texture_address_mode_v != thisaddressmode_v ||
|
||||
nextcmd->data.draw.blend != thisblend) {
|
||||
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
||||
} else {
|
||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||
count += nextcmd->data.draw.count;
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, start, count);
|
||||
if (thiscmdtype == SDL_RENDERCMD_GEOMETRY) {
|
||||
if (thistexture) {
|
||||
D3D12_SetCopyState(renderer, cmd);
|
||||
} else {
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, 0, NULL, 0, NULL);
|
||||
}
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, start, count);
|
||||
} else {
|
||||
D3D12_SetDrawState(renderer, cmd, NULL, D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT, 0, NULL, 0, NULL);
|
||||
D3D12_DrawPrimitives(renderer, D3D_PRIMITIVE_TOPOLOGY_POINTLIST, start, count);
|
||||
}
|
||||
cmd = finalcmd; // skip any copy commands we just combined in here.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1250,7 +1250,7 @@ static bool METAL_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
|
||||
angles. Maybe !!! FIXME for later, though. */
|
||||
|
||||
points -= 2; // update the last line.
|
||||
verts -= 2 + 1;
|
||||
verts -= 6;
|
||||
|
||||
{
|
||||
const float xstart = points[0].x;
|
||||
@@ -1784,13 +1784,40 @@ static bool METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
case SDL_RENDERCMD_DRAW_LINES:
|
||||
{
|
||||
const size_t count = cmd->data.draw.count;
|
||||
const MTLPrimitiveType primtype = (cmd->command == SDL_RENDERCMD_DRAW_POINTS) ? MTLPrimitiveTypePoint : MTLPrimitiveTypeLineStrip;
|
||||
if (SetDrawState(renderer, cmd, SDL_METAL_FRAGMENT_SOLID, NULL, CONSTANTS_OFFSET_HALF_PIXEL_TRANSFORM, mtlbufvertex, &statecache)) {
|
||||
[data.mtlcmdencoder drawPrimitives:primtype vertexStart:0 vertexCount:count];
|
||||
size_t count = cmd->data.draw.count;
|
||||
if (count > 2) {
|
||||
// joined lines cannot be grouped
|
||||
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:0 vertexCount:count];
|
||||
} else {
|
||||
// let's group non joined lines
|
||||
SDL_RenderCommand *finalcmd = cmd;
|
||||
SDL_RenderCommand *nextcmd;
|
||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||
|
||||
for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
|
||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||
if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
|
||||
if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
|
||||
// The vertex data has the draw color built in, ignore this
|
||||
continue;
|
||||
}
|
||||
break; // can't go any further on this draw call, different render command up next.
|
||||
} else if (nextcmd->data.draw.count != 2) {
|
||||
break; // can't go any further on this draw call, those are joined lines
|
||||
} else if (nextcmd->data.draw.blend != thisblend) {
|
||||
break; // can't go any further on this draw call, different blendmode copy up next.
|
||||
} else {
|
||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||
count += nextcmd->data.draw.count;
|
||||
}
|
||||
}
|
||||
|
||||
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:count];
|
||||
cmd = finalcmd; // skip any copy commands we just combined in here.
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1804,20 +1831,54 @@ static bool METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd
|
||||
case SDL_RENDERCMD_COPY_EX: // unused
|
||||
break;
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
case SDL_RENDERCMD_GEOMETRY:
|
||||
{
|
||||
const size_t count = cmd->data.draw.count;
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
|
||||
if (texture) {
|
||||
if (SetCopyState(renderer, cmd, CONSTANTS_OFFSET_IDENTITY, mtlbufvertex, &statecache)) {
|
||||
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:count];
|
||||
}
|
||||
} else {
|
||||
if (SetDrawState(renderer, cmd, SDL_METAL_FRAGMENT_SOLID, NULL, CONSTANTS_OFFSET_IDENTITY, mtlbufvertex, &statecache)) {
|
||||
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:count];
|
||||
SDL_Texture *thistexture = cmd->data.draw.texture;
|
||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
|
||||
SDL_TextureAddressMode thisaddressmode_u = cmd->data.draw.texture_address_mode_u;
|
||||
SDL_TextureAddressMode thisaddressmode_v = cmd->data.draw.texture_address_mode_v;
|
||||
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
||||
SDL_RenderCommand *finalcmd = cmd;
|
||||
SDL_RenderCommand *nextcmd;
|
||||
size_t count = cmd->data.draw.count;
|
||||
for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
|
||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||
if (nextcmdtype != thiscmdtype) {
|
||||
if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
|
||||
// The vertex data has the draw color built in, ignore this
|
||||
continue;
|
||||
}
|
||||
break; // can't go any further on this draw call, different render command up next.
|
||||
} else if (nextcmd->data.draw.texture != thistexture ||
|
||||
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
|
||||
nextcmd->data.draw.texture_address_mode_u != thisaddressmode_u ||
|
||||
nextcmd->data.draw.texture_address_mode_v != thisaddressmode_v ||
|
||||
nextcmd->data.draw.blend != thisblend) {
|
||||
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
||||
} else {
|
||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||
count += nextcmd->data.draw.count;
|
||||
}
|
||||
}
|
||||
|
||||
if (thiscmdtype == SDL_RENDERCMD_GEOMETRY) {
|
||||
if (thistexture) {
|
||||
if (SetCopyState(renderer, cmd, CONSTANTS_OFFSET_IDENTITY, mtlbufvertex, &statecache)) {
|
||||
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:count];
|
||||
}
|
||||
} else {
|
||||
if (SetDrawState(renderer, cmd, SDL_METAL_FRAGMENT_SOLID, NULL, CONSTANTS_OFFSET_IDENTITY, mtlbufvertex, &statecache)) {
|
||||
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:count];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (SetDrawState(renderer, cmd, SDL_METAL_FRAGMENT_SOLID, NULL, CONSTANTS_OFFSET_HALF_PIXEL_TRANSFORM, mtlbufvertex, &statecache)) {
|
||||
[data.mtlcmdencoder drawPrimitives:MTLPrimitiveTypePoint vertexStart:0 vertexCount:count];
|
||||
}
|
||||
}
|
||||
cmd = finalcmd; // skip any copy commands we just combined in here.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -4068,27 +4068,66 @@ static bool VULKAN_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cm
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
{
|
||||
const size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(VULKAN_VertexPositionColor);
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, start, count);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_LINES:
|
||||
{
|
||||
const size_t count = cmd->data.draw.count;
|
||||
size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(VULKAN_VertexPositionColor);
|
||||
const VULKAN_VertexPositionColor *verts = (VULKAN_VertexPositionColor *)(((Uint8 *)vertices) + first);
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, start, count);
|
||||
if (verts[0].pos[0] != verts[count - 1].pos[0] || verts[0].pos[1] != verts[count - 1].pos[1]) {
|
||||
bool have_point_draw_state = false;
|
||||
|
||||
// Add the final point in the line
|
||||
size_t line_start = 0;
|
||||
size_t line_end = line_start + count - 1;
|
||||
if (verts[line_start].pos[0] != verts[line_end].pos[0] || verts[line_start].pos[1] != verts[line_end].pos[1]) {
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, start + (count - 1), 1);
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, start + line_end, 1);
|
||||
have_point_draw_state = true;
|
||||
}
|
||||
|
||||
if (count > 2) {
|
||||
// joined lines cannot be grouped
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, start, count);
|
||||
} else {
|
||||
// let's group non joined lines
|
||||
SDL_RenderCommand *finalcmd = cmd;
|
||||
SDL_RenderCommand *nextcmd;
|
||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||
|
||||
for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
|
||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||
if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
|
||||
if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
|
||||
// The vertex data has the draw color built in, ignore this
|
||||
continue;
|
||||
}
|
||||
break; // can't go any further on this draw call, different render command up next.
|
||||
} else if (nextcmd->data.draw.count != 2) {
|
||||
break; // can't go any further on this draw call, those are joined lines
|
||||
} else if (nextcmd->data.draw.blend != thisblend) {
|
||||
break; // can't go any further on this draw call, different blendmode copy up next.
|
||||
} else {
|
||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||
|
||||
// Add the final point in the line
|
||||
line_start = count;
|
||||
line_end = line_start + nextcmd->data.draw.count - 1;
|
||||
if (verts[line_start].pos[0] != verts[line_end].pos[0] || verts[line_start].pos[1] != verts[line_end].pos[1]) {
|
||||
if (!have_point_draw_state) {
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
have_point_draw_state = true;
|
||||
}
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, start + line_end, 1);
|
||||
}
|
||||
count += nextcmd->data.draw.count;
|
||||
}
|
||||
}
|
||||
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, start, count);
|
||||
|
||||
cmd = finalcmd; // skip any copy commands we just combined in here.
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4102,20 +4141,55 @@ static bool VULKAN_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cm
|
||||
case SDL_RENDERCMD_COPY_EX: // unused
|
||||
break;
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
case SDL_RENDERCMD_GEOMETRY:
|
||||
{
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
const size_t count = cmd->data.draw.count;
|
||||
/* as long as we have the same copy command in a row, with the
|
||||
same texture, we can combine them all into a single draw call. */
|
||||
SDL_Texture *thistexture = cmd->data.draw.texture;
|
||||
SDL_BlendMode thisblend = cmd->data.draw.blend;
|
||||
SDL_ScaleMode thisscalemode = cmd->data.draw.texture_scale_mode;
|
||||
SDL_TextureAddressMode thisaddressmode_u = cmd->data.draw.texture_address_mode_u;
|
||||
SDL_TextureAddressMode thisaddressmode_v = cmd->data.draw.texture_address_mode_v;
|
||||
const SDL_RenderCommandType thiscmdtype = cmd->command;
|
||||
SDL_RenderCommand *finalcmd = cmd;
|
||||
SDL_RenderCommand *nextcmd;
|
||||
size_t count = cmd->data.draw.count;
|
||||
const size_t first = cmd->data.draw.first;
|
||||
const size_t start = first / sizeof(VULKAN_VertexPositionColor);
|
||||
|
||||
if (texture) {
|
||||
VULKAN_SetCopyState(renderer, cmd, NULL, &stateCache);
|
||||
} else {
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
for (nextcmd = cmd->next; nextcmd; nextcmd = nextcmd->next) {
|
||||
const SDL_RenderCommandType nextcmdtype = nextcmd->command;
|
||||
if (nextcmdtype != thiscmdtype) {
|
||||
if (nextcmdtype == SDL_RENDERCMD_SETDRAWCOLOR) {
|
||||
// The vertex data has the draw color built in, ignore this
|
||||
continue;
|
||||
}
|
||||
break; // can't go any further on this draw call, different render command up next.
|
||||
} else if (nextcmd->data.draw.texture != thistexture ||
|
||||
nextcmd->data.draw.texture_scale_mode != thisscalemode ||
|
||||
nextcmd->data.draw.texture_address_mode_u != thisaddressmode_u ||
|
||||
nextcmd->data.draw.texture_address_mode_v != thisaddressmode_v ||
|
||||
nextcmd->data.draw.blend != thisblend) {
|
||||
break; // can't go any further on this draw call, different texture/blendmode copy up next.
|
||||
} else {
|
||||
finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
|
||||
count += nextcmd->data.draw.count;
|
||||
}
|
||||
}
|
||||
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, start, count);
|
||||
if (thiscmdtype == SDL_RENDERCMD_GEOMETRY) {
|
||||
if (thistexture) {
|
||||
VULKAN_SetCopyState(renderer, cmd, NULL, &stateCache);
|
||||
} else {
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
}
|
||||
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, start, count);
|
||||
} else {
|
||||
VULKAN_SetDrawState(renderer, cmd, rendererData->pipelineLayout, rendererData->descriptorSetLayout, NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, NULL, 0, NULL, NULL, &stateCache);
|
||||
VULKAN_DrawPrimitives(renderer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, start, count);
|
||||
}
|
||||
cmd = finalcmd; // skip any copy commands we just combined in here.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user