mirror of https://github.com/encounter/SDL.git
metal renderer: use vertex attributes instead of indexing into a buffer with the vertex id in the shader. Allows for more flexibility with vertex setup in the future.
Also optimize vertex buffer binding slightly.
This commit is contained in:
parent
55a46abf0a
commit
e8278d0d5b
|
@ -265,8 +265,36 @@ MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
|||
mtlpipedesc.vertexFunction = mtlvertfn;
|
||||
mtlpipedesc.fragmentFunction = mtlfragfn;
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *rtdesc = mtlpipedesc.colorAttachments[0];
|
||||
MTLVertexDescriptor *vertdesc = [MTLVertexDescriptor vertexDescriptor];
|
||||
|
||||
switch (cache->vertexFunction) {
|
||||
case SDL_METAL_VERTEX_SOLID:
|
||||
/* position (float2) */
|
||||
vertdesc.layouts[0].stride = sizeof(float) * 2;
|
||||
vertdesc.layouts[0].stepFunction = MTLStepFunctionPerVertex;
|
||||
|
||||
vertdesc.attributes[0].format = MTLVertexFormatFloat2;
|
||||
vertdesc.attributes[0].offset = 0;
|
||||
vertdesc.attributes[0].bufferIndex = 0;
|
||||
break;
|
||||
case SDL_METAL_VERTEX_COPY:
|
||||
/* position (float2), texcoord (float2) */
|
||||
vertdesc.layouts[0].stride = sizeof(float) * 4;
|
||||
vertdesc.layouts[0].stepFunction = MTLStepFunctionPerVertex;
|
||||
|
||||
vertdesc.attributes[0].format = MTLVertexFormatFloat2;
|
||||
vertdesc.attributes[0].offset = 0;
|
||||
vertdesc.attributes[0].bufferIndex = 0;
|
||||
|
||||
vertdesc.attributes[1].format = MTLVertexFormatFloat2;
|
||||
vertdesc.attributes[1].offset = sizeof(float) * 2;
|
||||
vertdesc.attributes[1].bufferIndex = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
mtlpipedesc.vertexDescriptor = vertdesc;
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *rtdesc = mtlpipedesc.colorAttachments[0];
|
||||
rtdesc.pixelFormat = cache->renderTargetFormat;
|
||||
|
||||
if (blendmode != SDL_BLENDMODE_NONE) {
|
||||
|
@ -412,7 +440,7 @@ ChoosePipelineState(METAL_RenderData *data, METAL_ShaderPipelines *pipelines, SD
|
|||
}
|
||||
|
||||
static void
|
||||
METAL_ActivateRenderCommandEncoder(SDL_Renderer * renderer, MTLLoadAction load, MTLClearColor *clear_color)
|
||||
METAL_ActivateRenderCommandEncoder(SDL_Renderer * renderer, MTLLoadAction load, MTLClearColor *clear_color, id<MTLBuffer> vertex_buffer)
|
||||
{
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
|
||||
|
@ -455,6 +483,13 @@ METAL_ActivateRenderCommandEncoder(SDL_Renderer * renderer, MTLLoadAction load,
|
|||
data.mtlcmdencoder.label = @"SDL metal renderer render target";
|
||||
}
|
||||
|
||||
/* Set up buffer bindings for positions, texcoords, and color once here,
|
||||
* the offsets are adjusted in the code that uses them. */
|
||||
if (vertex_buffer != nil) {
|
||||
[data.mtlcmdencoder setVertexBuffer:vertex_buffer offset:0 atIndex:0];
|
||||
[data.mtlcmdencoder setFragmentBuffer:vertex_buffer offset:0 atIndex:0];
|
||||
}
|
||||
|
||||
data.activepipelines = ChooseShaderPipelines(data, mtltexture.pixelFormat);
|
||||
|
||||
// make sure this has a definite place in the queue. This way it will
|
||||
|
@ -1042,21 +1077,24 @@ METAL_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * t
|
|||
|
||||
cmd->data.draw.count = 1;
|
||||
|
||||
/* Interleaved positions and texture coordinates */
|
||||
*(verts++) = dstrect->x;
|
||||
*(verts++) = dstrect->y + dstrect->h;
|
||||
*(verts++) = dstrect->x;
|
||||
*(verts++) = dstrect->y;
|
||||
*(verts++) = dstrect->x + dstrect->w;
|
||||
*(verts++) = dstrect->y + dstrect->h;
|
||||
*(verts++) = dstrect->x + dstrect->w;
|
||||
*(verts++) = dstrect->y;
|
||||
|
||||
*(verts++) = normtex(srcrect->x, texw);
|
||||
*(verts++) = normtex(srcrect->y + srcrect->h, texh);
|
||||
|
||||
*(verts++) = dstrect->x;
|
||||
*(verts++) = dstrect->y;
|
||||
*(verts++) = normtex(srcrect->x, texw);
|
||||
*(verts++) = normtex(srcrect->y, texh);
|
||||
|
||||
*(verts++) = dstrect->x + dstrect->w;
|
||||
*(verts++) = dstrect->y + dstrect->h;
|
||||
*(verts++) = normtex(srcrect->x + srcrect->w, texw);
|
||||
*(verts++) = normtex(srcrect->y + srcrect->h, texh);
|
||||
|
||||
*(verts++) = dstrect->x + dstrect->w;
|
||||
*(verts++) = dstrect->y;
|
||||
*(verts++) = normtex(srcrect->x + srcrect->w, texw);
|
||||
*(verts++) = normtex(srcrect->y, texh);
|
||||
|
||||
|
@ -1117,23 +1155,24 @@ METAL_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture *
|
|||
minv = tmp;
|
||||
}
|
||||
|
||||
// vertices
|
||||
/* Interleaved positions and texture coordinates */
|
||||
*(verts++) = -center->x;
|
||||
*(verts++) = dstrect->h - center->y;
|
||||
*(verts++) = -center->x;
|
||||
*(verts++) = -center->y;
|
||||
*(verts++) = dstrect->w - center->x;
|
||||
*(verts++) = dstrect->h - center->y;
|
||||
*(verts++) = dstrect->w - center->x;
|
||||
*(verts++) = -center->y;
|
||||
|
||||
// texcoords
|
||||
*(verts++) = minu;
|
||||
*(verts++) = maxv;
|
||||
|
||||
*(verts++) = -center->x;
|
||||
*(verts++) = -center->y;
|
||||
*(verts++) = minu;
|
||||
*(verts++) = minv;
|
||||
|
||||
*(verts++) = dstrect->w - center->x;
|
||||
*(verts++) = dstrect->h - center->y;
|
||||
*(verts++) = maxu;
|
||||
*(verts++) = maxv;
|
||||
|
||||
*(verts++) = dstrect->w - center->x;
|
||||
*(verts++) = -center->y;
|
||||
*(verts++) = maxu;
|
||||
*(verts++) = minv;
|
||||
|
||||
|
@ -1145,8 +1184,10 @@ typedef struct
|
|||
{
|
||||
#if __has_feature(objc_arc)
|
||||
__unsafe_unretained id<MTLRenderPipelineState> pipeline;
|
||||
__unsafe_unretained id<MTLBuffer> vertex_buffer;
|
||||
#else
|
||||
id<MTLRenderPipelineState> pipeline;
|
||||
id<MTLBuffer> vertex_buffer;
|
||||
#endif
|
||||
size_t constants_offset;
|
||||
SDL_Texture *texture;
|
||||
|
@ -1169,7 +1210,7 @@ SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Met
|
|||
size_t first = cmd->data.draw.first;
|
||||
id<MTLRenderPipelineState> newpipeline;
|
||||
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL);
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, statecache->vertex_buffer);
|
||||
|
||||
if (statecache->viewport_dirty) {
|
||||
MTLViewport viewport;
|
||||
|
@ -1205,7 +1246,7 @@ SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Met
|
|||
}
|
||||
|
||||
if (statecache->color_dirty) {
|
||||
[data.mtlcmdencoder setFragmentBuffer:mtlbufvertex offset:statecache->color_offset atIndex:0];
|
||||
[data.mtlcmdencoder setFragmentBufferOffset:statecache->color_offset atIndex:0];
|
||||
statecache->color_dirty = SDL_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1222,7 +1263,7 @@ SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Met
|
|||
statecache->constants_offset = constants_offset;
|
||||
}
|
||||
|
||||
[data.mtlcmdencoder setVertexBuffer:mtlbufvertex offset:first atIndex:0]; // position
|
||||
[data.mtlcmdencoder setVertexBufferOffset:first atIndex:0]; /* position/texcoords */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1235,8 +1276,6 @@ SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const size_t
|
|||
|
||||
SetDrawState(renderer, cmd, texturedata.fragmentFunction, constants_offset, mtlbufvertex, statecache);
|
||||
|
||||
[data.mtlcmdencoder setVertexBuffer:mtlbufvertex offset:cmd->data.draw.first+(8*sizeof (float)) atIndex:1]; // texcoords
|
||||
|
||||
if (texture != statecache->texture) {
|
||||
METAL_TextureData *oldtexturedata = NULL;
|
||||
if (statecache->texture) {
|
||||
|
@ -1263,6 +1302,7 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|||
id<MTLBuffer> mtlbufvertex = nil;
|
||||
|
||||
statecache.pipeline = nil;
|
||||
statecache.vertex_buffer = nil;
|
||||
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
|
||||
statecache.texture = NULL;
|
||||
statecache.color_dirty = SDL_TRUE;
|
||||
|
@ -1286,6 +1326,8 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|||
#endif
|
||||
mtlbufvertex.label = @"SDL vertex data";
|
||||
SDL_memcpy([mtlbufvertex contents], vertices, vertsize);
|
||||
|
||||
statecache.vertex_buffer = mtlbufvertex;
|
||||
}
|
||||
|
||||
// If there's a command buffer here unexpectedly (app requested one?). Commit it so we can start fresh.
|
||||
|
@ -1344,7 +1386,7 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
|||
MTLClearColor color = MTLClearColorMake(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||
|
||||
// get new command encoder, set up with an initial clear operation.
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color);
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1403,7 +1445,7 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
|||
Uint32 pixel_format, void * pixels, int pitch)
|
||||
{ @autoreleasepool {
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL);
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
|
||||
|
||||
[data.mtlcmdencoder endEncoding];
|
||||
id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
|
||||
|
@ -1498,7 +1540,7 @@ METAL_GetMetalLayer(SDL_Renderer * renderer)
|
|||
static void *
|
||||
METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
|
||||
{ @autoreleasepool {
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL);
|
||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
|
||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||
return (__bridge void*)data.mtlcmdencoder;
|
||||
}}
|
||||
|
|
|
@ -3,19 +3,23 @@
|
|||
|
||||
using namespace metal;
|
||||
|
||||
struct SolidVertexInput
|
||||
{
|
||||
float2 position [[attribute(0)]];
|
||||
};
|
||||
|
||||
struct SolidVertexOutput
|
||||
{
|
||||
float4 position [[position]];
|
||||
float pointSize [[point_size]];
|
||||
};
|
||||
|
||||
vertex SolidVertexOutput SDL_Solid_vertex(const device float2 *position [[buffer(0)]],
|
||||
vertex SolidVertexOutput SDL_Solid_vertex(SolidVertexInput in [[stage_in]],
|
||||
constant float4x4 &projection [[buffer(2)]],
|
||||
constant float4x4 &transform [[buffer(3)]],
|
||||
uint vid [[vertex_id]])
|
||||
constant float4x4 &transform [[buffer(3)]])
|
||||
{
|
||||
SolidVertexOutput v;
|
||||
v.position = (projection * transform) * float4(position[vid], 0.0f, 1.0f);
|
||||
v.position = (projection * transform) * float4(in.position, 0.0f, 1.0f);
|
||||
v.pointSize = 1.0f;
|
||||
return v;
|
||||
}
|
||||
|
@ -25,21 +29,25 @@ fragment float4 SDL_Solid_fragment(const device float4 &col [[buffer(0)]])
|
|||
return col;
|
||||
}
|
||||
|
||||
struct CopyVertexInput
|
||||
{
|
||||
float2 position [[attribute(0)]];
|
||||
float2 texcoord [[attribute(1)]];
|
||||
};
|
||||
|
||||
struct CopyVertexOutput
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 texcoord;
|
||||
};
|
||||
|
||||
vertex CopyVertexOutput SDL_Copy_vertex(const device float2 *position [[buffer(0)]],
|
||||
const device float2 *texcoords [[buffer(1)]],
|
||||
vertex CopyVertexOutput SDL_Copy_vertex(CopyVertexInput in [[stage_in]],
|
||||
constant float4x4 &projection [[buffer(2)]],
|
||||
constant float4x4 &transform [[buffer(3)]],
|
||||
uint vid [[vertex_id]])
|
||||
constant float4x4 &transform [[buffer(3)]])
|
||||
{
|
||||
CopyVertexOutput v;
|
||||
v.position = (projection * transform) * float4(position[vid], 0.0f, 1.0f);
|
||||
v.texcoord = texcoords[vid];
|
||||
v.position = (projection * transform) * float4(in.position, 0.0f, 1.0f);
|
||||
v.texcoord = in.texcoord;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue