This commit is contained in:
Bill Hollings 2019-04-18 15:12:42 -04:00
commit e91d2f6b35
16 changed files with 185 additions and 37 deletions

View File

@ -1 +1 @@
ac5a9570a744eb72725c23c34f36fbc564c0bb51
942273dc7b107d4f0c2cf3449ae306525e1cbae7

View File

@ -70,7 +70,7 @@ protected:
#pragma mark MVKCmdDraw
/** Vulkan command to draw vertices. */
class MVKCmdDraw : public MVKCommand {
class MVKCmdDraw : public MVKCommand, public MVKLoadStoreOverride {
public:
void setContent(uint32_t vertexCount,
@ -94,7 +94,7 @@ protected:
#pragma mark MVKCmdDrawIndexed
/** Vulkan command to draw indexed vertices. */
class MVKCmdDrawIndexed : public MVKCommand {
class MVKCmdDrawIndexed : public MVKCommand, public MVKLoadStoreOverride {
public:
void setContent(uint32_t indexCount,
@ -120,7 +120,7 @@ protected:
#pragma mark MVKCmdDrawIndirect
/** Vulkan command to draw vertices indirectly. */
class MVKCmdDrawIndirect : public MVKCommand {
class MVKCmdDrawIndirect : public MVKCommand, public MVKLoadStoreOverride {
public:
void setContent(VkBuffer buffer,
@ -144,7 +144,7 @@ protected:
#pragma mark MVKCmdDrawIndexedIndirect
/** Vulkan command to draw indexed vertices indirectly. */
class MVKCmdDrawIndexedIndirect : public MVKCommand {
class MVKCmdDrawIndexedIndirect : public MVKCommand, public MVKLoadStoreOverride {
public:
void setContent(VkBuffer buffer,

View File

@ -84,6 +84,8 @@ void MVKCmdDraw::setContent(uint32_t vertexCount,
_instanceCount = instanceCount;
_firstVertex = firstVertex;
_firstInstance = firstInstance;
_loadOverride = false;
_storeOverride = false;
// Validate
clearConfigurationResult();
@ -113,6 +115,8 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) {
}
for (uint32_t s : stages) {
auto stage = MVKGraphicsStage(s);
if (stage == kMVKGraphicsStageVertex)
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->finalizeDrawState(stage); // Ensure all updated state has been submitted to Metal
id<MTLComputeCommandEncoder> mtlTessCtlEncoder = nil;
@ -148,6 +152,7 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) {
// so I apply them during the next stage.
cmdEncoder->_graphicsPipelineState.beginMetalRenderPass();
cmdEncoder->_graphicsResourcesState.beginMetalRenderPass();
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass();
break;
case kMVKGraphicsStageTessControl:
@ -198,7 +203,7 @@ void MVKCmdDraw::encode(MVKCommandEncoder* cmdEncoder) {
threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)];
// Running this stage prematurely ended the render pass, so we have to start it up again.
// TODO: On iOS, maybe we could use a tile shader to avoid this.
cmdEncoder->beginMetalRenderPass(true);
cmdEncoder->beginMetalRenderPass(_loadOverride, _storeOverride);
break;
case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) {
@ -267,6 +272,8 @@ void MVKCmdDrawIndexed::setContent(uint32_t indexCount,
_firstIndex = firstIndex;
_vertexOffset = vertexOffset;
_firstInstance = firstInstance;
_loadOverride = false;
_storeOverride = false;
// Validate
clearConfigurationResult();
@ -339,6 +346,8 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) {
atIndex: 4];
[mtlTessCtlEncoder dispatchThreadgroups: MTLSizeMake(1, 1, 1) threadsPerThreadgroup: MTLSizeMake(1, 1, 1)];
}
if (stage == kMVKGraphicsStageVertex)
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->finalizeDrawState(stage); // Ensure all updated state has been submitted to Metal
switch (stage) {
@ -376,6 +385,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) {
// so I apply them during the next stage.
cmdEncoder->_graphicsPipelineState.beginMetalRenderPass();
cmdEncoder->_graphicsResourcesState.beginMetalRenderPass();
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass();
break;
case kMVKGraphicsStageTessControl:
@ -419,7 +429,7 @@ void MVKCmdDrawIndexed::encode(MVKCommandEncoder* cmdEncoder) {
threadsPerThreadgroup: MTLSizeMake(std::max(inControlPointCount, outControlPointCount), 1, 1)];
// Running this stage prematurely ended the render pass, so we have to start it up again.
// TODO: On iOS, maybe we could use a tile shader to avoid this.
cmdEncoder->beginMetalRenderPass(true);
cmdEncoder->beginMetalRenderPass(_loadOverride, _storeOverride);
break;
case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) {
@ -493,6 +503,8 @@ void MVKCmdDrawIndirect::setContent(VkBuffer buffer,
_mtlIndirectBufferOffset = mvkBuffer->getMTLBufferOffset() + offset;
_mtlIndirectBufferStride = stride;
_drawCount = drawCount;
_loadOverride = false;
_storeOverride = false;
// Validate
clearConfigurationResult();
@ -604,6 +616,8 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
threadsPerThreadgroup: MTLSizeMake(mtlConvertState.threadExecutionWidth, 1, 1)];
}
if (stage == kMVKGraphicsStageVertex)
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->finalizeDrawState(stage); // Ensure all updated state has been submitted to Metal
switch (stage) {
@ -624,6 +638,7 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
// so I apply them during the next stage.
cmdEncoder->_graphicsPipelineState.beginMetalRenderPass();
cmdEncoder->_graphicsResourcesState.beginMetalRenderPass();
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass();
break;
case kMVKGraphicsStageTessControl:
@ -650,8 +665,10 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
offset: vtxOutBuff->_offset
atIndex: kMVKTessCtlInputBufferIndex];
if ([mtlTessCtlEncoder respondsToSelector: @selector(setStageInRegionWithIndirectBuffer:indirectBufferOffset:)]) {
[mtlTessCtlEncoder setStageInRegionWithIndirectBuffer: tcIndirectBuff->_mtlBuffer
indirectBufferOffset: mtlTCIndBuffOfst];
// setStageInRegionWithIndirectBuffer appears to be broken. We have a 1D linear region anyway, so size is irrelevant
//[mtlTessCtlEncoder setStageInRegionWithIndirectBuffer: tcIndirectBuff->_mtlBuffer
// indirectBufferOffset: mtlTCIndBuffOfst];
[mtlTessCtlEncoder setStageInRegion: MTLRegionMake1D(0, std::max(inControlPointCount, outControlPointCount) * patchCount)];
mtlTCIndBuffOfst += sizeof(MTLStageInRegionIndirectArguments);
} else {
// We must assume we can read up to the maximum number of vertices.
@ -669,7 +686,7 @@ void MVKCmdDrawIndirect::encode(MVKCommandEncoder* cmdEncoder) {
mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments);
// Running this stage prematurely ended the render pass, so we have to start it up again.
// TODO: On iOS, maybe we could use a tile shader to avoid this.
cmdEncoder->beginMetalRenderPass(true);
cmdEncoder->beginMetalRenderPass(_loadOverride, _storeOverride);
break;
case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) {
@ -728,6 +745,8 @@ void MVKCmdDrawIndexedIndirect::setContent(VkBuffer buffer,
_mtlIndirectBufferOffset = mvkBuffer->getMTLBufferOffset() + offset;
_mtlIndirectBufferStride = stride;
_drawCount = drawCount;
_loadOverride = false;
_storeOverride = false;
// Validate
clearConfigurationResult();
@ -849,6 +868,8 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) {
[mtlTessCtlEncoder dispatchThreadgroups: MTLSizeMake(1, 1, 1) threadsPerThreadgroup: MTLSizeMake(1, 1, 1)];
}
if (stage == kMVKGraphicsStageVertex)
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->finalizeDrawState(stage); // Ensure all updated state has been submitted to Metal
switch (stage) {
@ -872,6 +893,7 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) {
// so I apply them during the next stage.
cmdEncoder->_graphicsPipelineState.beginMetalRenderPass();
cmdEncoder->_graphicsResourcesState.beginMetalRenderPass();
cmdEncoder->_depthStencilState.markDirty();
cmdEncoder->getPushConstants(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)->beginMetalRenderPass();
break;
case kMVKGraphicsStageTessControl:
@ -898,8 +920,10 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) {
offset: vtxOutBuff->_offset
atIndex: kMVKTessCtlInputBufferIndex];
if ([mtlTessCtlEncoder respondsToSelector: @selector(setStageInRegionWithIndirectBuffer:indirectBufferOffset:)]) {
[mtlTessCtlEncoder setStageInRegionWithIndirectBuffer: tcIndirectBuff->_mtlBuffer
indirectBufferOffset: mtlTCIndBuffOfst];
// setStageInRegionWithIndirectBuffer appears to be broken. We have a 1D linear region anyway, so size is irrelevant
//[mtlTessCtlEncoder setStageInRegionWithIndirectBuffer: tcIndirectBuff->_mtlBuffer
// indirectBufferOffset: mtlTCIndBuffOfst];
[mtlTessCtlEncoder setStageInRegion: MTLRegionMake1D(0, std::max(inControlPointCount, outControlPointCount) * patchCount)];
mtlTCIndBuffOfst += sizeof(MTLStageInRegionIndirectArguments);
} else {
// We must assume we can read up to the maximum number of vertices.
@ -915,7 +939,7 @@ void MVKCmdDrawIndexedIndirect::encode(MVKCommandEncoder* cmdEncoder) {
mtlTCIndBuffOfst += sizeof(MTLDispatchThreadgroupsIndirectArguments);
// Running this stage prematurely ended the render pass, so we have to start it up again.
// TODO: On iOS, maybe we could use a tile shader to avoid this.
cmdEncoder->beginMetalRenderPass(true);
cmdEncoder->beginMetalRenderPass(_loadOverride, _storeOverride);
break;
case kMVKGraphicsStageRasterization:
if (pipeline->isTessellationPipeline()) {
@ -985,6 +1009,7 @@ void mvkCmdDraw(MVKCommandBuffer* cmdBuff,
uint32_t firstInstance) {
MVKCmdDraw* cmd = cmdBuff->_commandPool->_cmdDrawPool.acquireObject();
cmd->setContent(vertexCount, instanceCount, firstVertex, firstInstance);
cmdBuff->recordDraw(cmd);
cmdBuff->addCommand(cmd);
}
@ -996,6 +1021,7 @@ void mvkCmdDrawIndexed(MVKCommandBuffer* cmdBuff,
uint32_t firstInstance) {
MVKCmdDrawIndexed* cmd = cmdBuff->_commandPool->_cmdDrawIndexedPool.acquireObject();
cmd->setContent(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
cmdBuff->recordDraw(cmd);
cmdBuff->addCommand(cmd);
}
@ -1015,6 +1041,7 @@ void mvkCmdDrawIndirect(MVKCommandBuffer* cmdBuff,
uint32_t stride) {
MVKCmdDrawIndirect* cmd = cmdBuff->_commandPool->_cmdDrawIndirectPool.acquireObject();
cmd->setContent(buffer, offset, drawCount, stride);
cmdBuff->recordDraw(cmd);
cmdBuff->addCommand(cmd);
}
@ -1025,6 +1052,7 @@ void mvkCmdDrawIndexedIndirect(MVKCommandBuffer* cmdBuff,
uint32_t stride) {
MVKCmdDrawIndexedIndirect* cmd = cmdBuff->_commandPool->_cmdDrawIndexedIndirectPool.acquireObject();
cmd->setContent(buffer, offset, drawCount, stride);
cmdBuff->recordDraw(cmd);
cmdBuff->addCommand(cmd);
}

View File

@ -73,6 +73,8 @@ public:
MVKCmdBindPipeline(MVKCommandTypePool<MVKCmdBindPipeline>* pool);
bool isTessellationPipeline();
private:
VkPipelineBindPoint _bindPoint;
MVKPipeline* _pipeline;

View File

@ -109,6 +109,13 @@ void MVKCmdBindPipeline::encode(MVKCommandEncoder* cmdEncoder) {
MVKCmdBindPipeline::MVKCmdBindPipeline(MVKCommandTypePool<MVKCmdBindPipeline>* pool)
: MVKCommand::MVKCommand((MVKCommandTypePool<MVKCommand>*)pool) {}
bool MVKCmdBindPipeline::isTessellationPipeline() {
if (_bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS)
return ((MVKGraphicsPipeline*)_pipeline)->isTessellationPipeline();
else
return false;
}
#pragma mark -
#pragma mark MVKCmdBindDescriptorSets
@ -327,6 +334,7 @@ void mvkCmdBindPipeline(MVKCommandBuffer* cmdBuff,
VkPipeline pipeline) {
MVKCmdBindPipeline* cmd = cmdBuff->_commandPool->_cmdBindPipelinePool.acquireObject();
cmd->setContent(pipelineBindPoint, pipeline);
cmdBuff->recordBindPipeline(cmd);
cmdBuff->addCommand(cmd);
}

View File

@ -33,7 +33,7 @@ class MVKFramebuffer;
#pragma mark MVKCmdBeginRenderPass
/** Vulkan command to begin a render pass. */
class MVKCmdBeginRenderPass : public MVKCommand {
class MVKCmdBeginRenderPass : public MVKCommand, public MVKLoadStoreOverride {
public:
void setContent(const VkRenderPassBeginInfo* pRenderPassBegin,

View File

@ -34,6 +34,8 @@ void MVKCmdBeginRenderPass::setContent(const VkRenderPassBeginInfo* pRenderPassB
_contents = contents;
_renderPass = (MVKRenderPass*)_info.renderPass;
_framebuffer = (MVKFramebuffer*)_info.framebuffer;
_loadOverride = false;
_storeOverride = false;
// Add clear values
_clearValues.clear(); // Clear for reuse
@ -45,7 +47,7 @@ void MVKCmdBeginRenderPass::setContent(const VkRenderPassBeginInfo* pRenderPassB
void MVKCmdBeginRenderPass::encode(MVKCommandEncoder* cmdEncoder) {
// MVKLogDebug("Encoding vkCmdBeginRenderPass(). Elapsed time: %.6f ms.", mvkGetElapsedMilliseconds());
cmdEncoder->beginRenderpass(_contents, _renderPass, _framebuffer, _info.renderArea, &_clearValues);
cmdEncoder->beginRenderpass(_contents, _renderPass, _framebuffer, _info.renderArea, &_clearValues, _loadOverride, _storeOverride);
}
MVKCmdBeginRenderPass::MVKCmdBeginRenderPass(MVKCommandTypePool<MVKCmdBeginRenderPass>* pool)
@ -277,6 +279,7 @@ void mvkCmdBeginRenderPass(MVKCommandBuffer* cmdBuff,
VkSubpassContents contents) {
MVKCmdBeginRenderPass* cmd = cmdBuff->_commandPool->_cmdBeginRenderPassPool.acquireObject();
cmd->setContent(pRenderPassBegin, contents);
cmdBuff->recordBeginRenderPass(cmd);
cmdBuff->addCommand(cmd);
}
@ -288,6 +291,7 @@ void mvkCmdNextSubpass(MVKCommandBuffer* cmdBuff, VkSubpassContents contents) {
void mvkCmdEndRenderPass(MVKCommandBuffer* cmdBuff) {
MVKCmdEndRenderPass* cmd = cmdBuff->_commandPool->_cmdEndRenderPassPool.acquireObject();
cmdBuff->recordEndRenderPass(cmd);
cmdBuff->addCommand(cmd);
}

View File

@ -112,3 +112,19 @@ protected:
MVKCommandPool* _commandPool;
};
#pragma mark -
#pragma mark MVKLoadStoreOverride
/** Shared state with all draw commands */
class MVKLoadStoreOverride {
public:
void setLoadOverride(bool loadOverride);
void setStoreOverride(bool storeOverride);
protected:
bool _loadOverride;
bool _storeOverride;
};

View File

@ -37,3 +37,16 @@ MVKDevice* MVKCommand::getDevice() { return getCommandPool()->getDevice(); }
id<MTLDevice> MVKCommand::getMTLDevice() { return getCommandPool()->getMTLDevice(); }
#pragma mark -
#pragma mark MVKLoadStoreOverride
void MVKLoadStoreOverride::setLoadOverride(bool loadOverride) {
_loadOverride = loadOverride;
}
void MVKLoadStoreOverride::setStoreOverride(bool storeOverride) {
_storeOverride = storeOverride;
}

View File

@ -39,6 +39,9 @@ class MVKQueryPool;
class MVKPipeline;
class MVKGraphicsPipeline;
class MVKComputePipeline;
class MVKCmdBeginRenderPass;
class MVKCmdEndRenderPass;
class MVKLoadStoreOverride;
typedef uint64_t MVKMTLCommandBufferID;
@ -98,6 +101,29 @@ public:
MVKCommandBuffer* _next;
#pragma mark Constituent render pass management
/** Preps metadata for recording render pass */
void recordBeginRenderPass(MVKCmdBeginRenderPass* mvkBeginRenderPass);
/** Finishes metadata for recording render pass */
void recordEndRenderPass(MVKCmdEndRenderPass* mvkEndRenderPass);
/** Update the last recorded pipeline if it will end and start a new Metal render pass (ie, in tessellation) */
void recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline);
/** Update the last recorded drawcall to determine load/store actions */
void recordDraw(MVKLoadStoreOverride* mvkDraw);
/** The most recent recorded begin renderpass */
MVKCmdBeginRenderPass* _lastBeginRenderPass;
/** The most recent recorded multi-pass (ie, tessellation) pipeline */
MVKCmdBindPipeline* _lastTessellationPipeline;
/** The most recent recorded multi-pass (ie, tessellation) draw */
MVKLoadStoreOverride* _lastTessellationDraw;
#pragma mark Construction
MVKCommandBuffer(MVKDevice* device) : MVKDispatchableDeviceObject(device) {}
@ -240,13 +266,15 @@ public:
MVKRenderPass* renderPass,
MVKFramebuffer* framebuffer,
VkRect2D& renderArea,
MVKVector<VkClearValue>* clearValues);
MVKVector<VkClearValue>* clearValues,
bool loadOverride = false,
bool storeOverride = false);
/** Begins the next render subpass. */
void beginNextSubpass(VkSubpassContents renderpassContents);
/** Begins a Metal render pass for the current render subpass. */
void beginMetalRenderPass(bool loadOverride = false);
void beginMetalRenderPass(bool loadOverride = false, bool storeOverride = false);
/** Returns the render subpass that is currently active. */
MVKRenderSubpass* getSubpass();
@ -327,7 +355,6 @@ public:
/** Marks a timestamp for the specified query. */
void markTimestamp(MVKQueryPool* pQueryPool, uint32_t query);
#pragma mark Dynamic encoding state accessed directly
/** A reference to the Metal features supported by the device. */
@ -398,7 +425,7 @@ public:
protected:
void addActivatedQuery(MVKQueryPool* pQueryPool, uint32_t query);
void finishQueries();
void setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex);
void setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex, bool loadOverride = false, bool storeOverride = false);
void clearRenderArea();
const MVKMTLBufferAllocation* copyToTempMTLBufferAllocation(const void* bytes, NSUInteger length);
NSString* getMTLRenderCommandEncoderName();

View File

@ -25,6 +25,7 @@
#include "MVKQueryPool.h"
#include "MVKFoundation.h"
#include "MTLRenderPassDescriptor+MoltenVK.h"
#include "MVKCmdDraw.h"
using namespace std;
@ -188,6 +189,44 @@ MVKCommandBuffer::~MVKCommandBuffer() {
}
#pragma mark -
#pragma mark Constituent render pass management
void MVKCommandBuffer::recordBeginRenderPass(MVKCmdBeginRenderPass* mvkBeginRenderPass) {
_lastBeginRenderPass = mvkBeginRenderPass;
_lastTessellationPipeline = nullptr;
_lastTessellationDraw = nullptr;
}
void MVKCommandBuffer::recordEndRenderPass(MVKCmdEndRenderPass* /*mvkEndRenderPass*/) {
// Unset the store override for the last draw call
if (_lastTessellationDraw != nullptr)
{
_lastTessellationDraw->setStoreOverride(false);
_lastBeginRenderPass->setStoreOverride(true);
}
_lastBeginRenderPass = nullptr;
_lastTessellationPipeline = nullptr;
_lastTessellationDraw = nullptr;
}
void MVKCommandBuffer::recordBindPipeline(MVKCmdBindPipeline* mvkBindPipeline) {
if (mvkBindPipeline->isTessellationPipeline())
_lastTessellationPipeline = mvkBindPipeline;
else
_lastTessellationPipeline = nullptr;
}
void MVKCommandBuffer::recordDraw(MVKLoadStoreOverride* mvkDraw) {
if (_lastTessellationPipeline != nullptr) {
// If a multi-pass pipeline is bound and we've already drawn something, need to override load actions
mvkDraw->setLoadOverride(true);
mvkDraw->setStoreOverride(true);
_lastTessellationDraw = mvkDraw;
}
}
#pragma mark -
#pragma mark MVKCommandEncoder
@ -219,14 +258,16 @@ void MVKCommandEncoder::beginRenderpass(VkSubpassContents subpassContents,
MVKRenderPass* renderPass,
MVKFramebuffer* framebuffer,
VkRect2D& renderArea,
MVKVector<VkClearValue>* clearValues) {
MVKVector<VkClearValue>* clearValues,
bool loadOverride,
bool storeOverride) {
_renderPass = renderPass;
_framebuffer = framebuffer;
_renderArea = renderArea;
_isRenderingEntireAttachment = (mvkVkOffset2DsAreEqual(_renderArea.offset, {0,0}) &&
mvkVkExtent2DsAreEqual(_renderArea.extent, _framebuffer->getExtent2D()));
_clearValues.assign(clearValues->begin(), clearValues->end());
setSubpass(subpassContents, 0);
setSubpass(subpassContents, 0, loadOverride, storeOverride);
}
void MVKCommandEncoder::beginNextSubpass(VkSubpassContents contents) {
@ -234,20 +275,20 @@ void MVKCommandEncoder::beginNextSubpass(VkSubpassContents contents) {
}
// Sets the current render subpass to the subpass with the specified index.
void MVKCommandEncoder::setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex) {
void MVKCommandEncoder::setSubpass(VkSubpassContents subpassContents, uint32_t subpassIndex, bool loadOverride, bool storeOverride) {
_subpassContents = subpassContents;
_renderSubpassIndex = subpassIndex;
beginMetalRenderPass();
beginMetalRenderPass(loadOverride, storeOverride);
}
// Creates _mtlRenderEncoder and marks cached render state as dirty so it will be set into the _mtlRenderEncoder.
void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride) {
void MVKCommandEncoder::beginMetalRenderPass(bool loadOverride, bool storeOverride) {
endCurrentMetalEncoding();
MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor];
getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _framebuffer, _clearValues, _isRenderingEntireAttachment, loadOverride);
getSubpass()->populateMTLRenderPassDescriptor(mtlRPDesc, _framebuffer, _clearValues, _isRenderingEntireAttachment, loadOverride, storeOverride);
mtlRPDesc.visibilityResultBuffer = _occlusionQueryState.getVisibilityResultMTLBuffer();
if (_device->_pMetalFeatures->layeredRendering) {

View File

@ -277,10 +277,10 @@ void MVKDepthStencilCommandEncoderState::setStencilWriteMask(VkStencilFaceFlags
}
void MVKDepthStencilCommandEncoderState::encodeImpl(uint32_t stage) {
if (stage != kMVKGraphicsStageRasterization) { return; }
if (stage != kMVKGraphicsStageRasterization && stage != kMVKGraphicsStageVertex) { return; }
MVKRenderSubpass *subpass = _cmdEncoder->getSubpass();
id<MTLDepthStencilState> mtlDSS = nil;
if (subpass->getDepthStencilFormat() != VK_FORMAT_UNDEFINED) {
if (stage != kMVKGraphicsStageVertex && subpass->getDepthStencilFormat() != VK_FORMAT_UNDEFINED) {
mtlDSS = _cmdEncoder->getCommandEncodingPool()->getMTLDepthStencilState(_depthStencilData);
} else {
// If there is no depth attachment but the depth/stencil state contains a non-always depth

View File

@ -168,7 +168,7 @@ kernel void cmdCopyBufferToImage3DDecompressTempBufferDXTn(constant uint8_t* src
} \n\
} \n\
\n\
#if __METAL_VERSION__ == 210 \n\
#if __METAL_VERSION__ >= 210 \n\
// This structure is missing from the MSL headers. :/ \n\
struct MTLStageInRegionIndirectArguments { \n\
uint32_t stageInOrigin[3]; \n\

View File

@ -386,8 +386,8 @@ id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdCopyBufferToImage3D
}
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndirectConvertBuffersMTLComputePipelineState(bool indexed) {
return newMTLComputePipelineState(getFunctionNamed(indexed ? "cmdDrawIndirectConvertBuffers" :
"cmdDrawIndexedIndirectConvertBuffers"));
return newMTLComputePipelineState(getFunctionNamed(indexed ? "cmdDrawIndexedIndirectConvertBuffers" :
"cmdDrawIndirectConvertBuffers"));
}
id<MTLComputePipelineState> MVKCommandResourceFactory::newCmdDrawIndexedCopyIndexBufferMTLComputePipelineState(MTLIndexType type) {

View File

@ -59,7 +59,8 @@ public:
MVKFramebuffer* framebuffer,
MVKVector<VkClearValue>& clearValues,
bool isRenderingEntireAttachment,
bool loadOverride = false);
bool loadOverride = false,
bool storeOverride = false);
/**
* Populates the specified vector with the attachments that need to be cleared
@ -113,7 +114,8 @@ public:
bool isRenderingEntireAttachment,
bool hasResolveAttachment,
bool isStencil,
bool loadOverride = false);
bool loadOverride = false,
bool storeOverride = false);
/** Returns whether this attachment should be cleared in the subpass. */
bool shouldUseClearAttachment(MVKRenderSubpass* subpass);

View File

@ -69,7 +69,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
MVKFramebuffer* framebuffer,
MVKVector<VkClearValue>& clearValues,
bool isRenderingEntireAttachment,
bool loadOverride) {
bool loadOverride,
bool storeOverride) {
// Populate the Metal color attachments
uint32_t caCnt = getColorAttachmentCount();
for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) {
@ -91,7 +92,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
if (clrMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlColorAttDesc, this,
isRenderingEntireAttachment,
hasResolveAttachment, false,
loadOverride)) {
loadOverride,
storeOverride)) {
mtlColorAttDesc.clearColor = mvkMTLClearColorFromVkClearValue(clearValues[clrRPAttIdx], clrMVKRPAtt->getFormat());
}
@ -113,7 +115,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlDepthAttDesc, this,
isRenderingEntireAttachment,
false, false,
loadOverride)) {
loadOverride,
storeOverride)) {
mtlDepthAttDesc.clearDepth = mvkMTLClearDepthFromVkClearValue(clearValues[dsRPAttIdx]);
}
}
@ -123,7 +126,8 @@ void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor*
if (dsMVKRPAtt->populateMTLRenderPassAttachmentDescriptor(mtlStencilAttDesc, this,
isRenderingEntireAttachment,
false, true,
loadOverride)) {
loadOverride,
storeOverride)) {
mtlStencilAttDesc.clearStencil = mvkMTLClearStencilFromVkClearValue(clearValues[dsRPAttIdx]);
}
}
@ -257,7 +261,8 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende
bool isRenderingEntireAttachment,
bool hasResolveAttachment,
bool isStencil,
bool loadOverride) {
bool loadOverride,
bool storeOverride) {
bool willClear = false; // Assume the attachment won't be cleared
@ -278,6 +283,8 @@ bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRende
// to the entire attachment and we're in the last subpass.
if (hasResolveAttachment && !_renderPass->getDevice()->getPhysicalDevice()->getMetalFeatures()->combinedStoreResolveAction) {
mtlAttDesc.storeAction = MTLStoreActionMultisampleResolve;
} else if ( storeOverride ) {
mtlAttDesc.storeAction = MTLStoreActionStore;
} else if ( isRenderingEntireAttachment && (subpass->_subpassIndex == _lastUseSubpassIdx) ) {
VkAttachmentStoreOp storeOp = isStencil ? _info.stencilStoreOp : _info.storeOp;
mtlAttDesc.storeAction = mvkMTLStoreActionFromVkAttachmentStoreOp(storeOp, hasResolveAttachment);