Merge branch 'master' of https://github.com/KhronosGroup/MoltenVK
This commit is contained in:
commit
e91d2f6b35
@ -1 +1 @@
|
||||
ac5a9570a744eb72725c23c34f36fbc564c0bb51
|
||||
942273dc7b107d4f0c2cf3449ae306525e1cbae7
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,8 @@ public:
|
||||
|
||||
MVKCmdBindPipeline(MVKCommandTypePool<MVKCmdBindPipeline>* pool);
|
||||
|
||||
bool isTessellationPipeline();
|
||||
|
||||
private:
|
||||
VkPipelineBindPoint _bindPoint;
|
||||
MVKPipeline* _pipeline;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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\
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user