Merge pull request #1137 from cdavis5e/layered-blits
MVKCmdBlitImage: Use layered draws when possible.
This commit is contained in:
commit
426b699703
@ -485,18 +485,34 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
|
|||||||
mtlColorAttDesc.level = mvkIBR.region.dstSubresource.mipLevel;
|
mtlColorAttDesc.level = mvkIBR.region.dstSubresource.mipLevel;
|
||||||
mtlDepthAttDesc.level = mvkIBR.region.dstSubresource.mipLevel;
|
mtlDepthAttDesc.level = mvkIBR.region.dstSubresource.mipLevel;
|
||||||
mtlStencilAttDesc.level = mvkIBR.region.dstSubresource.mipLevel;
|
mtlStencilAttDesc.level = mvkIBR.region.dstSubresource.mipLevel;
|
||||||
|
|
||||||
|
bool isLayeredBlit = blitKey.dstSampleCount > 1 ? cmdEncoder->getDevice()->_pMetalFeatures->multisampleLayeredRendering : cmdEncoder->getDevice()->_pMetalFeatures->layeredRendering;
|
||||||
|
|
||||||
uint32_t layCnt = mvkIBR.region.srcSubresource.layerCount;
|
uint32_t layCnt = mvkIBR.region.srcSubresource.layerCount;
|
||||||
if (_dstImage->getMTLTextureType() == MTLTextureType3D) {
|
if (_dstImage->getMTLTextureType() == MTLTextureType3D) {
|
||||||
layCnt = mvkAbsDiff(mvkIBR.region.dstOffsets[1].z, mvkIBR.region.dstOffsets[0].z);
|
layCnt = mvkAbsDiff(mvkIBR.region.dstOffsets[1].z, mvkIBR.region.dstOffsets[0].z);
|
||||||
}
|
}
|
||||||
|
if (isLayeredBlit) {
|
||||||
|
// In this case, I can blit all layers at once with a layered draw.
|
||||||
|
mtlRPD.renderTargetArrayLengthMVK = layCnt;
|
||||||
|
layCnt = 1; // Only need to run the loop once.
|
||||||
|
}
|
||||||
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
for (uint32_t layIdx = 0; layIdx < layCnt; layIdx++) {
|
||||||
// Update the render pass descriptor for the texture level and slice, and create a render encoder.
|
// Update the render pass descriptor for the texture level and slice, and create a render encoder.
|
||||||
if (_dstImage->getMTLTextureType() == MTLTextureType3D) {
|
if (_dstImage->getMTLTextureType() == MTLTextureType3D) {
|
||||||
uint32_t depthPlane = mvkIBR.region.dstOffsets[0].z + (mvkIBR.region.dstOffsets[1].z > mvkIBR.region.dstOffsets[0].z ? layIdx : -(layIdx + 1));
|
if (isLayeredBlit) {
|
||||||
mtlColorAttDesc.depthPlane = depthPlane;
|
// For layered blits, the layers are always in ascending order. I'll reverse the order
|
||||||
mtlDepthAttDesc.depthPlane = depthPlane;
|
// of the 'r' coordinates if the destination is mirrored.
|
||||||
mtlStencilAttDesc.depthPlane = depthPlane;
|
uint32_t depthPlane = std::min(mvkIBR.region.dstOffsets[0].z, mvkIBR.region.dstOffsets[1].z);
|
||||||
|
mtlColorAttDesc.depthPlane = depthPlane;
|
||||||
|
mtlDepthAttDesc.depthPlane = depthPlane;
|
||||||
|
mtlStencilAttDesc.depthPlane = depthPlane;
|
||||||
|
} else {
|
||||||
|
uint32_t depthPlane = mvkIBR.region.dstOffsets[0].z + (mvkIBR.region.dstOffsets[1].z > mvkIBR.region.dstOffsets[0].z ? layIdx : -(layIdx + 1));
|
||||||
|
mtlColorAttDesc.depthPlane = depthPlane;
|
||||||
|
mtlDepthAttDesc.depthPlane = depthPlane;
|
||||||
|
mtlStencilAttDesc.depthPlane = depthPlane;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mtlColorAttDesc.slice = mvkIBR.region.dstSubresource.baseArrayLayer + layIdx;
|
mtlColorAttDesc.slice = mvkIBR.region.dstSubresource.baseArrayLayer + layIdx;
|
||||||
mtlDepthAttDesc.slice = mvkIBR.region.dstSubresource.baseArrayLayer + layIdx;
|
mtlDepthAttDesc.slice = mvkIBR.region.dstSubresource.baseArrayLayer + layIdx;
|
||||||
@ -505,6 +521,7 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
|
|||||||
id<MTLRenderCommandEncoder> mtlRendEnc = [cmdEncoder->_mtlCmdBuffer renderCommandEncoderWithDescriptor: mtlRPD];
|
id<MTLRenderCommandEncoder> mtlRendEnc = [cmdEncoder->_mtlCmdBuffer renderCommandEncoderWithDescriptor: mtlRPD];
|
||||||
setLabelIfNotNil(mtlRendEnc, mvkMTLRenderCommandEncoderLabel(commandUse));
|
setLabelIfNotNil(mtlRendEnc, mvkMTLRenderCommandEncoderLabel(commandUse));
|
||||||
|
|
||||||
|
float zIncr;
|
||||||
if (blitKey.srcMTLTextureType == MTLTextureType3D) {
|
if (blitKey.srcMTLTextureType == MTLTextureType3D) {
|
||||||
// In this case, I need to interpolate along the third dimension manually.
|
// In this case, I need to interpolate along the third dimension manually.
|
||||||
VkExtent3D srcExtent = _srcImage->getExtent3D(srcPlaneIndex, mvkIBR.region.dstSubresource.mipLevel);
|
VkExtent3D srcExtent = _srcImage->getExtent3D(srcPlaneIndex, mvkIBR.region.dstSubresource.mipLevel);
|
||||||
@ -512,7 +529,12 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
|
|||||||
VkOffset3D do0 = mvkIBR.region.dstOffsets[0], do1 = mvkIBR.region.dstOffsets[1];
|
VkOffset3D do0 = mvkIBR.region.dstOffsets[0], do1 = mvkIBR.region.dstOffsets[1];
|
||||||
float startZ = (float)so0.z / (float)srcExtent.depth;
|
float startZ = (float)so0.z / (float)srcExtent.depth;
|
||||||
float endZ = (float)so1.z / (float)srcExtent.depth;
|
float endZ = (float)so1.z / (float)srcExtent.depth;
|
||||||
float z = startZ + (endZ - startZ) * (layIdx + 0.5) / mvkAbsDiff(do1.z, do0.z);
|
if (isLayeredBlit && do0.z > do1.z) {
|
||||||
|
// Swap start and end points so interpolation moves in the right direction.
|
||||||
|
std::swap(startZ, endZ);
|
||||||
|
}
|
||||||
|
zIncr = (endZ - startZ) / mvkAbsDiff(do1.z, do0.z);
|
||||||
|
float z = startZ + (isLayeredBlit ? 0.0 : (layIdx + 0.5)) * zIncr;
|
||||||
for (uint32_t i = 0; i < kMVKBlitVertexCount; ++i) {
|
for (uint32_t i = 0; i < kMVKBlitVertexCount; ++i) {
|
||||||
mvkIBR.vertices[i].texCoord.z = z;
|
mvkIBR.vertices[i].texCoord.z = z;
|
||||||
}
|
}
|
||||||
@ -521,6 +543,9 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
|
|||||||
[mtlRendEnc setRenderPipelineState: mtlRPS];
|
[mtlRendEnc setRenderPipelineState: mtlRPS];
|
||||||
[mtlRendEnc setDepthStencilState: mtlDSS];
|
[mtlRendEnc setDepthStencilState: mtlDSS];
|
||||||
cmdEncoder->setVertexBytes(mtlRendEnc, mvkIBR.vertices, sizeof(mvkIBR.vertices), vtxBuffIdx);
|
cmdEncoder->setVertexBytes(mtlRendEnc, mvkIBR.vertices, sizeof(mvkIBR.vertices), vtxBuffIdx);
|
||||||
|
if (isLayeredBlit) {
|
||||||
|
cmdEncoder->setVertexBytes(mtlRendEnc, &zIncr, sizeof(zIncr), 0);
|
||||||
|
}
|
||||||
if (!mvkIsOnlyAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_STENCIL_BIT))) {
|
if (!mvkIsOnlyAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_STENCIL_BIT))) {
|
||||||
[mtlRendEnc setFragmentTexture: srcMTLTex atIndex: 0];
|
[mtlRendEnc setFragmentTexture: srcMTLTex atIndex: 0];
|
||||||
}
|
}
|
||||||
@ -556,7 +581,8 @@ void MVKCmdBlitImage<N>::encode(MVKCommandEncoder* cmdEncoder, MVKCommandUse com
|
|||||||
texSubRez.lod = mvkIBR.region.srcSubresource.mipLevel;
|
texSubRez.lod = mvkIBR.region.srcSubresource.mipLevel;
|
||||||
cmdEncoder->setFragmentBytes(mtlRendEnc, &texSubRez, sizeof(texSubRez), 0);
|
cmdEncoder->setFragmentBytes(mtlRendEnc, &texSubRez, sizeof(texSubRez), 0);
|
||||||
|
|
||||||
[mtlRendEnc drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart: 0 vertexCount: kMVKBlitVertexCount];
|
NSUInteger instanceCount = isLayeredBlit ? mtlRPD.renderTargetArrayLengthMVK : 1;
|
||||||
|
[mtlRendEnc drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart: 0 vertexCount: kMVKBlitVertexCount instanceCount: instanceCount];
|
||||||
[mtlRendEnc popDebugGroup];
|
[mtlRendEnc popDebugGroup];
|
||||||
[mtlRendEnc endEncoding];
|
[mtlRendEnc endEncoding];
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,12 @@ typedef struct {
|
|||||||
float3 v_texCoord; \n\
|
float3 v_texCoord; \n\
|
||||||
} VaryingsPosTex; \n\
|
} VaryingsPosTex; \n\
|
||||||
\n\
|
\n\
|
||||||
|
typedef struct { \n\
|
||||||
|
float4 v_position [[position]]; \n\
|
||||||
|
float3 v_texCoord; \n\
|
||||||
|
uint v_layer [[render_target_array_index]]; \n\
|
||||||
|
} VaryingsPosTexLayer; \n\
|
||||||
|
\n\
|
||||||
typedef size_t VkDeviceSize; \n\
|
typedef size_t VkDeviceSize; \n\
|
||||||
\n\
|
\n\
|
||||||
typedef enum : uint32_t { \n\
|
typedef enum : uint32_t { \n\
|
||||||
@ -79,6 +85,16 @@ vertex VaryingsPosTex vtxCmdBlitImage(AttributesPosTex attributes [[stage_in]])
|
|||||||
return varyings; \n\
|
return varyings; \n\
|
||||||
} \n\
|
} \n\
|
||||||
\n\
|
\n\
|
||||||
|
vertex VaryingsPosTexLayer vtxCmdBlitImageLayered(AttributesPosTex attributes [[stage_in]], \n\
|
||||||
|
uint instanceID [[instance_id]], \n\
|
||||||
|
constant float &zIncr [[buffer(0)]]) { \n\
|
||||||
|
VaryingsPosTexLayer varyings; \n\
|
||||||
|
varyings.v_position = float4(attributes.a_position, 0.0, 1.0); \n\
|
||||||
|
varyings.v_texCoord = float3(attributes.a_texCoord.xy, attributes.a_texCoord.z + (instanceID + 0.5) * zIncr);\n\
|
||||||
|
varyings.v_layer = instanceID; \n\
|
||||||
|
return varyings; \n\
|
||||||
|
} \n\
|
||||||
|
\n\
|
||||||
typedef struct { \n\
|
typedef struct { \n\
|
||||||
uint32_t srcOffset; \n\
|
uint32_t srcOffset; \n\
|
||||||
uint32_t dstOffset; \n\
|
uint32_t dstOffset; \n\
|
||||||
|
@ -33,14 +33,18 @@ using namespace std;
|
|||||||
|
|
||||||
id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey,
|
id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdBlitImageMTLRenderPipelineState(MVKRPSKeyBlitImg& blitKey,
|
||||||
MVKVulkanAPIDeviceObject* owner) {
|
MVKVulkanAPIDeviceObject* owner) {
|
||||||
id<MTLFunction> vtxFunc = newFunctionNamed("vtxCmdBlitImage"); // temp retain
|
bool isLayeredBlit = blitKey.dstSampleCount > 1 ? _device->_pMetalFeatures->multisampleLayeredRendering : _device->_pMetalFeatures->layeredRendering;
|
||||||
id<MTLFunction> fragFunc = newBlitFragFunction(blitKey); // temp retain
|
id<MTLFunction> vtxFunc = newFunctionNamed(isLayeredBlit ? "vtxCmdBlitImageLayered" : "vtxCmdBlitImage"); // temp retain
|
||||||
MTLRenderPipelineDescriptor* plDesc = [MTLRenderPipelineDescriptor new]; // temp retain
|
id<MTLFunction> fragFunc = newBlitFragFunction(blitKey); // temp retain
|
||||||
|
MTLRenderPipelineDescriptor* plDesc = [MTLRenderPipelineDescriptor new]; // temp retain
|
||||||
plDesc.label = @"CmdBlitImage";
|
plDesc.label = @"CmdBlitImage";
|
||||||
|
|
||||||
plDesc.vertexFunction = vtxFunc;
|
plDesc.vertexFunction = vtxFunc;
|
||||||
plDesc.fragmentFunction = fragFunc;
|
plDesc.fragmentFunction = fragFunc;
|
||||||
plDesc.sampleCount = blitKey.dstSampleCount;
|
plDesc.sampleCount = blitKey.dstSampleCount;
|
||||||
|
if (isLayeredBlit) {
|
||||||
|
plDesc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
|
||||||
|
}
|
||||||
|
|
||||||
if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT))) {
|
if (mvkIsAnyFlagEnabled(blitKey.srcAspect, (VK_IMAGE_ASPECT_DEPTH_BIT))) {
|
||||||
plDesc.depthAttachmentPixelFormat = blitKey.getDstMTLPixelFormat();
|
plDesc.depthAttachmentPixelFormat = blitKey.getDstMTLPixelFormat();
|
||||||
@ -162,6 +166,7 @@ id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipeli
|
|||||||
|
|
||||||
id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg& blitKey) {
|
id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg& blitKey) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
bool isLayeredBlit = blitKey.dstSampleCount > 1 ? _device->_pMetalFeatures->multisampleLayeredRendering : _device->_pMetalFeatures->layeredRendering;
|
||||||
NSString* typeStr = getMTLFormatTypeString(blitKey.getSrcMTLPixelFormat());
|
NSString* typeStr = getMTLFormatTypeString(blitKey.getSrcMTLPixelFormat());
|
||||||
|
|
||||||
bool isArrayType = blitKey.isSrcArrayType();
|
bool isArrayType = blitKey.isSrcArrayType();
|
||||||
@ -198,7 +203,7 @@ id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg&
|
|||||||
coordArg = @"";
|
coordArg = @"";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NSString* sliceArg = isArrayType ? @", subRez.slice" : @"";
|
NSString* sliceArg = isArrayType ? (isLayeredBlit ? @", subRez.slice + varyings.v_layer" : @", subRez.slice") : @"";
|
||||||
NSString* srcFilter = isLinearFilter ? @"linear" : @"nearest";
|
NSString* srcFilter = isLinearFilter ? @"linear" : @"nearest";
|
||||||
|
|
||||||
NSMutableString* msl = [NSMutableString stringWithCapacity: (2 * KIBI) ];
|
NSMutableString* msl = [NSMutableString stringWithCapacity: (2 * KIBI) ];
|
||||||
@ -208,6 +213,9 @@ id<MTLFunction> MVKCommandResourceFactory::newBlitFragFunction(MVKRPSKeyBlitImg&
|
|||||||
[msl appendLineMVK: @"typedef struct {"];
|
[msl appendLineMVK: @"typedef struct {"];
|
||||||
[msl appendLineMVK: @" float4 v_position [[position]];"];
|
[msl appendLineMVK: @" float4 v_position [[position]];"];
|
||||||
[msl appendLineMVK: @" float3 v_texCoord;"];
|
[msl appendLineMVK: @" float3 v_texCoord;"];
|
||||||
|
if (isLayeredBlit && isArrayType) {
|
||||||
|
[msl appendLineMVK: @" uint v_layer [[render_target_array_index]];"];
|
||||||
|
}
|
||||||
[msl appendLineMVK: @"} VaryingsPosTex;"];
|
[msl appendLineMVK: @"} VaryingsPosTex;"];
|
||||||
[msl appendLineMVK];
|
[msl appendLineMVK];
|
||||||
[msl appendLineMVK: @"typedef struct {"];
|
[msl appendLineMVK: @"typedef struct {"];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user