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:
1 parent
55a46abf0a
commit
e8278d0d5b
5 files changed
+3745
-3701
No files matched your search
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1223
-1225
File diff suppressed because it is too large.
Load diff
+1213
-1215
File diff suppressed because it is too large.
Load diff
+1223
-1225
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user