Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Transform feedback #1943

Draft
wants to merge 60 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
301d384
Advertise the VK_EXT_shader_demote_to_helper_invocation extension.
cdavis5e Oct 29, 2020
d010c61
Work around problems with explicit LoD with arrayed depth images on A…
cdavis5e Feb 3, 2023
0e5e28a
Merged in sample-dref-lod-array-workaround (pull request #5)
cdavis5e Feb 4, 2023
1c5cc7a
add in CMake build capability
gpx1000 May 18, 2023
ac64308
Advertise the VK_EXT_shader_demote_to_helper_invocation extension.
cdavis5e Oct 29, 2020
8aa8bfc
Merged in shader-demote-to-helper (pull request #6)
cdavis5e Jun 6, 2023
11aba7b
Transform Feedback initial implementation.
gpx1000 Jun 7, 2023
c00d168
Merge branch 'transform_feedback'
gpx1000 Jun 7, 2023
8450aa6
not sure how the merge commit didn't make it in.
gpx1000 Jun 7, 2023
56fa3b5
Merge remote-tracking branch 'origin/master'
gpx1000 Jun 14, 2023
dcd5873
Merge branch 'master' into transform_feedback
gpx1000 Jun 14, 2023
07bd3b0
make CMake work for all build types and fix the merge conflicts by up…
gpx1000 Jun 14, 2023
48c2a9c
1.) remove Query path as it is optional. We might add it in at a lat…
gpx1000 Jun 14, 2023
482c19a
put the counter buffers into the current graphics resources state.
gpx1000 Jun 19, 2023
c262cc4
address rest of comments.
gpx1000 Jun 19, 2023
39a9082
move buffers and try to write to them.
gpx1000 Jun 19, 2023
df3cd19
fix building
gpx1000 Jun 19, 2023
2489c0c
Add methods to map transform feedback bindings to Metal bindings.
cdavis5e Jun 19, 2023
f935aff
Working together with Chip
gpx1000 Jun 19, 2023
942b5bf
Working together with Chip
gpx1000 Jun 19, 2023
4cf27c6
update SPIRV-Cross_repo_revision to point at the right PR location.
gpx1000 Jun 19, 2023
bb1ddf6
Merge branch 'transform_feedback' into transform_feedback_public
gpx1000 Jun 19, 2023
8d131f2
Update SPIRV-Cross_repo_revision
gpx1000 Jun 20, 2023
17f5dc5
fix the build after merge conflicts
gpx1000 Jun 20, 2023
a7771ab
Merge remote-tracking branch 'upstream/transform_feedback_public' int…
gpx1000 Jun 20, 2023
2d7cc1f
Merge branch 'main' into transform_feedback_public
gpx1000 Jun 20, 2023
50830de
revert spriv-cross revision number
gpx1000 Jun 20, 2023
af071d3
Merge remote-tracking branch 'upstream/transform_feedback_public' int…
gpx1000 Jun 20, 2023
fc3c263
mystery merge error fix
gpx1000 Jun 20, 2023
6a8858c
Merge branch 'master' into transform_feedback
cdavis5e Jul 11, 2023
b5bcb0f
Add missing handling of `VK_EXT_transform_feedback` nuts and bolts.
cdavis5e Jul 17, 2023
01d6c1c
Remove extraneous `if`-branch.
cdavis5e Jul 17, 2023
244afc6
Merge remote-tracking branch 'origin/main' into transform_feedback
cdavis5e Sep 21, 2023
1bbfd3e
Checkpoint for transform feedback support.
cdavis5e Sep 22, 2023
c4977ad
Merge remote-tracking branch 'steve/transform_feedback_public' into t…
cdavis5e Sep 22, 2023
8c428a6
Really preliminary checkpoint for pass-through vertex shader support.
cdavis5e Oct 4, 2023
7f21588
Ridiculously small checkpoint with very little to show for it.
cdavis5e Oct 9, 2023
d112c8d
Grab outputs from the vertex shader in preparation for generating the…
cdavis5e Oct 11, 2023
2ed6387
Add bare-bones method to emit the pass-through vertex shader.
cdavis5e Oct 18, 2023
250a9a2
Incomplete checkpoint for getting XFB buffer indices and offsets from…
cdavis5e Oct 20, 2023
804fd9f
Add a little bit more reflection data for transform feedback.
cdavis5e Oct 23, 2023
92ea5ca
Add buffer parameters to the passthrough shader.
cdavis5e Oct 23, 2023
1f085a0
Generate the passthrough stage output structure.
cdavis5e Oct 25, 2023
5ccf045
Emit loads and stores in the passthrough vertex shader.
cdavis5e Oct 27, 2023
38c6533
Sort vertex shader outputs.
cdavis5e Oct 31, 2023
9422cbc
Emit the buffer structs.
cdavis5e Nov 2, 2023
3daf3f5
Return the XFB buffer stride.
cdavis5e Nov 3, 2023
d46b781
Emit padding for the buffer stride.
cdavis5e Nov 7, 2023
9976745
Remove redundant helper.
cdavis5e Nov 7, 2023
a4a7ac9
Handle clip/cull distances properly.
cdavis5e Nov 9, 2023
0e6d694
Also emit clip distance array to the rasterizer.
cdavis5e Nov 9, 2023
8fc4f2a
Recurisvely handle structure types in vertex input for XFB.
cdavis5e Nov 13, 2023
7eb2da8
Add the pass-through shader to the raster pipeline.
cdavis5e Nov 16, 2023
c6e3d88
Don't try to create a rasterization pipeline if we're not rasterizing.
cdavis5e Nov 17, 2023
c0581f4
Reserve buffer slots for the transform feedback buffers.
cdavis5e Nov 17, 2023
0fb9f33
Merge remote-tracking branch 'origin' into transform_feedback
cdavis5e Nov 17, 2023
159ee5f
Update some references to tessellation vertex shaders for XFB.
cdavis5e Nov 17, 2023
ba12429
Use the preexisting method on `MVKDevice` to get the XFB binding numb…
cdavis5e Nov 17, 2023
b604f13
Fix broken build.
cdavis5e Nov 18, 2023
be3a4b3
remove CMakeLists.txt from Transform Feedback PR.
gpx1000 Nov 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Docs/Whats_New.md
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,7 @@ Released 2020/12/09
- `VK_EXT_descriptor_indexing` (initial release limited to Metal Tier 1: 96/128 textures, 16 samplers)
- `VK_EXT_post_depth_coverage` (macOS)
- `VK_EXT_private_data`
- `VK_EXT_shader_demote_to_helper_invocation`
- `VK_EXT_subgroup_size_control`
- `VK_EXT_texture_compression_astc_hdr`
- `VK_AMD_shader_image_load_store` (macOS)
Expand Down
2 changes: 1 addition & 1 deletion ExternalRevisions/SPIRV-Cross_repo_revision
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4818f7e7ef7b7078a3a7a5a52c4a338e0dda22f4
15a8b709ffb9f941ed7fc48013bc7deda5659275
1 change: 1 addition & 0 deletions MoltenVK/MoltenVK/API/mvk_private_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ typedef struct {
VkBool32 needsSampleDrefLodArrayWorkaround; /**< If true, sampling from arrayed depth images with explicit LoD is broken and needs a workaround. */
VkDeviceSize hostMemoryPageSize; /**< The size of a page of host memory on this platform. */
VkBool32 dynamicVertexStride; /**< If true, VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE is supported. */
uint32_t maxTransformFeedbackBuffers; /**< The maximum transform feedback Buffers to support */
} MVKPhysicalDeviceMetalFeatures;

/**
Expand Down
102 changes: 102 additions & 0 deletions MoltenVK/MoltenVK/Commands/MVKCmdDraw.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,105 @@ class MVKCmdDrawIndexedIndirect : public MVKCommand {
uint32_t _drawCount;
uint32_t _directCmdFirstInstance;
};


#pragma mark -
#pragma mark MVKCmdBeginTransformFeedback

/*
* The active transform feedback buffers will capture primitives emitted from the corresponding XfbBuffer in the bound
* graphics pipeline. Any XfbBuffer emitted that does not output to an active transform feedback buffer will not be
* captured.
*/

template <size_t N>
class MVKCmdBeginTransformFeedback : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuffer,
uint32_t firstCounterBuffer,
uint32_t counterBufferCount,
const VkBuffer* counterBuffers,
const VkDeviceSize* counterBufferOffsets);
void encode(MVKCommandEncoder* cmdEncoder) override;

protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;

MVKSmallVector<MVKMTLBufferBinding, N> _counterBuffers;
};

// Concrete template class implementations.
typedef MVKCmdBeginTransformFeedback<1> MVKCmdBeginTransformFeedback1;
typedef MVKCmdBeginTransformFeedback<2> MVKCmdBeginTransformFeedback2;
typedef MVKCmdBeginTransformFeedback<4> MVKCmdBeginTransformFeedbackMulti;

#pragma mark -
#pragma mark MVKCmdBindTransformFeedbackBuffers

/*
* The values taken from elements i of pBuffers, pOffsets and pSizes replace the current state for the transform
* feedback binding firstBinding + i, for i in [0, bindingCount). The transform feedback binding is updated to start
* at the offset indicated by pOffsets[i] from the start of the buffer pBuffers[i].
*/
template <size_t N>
class MVKCmdBindTransformFeedbackBuffers : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuffer,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets,
const VkDeviceSize* pSizes);
void encode(MVKCommandEncoder* cmdEncoder) override;

protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;

MVKSmallVector<MVKMTLBufferBinding, N> _bindings;
};

// Concrete template class implementations.
typedef MVKCmdBindTransformFeedbackBuffers<1> MVKCmdBindTransformFeedbackBuffers1;
typedef MVKCmdBindTransformFeedbackBuffers<2> MVKCmdBindTransformFeedbackBuffers2;
typedef MVKCmdBindTransformFeedbackBuffers<4> MVKCmdBindTransformFeedbackBuffersMulti;

#pragma mark -
#pragma mark MVKCmdDrawIndirectByteCount

/*
* Draw primitives where the vertex count is derived from the counter byte value in the counter buffer
*/

class MVKCmdDrawIndirectByteCount : public MVKCommand {
public:
MVKCmdDrawIndirectByteCount() :
instanceCount(0), firstInstance(0), counterBuffer(), deviceSize(), stride() {}
VkResult setContent(MVKCommandBuffer* cmdBuffer,
uint32_t instanceCount,
uint32_t firstInstance,
VkBuffer counterBuffer,
uint32_t deviceSize,
uint32_t stride);
void encode(MVKCommandEncoder* cmdEncoder) override;

protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;

uint32_t instanceCount;
uint32_t firstInstance;
VkBuffer counterBuffer;
uint32_t deviceSize;
uint32_t stride;
};

#pragma mark -
#pragma mark MVKCmdEndTransformFeedback

class MVKCmdEndTransformFeedback : public MVKCommand {
public:
VkResult setContent(MVKCommandBuffer* cmdBuffer);
void encode(MVKCommandEncoder* cmdEncoder) override;

protected:
MVKCommandTypePool<MVKCommand>* getTypePool(MVKCommandPool* cmdPool) override;
};
147 changes: 134 additions & 13 deletions MoltenVK/MoltenVK/Commands/MVKCmdDraw.mm
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
#include "MVKCmdDraw.h"
#include "MVKCommandBuffer.h"
#include "MVKCommandPool.h"
#include "MVKBuffer.h"
#include "MVKPipeline.h"
#include "MVKFoundation.h"
#include "mvk_datatypes.hpp"


#pragma mark -
Expand All @@ -41,7 +38,7 @@
_bindings.reserve(bindingCount);
MVKMTLBufferBinding b;
for (uint32_t bindIdx = 0; bindIdx < bindingCount; bindIdx++) {
MVKBuffer* mvkBuffer = (MVKBuffer*)pBuffers[bindIdx];
auto* mvkBuffer = (MVKBuffer*)pBuffers[bindIdx];
b.index = mvkDvc->getMetalBufferIndexForVertexAttributeBinding(firstBinding + bindIdx);
b.mtlBuffer = mvkBuffer->getMTLBuffer();
b.offset = mvkBuffer->getMTLBufferOffset() + pOffsets[bindIdx];
Expand All @@ -66,11 +63,11 @@
#pragma mark -
#pragma mark MVKCmdBindIndexBuffer

VkResult MVKCmdBindIndexBuffer::setContent(MVKCommandBuffer* cmdBuff,
VkResult MVKCmdBindIndexBuffer::setContent(MVKCommandBuffer*,
VkBuffer buffer,
VkDeviceSize offset,
VkIndexType indexType) {
MVKBuffer* mvkBuffer = (MVKBuffer*)buffer;
auto* mvkBuffer = (MVKBuffer*)buffer;
_binding.mtlBuffer = mvkBuffer->getMTLBuffer();
_binding.offset = mvkBuffer->getMTLBufferOffset() + offset;
_binding.mtlIndexType = mvkMTLIndexTypeFromVkIndexType(indexType);
Expand Down Expand Up @@ -188,6 +185,16 @@
mtlTessCtlEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseTessellationVertexTessCtl);
if (pipeline->needsVertexOutputBuffer()) {
vtxOutBuff = cmdEncoder->getTempMTLBuffer(_vertexCount * _instanceCount * 4 * cmdEncoder->_pDeviceProperties->limits.maxVertexOutputComponents, true);
if (cmdEncoder->getDevice()->_enabledTransformFeedbackFeatures.transformFeedback &&
cmdEncoder->_transformFeedbackRunning) {
for (auto& xfbBufferBinding : cmdEncoder->_graphicsResourcesState
._transformFeedbackBufferBindings)
{
[mtlTessCtlEncoder setBuffer:xfbBufferBinding.mtlBuffer
offset:xfbBufferBinding.offset
atIndex:xfbBufferBinding.index];
}
}
[mtlTessCtlEncoder setBuffer: vtxOutBuff->_mtlBuffer
offset: vtxOutBuff->_offset
atIndex: pipeline->getOutputBufferIndex().stages[kMVKShaderStageVertex]];
Expand All @@ -196,7 +203,7 @@
// If there are vertex bindings with a zero vertex divisor, I need to offset them by
// _firstInstance * stride, since that is the expected behaviour for a divisor of 0.
cmdEncoder->_graphicsResourcesState.offsetZeroDivisorVertexBuffers(stage, pipeline, _firstInstance);
id<MTLComputePipelineState> vtxState = pipeline->getTessVertexStageState();
id<MTLComputePipelineState> vtxState = pipeline->getVertexStageState();
if (cmdEncoder->getDevice()->_pMetalFeatures->nonUniformThreadgroups) {
#if MVK_MACOS_OR_IOS
[mtlTessCtlEncoder dispatchThreads: MTLSizeMake(_vertexCount, _instanceCount, 1)
Expand Down Expand Up @@ -426,7 +433,7 @@
// If there are vertex bindings with a zero vertex divisor, I need to offset them by
// _firstInstance * stride, since that is the expected behaviour for a divisor of 0.
cmdEncoder->_graphicsResourcesState.offsetZeroDivisorVertexBuffers(stage, pipeline, _firstInstance);
id<MTLComputePipelineState> vtxState = ibb.mtlIndexType == MTLIndexTypeUInt16 ? pipeline->getTessVertexStageIndex16State() : pipeline->getTessVertexStageIndex32State();
id<MTLComputePipelineState> vtxState = ibb.mtlIndexType == MTLIndexTypeUInt16 ? pipeline->getVertexStageIndex16State() : pipeline->getVertexStageIndex32State();
if (cmdEncoder->getDevice()->_pMetalFeatures->nonUniformThreadgroups) {
#if MVK_MACOS_OR_IOS
[mtlTessCtlEncoder dispatchThreads: MTLSizeMake(_indexCount, _instanceCount, 1)
Expand Down Expand Up @@ -568,7 +575,7 @@
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride) {
MVKBuffer* mvkBuffer = (MVKBuffer*)buffer;
auto* mvkBuffer = (MVKBuffer*)buffer;
_mtlIndirectBuffer = mvkBuffer->getMTLBuffer();
_mtlIndirectBufferOffset = mvkBuffer->getMTLBufferOffset() + offset;
_mtlIndirectBufferStride = stride;
Expand Down Expand Up @@ -694,7 +701,7 @@
if (cmdEncoder->_pDeviceMetalFeatures->mslVersion >= 20100) {
indirectSize += sizeof(MTLStageInRegionIndirectArguments) * _drawCount;
}
paramsIncr = std::max((size_t)cmdEncoder->getDevice()->_pProperties->limits.minUniformBufferOffsetAlignment, sizeof(uint32_t) * 2);
paramsIncr = std::max<size_t>((size_t)cmdEncoder->getDevice()->_pProperties->limits.minUniformBufferOffsetAlignment, sizeof(uint32_t) * 2);
VkDeviceSize paramsSize = paramsIncr * _drawCount;
tempIndirectBuff = cmdEncoder->getTempMTLBuffer(indirectSize, true);
mtlIndBuff = tempIndirectBuff->_mtlBuffer;
Expand All @@ -712,7 +719,7 @@
}
tcLevelBuff = cmdEncoder->getTempMTLBuffer(patchCount * sizeof(MTLQuadTessellationFactorsHalf), true);

vtxThreadExecWidth = pipeline->getTessVertexStageState().threadExecutionWidth;
vtxThreadExecWidth = pipeline->getVertexStageState().threadExecutionWidth;
NSUInteger sgSize = pipeline->getTessControlStageState().threadExecutionWidth;
tcWorkgroupSize = mvkLeastCommonMultiple(outControlPointCount, sgSize);
while (tcWorkgroupSize > cmdEncoder->getDevice()->_pProperties->limits.maxComputeWorkGroupSize[0]) {
Expand Down Expand Up @@ -836,6 +843,7 @@
if ( !pipeline->hasValidMTLPipelineStates() ) { return; } // Abort if this pipeline stage could not be compiled.

switch (stage) {
//look for tesselation stage
case kMVKGraphicsStageVertex:
mtlTessCtlEncoder = cmdEncoder->getMTLComputeEncoder(kMVKCommandUseTessellationVertexTessCtl);
if (pipeline->needsVertexOutputBuffer()) {
Expand Down Expand Up @@ -1043,7 +1051,7 @@
if (cmdEncoder->_pDeviceMetalFeatures->mslVersion >= 20100) {
indirectSize += sizeof(MTLStageInRegionIndirectArguments) * _drawCount;
}
paramsIncr = std::max((size_t)cmdEncoder->getDevice()->_pProperties->limits.minUniformBufferOffsetAlignment, sizeof(uint32_t) * 2);
paramsIncr = std::max<size_t>((size_t)cmdEncoder->getDevice()->_pProperties->limits.minUniformBufferOffsetAlignment, sizeof(uint32_t) * 2);
VkDeviceSize paramsSize = paramsIncr * _drawCount;
tempIndirectBuff = cmdEncoder->getTempMTLBuffer(indirectSize, true);
mtlIndBuff = tempIndirectBuff->_mtlBuffer;
Expand All @@ -1063,7 +1071,7 @@
vtxIndexBuff = cmdEncoder->getTempMTLBuffer(ibb.mtlBuffer.length, true);

id<MTLComputePipelineState> vtxState;
vtxState = ibb.mtlIndexType == MTLIndexTypeUInt16 ? pipeline->getTessVertexStageIndex16State() : pipeline->getTessVertexStageIndex32State();
vtxState = ibb.mtlIndexType == MTLIndexTypeUInt16 ? pipeline->getVertexStageIndex16State() : pipeline->getVertexStageIndex32State();
vtxThreadExecWidth = vtxState.threadExecutionWidth;

NSUInteger sgSize = pipeline->getTessControlStageState().threadExecutionWidth;
Expand Down Expand Up @@ -1330,3 +1338,116 @@
}
}

#pragma mark -
#pragma mark MVKCmdBeginTransformFeedback

template <size_t N>
VkResult MVKCmdBeginTransformFeedback<N>::setContent(MVKCommandBuffer* cmdBuff,
uint32_t firstCounterBuffer,
uint32_t counterBufferCount,
const VkBuffer* pCounterBuffers,
const VkDeviceSize* pCounterBufferOffsets) {
MVKDevice* mvkDvc = cmdBuff->getDevice();
_counterBuffers.clear(); // Clear for reuse
_counterBuffers.reserve(counterBufferCount);
MVKMTLBufferBinding b;
for (uint32_t bindIdx = 0; bindIdx < counterBufferCount; bindIdx++) {
auto* mvkBuffer = (MVKBuffer*)pCounterBuffers[bindIdx];
b.index = mvkDvc->getMetalBufferIndexForTransformFeedbackCounterBinding(kMVKShaderStageVertex, firstCounterBuffer + bindIdx);
b.mtlBuffer = mvkBuffer->getMTLBuffer();
b.offset = mvkBuffer->getMTLBufferOffset() + pCounterBufferOffsets[bindIdx];
_counterBuffers.push_back(b);
}

return VK_SUCCESS;
}

template <size_t N>
void MVKCmdBeginTransformFeedback<N>::encode(MVKCommandEncoder* cmdEncoder) {
if (cmdEncoder->_transformFeedbackRunning) {
return;
}

cmdEncoder->_graphicsResourcesState._transformFeedbackCounterBufferBinding = _counterBuffers[0];
cmdEncoder->_transformFeedbackRunning = true;
}

template class MVKCmdBeginTransformFeedback<1>;
template class MVKCmdBeginTransformFeedback<2>;
template class MVKCmdBeginTransformFeedback<4>;


#pragma mark -
#pragma mark MVKCmdBindTransformFeedbackBuffers

template <size_t N>
VkResult MVKCmdBindTransformFeedbackBuffers<N>::setContent(MVKCommandBuffer *cmdBuffer,
uint32_t firstBinding, uint32_t bindingCount,
const VkBuffer *pBuffers,
const VkDeviceSize *pOffsets,
const VkDeviceSize *pSizes) {
MVKDevice* mvkDvc = cmdBuffer->getDevice();
_bindings.clear(); // Clear for reuse
_bindings.reserve(bindingCount);
MVKMTLBufferBinding b;
for (uint32_t bindIdx = 0; bindIdx < bindingCount; bindIdx++) {
auto* mvkBuffer = (MVKBuffer*)pBuffers[bindIdx];
b.index = mvkDvc->getMetalBufferIndexForTransformFeedbackBinding(kMVKShaderStageVertex, firstBinding + bindIdx);
b.mtlBuffer = mvkBuffer->getMTLBuffer();
b.offset = mvkBuffer->getMTLBufferOffset() + pOffsets[bindIdx];
if (pSizes != nullptr) {
if (pSizes[bindIdx] == VK_WHOLE_SIZE) {
b.size = b.mtlBuffer.allocatedSize - b.offset;
} else {
b.size = pSizes[bindIdx];
}
} else {
b.size = b.mtlBuffer.allocatedSize - b.offset;
}
_bindings.push_back(b);
}

return VK_SUCCESS;
}

template <size_t N>
void MVKCmdBindTransformFeedbackBuffers<N>::encode(MVKCommandEncoder *cmdEncoder) {
cmdEncoder->_graphicsResourcesState._transformFeedbackBufferBindings.clear();
for (auto& b : _bindings) { cmdEncoder->_graphicsResourcesState._transformFeedbackBufferBindings.push_back(b); }
}

template class MVKCmdBindTransformFeedbackBuffers<1>;
template class MVKCmdBindTransformFeedbackBuffers<2>;
template class MVKCmdBindTransformFeedbackBuffers<4>;


#pragma mark -
#pragma mark MVKCmdDrawIndirectByteCount

VkResult MVKCmdDrawIndirectByteCount::setContent(MVKCommandBuffer *cmdBuffer,
uint32_t _instanceCount, uint32_t _firstInstance,
VkBuffer _counterBuffer, uint32_t _deviceSize, uint32_t _stride) {
/// @TODO SW: this extension allows drawing from the transform feedback buffers
instanceCount = _instanceCount;
firstInstance = _firstInstance;
counterBuffer = _counterBuffer;
deviceSize = _deviceSize;
stride = _stride;
return cmdBuffer->reportError(VK_ERROR_FEATURE_NOT_PRESENT, "DrawIndirectByteCount is not yet implemented");
}

void MVKCmdDrawIndirectByteCount::encode(MVKCommandEncoder *cmdEncoder) {
/// @TODO SW: this extension allows drawing from the transform feedback buffers
(void) cmdEncoder;
}

#pragma mark -
#pragma mark MVKCmdEndTransformFeedback

VkResult MVKCmdEndTransformFeedback::setContent(MVKCommandBuffer *) {
return VK_SUCCESS;
}

void MVKCmdEndTransformFeedback::encode(MVKCommandEncoder *cmdEncoder) {
cmdEncoder->_transformFeedbackRunning = false;
}
4 changes: 4 additions & 0 deletions MoltenVK/MoltenVK/Commands/MVKCommandBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,10 @@ class MVKCommandEncoder : public MVKBaseDeviceObject {
/** Indicates whether the current draw is an indexed draw. */
bool _isIndexedDraw;

/** If true, transform feedback is currently running. */
VkBool32 _transformFeedbackRunning;


#pragma mark Construction

MVKCommandEncoder(MVKCommandBuffer* cmdBuffer,
Expand Down
4 changes: 4 additions & 0 deletions MoltenVK/MoltenVK/Commands/MVKCommandEncoderState.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@ class MVKGraphicsResourcesCommandEncoderState : public MVKResourcesCommandEncode

/** The type of index that will be used to render primitives. Exposed directly. */
MVKIndexMTLBufferBinding _mtlIndexBufferBinding;
MVKMTLBufferBinding _transformFeedbackCounterBufferBinding;
MVKSmallVector<MVKMTLBufferBinding, 4> _transformFeedbackBufferBindings;

/** Binds the specified index buffer. */
void bindIndexBuffer(const MVKIndexMTLBufferBinding& binding) {
Expand Down Expand Up @@ -539,6 +541,8 @@ class MVKGraphicsResourcesCommandEncoderState : public MVKResourcesCommandEncode
bool needVertexViewBuffer,
bool needFragmentViewBuffer);

void bindTransformFeedbackBuffer(MVKMTLBufferBinding binding);

void encodeBindings(MVKShaderStage stage,
const char* pStageName,
bool fullImageViewSwizzle,
Expand Down
Loading
Loading