D3D12: Indirect validation shader name cleanup and parameter merge
Bug: dawn:548 Change-Id: Id2bf9c54e10ba791e5878844a0fe98efd4fc85d6 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/87705 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Enrico Galli <enrico.galli@intel.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
857175e59b
commit
b52d740227
|
@ -39,7 +39,7 @@ namespace dawn::native {
|
||||||
uint32_t maxDrawCallsPerIndirectValidationBatch,
|
uint32_t maxDrawCallsPerIndirectValidationBatch,
|
||||||
uint64_t maxBatchOffsetRange,
|
uint64_t maxBatchOffsetRange,
|
||||||
IndirectDraw draw) {
|
IndirectDraw draw) {
|
||||||
const uint64_t newOffset = draw.clientBufferOffset;
|
const uint64_t newOffset = draw.inputBufferOffset;
|
||||||
auto it = mBatches.begin();
|
auto it = mBatches.begin();
|
||||||
while (it != mBatches.end()) {
|
while (it != mBatches.end()) {
|
||||||
IndirectValidationBatch& batch = *it;
|
IndirectValidationBatch& batch = *it;
|
||||||
|
@ -186,7 +186,7 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
IndirectDraw draw{};
|
IndirectDraw draw{};
|
||||||
draw.clientBufferOffset = indirectOffset;
|
draw.inputBufferOffset = indirectOffset;
|
||||||
draw.cmd = cmd;
|
draw.cmd = cmd;
|
||||||
it->second.AddIndirectDraw(mMaxDrawCallsPerBatch, mMaxBatchOffsetRange, draw);
|
it->second.AddIndirectDraw(mMaxDrawCallsPerBatch, mMaxBatchOffsetRange, draw);
|
||||||
}
|
}
|
||||||
|
@ -205,23 +205,23 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
IndirectDraw draw{};
|
IndirectDraw draw{};
|
||||||
draw.clientBufferOffset = indirectOffset;
|
draw.inputBufferOffset = indirectOffset;
|
||||||
draw.cmd = cmd;
|
draw.cmd = cmd;
|
||||||
it->second.AddIndirectDraw(mMaxDrawCallsPerBatch, mMaxBatchOffsetRange, draw);
|
it->second.AddIndirectDraw(mMaxDrawCallsPerBatch, mMaxBatchOffsetRange, draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IndirectDrawMetadata::IndexedIndirectConfig::operator<(
|
bool IndirectDrawMetadata::IndexedIndirectConfig::operator<(
|
||||||
const IndexedIndirectConfig& other) const {
|
const IndexedIndirectConfig& other) const {
|
||||||
return std::tie(clientIndirectBuffer, numIndexBufferElements, duplicateBaseVertexInstance,
|
return std::tie(inputIndirectBuffer, numIndexBufferElements, duplicateBaseVertexInstance,
|
||||||
drawType) < std::tie(other.clientIndirectBuffer,
|
drawType) < std::tie(other.inputIndirectBuffer,
|
||||||
other.numIndexBufferElements,
|
other.numIndexBufferElements,
|
||||||
other.duplicateBaseVertexInstance, other.drawType);
|
other.duplicateBaseVertexInstance, other.drawType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IndirectDrawMetadata::IndexedIndirectConfig::operator==(
|
bool IndirectDrawMetadata::IndexedIndirectConfig::operator==(
|
||||||
const IndexedIndirectConfig& other) const {
|
const IndexedIndirectConfig& other) const {
|
||||||
return std::tie(clientIndirectBuffer, numIndexBufferElements, duplicateBaseVertexInstance,
|
return std::tie(inputIndirectBuffer, numIndexBufferElements, duplicateBaseVertexInstance,
|
||||||
drawType) == std::tie(other.clientIndirectBuffer,
|
drawType) == std::tie(other.inputIndirectBuffer,
|
||||||
other.numIndexBufferElements,
|
other.numIndexBufferElements,
|
||||||
other.duplicateBaseVertexInstance, other.drawType);
|
other.duplicateBaseVertexInstance, other.drawType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace dawn::native {
|
||||||
class IndirectDrawMetadata : public NonCopyable {
|
class IndirectDrawMetadata : public NonCopyable {
|
||||||
public:
|
public:
|
||||||
struct IndirectDraw {
|
struct IndirectDraw {
|
||||||
uint64_t clientBufferOffset;
|
uint64_t inputBufferOffset;
|
||||||
// This is a pointer to the command that should be populated with the validated
|
// This is a pointer to the command that should be populated with the validated
|
||||||
// indirect scratch buffer. It is only valid up until the encoded command buffer
|
// indirect scratch buffer. It is only valid up until the encoded command buffer
|
||||||
// is submitted.
|
// is submitted.
|
||||||
|
@ -97,7 +97,7 @@ namespace dawn::native {
|
||||||
Indexed,
|
Indexed,
|
||||||
};
|
};
|
||||||
struct IndexedIndirectConfig {
|
struct IndexedIndirectConfig {
|
||||||
BufferBase* clientIndirectBuffer;
|
BufferBase* inputIndirectBuffer;
|
||||||
uint64_t numIndexBufferElements;
|
uint64_t numIndexBufferElements;
|
||||||
bool duplicateBaseVertexInstance;
|
bool duplicateBaseVertexInstance;
|
||||||
DrawType drawType;
|
DrawType drawType;
|
||||||
|
|
|
@ -78,10 +78,10 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
@group(0) @binding(0) var<storage, read> batch: BatchInfo;
|
@group(0) @binding(0) var<storage, read> batch: BatchInfo;
|
||||||
@group(0) @binding(1) var<storage, read_write> clientParams: IndirectParams;
|
@group(0) @binding(1) var<storage, read_write> inputParams: IndirectParams;
|
||||||
@group(0) @binding(2) var<storage, write> validatedParams: IndirectParams;
|
@group(0) @binding(2) var<storage, write> outputParams: IndirectParams;
|
||||||
|
|
||||||
fn numIndirectParamsPerDrawCallClient() -> u32 {
|
fn numIndirectParamsPerDrawCallInput() -> u32 {
|
||||||
var numParams = kNumDrawIndirectParams;
|
var numParams = kNumDrawIndirectParams;
|
||||||
// Indexed Draw has an extra parameter (firstIndex)
|
// Indexed Draw has an extra parameter (firstIndex)
|
||||||
if (bool(batch.flags & kIndexedDraw)) {
|
if (bool(batch.flags & kIndexedDraw)) {
|
||||||
|
@ -90,8 +90,8 @@ namespace dawn::native {
|
||||||
return numParams;
|
return numParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn numIndirectParamsPerDrawCallValidated() -> u32 {
|
fn numIndirectParamsPerDrawCallOutput() -> u32 {
|
||||||
var numParams = numIndirectParamsPerDrawCallClient();
|
var numParams = numIndirectParamsPerDrawCallInput();
|
||||||
// 2 extra parameter for duplicated first/baseVexter and firstInstance
|
// 2 extra parameter for duplicated first/baseVexter and firstInstance
|
||||||
if (bool(batch.flags & kDuplicateBaseVertexInstance)) {
|
if (bool(batch.flags & kDuplicateBaseVertexInstance)) {
|
||||||
numParams = numParams + 2u;
|
numParams = numParams + 2u;
|
||||||
|
@ -100,31 +100,31 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fail(drawIndex: u32) {
|
fn fail(drawIndex: u32) {
|
||||||
let numParams = numIndirectParamsPerDrawCallValidated();
|
let numParams = numIndirectParamsPerDrawCallOutput();
|
||||||
let index = drawIndex * numParams;
|
let index = drawIndex * numParams;
|
||||||
for(var i = 0u; i < numParams; i = i + 1u) {
|
for(var i = 0u; i < numParams; i = i + 1u) {
|
||||||
validatedParams.data[index + i] = 0u;
|
outputParams.data[index + i] = 0u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pass(drawIndex: u32) {
|
fn pass(drawIndex: u32) {
|
||||||
let numClientParams = numIndirectParamsPerDrawCallClient();
|
let numInputParams = numIndirectParamsPerDrawCallInput();
|
||||||
var vIndex = drawIndex * numIndirectParamsPerDrawCallValidated();
|
var outIndex = drawIndex * numIndirectParamsPerDrawCallOutput();
|
||||||
let cIndex = batch.indirectOffsets[drawIndex];
|
let inIndex = batch.indirectOffsets[drawIndex];
|
||||||
|
|
||||||
// The first 2 parameter is reserved for the duplicated first/baseVertex and firstInstance
|
// The first 2 parameter is reserved for the duplicated first/baseVertex and firstInstance
|
||||||
|
|
||||||
if (bool(batch.flags & kDuplicateBaseVertexInstance)) {
|
if (bool(batch.flags & kDuplicateBaseVertexInstance)) {
|
||||||
// first/baseVertex and firstInstance are always last two parameters
|
// first/baseVertex and firstInstance are always last two parameters
|
||||||
let dupIndex = cIndex + numClientParams - 2u;
|
let dupIndex = inIndex + numInputParams - 2u;
|
||||||
validatedParams.data[vIndex] = clientParams.data[dupIndex];
|
outputParams.data[outIndex] = inputParams.data[dupIndex];
|
||||||
validatedParams.data[vIndex + 1u] = clientParams.data[dupIndex + 1u];
|
outputParams.data[outIndex + 1u] = inputParams.data[dupIndex + 1u];
|
||||||
|
|
||||||
vIndex = vIndex + 2u;
|
outIndex = outIndex + 2u;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0u; i < numClientParams; i = i + 1u) {
|
for(var i = 0u; i < numInputParams; i = i + 1u) {
|
||||||
validatedParams.data[vIndex + i] = clientParams.data[cIndex + i];
|
outputParams.data[outIndex + i] = inputParams.data[inIndex + i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,9 +139,9 @@ namespace dawn::native {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let clientIndex = batch.indirectOffsets[id.x];
|
let inputIndex = batch.indirectOffsets[id.x];
|
||||||
// firstInstance is always the last parameter
|
// firstInstance is always the last parameter
|
||||||
let firstInstance = clientParams.data[clientIndex + numIndirectParamsPerDrawCallClient() - 1u];
|
let firstInstance = inputParams.data[inputIndex + numIndirectParamsPerDrawCallInput() - 1u];
|
||||||
if (firstInstance != 0u) {
|
if (firstInstance != 0u) {
|
||||||
fail(id.x);
|
fail(id.x);
|
||||||
return;
|
return;
|
||||||
|
@ -159,7 +159,7 @@ namespace dawn::native {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let firstIndex = clientParams.data[clientIndex + kFirstIndexEntry];
|
let firstIndex = inputParams.data[inputIndex + kFirstIndexEntry];
|
||||||
if (batch.numIndexBufferElementsHigh == 0u &&
|
if (batch.numIndexBufferElementsHigh == 0u &&
|
||||||
batch.numIndexBufferElementsLow < firstIndex) {
|
batch.numIndexBufferElementsLow < firstIndex) {
|
||||||
fail(id.x);
|
fail(id.x);
|
||||||
|
@ -169,7 +169,7 @@ namespace dawn::native {
|
||||||
// Note that this subtraction may underflow, but only when
|
// Note that this subtraction may underflow, but only when
|
||||||
// numIndexBufferElementsHigh is 1u. The result is still correct in that case.
|
// numIndexBufferElementsHigh is 1u. The result is still correct in that case.
|
||||||
let maxIndexCount = batch.numIndexBufferElementsLow - firstIndex;
|
let maxIndexCount = batch.numIndexBufferElementsLow - firstIndex;
|
||||||
let indexCount = clientParams.data[clientIndex + kIndexCountEntry];
|
let indexCount = inputParams.data[inputIndex + kIndexCountEntry];
|
||||||
if (indexCount > maxIndexCount) {
|
if (indexCount > maxIndexCount) {
|
||||||
fail(id.x);
|
fail(id.x);
|
||||||
return;
|
return;
|
||||||
|
@ -244,17 +244,17 @@ namespace dawn::native {
|
||||||
uint64_t numIndexBufferElements;
|
uint64_t numIndexBufferElements;
|
||||||
uint64_t dataBufferOffset;
|
uint64_t dataBufferOffset;
|
||||||
uint64_t dataSize;
|
uint64_t dataSize;
|
||||||
uint64_t clientIndirectOffset;
|
uint64_t inputIndirectOffset;
|
||||||
uint64_t clientIndirectSize;
|
uint64_t inputIndirectSize;
|
||||||
uint64_t validatedParamsOffset;
|
uint64_t outputParamsOffset;
|
||||||
uint64_t validatedParamsSize;
|
uint64_t outputParamsSize;
|
||||||
BatchInfo* batchInfo;
|
BatchInfo* batchInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Pass {
|
struct Pass {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
BufferBase* clientIndirectBuffer;
|
BufferBase* inputIndirectBuffer;
|
||||||
uint64_t validatedParamsSize = 0;
|
uint64_t outputParamsSize = 0;
|
||||||
uint64_t batchDataSize = 0;
|
uint64_t batchDataSize = 0;
|
||||||
std::unique_ptr<void, void (*)(void*)> batchData{nullptr, std::free};
|
std::unique_ptr<void, void (*)(void*)> batchData{nullptr, std::free};
|
||||||
std::vector<Batch> batches;
|
std::vector<Batch> batches;
|
||||||
|
@ -264,7 +264,7 @@ namespace dawn::native {
|
||||||
// single pass as possible. Batches can be grouped together as long as they're validating
|
// single pass as possible. Batches can be grouped together as long as they're validating
|
||||||
// data from the same indirect buffer, but they may still be split into multiple passes if
|
// data from the same indirect buffer, but they may still be split into multiple passes if
|
||||||
// the number of draw calls in a pass would exceed some (very high) upper bound.
|
// the number of draw calls in a pass would exceed some (very high) upper bound.
|
||||||
uint64_t validatedParamsSize = 0;
|
uint64_t outputParamsSize = 0;
|
||||||
std::vector<Pass> passes;
|
std::vector<Pass> passes;
|
||||||
IndirectDrawMetadata::IndexedIndirectBufferValidationInfoMap& bufferInfoMap =
|
IndirectDrawMetadata::IndexedIndirectBufferValidationInfoMap& bufferInfoMap =
|
||||||
*indirectDrawMetadata->GetIndexedIndirectBufferValidationInfo();
|
*indirectDrawMetadata->GetIndexedIndirectBufferValidationInfo();
|
||||||
|
@ -283,9 +283,9 @@ namespace dawn::native {
|
||||||
? kDrawIndexedIndirectSize
|
? kDrawIndexedIndirectSize
|
||||||
: kDrawIndirectSize;
|
: kDrawIndirectSize;
|
||||||
|
|
||||||
uint64_t validatedIndirectSize = indirectDrawCommandSize;
|
uint64_t outputIndirectSize = indirectDrawCommandSize;
|
||||||
if (config.duplicateBaseVertexInstance) {
|
if (config.duplicateBaseVertexInstance) {
|
||||||
validatedIndirectSize += 2 * sizeof(uint32_t);
|
outputIndirectSize += 2 * sizeof(uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const IndirectDrawMetadata::IndirectValidationBatch& batch :
|
for (const IndirectDrawMetadata::IndirectValidationBatch& batch :
|
||||||
|
@ -299,21 +299,20 @@ namespace dawn::native {
|
||||||
newBatch.metadata = &batch;
|
newBatch.metadata = &batch;
|
||||||
newBatch.numIndexBufferElements = config.numIndexBufferElements;
|
newBatch.numIndexBufferElements = config.numIndexBufferElements;
|
||||||
newBatch.dataSize = GetBatchDataSize(batch.draws.size());
|
newBatch.dataSize = GetBatchDataSize(batch.draws.size());
|
||||||
newBatch.clientIndirectOffset = minOffsetAlignedDown;
|
newBatch.inputIndirectOffset = minOffsetAlignedDown;
|
||||||
newBatch.clientIndirectSize =
|
newBatch.inputIndirectSize =
|
||||||
batch.maxOffset + indirectDrawCommandSize - minOffsetAlignedDown;
|
batch.maxOffset + indirectDrawCommandSize - minOffsetAlignedDown;
|
||||||
|
|
||||||
newBatch.validatedParamsSize = batch.draws.size() * validatedIndirectSize;
|
newBatch.outputParamsSize = batch.draws.size() * outputIndirectSize;
|
||||||
newBatch.validatedParamsOffset =
|
newBatch.outputParamsOffset =
|
||||||
Align(validatedParamsSize, minStorageBufferOffsetAlignment);
|
Align(outputParamsSize, minStorageBufferOffsetAlignment);
|
||||||
validatedParamsSize = newBatch.validatedParamsOffset + newBatch.validatedParamsSize;
|
outputParamsSize = newBatch.outputParamsOffset + newBatch.outputParamsSize;
|
||||||
if (validatedParamsSize > maxStorageBufferBindingSize) {
|
if (outputParamsSize > maxStorageBufferBindingSize) {
|
||||||
return DAWN_INTERNAL_ERROR("Too many drawIndexedIndirect calls to validate");
|
return DAWN_INTERNAL_ERROR("Too many drawIndexedIndirect calls to validate");
|
||||||
}
|
}
|
||||||
|
|
||||||
Pass* currentPass = passes.empty() ? nullptr : &passes.back();
|
Pass* currentPass = passes.empty() ? nullptr : &passes.back();
|
||||||
if (currentPass &&
|
if (currentPass && currentPass->inputIndirectBuffer == config.inputIndirectBuffer) {
|
||||||
currentPass->clientIndirectBuffer == config.clientIndirectBuffer) {
|
|
||||||
uint64_t nextBatchDataOffset =
|
uint64_t nextBatchDataOffset =
|
||||||
Align(currentPass->batchDataSize, minStorageBufferOffsetAlignment);
|
Align(currentPass->batchDataSize, minStorageBufferOffsetAlignment);
|
||||||
uint64_t newPassBatchDataSize = nextBatchDataOffset + newBatch.dataSize;
|
uint64_t newPassBatchDataSize = nextBatchDataOffset + newBatch.dataSize;
|
||||||
|
@ -330,7 +329,7 @@ namespace dawn::native {
|
||||||
newBatch.dataBufferOffset = 0;
|
newBatch.dataBufferOffset = 0;
|
||||||
|
|
||||||
Pass newPass{};
|
Pass newPass{};
|
||||||
newPass.clientIndirectBuffer = config.clientIndirectBuffer;
|
newPass.inputIndirectBuffer = config.inputIndirectBuffer;
|
||||||
newPass.batchDataSize = newBatch.dataSize;
|
newPass.batchDataSize = newBatch.dataSize;
|
||||||
newPass.batches.push_back(newBatch);
|
newPass.batches.push_back(newBatch);
|
||||||
newPass.flags = 0;
|
newPass.flags = 0;
|
||||||
|
@ -348,7 +347,7 @@ namespace dawn::native {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* const store = device->GetInternalPipelineStore();
|
auto* const store = device->GetInternalPipelineStore();
|
||||||
ScratchBuffer& validatedParamsBuffer = store->scratchIndirectStorage;
|
ScratchBuffer& outputParamsBuffer = store->scratchIndirectStorage;
|
||||||
ScratchBuffer& batchDataBuffer = store->scratchStorage;
|
ScratchBuffer& batchDataBuffer = store->scratchStorage;
|
||||||
|
|
||||||
uint64_t requiredBatchDataBufferSize = 0;
|
uint64_t requiredBatchDataBufferSize = 0;
|
||||||
|
@ -358,8 +357,8 @@ namespace dawn::native {
|
||||||
DAWN_TRY(batchDataBuffer.EnsureCapacity(requiredBatchDataBufferSize));
|
DAWN_TRY(batchDataBuffer.EnsureCapacity(requiredBatchDataBufferSize));
|
||||||
usageTracker->BufferUsedAs(batchDataBuffer.GetBuffer(), wgpu::BufferUsage::Storage);
|
usageTracker->BufferUsedAs(batchDataBuffer.GetBuffer(), wgpu::BufferUsage::Storage);
|
||||||
|
|
||||||
DAWN_TRY(validatedParamsBuffer.EnsureCapacity(validatedParamsSize));
|
DAWN_TRY(outputParamsBuffer.EnsureCapacity(outputParamsSize));
|
||||||
usageTracker->BufferUsedAs(validatedParamsBuffer.GetBuffer(), wgpu::BufferUsage::Indirect);
|
usageTracker->BufferUsedAs(outputParamsBuffer.GetBuffer(), wgpu::BufferUsage::Indirect);
|
||||||
|
|
||||||
// Now we allocate and populate host-side batch data to be copied to the GPU.
|
// Now we allocate and populate host-side batch data to be copied to the GPU.
|
||||||
for (Pass& pass : passes) {
|
for (Pass& pass : passes) {
|
||||||
|
@ -374,18 +373,18 @@ namespace dawn::native {
|
||||||
batch.batchInfo->flags = pass.flags;
|
batch.batchInfo->flags = pass.flags;
|
||||||
|
|
||||||
uint32_t* indirectOffsets = reinterpret_cast<uint32_t*>(batch.batchInfo + 1);
|
uint32_t* indirectOffsets = reinterpret_cast<uint32_t*>(batch.batchInfo + 1);
|
||||||
uint64_t validatedParamsOffset = batch.validatedParamsOffset;
|
uint64_t outputParamsOffset = batch.outputParamsOffset;
|
||||||
for (auto& draw : batch.metadata->draws) {
|
for (auto& draw : batch.metadata->draws) {
|
||||||
// The shader uses this to index an array of u32, hence the division by 4 bytes.
|
// The shader uses this to index an array of u32, hence the division by 4 bytes.
|
||||||
*indirectOffsets++ = static_cast<uint32_t>(
|
*indirectOffsets++ = static_cast<uint32_t>(
|
||||||
(draw.clientBufferOffset - batch.clientIndirectOffset) / 4);
|
(draw.inputBufferOffset - batch.inputIndirectOffset) / 4);
|
||||||
|
|
||||||
draw.cmd->indirectBuffer = validatedParamsBuffer.GetBuffer();
|
draw.cmd->indirectBuffer = outputParamsBuffer.GetBuffer();
|
||||||
draw.cmd->indirectOffset = validatedParamsOffset;
|
draw.cmd->indirectOffset = outputParamsOffset;
|
||||||
if (pass.flags & kIndexedDraw) {
|
if (pass.flags & kIndexedDraw) {
|
||||||
validatedParamsOffset += kDrawIndexedIndirectSize;
|
outputParamsOffset += kDrawIndexedIndirectSize;
|
||||||
} else {
|
} else {
|
||||||
validatedParamsOffset += kDrawIndirectSize;
|
outputParamsOffset += kDrawIndirectSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,12 +401,12 @@ namespace dawn::native {
|
||||||
bufferDataBinding.binding = 0;
|
bufferDataBinding.binding = 0;
|
||||||
bufferDataBinding.buffer = batchDataBuffer.GetBuffer();
|
bufferDataBinding.buffer = batchDataBuffer.GetBuffer();
|
||||||
|
|
||||||
BindGroupEntry& clientIndirectBinding = bindings[1];
|
BindGroupEntry& inputIndirectBinding = bindings[1];
|
||||||
clientIndirectBinding.binding = 1;
|
inputIndirectBinding.binding = 1;
|
||||||
|
|
||||||
BindGroupEntry& validatedParamsBinding = bindings[2];
|
BindGroupEntry& outputParamsBinding = bindings[2];
|
||||||
validatedParamsBinding.binding = 2;
|
outputParamsBinding.binding = 2;
|
||||||
validatedParamsBinding.buffer = validatedParamsBuffer.GetBuffer();
|
outputParamsBinding.buffer = outputParamsBuffer.GetBuffer();
|
||||||
|
|
||||||
BindGroupDescriptor bindGroupDescriptor = {};
|
BindGroupDescriptor bindGroupDescriptor = {};
|
||||||
bindGroupDescriptor.layout = layout.Get();
|
bindGroupDescriptor.layout = layout.Get();
|
||||||
|
@ -426,15 +425,15 @@ namespace dawn::native {
|
||||||
Ref<ComputePassEncoder> passEncoder = commandEncoder->BeginComputePass();
|
Ref<ComputePassEncoder> passEncoder = commandEncoder->BeginComputePass();
|
||||||
passEncoder->APISetPipeline(pipeline);
|
passEncoder->APISetPipeline(pipeline);
|
||||||
|
|
||||||
clientIndirectBinding.buffer = pass.clientIndirectBuffer;
|
inputIndirectBinding.buffer = pass.inputIndirectBuffer;
|
||||||
|
|
||||||
for (const Batch& batch : pass.batches) {
|
for (const Batch& batch : pass.batches) {
|
||||||
bufferDataBinding.offset = batch.dataBufferOffset;
|
bufferDataBinding.offset = batch.dataBufferOffset;
|
||||||
bufferDataBinding.size = batch.dataSize;
|
bufferDataBinding.size = batch.dataSize;
|
||||||
clientIndirectBinding.offset = batch.clientIndirectOffset;
|
inputIndirectBinding.offset = batch.inputIndirectOffset;
|
||||||
clientIndirectBinding.size = batch.clientIndirectSize;
|
inputIndirectBinding.size = batch.inputIndirectSize;
|
||||||
validatedParamsBinding.offset = batch.validatedParamsOffset;
|
outputParamsBinding.offset = batch.outputParamsOffset;
|
||||||
validatedParamsBinding.size = batch.validatedParamsSize;
|
outputParamsBinding.size = batch.outputParamsSize;
|
||||||
|
|
||||||
Ref<BindGroupBase> bindGroup;
|
Ref<BindGroupBase> bindGroup;
|
||||||
DAWN_TRY_ASSIGN(bindGroup, device->CreateBindGroup(&bindGroupDescriptor));
|
DAWN_TRY_ASSIGN(bindGroup, device->CreateBindGroup(&bindGroupDescriptor));
|
||||||
|
|
|
@ -145,8 +145,7 @@ namespace dawn::native::d3d12 {
|
||||||
RenderPipeline* pipeline,
|
RenderPipeline* pipeline,
|
||||||
uint32_t firstVertex,
|
uint32_t firstVertex,
|
||||||
uint32_t firstInstance) {
|
uint32_t firstInstance) {
|
||||||
const FirstOffsetInfo& firstOffsetInfo = pipeline->GetFirstOffsetInfo();
|
if (!pipeline->UsesVertexOrInstanceIndex()) {
|
||||||
if (!firstOffsetInfo.usesVertexIndex && !firstOffsetInfo.usesInstanceIndex) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::array<uint32_t, 2> offsets{firstVertex, firstInstance};
|
std::array<uint32_t, 2> offsets{firstVertex, firstInstance};
|
||||||
|
|
|
@ -766,8 +766,7 @@ namespace dawn::native::d3d12 {
|
||||||
|
|
||||||
bool Device::ShouldDuplicateParametersForDrawIndirect(
|
bool Device::ShouldDuplicateParametersForDrawIndirect(
|
||||||
const RenderPipelineBase* renderPipelineBase) const {
|
const RenderPipelineBase* renderPipelineBase) const {
|
||||||
return ToBackend(renderPipelineBase)->GetFirstOffsetInfo().usesVertexIndex ||
|
return ToBackend(renderPipelineBase)->UsesVertexOrInstanceIndex();
|
||||||
ToBackend(renderPipelineBase)->GetFirstOffsetInfo().usesInstanceIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace dawn::native::d3d12
|
} // namespace dawn::native::d3d12
|
||||||
|
|
|
@ -367,7 +367,8 @@ namespace dawn::native::d3d12 {
|
||||||
*shaders[stage] = compiledShader[stage].GetD3D12ShaderBytecode();
|
*shaders[stage] = compiledShader[stage].GetD3D12ShaderBytecode();
|
||||||
}
|
}
|
||||||
|
|
||||||
mFirstOffsetInfo = compiledShader[SingleShaderStage::Vertex].firstOffsetInfo;
|
mUsesVertexOrInstanceIndex =
|
||||||
|
compiledShader[SingleShaderStage::Vertex].usesVertexOrInstanceIndex;
|
||||||
|
|
||||||
PipelineLayout* layout = ToBackend(GetLayout());
|
PipelineLayout* layout = ToBackend(GetLayout());
|
||||||
|
|
||||||
|
@ -455,8 +456,8 @@ namespace dawn::native::d3d12 {
|
||||||
return mPipelineState.Get();
|
return mPipelineState.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
const FirstOffsetInfo& RenderPipeline::GetFirstOffsetInfo() const {
|
bool RenderPipeline::UsesVertexOrInstanceIndex() const {
|
||||||
return mFirstOffsetInfo;
|
return mUsesVertexOrInstanceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPipeline::SetLabelImpl() {
|
void RenderPipeline::SetLabelImpl() {
|
||||||
|
@ -464,7 +465,7 @@ namespace dawn::native::d3d12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
ComPtr<ID3D12CommandSignature> RenderPipeline::GetDrawIndirectCommandSignature() {
|
ComPtr<ID3D12CommandSignature> RenderPipeline::GetDrawIndirectCommandSignature() {
|
||||||
if (mFirstOffsetInfo.usesVertexIndex || mFirstOffsetInfo.usesInstanceIndex) {
|
if (mUsesVertexOrInstanceIndex) {
|
||||||
return ToBackend(GetLayout())
|
return ToBackend(GetLayout())
|
||||||
->GetDrawIndirectCommandSignatureWithInstanceVertexOffsets();
|
->GetDrawIndirectCommandSignatureWithInstanceVertexOffsets();
|
||||||
}
|
}
|
||||||
|
@ -473,7 +474,7 @@ namespace dawn::native::d3d12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
ComPtr<ID3D12CommandSignature> RenderPipeline::GetDrawIndexedIndirectCommandSignature() {
|
ComPtr<ID3D12CommandSignature> RenderPipeline::GetDrawIndexedIndirectCommandSignature() {
|
||||||
if (mFirstOffsetInfo.usesVertexIndex || mFirstOffsetInfo.usesInstanceIndex) {
|
if (mUsesVertexOrInstanceIndex) {
|
||||||
return ToBackend(GetLayout())
|
return ToBackend(GetLayout())
|
||||||
->GetDrawIndexedIndirectCommandSignatureWithInstanceVertexOffsets();
|
->GetDrawIndexedIndirectCommandSignatureWithInstanceVertexOffsets();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace dawn::native::d3d12 {
|
||||||
D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
|
D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
|
||||||
ID3D12PipelineState* GetPipelineState() const;
|
ID3D12PipelineState* GetPipelineState() const;
|
||||||
|
|
||||||
const FirstOffsetInfo& GetFirstOffsetInfo() const;
|
bool UsesVertexOrInstanceIndex() const;
|
||||||
|
|
||||||
// Dawn API
|
// Dawn API
|
||||||
void SetLabelImpl() override;
|
void SetLabelImpl() override;
|
||||||
|
@ -58,7 +58,7 @@ namespace dawn::native::d3d12 {
|
||||||
|
|
||||||
D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology;
|
D3D12_PRIMITIVE_TOPOLOGY mD3d12PrimitiveTopology;
|
||||||
ComPtr<ID3D12PipelineState> mPipelineState;
|
ComPtr<ID3D12PipelineState> mPipelineState;
|
||||||
FirstOffsetInfo mFirstOffsetInfo;
|
bool mUsesVertexOrInstanceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn::native::d3d12
|
} // namespace dawn::native::d3d12
|
||||||
|
|
|
@ -793,15 +793,7 @@ namespace dawn::native::d3d12 {
|
||||||
if (auto* data = transformOutputs.Get<tint::transform::FirstIndexOffset::Data>()) {
|
if (auto* data = transformOutputs.Get<tint::transform::FirstIndexOffset::Data>()) {
|
||||||
// TODO(dawn:549): Consider adding this information to the pipeline cache once we
|
// TODO(dawn:549): Consider adding this information to the pipeline cache once we
|
||||||
// can store more than the shader blob in it.
|
// can store more than the shader blob in it.
|
||||||
compiledShader.firstOffsetInfo.usesVertexIndex = data->has_vertex_index;
|
compiledShader.usesVertexOrInstanceIndex = data->has_vertex_or_instance_index;
|
||||||
if (compiledShader.firstOffsetInfo.usesVertexIndex) {
|
|
||||||
compiledShader.firstOffsetInfo.vertexIndexOffset = data->first_vertex_offset;
|
|
||||||
}
|
|
||||||
compiledShader.firstOffsetInfo.usesInstanceIndex = data->has_instance_index;
|
|
||||||
if (compiledShader.firstOffsetInfo.usesInstanceIndex) {
|
|
||||||
compiledShader.firstOffsetInfo.instanceIndexOffset =
|
|
||||||
data->first_instance_offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,13 +29,6 @@ namespace dawn::native::d3d12 {
|
||||||
class Device;
|
class Device;
|
||||||
class PipelineLayout;
|
class PipelineLayout;
|
||||||
|
|
||||||
struct FirstOffsetInfo {
|
|
||||||
bool usesVertexIndex;
|
|
||||||
uint32_t vertexIndexOffset;
|
|
||||||
bool usesInstanceIndex;
|
|
||||||
uint32_t instanceIndexOffset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Manages a ref to one of the various representations of shader blobs and information used to
|
// Manages a ref to one of the various representations of shader blobs and information used to
|
||||||
// emulate vertex/instance index starts
|
// emulate vertex/instance index starts
|
||||||
struct CompiledShader {
|
struct CompiledShader {
|
||||||
|
@ -44,7 +37,7 @@ namespace dawn::native::d3d12 {
|
||||||
ComPtr<IDxcBlob> compiledDXCShader;
|
ComPtr<IDxcBlob> compiledDXCShader;
|
||||||
D3D12_SHADER_BYTECODE GetD3D12ShaderBytecode() const;
|
D3D12_SHADER_BYTECODE GetD3D12ShaderBytecode() const;
|
||||||
|
|
||||||
FirstOffsetInfo firstOffsetInfo;
|
bool usesVertexOrInstanceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShaderModule final : public ShaderModuleBase {
|
class ShaderModule final : public ShaderModuleBase {
|
||||||
|
|
|
@ -42,14 +42,8 @@ FirstIndexOffset::BindingPoint::BindingPoint(uint32_t b, uint32_t g)
|
||||||
: binding(b), group(g) {}
|
: binding(b), group(g) {}
|
||||||
FirstIndexOffset::BindingPoint::~BindingPoint() = default;
|
FirstIndexOffset::BindingPoint::~BindingPoint() = default;
|
||||||
|
|
||||||
FirstIndexOffset::Data::Data(bool has_vtx_index,
|
FirstIndexOffset::Data::Data(bool has_vtx_or_inst_index)
|
||||||
bool has_inst_index,
|
: has_vertex_or_instance_index(has_vtx_or_inst_index) {}
|
||||||
uint32_t first_vtx_offset,
|
|
||||||
uint32_t first_inst_offset)
|
|
||||||
: has_vertex_index(has_vtx_index),
|
|
||||||
has_instance_index(has_inst_index),
|
|
||||||
first_vertex_offset(first_vtx_offset),
|
|
||||||
first_instance_offset(first_inst_offset) {}
|
|
||||||
FirstIndexOffset::Data::Data(const Data&) = default;
|
FirstIndexOffset::Data::Data(const Data&) = default;
|
||||||
FirstIndexOffset::Data::~Data() = default;
|
FirstIndexOffset::Data::~Data() = default;
|
||||||
|
|
||||||
|
@ -80,8 +74,7 @@ void FirstIndexOffset::Run(CloneContext& ctx,
|
||||||
std::unordered_map<const sem::Variable*, const char*> builtin_vars;
|
std::unordered_map<const sem::Variable*, const char*> builtin_vars;
|
||||||
std::unordered_map<const sem::StructMember*, const char*> builtin_members;
|
std::unordered_map<const sem::StructMember*, const char*> builtin_members;
|
||||||
|
|
||||||
bool has_vertex_index = false;
|
bool has_vertex_or_instance_index = false;
|
||||||
bool has_instance_index = false;
|
|
||||||
|
|
||||||
// Traverse the AST scanning for builtin accesses via variables (includes
|
// Traverse the AST scanning for builtin accesses via variables (includes
|
||||||
// parameters) or structure member accesses.
|
// parameters) or structure member accesses.
|
||||||
|
@ -93,12 +86,12 @@ void FirstIndexOffset::Run(CloneContext& ctx,
|
||||||
if (builtin == ast::Builtin::kVertexIndex) {
|
if (builtin == ast::Builtin::kVertexIndex) {
|
||||||
auto* sem_var = ctx.src->Sem().Get(var);
|
auto* sem_var = ctx.src->Sem().Get(var);
|
||||||
builtin_vars.emplace(sem_var, kFirstVertexName);
|
builtin_vars.emplace(sem_var, kFirstVertexName);
|
||||||
has_vertex_index = true;
|
has_vertex_or_instance_index = true;
|
||||||
}
|
}
|
||||||
if (builtin == ast::Builtin::kInstanceIndex) {
|
if (builtin == ast::Builtin::kInstanceIndex) {
|
||||||
auto* sem_var = ctx.src->Sem().Get(var);
|
auto* sem_var = ctx.src->Sem().Get(var);
|
||||||
builtin_vars.emplace(sem_var, kFirstInstanceName);
|
builtin_vars.emplace(sem_var, kFirstInstanceName);
|
||||||
has_instance_index = true;
|
has_vertex_or_instance_index = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,29 +103,23 @@ void FirstIndexOffset::Run(CloneContext& ctx,
|
||||||
if (builtin == ast::Builtin::kVertexIndex) {
|
if (builtin == ast::Builtin::kVertexIndex) {
|
||||||
auto* sem_mem = ctx.src->Sem().Get(member);
|
auto* sem_mem = ctx.src->Sem().Get(member);
|
||||||
builtin_members.emplace(sem_mem, kFirstVertexName);
|
builtin_members.emplace(sem_mem, kFirstVertexName);
|
||||||
has_vertex_index = true;
|
has_vertex_or_instance_index = true;
|
||||||
}
|
}
|
||||||
if (builtin == ast::Builtin::kInstanceIndex) {
|
if (builtin == ast::Builtin::kInstanceIndex) {
|
||||||
auto* sem_mem = ctx.src->Sem().Get(member);
|
auto* sem_mem = ctx.src->Sem().Get(member);
|
||||||
builtin_members.emplace(sem_mem, kFirstInstanceName);
|
builtin_members.emplace(sem_mem, kFirstInstanceName);
|
||||||
has_instance_index = true;
|
has_vertex_or_instance_index = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Byte offsets on the uniform buffer
|
if (has_vertex_or_instance_index) {
|
||||||
uint32_t vertex_index_offset = 0;
|
|
||||||
uint32_t instance_index_offset = 0;
|
|
||||||
|
|
||||||
if (has_vertex_index || has_instance_index) {
|
|
||||||
// Add uniform buffer members and calculate byte offsets
|
// Add uniform buffer members and calculate byte offsets
|
||||||
ast::StructMemberList members;
|
ast::StructMemberList members;
|
||||||
members.push_back(ctx.dst->Member(kFirstVertexName, ctx.dst->ty.u32()));
|
members.push_back(ctx.dst->Member(kFirstVertexName, ctx.dst->ty.u32()));
|
||||||
vertex_index_offset = 0;
|
|
||||||
members.push_back(ctx.dst->Member(kFirstInstanceName, ctx.dst->ty.u32()));
|
members.push_back(ctx.dst->Member(kFirstInstanceName, ctx.dst->ty.u32()));
|
||||||
instance_index_offset = 4;
|
|
||||||
auto* struct_ = ctx.dst->Structure(ctx.dst->Sym(), std::move(members));
|
auto* struct_ = ctx.dst->Structure(ctx.dst->Sym(), std::move(members));
|
||||||
|
|
||||||
// Create a global to hold the uniform buffer
|
// Create a global to hold the uniform buffer
|
||||||
|
@ -172,8 +159,7 @@ void FirstIndexOffset::Run(CloneContext& ctx,
|
||||||
|
|
||||||
ctx.Clone();
|
ctx.Clone();
|
||||||
|
|
||||||
outputs.Add<Data>(has_vertex_index, has_instance_index, vertex_index_offset,
|
outputs.Add<Data>(has_vertex_or_instance_index);
|
||||||
instance_index_offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::transform
|
} // namespace tint::transform
|
||||||
|
|
|
@ -84,14 +84,9 @@ class FirstIndexOffset final : public Castable<FirstIndexOffset, Transform> {
|
||||||
/// Data holds information about shader usage and constant buffer offsets.
|
/// Data holds information about shader usage and constant buffer offsets.
|
||||||
struct Data final : public Castable<Data, transform::Data> {
|
struct Data final : public Castable<Data, transform::Data> {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param has_vtx_index True if the shader uses vertex_index
|
/// @param has_vtx_or_inst_index True if the shader uses vertex_index or
|
||||||
/// @param has_inst_index True if the shader uses instance_index
|
/// instance_index
|
||||||
/// @param first_vtx_offset Offset of first vertex into constant buffer
|
explicit Data(bool has_vtx_or_inst_index);
|
||||||
/// @param first_inst_offset Offset of first instance into constant buffer
|
|
||||||
Data(bool has_vtx_index,
|
|
||||||
bool has_inst_index,
|
|
||||||
uint32_t first_vtx_offset,
|
|
||||||
uint32_t first_inst_offset);
|
|
||||||
|
|
||||||
/// Copy constructor
|
/// Copy constructor
|
||||||
Data(const Data&);
|
Data(const Data&);
|
||||||
|
@ -100,13 +95,7 @@ class FirstIndexOffset final : public Castable<FirstIndexOffset, Transform> {
|
||||||
~Data() override;
|
~Data() override;
|
||||||
|
|
||||||
/// True if the shader uses vertex_index
|
/// True if the shader uses vertex_index
|
||||||
const bool has_vertex_index;
|
const bool has_vertex_or_instance_index;
|
||||||
/// True if the shader uses instance_index
|
|
||||||
const bool has_instance_index;
|
|
||||||
/// Offset of first vertex into constant buffer
|
|
||||||
const uint32_t first_vertex_offset;
|
|
||||||
/// Offset of first instance into constant buffer
|
|
||||||
const uint32_t first_instance_offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
|
|
@ -86,10 +86,7 @@ fn entry() -> @builtin(position) vec4<f32> {
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, false);
|
EXPECT_EQ(data->has_vertex_or_instance_index, false);
|
||||||
EXPECT_EQ(data->has_instance_index, false);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 0u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, BasicModuleVertexIndex) {
|
TEST_F(FirstIndexOffsetTest, BasicModuleVertexIndex) {
|
||||||
|
@ -133,10 +130,7 @@ fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32>
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, true);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, false);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, BasicModuleVertexIndex_OutOfOrder) {
|
TEST_F(FirstIndexOffsetTest, BasicModuleVertexIndex_OutOfOrder) {
|
||||||
|
@ -180,10 +174,7 @@ fn test(vert_idx : u32) -> u32 {
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, true);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, false);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, BasicModuleInstanceIndex) {
|
TEST_F(FirstIndexOffsetTest, BasicModuleInstanceIndex) {
|
||||||
|
@ -227,10 +218,7 @@ fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, false);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, true);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, BasicModuleInstanceIndex_OutOfOrder) {
|
TEST_F(FirstIndexOffsetTest, BasicModuleInstanceIndex_OutOfOrder) {
|
||||||
|
@ -274,10 +262,7 @@ fn test(inst_idx : u32) -> u32 {
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, false);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, true);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, BasicModuleBothIndex) {
|
TEST_F(FirstIndexOffsetTest, BasicModuleBothIndex) {
|
||||||
|
@ -333,10 +318,7 @@ fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, true);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, true);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, BasicModuleBothIndex_OutOfOrder) {
|
TEST_F(FirstIndexOffsetTest, BasicModuleBothIndex_OutOfOrder) {
|
||||||
|
@ -392,10 +374,7 @@ fn test(instance_idx : u32, vert_idx : u32) -> u32 {
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, true);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, true);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, NestedCalls) {
|
TEST_F(FirstIndexOffsetTest, NestedCalls) {
|
||||||
|
@ -447,10 +426,7 @@ fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32>
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, true);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, false);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, NestedCalls_OutOfOrder) {
|
TEST_F(FirstIndexOffsetTest, NestedCalls_OutOfOrder) {
|
||||||
|
@ -502,10 +478,7 @@ fn func1(vert_idx : u32) -> u32 {
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, true);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, false);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, MultipleEntryPoints) {
|
TEST_F(FirstIndexOffsetTest, MultipleEntryPoints) {
|
||||||
|
@ -573,10 +546,7 @@ fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, true);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, true);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FirstIndexOffsetTest, MultipleEntryPoints_OutOfOrder) {
|
TEST_F(FirstIndexOffsetTest, MultipleEntryPoints_OutOfOrder) {
|
||||||
|
@ -644,10 +614,7 @@ fn func(i : u32) -> u32 {
|
||||||
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
auto* data = got.data.Get<FirstIndexOffset::Data>();
|
||||||
|
|
||||||
ASSERT_NE(data, nullptr);
|
ASSERT_NE(data, nullptr);
|
||||||
EXPECT_EQ(data->has_vertex_index, true);
|
EXPECT_EQ(data->has_vertex_or_instance_index, true);
|
||||||
EXPECT_EQ(data->has_instance_index, true);
|
|
||||||
EXPECT_EQ(data->first_vertex_offset, 0u);
|
|
||||||
EXPECT_EQ(data->first_instance_offset, 4u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue