Cocoa Port: Update the Metal blitter to support Y-flipping of the rendered video frame, matching the same feature that already exists in the OpenGL blitter.

This commit is contained in:
rogerman 2018-07-27 02:10:28 -07:00
parent 4913c0e7ae
commit bee3fd30ce
3 changed files with 26 additions and 10 deletions

View File

@ -246,7 +246,8 @@ typedef DisplayViewShaderProperties DisplayViewShaderProperties;
outputPipelineState:(id<MTLRenderPipelineState>)outputPipelineState outputPipelineState:(id<MTLRenderPipelineState>)outputPipelineState
hudPipelineState:(id<MTLRenderPipelineState>)hudPipelineState hudPipelineState:(id<MTLRenderPipelineState>)hudPipelineState
texDisplays:(MetalTexturePair)texDisplay texDisplays:(MetalTexturePair)texDisplay
mrfi:(MetalRenderFrameInfo)mrfi; mrfi:(MetalRenderFrameInfo)mrfi
doYFlip:(BOOL)willFlip;
- (void) renderStartAtIndex:(uint8_t)index; - (void) renderStartAtIndex:(uint8_t)index;
- (void) renderFinishAtIndex:(uint8_t)index; - (void) renderFinishAtIndex:(uint8_t)index;
- (ClientDisplayBufferState) renderBufferStateAtIndex:(uint8_t)index; - (ClientDisplayBufferState) renderBufferStateAtIndex:(uint8_t)index;

View File

@ -1885,6 +1885,7 @@
hudPipelineState:(id<MTLRenderPipelineState>)hudPipelineState hudPipelineState:(id<MTLRenderPipelineState>)hudPipelineState
texDisplays:(MetalTexturePair)texDisplay texDisplays:(MetalTexturePair)texDisplay
mrfi:(MetalRenderFrameInfo)mrfi mrfi:(MetalRenderFrameInfo)mrfi
doYFlip:(BOOL)willFlip
{ {
// Generate the command encoder. // Generate the command encoder.
id<MTLRenderCommandEncoder> rce = [cb renderCommandEncoderWithDescriptor:_outputRenderPassDesc]; id<MTLRenderCommandEncoder> rce = [cb renderCommandEncoderWithDescriptor:_outputRenderPassDesc];
@ -1899,6 +1900,7 @@
} }
// Draw the NDS displays. // Draw the NDS displays.
const uint8_t doYFlip = (willFlip) ? 1 : 0;
const NDSDisplayInfo &displayInfo = cdp->GetEmuDisplayInfo(); const NDSDisplayInfo &displayInfo = cdp->GetEmuDisplayInfo();
const float backlightIntensity[2] = { displayInfo.backlightIntensity[NDSDisplayID_Main], displayInfo.backlightIntensity[NDSDisplayID_Touch] }; const float backlightIntensity[2] = { displayInfo.backlightIntensity[NDSDisplayID_Main], displayInfo.backlightIntensity[NDSDisplayID_Touch] };
@ -1906,6 +1908,7 @@
[rce setVertexBytes:_vtxPositionBuffer length:sizeof(_vtxPositionBuffer) atIndex:0]; [rce setVertexBytes:_vtxPositionBuffer length:sizeof(_vtxPositionBuffer) atIndex:0];
[rce setVertexBytes:_texCoordBuffer length:sizeof(_texCoordBuffer) atIndex:1]; [rce setVertexBytes:_texCoordBuffer length:sizeof(_texCoordBuffer) atIndex:1];
[rce setVertexBytes:&_cdvPropertiesBuffer length:sizeof(_cdvPropertiesBuffer) atIndex:2]; [rce setVertexBytes:&_cdvPropertiesBuffer length:sizeof(_cdvPropertiesBuffer) atIndex:2];
[rce setVertexBytes:&doYFlip length:sizeof(uint8_t) atIndex:3];
switch (cdp->GetPresenterProperties().mode) switch (cdp->GetPresenterProperties().mode)
{ {
@ -1986,13 +1989,14 @@
[rce setVertexBuffer:_hudVtxColorBuffer[mrfi.renderIndex] offset:0 atIndex:1]; [rce setVertexBuffer:_hudVtxColorBuffer[mrfi.renderIndex] offset:0 atIndex:1];
[rce setVertexBuffer:_hudTexCoordBuffer[mrfi.renderIndex] offset:0 atIndex:2]; [rce setVertexBuffer:_hudTexCoordBuffer[mrfi.renderIndex] offset:0 atIndex:2];
[rce setVertexBytes:&_cdvPropertiesBuffer length:sizeof(_cdvPropertiesBuffer) atIndex:3]; [rce setVertexBytes:&_cdvPropertiesBuffer length:sizeof(_cdvPropertiesBuffer) atIndex:3];
[rce setVertexBytes:&doYFlip length:sizeof(uint8_t) atIndex:4];
[rce setFragmentTexture:[self texHUDCharMap] atIndex:0]; [rce setFragmentTexture:[self texHUDCharMap] atIndex:0];
// First, draw the inputs. // First, draw the inputs.
if (mrfi.willDrawHUDInput) if (mrfi.willDrawHUDInput)
{ {
isScreenOverlay = 1; isScreenOverlay = 1;
[rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4]; [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:5];
[rce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0]; [rce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0];
[rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle [rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:mrfi.hudTouchLineLength * 6 indexCount:mrfi.hudTouchLineLength * 6
@ -2001,7 +2005,7 @@
indexBufferOffset:(mrfi.hudStringLength + HUD_INPUT_ELEMENT_LENGTH) * 6 * sizeof(uint16_t)]; indexBufferOffset:(mrfi.hudStringLength + HUD_INPUT_ELEMENT_LENGTH) * 6 * sizeof(uint16_t)];
isScreenOverlay = 0; isScreenOverlay = 0;
[rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4]; [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:5];
[rce setFragmentSamplerState:[sharedData samplerHUDText] atIndex:0]; [rce setFragmentSamplerState:[sharedData samplerHUDText] atIndex:0];
[rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle [rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:HUD_INPUT_ELEMENT_LENGTH * 6 indexCount:HUD_INPUT_ELEMENT_LENGTH * 6
@ -2011,7 +2015,7 @@
} }
// Next, draw the backing text box. // Next, draw the backing text box.
[rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:4]; [rce setVertexBytes:&isScreenOverlay length:sizeof(uint8_t) atIndex:5];
[rce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0]; [rce setFragmentSamplerState:[sharedData samplerHUDBox] atIndex:0];
[rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle [rce drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:6 indexCount:6
@ -2092,7 +2096,8 @@
outputPipelineState:[self outputRGBAPipeline] outputPipelineState:[self outputRGBAPipeline]
hudPipelineState:[sharedData hudRGBAPipeline] hudPipelineState:[sharedData hudRGBAPipeline]
texDisplays:texProcess texDisplays:texProcess
mrfi:mrfi]; mrfi:mrfi
doYFlip:YES];
id<MTLBlitCommandEncoder> bce = [cb blitCommandEncoder]; id<MTLBlitCommandEncoder> bce = [cb blitCommandEncoder];
@ -2198,7 +2203,8 @@
outputPipelineState:[presenterObject outputDrawablePipeline] outputPipelineState:[presenterObject outputDrawablePipeline]
hudPipelineState:[[presenterObject sharedData] hudPipeline] hudPipelineState:[[presenterObject sharedData] hudPipeline]
texDisplays:texProcess texDisplays:texProcess
mrfi:mrfi]; mrfi:mrfi
doYFlip:NO];
[cbRender addScheduledHandler:^(id<MTLCommandBuffer> block) { [cbRender addScheduledHandler:^(id<MTLCommandBuffer> block) {
[presenterObject setRenderBufferState:ClientDisplayBufferState_Reading index:mrfi.renderIndex]; [presenterObject setRenderBufferState:ClientDisplayBufferState_Reading index:mrfi.renderIndex];

View File

@ -146,7 +146,8 @@ vertex HUDVtx hud_vertex(const device float2 *inPosition [[buffer(0)]],
const device uint32_t *inColor [[buffer(1)]], const device uint32_t *inColor [[buffer(1)]],
const device float2 *inTexCoord [[buffer(2)]], const device float2 *inTexCoord [[buffer(2)]],
const constant DisplayViewShaderProperties &viewProps [[buffer(3)]], const constant DisplayViewShaderProperties &viewProps [[buffer(3)]],
const constant uint8_t &isScreenOverlay [[buffer(4)]], const constant uint8_t &doYFlip [[buffer(4)]],
const constant uint8_t &isScreenOverlay [[buffer(5)]],
const uint vid [[vertex_id]]) const uint vid [[vertex_id]])
{ {
const float angleRadians = viewProps.rotation * (M_PI_F/180.0f); const float angleRadians = viewProps.rotation * (M_PI_F/180.0f);
@ -160,8 +161,10 @@ vertex HUDVtx hud_vertex(const device float2 *inPosition [[buffer(0)]],
const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f), const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f),
float2( 0.0f, viewProps.viewScale)); float2( 0.0f, viewProps.viewScale));
const float2 yFlip = (doYFlip != 0) ? float2(1.0f, -1.0f) : float2(1.0f, 1.0f);
HUDVtx outVtx; HUDVtx outVtx;
outVtx.position = (isScreenOverlay != 0) ? float4(projection * rotation * scale * inPosition[vid], 0.0f, 1.0f) : float4(projection * inPosition[vid], 0.0f, 1.0f); outVtx.position = (isScreenOverlay != 0) ? float4(projection * rotation * scale * inPosition[vid] * yFlip, 0.0f, 1.0f) : float4(projection * inPosition[vid] * yFlip, 0.0f, 1.0f);
outVtx.color = float4( (float)((inColor[vid] >> 0) & 0xFF) / 255.0f, (float)((inColor[vid] >> 8) & 0xFF) / 255.0f, (float)((inColor[vid] >> 16) & 0xFF) / 255.0f, (float)((inColor[vid] >> 24) & 0xFF) / 255.0f ); outVtx.color = float4( (float)((inColor[vid] >> 0) & 0xFF) / 255.0f, (float)((inColor[vid] >> 8) & 0xFF) / 255.0f, (float)((inColor[vid] >> 16) & 0xFF) / 255.0f, (float)((inColor[vid] >> 24) & 0xFF) / 255.0f );
outVtx.texCoord = inTexCoord[vid]; outVtx.texCoord = inTexCoord[vid];
outVtx.lowerHUDMipMapLevel = (viewProps.lowerHUDMipMapLevel == 1); outVtx.lowerHUDMipMapLevel = (viewProps.lowerHUDMipMapLevel == 1);
@ -181,6 +184,7 @@ fragment float4 hud_fragment(const HUDVtx vtx [[stage_in]],
vertex DisplayVtx display_output_vertex(const device float2 *inPosition [[buffer(0)]], vertex DisplayVtx display_output_vertex(const device float2 *inPosition [[buffer(0)]],
const device float2 *inTexCoord [[buffer(1)]], const device float2 *inTexCoord [[buffer(1)]],
const constant DisplayViewShaderProperties &viewProps [[buffer(2)]], const constant DisplayViewShaderProperties &viewProps [[buffer(2)]],
const constant uint8_t &doYFlip [[buffer(3)]],
const uint vid [[vertex_id]]) const uint vid [[vertex_id]])
{ {
const float angleRadians = viewProps.rotation * (M_PI_F/180.0f); const float angleRadians = viewProps.rotation * (M_PI_F/180.0f);
@ -194,8 +198,10 @@ vertex DisplayVtx display_output_vertex(const device float2 *inPosition [[buffer
const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f), const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f),
float2( 0.0f, viewProps.viewScale)); float2( 0.0f, viewProps.viewScale));
const float2 yFlip = (doYFlip != 0) ? float2(1.0f, -1.0f) : float2(1.0f, 1.0f);
DisplayVtx outVtx; DisplayVtx outVtx;
outVtx.position = float4(projection * rotation * scale * inPosition[vid], 0.0f, 1.0f); outVtx.position = float4(projection * rotation * scale * inPosition[vid] * yFlip, 0.0f, 1.0f);
outVtx.texCoord = inTexCoord[vid]; outVtx.texCoord = inTexCoord[vid];
return outVtx; return outVtx;
@ -204,6 +210,7 @@ vertex DisplayVtx display_output_vertex(const device float2 *inPosition [[buffer
vertex DisplayVtx display_output_bicubic_vertex(const device float2 *inPosition [[buffer(0)]], vertex DisplayVtx display_output_bicubic_vertex(const device float2 *inPosition [[buffer(0)]],
const device float2 *inTexCoord [[buffer(1)]], const device float2 *inTexCoord [[buffer(1)]],
const constant DisplayViewShaderProperties &viewProps [[buffer(2)]], const constant DisplayViewShaderProperties &viewProps [[buffer(2)]],
const constant uint8_t &doYFlip [[buffer(3)]],
const uint vid [[vertex_id]]) const uint vid [[vertex_id]])
{ {
const float angleRadians = viewProps.rotation * (M_PI_F/180.0f); const float angleRadians = viewProps.rotation * (M_PI_F/180.0f);
@ -217,8 +224,10 @@ vertex DisplayVtx display_output_bicubic_vertex(const device float2 *inPosition
const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f), const float2x2 scale = float2x2( float2(viewProps.viewScale, 0.0f),
float2( 0.0f, viewProps.viewScale)); float2( 0.0f, viewProps.viewScale));
const float2 yFlip = (doYFlip != 0) ? float2(1.0f, -1.0f) : float2(1.0f, 1.0f);
DisplayVtx outVtx; DisplayVtx outVtx;
outVtx.position = float4(projection * rotation * scale * inPosition[vid], 0.0f, 1.0f); outVtx.position = float4(projection * rotation * scale * inPosition[vid] * yFlip, 0.0f, 1.0f);
outVtx.texCoord = floor(inTexCoord[vid] - 0.5f) + 0.5f; outVtx.texCoord = floor(inTexCoord[vid] - 0.5f) + 0.5f;
return outVtx; return outVtx;