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.
parent
55a46abf0a
commit
e8278d0d5b
|
@ -265,8 +265,36 @@ MakePipelineState(METAL_RenderData *data, METAL_PipelineCache *cache,
|
||||||
mtlpipedesc.vertexFunction = mtlvertfn;
|
mtlpipedesc.vertexFunction = mtlvertfn;
|
||||||
mtlpipedesc.fragmentFunction = mtlfragfn;
|
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;
|
rtdesc.pixelFormat = cache->renderTargetFormat;
|
||||||
|
|
||||||
if (blendmode != SDL_BLENDMODE_NONE) {
|
if (blendmode != SDL_BLENDMODE_NONE) {
|
||||||
|
@ -412,7 +440,7 @@ ChoosePipelineState(METAL_RenderData *data, METAL_ShaderPipelines *pipelines, SD
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
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";
|
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);
|
data.activepipelines = ChooseShaderPipelines(data, mtltexture.pixelFormat);
|
||||||
|
|
||||||
// make sure this has a definite place in the queue. This way it will
|
// 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;
|
cmd->data.draw.count = 1;
|
||||||
|
|
||||||
|
/* Interleaved positions and texture coordinates */
|
||||||
*(verts++) = dstrect->x;
|
*(verts++) = dstrect->x;
|
||||||
*(verts++) = dstrect->y + dstrect->h;
|
*(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->x, texw);
|
||||||
*(verts++) = normtex(srcrect->y + srcrect->h, texh);
|
*(verts++) = normtex(srcrect->y + srcrect->h, texh);
|
||||||
|
|
||||||
|
*(verts++) = dstrect->x;
|
||||||
|
*(verts++) = dstrect->y;
|
||||||
*(verts++) = normtex(srcrect->x, texw);
|
*(verts++) = normtex(srcrect->x, texw);
|
||||||
*(verts++) = normtex(srcrect->y, texh);
|
*(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->x + srcrect->w, texw);
|
||||||
*(verts++) = normtex(srcrect->y + srcrect->h, texh);
|
*(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->x + srcrect->w, texw);
|
||||||
*(verts++) = normtex(srcrect->y, texh);
|
*(verts++) = normtex(srcrect->y, texh);
|
||||||
|
|
||||||
|
@ -1117,23 +1155,24 @@ METAL_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture *
|
||||||
minv = tmp;
|
minv = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vertices
|
/* Interleaved positions and texture coordinates */
|
||||||
*(verts++) = -center->x;
|
*(verts++) = -center->x;
|
||||||
*(verts++) = dstrect->h - center->y;
|
*(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++) = minu;
|
||||||
*(verts++) = maxv;
|
*(verts++) = maxv;
|
||||||
|
|
||||||
|
*(verts++) = -center->x;
|
||||||
|
*(verts++) = -center->y;
|
||||||
*(verts++) = minu;
|
*(verts++) = minu;
|
||||||
*(verts++) = minv;
|
*(verts++) = minv;
|
||||||
|
|
||||||
|
*(verts++) = dstrect->w - center->x;
|
||||||
|
*(verts++) = dstrect->h - center->y;
|
||||||
*(verts++) = maxu;
|
*(verts++) = maxu;
|
||||||
*(verts++) = maxv;
|
*(verts++) = maxv;
|
||||||
|
|
||||||
|
*(verts++) = dstrect->w - center->x;
|
||||||
|
*(verts++) = -center->y;
|
||||||
*(verts++) = maxu;
|
*(verts++) = maxu;
|
||||||
*(verts++) = minv;
|
*(verts++) = minv;
|
||||||
|
|
||||||
|
@ -1145,8 +1184,10 @@ typedef struct
|
||||||
{
|
{
|
||||||
#if __has_feature(objc_arc)
|
#if __has_feature(objc_arc)
|
||||||
__unsafe_unretained id<MTLRenderPipelineState> pipeline;
|
__unsafe_unretained id<MTLRenderPipelineState> pipeline;
|
||||||
|
__unsafe_unretained id<MTLBuffer> vertex_buffer;
|
||||||
#else
|
#else
|
||||||
id<MTLRenderPipelineState> pipeline;
|
id<MTLRenderPipelineState> pipeline;
|
||||||
|
id<MTLBuffer> vertex_buffer;
|
||||||
#endif
|
#endif
|
||||||
size_t constants_offset;
|
size_t constants_offset;
|
||||||
SDL_Texture *texture;
|
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;
|
size_t first = cmd->data.draw.first;
|
||||||
id<MTLRenderPipelineState> newpipeline;
|
id<MTLRenderPipelineState> newpipeline;
|
||||||
|
|
||||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL);
|
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, statecache->vertex_buffer);
|
||||||
|
|
||||||
if (statecache->viewport_dirty) {
|
if (statecache->viewport_dirty) {
|
||||||
MTLViewport viewport;
|
MTLViewport viewport;
|
||||||
|
@ -1205,7 +1246,7 @@ SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Met
|
||||||
}
|
}
|
||||||
|
|
||||||
if (statecache->color_dirty) {
|
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;
|
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;
|
statecache->constants_offset = constants_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data.mtlcmdencoder setVertexBuffer:mtlbufvertex offset:first atIndex:0]; // position
|
[data.mtlcmdencoder setVertexBufferOffset:first atIndex:0]; /* position/texcoords */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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);
|
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) {
|
if (texture != statecache->texture) {
|
||||||
METAL_TextureData *oldtexturedata = NULL;
|
METAL_TextureData *oldtexturedata = NULL;
|
||||||
if (statecache->texture) {
|
if (statecache->texture) {
|
||||||
|
@ -1263,6 +1302,7 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
||||||
id<MTLBuffer> mtlbufvertex = nil;
|
id<MTLBuffer> mtlbufvertex = nil;
|
||||||
|
|
||||||
statecache.pipeline = nil;
|
statecache.pipeline = nil;
|
||||||
|
statecache.vertex_buffer = nil;
|
||||||
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
|
statecache.constants_offset = CONSTANTS_OFFSET_INVALID;
|
||||||
statecache.texture = NULL;
|
statecache.texture = NULL;
|
||||||
statecache.color_dirty = SDL_TRUE;
|
statecache.color_dirty = SDL_TRUE;
|
||||||
|
@ -1286,6 +1326,8 @@ METAL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *ver
|
||||||
#endif
|
#endif
|
||||||
mtlbufvertex.label = @"SDL vertex data";
|
mtlbufvertex.label = @"SDL vertex data";
|
||||||
SDL_memcpy([mtlbufvertex contents], vertices, vertsize);
|
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.
|
// 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);
|
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.
|
// get new command encoder, set up with an initial clear operation.
|
||||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color);
|
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1403,7 +1445,7 @@ METAL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
|
||||||
Uint32 pixel_format, void * pixels, int pitch)
|
Uint32 pixel_format, void * pixels, int pitch)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL);
|
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
|
||||||
|
|
||||||
[data.mtlcmdencoder endEncoding];
|
[data.mtlcmdencoder endEncoding];
|
||||||
id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
|
id<MTLTexture> mtltexture = data.mtlpassdesc.colorAttachments[0].texture;
|
||||||
|
@ -1498,7 +1540,7 @@ METAL_GetMetalLayer(SDL_Renderer * renderer)
|
||||||
static void *
|
static void *
|
||||||
METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
|
METAL_GetMetalCommandEncoder(SDL_Renderer * renderer)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL);
|
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
|
||||||
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
|
||||||
return (__bridge void*)data.mtlcmdencoder;
|
return (__bridge void*)data.mtlcmdencoder;
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -3,19 +3,23 @@
|
||||||
|
|
||||||
using namespace metal;
|
using namespace metal;
|
||||||
|
|
||||||
|
struct SolidVertexInput
|
||||||
|
{
|
||||||
|
float2 position [[attribute(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
struct SolidVertexOutput
|
struct SolidVertexOutput
|
||||||
{
|
{
|
||||||
float4 position [[position]];
|
float4 position [[position]];
|
||||||
float pointSize [[point_size]];
|
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 &projection [[buffer(2)]],
|
||||||
constant float4x4 &transform [[buffer(3)]],
|
constant float4x4 &transform [[buffer(3)]])
|
||||||
uint vid [[vertex_id]])
|
|
||||||
{
|
{
|
||||||
SolidVertexOutput v;
|
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;
|
v.pointSize = 1.0f;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -25,21 +29,25 @@ fragment float4 SDL_Solid_fragment(const device float4 &col [[buffer(0)]])
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CopyVertexInput
|
||||||
|
{
|
||||||
|
float2 position [[attribute(0)]];
|
||||||
|
float2 texcoord [[attribute(1)]];
|
||||||
|
};
|
||||||
|
|
||||||
struct CopyVertexOutput
|
struct CopyVertexOutput
|
||||||
{
|
{
|
||||||
float4 position [[position]];
|
float4 position [[position]];
|
||||||
float2 texcoord;
|
float2 texcoord;
|
||||||
};
|
};
|
||||||
|
|
||||||
vertex CopyVertexOutput SDL_Copy_vertex(const device float2 *position [[buffer(0)]],
|
vertex CopyVertexOutput SDL_Copy_vertex(CopyVertexInput in [[stage_in]],
|
||||||
const device float2 *texcoords [[buffer(1)]],
|
|
||||||
constant float4x4 &projection [[buffer(2)]],
|
constant float4x4 &projection [[buffer(2)]],
|
||||||
constant float4x4 &transform [[buffer(3)]],
|
constant float4x4 &transform [[buffer(3)]])
|
||||||
uint vid [[vertex_id]])
|
|
||||||
{
|
{
|
||||||
CopyVertexOutput v;
|
CopyVertexOutput v;
|
||||||
v.position = (projection * transform) * float4(position[vid], 0.0f, 1.0f);
|
v.position = (projection * transform) * float4(in.position, 0.0f, 1.0f);
|
||||||
v.texcoord = texcoords[vid];
|
v.texcoord = in.texcoord;
|
||||||
return v;
|
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