diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2019-08-22 15:58:28 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-22 15:58:28 -0400 |
| commit | 06a0e3980fd04fa265bd20eb11f2abc18bd6a215 (patch) | |
| tree | ea664d7f0ecfa4b6948319d4fcfb0bbd1e3af888 | |
| parent | bc392f9dbfb8cb6c359bb890fb85b831e49bfd55 (diff) | |
WIP: CPU compute coverage (#1030)
* Add support for '=' when defining a name in test.
* Add support for double intrinsics.
* Add support for asdouble
Add findOrAddInst - used instead of findOrEmitHoistableInst, for nominal instructions.
Support cloning of string literals.
C++ working on more compute tests.
* Constant buffer support in reflection.
Fixed debugging into source for generated C++.
buffer-layout.slang works.
* Added cpu test result.
* Remove some commented out code.
Comment on next fixes.
* Improvements to reflection CPU code.
* C++ working with ByteAddressBuffer.
* Enabled more compute tests for CPU.
* Enabled more compute tests on CPU.
Added support for [] style access to a vector.
* Enabled more CPU compute tests.
* Handling of buffer-type-splitting.slang
Named buffers can be paths to resources
* Fix some warnings, remove some dead code.
* Fix problem with verification of number of operands for asuint/asint as they can have 1 or 3 operands. asdouble takes 2.
* Fix handling in MemoryArena around aligned allocations. That _allocateAlignedFromNewBlock assumed the block allocated has the aligment that was requested and so did not correct the start address.
70 files changed, 748 insertions, 259 deletions
diff --git a/prelude/slang-cpp-scalar-intrinsics.h b/prelude/slang-cpp-scalar-intrinsics.h index 217a79e02..40d137395 100644 --- a/prelude/slang-cpp-scalar-intrinsics.h +++ b/prelude/slang-cpp-scalar-intrinsics.h @@ -20,6 +20,13 @@ union Union32 float f; }; +union Union64 +{ + uint64_t u; + int64_t i; + double d; +}; + // Helpers SLANG_FORCE_INLINE float F32_calcSafeRadians(float radians) { @@ -112,10 +119,6 @@ SLANG_FORCE_INLINE double F64_lerp(double x, double y, double s) { return x + s SLANG_FORCE_INLINE double F64_clamp(double x, double min, double max) { return (x < min) ? min : ((x > max) ? max : x); } SLANG_FORCE_INLINE void F64_sincos(double f, double& outSin, double& outCos) { outSin = F64_sin(f); outCos = F64_cos(f); } -// TODO! -//uint32_t F64_asuint(float f); -//int32_t F64_asint(float f); - // ----------------------------- I32 ----------------------------------------- SLANG_FORCE_INLINE int32_t I32_abs(int32_t f) { return (f < 0) ? -f : f; } @@ -126,7 +129,13 @@ SLANG_FORCE_INLINE int32_t I32_max(int32_t a, int32_t b) { return a > b ? a : b; SLANG_FORCE_INLINE int32_t I32_clamp(int32_t x, int32_t min, int32_t max) { return ( x < min) ? min : ((x > max) ? max : x); } SLANG_FORCE_INLINE float I32_asfloat(int32_t x) { Union32 u; u.i = x; return u.f; } -SLANG_FORCE_INLINE uint32_t I32_asuint(int32_t x) { return uint32_t(x); } +SLANG_FORCE_INLINE uint32_t I32_asuint(int32_t x) { return uint32_t(x); } +SLANG_FORCE_INLINE double I32_asdouble(int32_t low, int32_t hi ) +{ + Union64 u; + u.i = (int64_t(hi) << 32) | low; + return u.d; +} // ----------------------------- U32 ----------------------------------------- @@ -140,6 +149,32 @@ SLANG_FORCE_INLINE uint32_t U32_clamp(uint32_t x, uint32_t min, uint32_t max) { SLANG_FORCE_INLINE float U32_asfloat(uint32_t x) { Union32 u; u.u = x; return u.f; } SLANG_FORCE_INLINE uint32_t U32_asint(int32_t x) { return uint32_t(x); } +SLANG_FORCE_INLINE double U32_asdouble(uint32_t low, uint32_t hi) +{ + Union64 u; + u.u = (uint64_t(hi) << 32) | low; + return u.d; +} + +// ----------------------------- F64 ----------------------------------------- + +SLANG_FORCE_INLINE void F64_asuint(double d, uint32_t& low, uint32_t& hi) +{ + Union64 u; + u.d = d; + low = uint32_t(u.u); + hi = uint32_t(u.u >> 32); +} + +SLANG_FORCE_INLINE void F64_asint(double d, int32_t& low, uint32_t& hi) +{ + Union64 u; + u.d = d; + low = int32_t(u.u); + hi = int32_t(u.u >> 32); +} + + #ifdef SLANG_PRELUDE_NAMESPACE } #endif diff --git a/source/core/slang-memory-arena.cpp b/source/core/slang-memory-arena.cpp index 99e6261ff..a9fc1ec19 100644 --- a/source/core/slang-memory-arena.cpp +++ b/source/core/slang-memory-arena.cpp @@ -42,19 +42,19 @@ void MemoryArena::_initialize(size_t blockPayloadSize, size_t alignment) // Ensure it's alignment is at least kMinAlignment alignment = (alignment < kMinAlignment) ? kMinAlignment : alignment; + const size_t alignMask = alignment - 1; + + // Make sure the payload is rounded up to the alignment + blockPayloadSize = (blockPayloadSize + alignMask) & ~alignMask; + m_blockPayloadSize = blockPayloadSize; - size_t blockAllocSize = blockPayloadSize; // If alignment required is larger then the backing allocators then // make larger to ensure when alignment correction takes place it will be aligned - if (alignment > kMinAlignment) - { - blockAllocSize += alignment; - } - + const size_t blockAllocSize = (alignment > kMinAlignment) ? (blockPayloadSize + alignment) : blockPayloadSize; + m_blockAllocSize = blockAllocSize; m_blockAlignment = alignment; - m_availableBlocks = nullptr; m_blockFreeList.init(sizeof(Block), sizeof(void*), 16); @@ -217,12 +217,17 @@ MemoryArena::Block* MemoryArena::_newNormalBlock() return block; } - return _newBlock(m_blockAllocSize, m_blockAlignment); + Block* block = _newBlock(m_blockAllocSize, m_blockAlignment); + // Check that every normal block has m_blockPayloadSize space + assert(size_t(block->m_end - block->m_start) >= m_blockPayloadSize); + return block; } MemoryArena::Block* MemoryArena::_newBlock(size_t allocSize, size_t alignment) { assert(alignment >= m_blockAlignment); + // Alignment must be a power of 2 + assert(((alignment - 1) & alignment) == 0); // Allocate block Block* block = (Block*)m_blockFreeList.allocate(); @@ -289,9 +294,10 @@ void* MemoryArena::_allocateAlignedFromNewBlock(size_t size, size_t alignment) // // An improvement might be to have some abstraction that sits on top that can do this tracking (or have the blocks // themselves record if they alias over a previously used block - but we don't bother with this here. - if (allocSize > m_blockAllocSize) + // If the alignment is greater than regular alignment we need to handle specially + if (allocSize > m_blockPayloadSize || (alignment > m_blockAlignment && allocSize + alignment > m_blockPayloadSize)) { - // This is an odd-sized block so just allocate the whole thing + // This is an odd-sized block so just allocate the whole thing. block = _newBlock(allocSize, alignment); } else @@ -310,10 +316,11 @@ void* MemoryArena::_allocateAlignedFromNewBlock(size_t size, size_t alignment) // Make the current block _addCurrentBlock(block); - // Allocated memory is just the start of this block - uint8_t* memory = m_current; - // It must already be aligned - assert((size_t(m_current) & alignMask) == 0); + // Align the memory + uint8_t* memory = (uint8_t*)((size_t(m_current) + alignMask) & ~alignMask); + + // It must be aligned + assert((size_t(memory) & alignMask) == 0); // Do the aligned allocation (which must fit) by aligning the pointer // It must fit if the previous code is correct... diff --git a/source/core/slang-token-reader.h b/source/core/slang-token-reader.h index f8a455452..474db5c4a 100644 --- a/source/core/slang-token-reader.h +++ b/source/core/slang-token-reader.h @@ -189,6 +189,15 @@ namespace Slang { tokenPtr -= count; } + Token ReadMatchingToken(TokenType type) + { + auto token = ReadToken(); + if (token.Type != type) + { + throw TextFormatException("Text parsing error: unexpected token."); + } + return token; + } Token ReadToken() { if (tokenPtr < (int)tokens.getCount()) diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index 07e2b66fe..2d5557371 100644 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -1529,6 +1529,11 @@ SlangResult dissassembleDXILUsingDXC( sharedLib->m_temporaryFileSet = productFileSet; productFileSet.clear(); + // Copy the paths in the temporary file set + // We particularly want to do this to keep the source + sharedLib->m_temporaryFileSet.add(temporaryFileSet.m_paths); + temporaryFileSet.clear(); + // Output the shared library outSharedLib = sharedLib; } diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index dc9ab23cc..194ebfa2c 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -385,21 +385,7 @@ void CPPSourceEmitter::emitTypeDefinition(IRType* inType) } UnownedStringSlice CPPSourceEmitter::_getTypeName(IRType* inType) -{ - if (isNominalOp(inType->op)) - { - StringSlicePool::Handle handle; - // NOTE! This is somewhat unusual -> we are going to add types which aren't cloned and belong to - // m_uniqueModule. We *assume* nominal types are de-duped - if (!m_typeNameMap.TryGetValue(inType, handle)) - { - auto name = getName(inType); - handle = m_slicePool.add(name); - m_typeNameMap.Add(inType, handle); - } - return m_slicePool.getSlice(handle); - } - +{ IRType* type = _cloneType(inType); StringSlicePool::Handle handle = StringSlicePool::kNullHandle; @@ -480,6 +466,26 @@ SlangResult CPPSourceEmitter::_calcTextureTypeName(IRTextureTypeBase* texType, S return SLANG_OK; } +static UnownedStringSlice _getResourceTypePrefix(IROp op) +{ + switch (op) + { + case kIROp_HLSLStructuredBufferType: return UnownedStringSlice::fromLiteral("StructuredBuffer"); + case kIROp_HLSLRWStructuredBufferType: return UnownedStringSlice::fromLiteral("RWStructuredBuffer"); + case kIROp_HLSLRWByteAddressBufferType: return UnownedStringSlice::fromLiteral("RWByteAddressBuffer"); + case kIROp_HLSLByteAddressBufferType: return UnownedStringSlice::fromLiteral("ByteAddressBuffer"); + case kIROp_SamplerStateType: return UnownedStringSlice::fromLiteral("SamplerState"); + case kIROp_SamplerComparisonStateType: return UnownedStringSlice::fromLiteral("SamplerComparisonState"); + case kIROp_HLSLRasterizerOrderedStructuredBufferType: return UnownedStringSlice::fromLiteral("RasterizerOrderedStructuredBuffer"); + case kIROp_HLSLAppendStructuredBufferType: return UnownedStringSlice::fromLiteral("AppendStructuredBuffer"); + case kIROp_HLSLConsumeStructuredBufferType: return UnownedStringSlice::fromLiteral("ConsumeStructuredBuffer"); + case kIROp_HLSLRasterizerOrderedByteAddressBufferType: return UnownedStringSlice::fromLiteral("RasterizerOrderedByteAddressBuffer"); + case kIROp_RaytracingAccelerationStructureType: return UnownedStringSlice::fromLiteral("RaytracingAccelerationStructure"); + + default: return UnownedStringSlice(); + } +} + SlangResult CPPSourceEmitter::_calcTypeName(IRType* type, CodeGenTarget target, StringBuilder& out) { switch (type->op) @@ -540,15 +546,6 @@ SlangResult CPPSourceEmitter::_calcTypeName(IRType* type, CodeGenTarget target, } return SLANG_OK; } - case kIROp_HLSLRWStructuredBufferType: - { - auto bufType = static_cast<IRHLSLRWStructuredBufferType*>(type); - - out << "RWStructuredBuffer<"; - SLANG_RETURN_ON_FAIL(_calcTypeName(bufType->getElementType(), target, out)); - out << ">"; - return SLANG_OK; - } case kIROp_ArrayType: { auto arrayType = static_cast<IRArrayType*>(type); @@ -560,18 +557,14 @@ SlangResult CPPSourceEmitter::_calcTypeName(IRType* type, CodeGenTarget target, out << ", " << elementCount << ">"; return SLANG_OK; } - case kIROp_SamplerStateType: - { - out << "SamplerState"; - return SLANG_OK; - } - case kIROp_SamplerComparisonStateType: - { - out << "SamplerComparisonState"; - return SLANG_OK; - } default: { + if (isNominalOp(type->op)) + { + out << getName(type); + return SLANG_OK; + } + if (IRBasicType::isaImpl(type->op)) { out << getBuiltinTypeName(type->op); @@ -587,6 +580,47 @@ SlangResult CPPSourceEmitter::_calcTypeName(IRType* type, CodeGenTarget target, } } + // If _getResourceTypePrefix returns something, we assume can output any specialization after it in order. + { + UnownedStringSlice prefix = _getResourceTypePrefix(type->op); + if (prefix.size() > 0) + { + auto oldWriter = m_writer; + SourceManager* sourceManager = oldWriter->getSourceManager(); + + // TODO(JS): This is a bit of a hack. We don't want to emit the result here, + // so we replace the writer, write out the type, grab the contents, and restore the writer + + SourceWriter writer(sourceManager, LineDirectiveMode::None); + m_writer = &writer; + + m_writer->emit(prefix); + + // TODO(JS). + // Assumes ordering of types matches ordering of operands. + + UInt operandCount = type->getOperandCount(); + if (operandCount) + { + m_writer->emit("<"); + for (UInt ii = 0; ii < operandCount; ++ii) + { + if (ii != 0) + { + m_writer->emit(", "); + } + emitVal(type->getOperand(ii), getInfo(EmitOp::General)); + } + m_writer->emit(">"); + } + + out << writer.getContent(); + + m_writer = oldWriter; + return SLANG_OK; + } + } + break; } } @@ -607,29 +641,42 @@ IRInst* CPPSourceEmitter::_clone(IRInst* inst) return nullptr; } + IRModule* module = inst->getModule(); + // All inst's must belong to a module + SLANG_ASSERT(module); + // If it's in this module then we don't need to clone - if (inst->getModule() == m_uniqueModule) + if (module == m_uniqueModule) { return inst; } - if (isNominalOp(inst->op)) - { - // If it's nominal we don't bother copying, as we assumed it is already de-duped - return inst; - } - if (IRInst*const* newInstPtr = m_cloneMap.TryGetValue(inst)) { return *newInstPtr; } - + + if (isNominalOp(inst->op)) + { + // TODO(JS) + // This is arguably problematic - I'm adding an instruction from another module to the map, to be it's self. + // I did have code which created a copy of the nominal instruction and name hint, but because nominality means + // 'same address' other code would generate a different name for that instruction (say as compared to being a member in + // the original instruction) + // + // Because I use findOrAddInst which doesn't hoist instructions, the hoisting doesn't rely on parenting, that would + // break. + + // If nominal, we just use the original inst + m_cloneMap.Add(inst, inst); + return inst; + } + // It would be nice if I could use ir-clone.cpp to do this -> but it doesn't clone // operands. We wouldn't want to clone decorations, and it can't clone IRConstant(!) so // it's no use IRInst* clone = nullptr; - switch (inst->op) { case kIROp_IntLit: @@ -639,6 +686,12 @@ IRInst* CPPSourceEmitter::_clone(IRInst* inst) clone = m_irBuilder.getIntValue(cloneType, intLit->value.intVal); break; } + case kIROp_StringLit: + { + auto stringLit = static_cast<IRStringLit*>(inst); + clone = m_irBuilder.getStringValue(stringLit->getStringSlice()); + break; + } default: { if (IRBasicType::isaImpl(inst->op)) @@ -661,7 +714,12 @@ IRInst* CPPSourceEmitter::_clone(IRInst* inst) cloneOperands[i] = _clone(inst->getOperand(i)); } - clone = m_irBuilder.findOrEmitHoistableInst(cloneType, inst->op, operandCount, cloneOperands.getBuffer()); + //clone = m_irBuilder.findOrEmitHoistableInst(cloneType, inst->op, operandCount, cloneOperands.getBuffer()); + + UInt operandCounts[1] = { UInt(operandCount) }; + IRInst*const* listOperands[1] = { cloneOperands.getBuffer() }; + + clone = m_irBuilder.findOrAddInst(cloneType, inst->op, 1, operandCounts, listOperands); } else { @@ -1088,6 +1146,42 @@ void CPPSourceEmitter::_emitLengthDefinition(const UnownedStringSlice& funcName, writer->emit("}\n\n"); } +void CPPSourceEmitter::_emitGetAtDefinition(const UnownedStringSlice& funcName, const SpecializedIntrinsic& specOp) +{ + SourceWriter* writer = getSourceWriter(); + + IRFuncType* funcType = specOp.signatureType; + SLANG_ASSERT(funcType->getParamCount() == 2); + + IRType* srcType = funcType->getParamType(0); + + IRType* retType = specOp.returnType; + emitType(retType); + m_writer->emit("& "); + + writer->emit(funcName); + writer->emit("("); + + emitType(funcType->getParamType(0)); + writer->emit("& a, "); + emitType(funcType->getParamType(1)); + writer->emit(" b)\n{\n"); + + writer->indent(); + + IRVectorType* vectorType = as<IRVectorType>(srcType); + int vecSize = int(GetIntVal(vectorType->getElementCount())); + + writer->emit("assert(b >= 0 && b < "); + writer->emit(vecSize); + writer->emit(");\n"); + + writer->emit("return (&a.x)[b];\n"); + + writer->dedent(); + writer->emit("}\n\n"); +} + void CPPSourceEmitter::_emitNormalizeDefinition(const UnownedStringSlice& funcName, const SpecializedIntrinsic& specOp) { SourceWriter* writer = getSourceWriter(); @@ -1332,10 +1426,16 @@ void CPPSourceEmitter::emitSpecializedOperationDefinition(const SpecializedIntri { return _emitConstructFromScalarDefinition(_getFuncName(specOp), specOp); } + case IntrinsicOp::GetAt: + { + return _emitGetAtDefinition(_getFuncName(specOp), specOp); + } default: { const auto& info = getOperationInfo(specOp.op); - if (info.numOperands >= 1 && info.numOperands <= 3) + const int paramCount = (info.numOperands < 0) ? int(specOp.signatureType->getParamCount()) : info.numOperands; + + if (paramCount >= 1 && paramCount <= 3) { return _emitAryDefinition(specOp); } @@ -1500,7 +1600,7 @@ void CPPSourceEmitter::emitCall(const SpecializedIntrinsic& specOp, IRInst* inst useType(specOp.returnType); // add that we want a function - SLANG_ASSERT(numOperands == info.numOperands); + SLANG_ASSERT(info.numOperands < 0 || numOperands == info.numOperands); if (isOperator) { @@ -1603,6 +1703,14 @@ StringSlicePool::Handle CPPSourceEmitter::_calcFuncName(const SpecializedIntrins } return m_slicePool.add(builder); } + case IntrinsicOp::GetAt: + { + return m_slicePool.add(UnownedStringSlice::fromLiteral("getAt")); + } + case IntrinsicOp::SetAt: + { + return m_slicePool.add(UnownedStringSlice::fromLiteral("setAt")); + } default: break; } @@ -2193,7 +2301,18 @@ bool CPPSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOut return false; } - + case kIROp_getElement: + case kIROp_getElementPtr: + { + IRInst* target = inst->getOperand(0); + if (target->getDataType()->op == kIROp_VectorType) + { + // Specially handle this + emitOperationCall(IntrinsicOp::GetAt, inst, inst->getOperands(), int(inst->getOperandCount()), inst->getDataType(), inOuterPrec); + return true; + } + return false; + } default: { IntrinsicOp op = getOperation(inst->op); diff --git a/source/slang/slang-emit-cpp.h b/source/slang/slang-emit-cpp.h index 4280bdc80..6c300320a 100644 --- a/source/slang/slang-emit-cpp.h +++ b/source/slang/slang-emit-cpp.h @@ -110,11 +110,15 @@ just constructXXXFromScalar. Would be good if there was a suitable name to encom x(Step, "step", 2) \ \ x(AsFloat, "asfloat", 1) \ - x(AsInt, "asint", 1) \ - x(AsUInt, "asuint", 1) \ + x(AsInt, "asint", -1) \ + x(AsUInt, "asuint", -1) \ + x(AsDouble, "asdouble", 2) \ \ x(ConstructConvert, "", 1) \ - x(ConstructFromScalar, "", 1) + x(ConstructFromScalar, "", 1) \ + \ + x(GetAt, "", 2) \ + x(SetAt, "", 3) class CPPSourceEmitter: public CLikeSourceEmitter @@ -224,7 +228,8 @@ protected: void _emitReflectDefinition(const UnownedStringSlice& funcName, const SpecializedIntrinsic& specOp); void _emitConstructConvertDefinition(const UnownedStringSlice& funcName, const SpecializedIntrinsic& specOp); void _emitConstructFromScalarDefinition(const UnownedStringSlice& funcName, const SpecializedIntrinsic& specOp); - + void _emitGetAtDefinition(const UnownedStringSlice& funcName, const SpecializedIntrinsic& specOp); + void _emitSignature(const UnownedStringSlice& funcName, const SpecializedIntrinsic& specOp); void _emitInOutParamType(IRType* type, String const& name, IRType* valueType); diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index cd59630d8..2e2168b1a 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -955,6 +955,13 @@ struct IRBuilder IRUndefined* emitUndefined(IRType* type); + IRInst* findOrAddInst( + IRType* type, + IROp op, + UInt operandListCount, + UInt const* listOperandCounts, + IRInst* const* const* listOperands); + IRInst* findOrEmitHoistableInst( IRType* type, IROp op, diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 2e8de5e37..b6c88bb99 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -1528,7 +1528,6 @@ namespace Slang keyInst.value.ptrVal = value; return (IRPtrLit*) findOrEmitConstant(this, keyInst); } - IRInst* IRBuilder::findOrEmitHoistableInst( IRType* type, @@ -1617,6 +1616,93 @@ namespace Slang return inst; } + IRInst* IRBuilder::findOrAddInst( + IRType* type, + IROp op, + UInt operandListCount, + UInt const* listOperandCounts, + IRInst* const* const* listOperands) + { + UInt operandCount = 0; + for (UInt ii = 0; ii < operandListCount; ++ii) + { + operandCount += listOperandCounts[ii]; + } + + auto& memoryArena = getModule()->memoryArena; + void* cursor = memoryArena.getCursor(); + + // We are going to create a 'dummy' instruction on the memoryArena + // which can be used as a key for lookup, so see if we + // already have an equivalent instruction available to use. + size_t keySize = sizeof(IRInst) + operandCount * sizeof(IRUse); + IRInst* inst = (IRInst*)memoryArena.allocateAndZero(keySize); + + void* endCursor = memoryArena.getCursor(); + // Mark as 'unused' cos it is unused on release builds. + SLANG_UNUSED(endCursor); + + new(inst) IRInst(); + inst->op = op; + inst->typeUse.usedValue = type; + inst->operandCount = (uint32_t)operandCount; + + // Don't link up as we may free (if we already have this key) + { + IRUse* operand = inst->getOperands(); + for (UInt ii = 0; ii < operandListCount; ++ii) + { + UInt listOperandCount = listOperandCounts[ii]; + for (UInt jj = 0; jj < listOperandCount; ++jj) + { + operand->usedValue = listOperands[ii][jj]; + operand++; + } + } + } + + // Find or add the key/inst + { + IRInstKey key = { inst }; + + // Ideally we would add if not found, else return if was found instead of testing & then adding. + IRInst** found = sharedBuilder->globalValueNumberingMap.TryGetValueOrAdd(key, inst); + SLANG_ASSERT(endCursor == memoryArena.getCursor()); + // If it's found, just return, and throw away the instruction + if (found) + { + memoryArena.rewindToCursor(cursor); + return *found; + } + } + + // Make the lookup 'inst' instruction into 'proper' instruction. Equivalent to + // IRInst* inst = createInstImpl<IRInst>(builder, op, type, 0, nullptr, operandListCount, listOperandCounts, listOperands); + { + if (type) + { + inst->typeUse.usedValue = nullptr; + inst->typeUse.init(inst, type); + } + + maybeSetSourceLoc(this, inst); + + IRUse*const operands = inst->getOperands(); + for (UInt i = 0; i < operandCount; ++i) + { + IRUse& operand = operands[i]; + auto value = operand.usedValue; + + operand.usedValue = nullptr; + operand.init(inst, value); + } + } + + addInst(inst); + return inst; + } + + IRInst* IRBuilder::findOrEmitHoistableInst( IRType* type, IROp op, diff --git a/tests/compute/assoctype-complex.slang b/tests/compute/assoctype-complex.slang index ee5f2c86f..29df5310a 100644 --- a/tests/compute/assoctype-complex.slang +++ b/tests/compute/assoctype-complex.slang @@ -1,7 +1,9 @@ +//TEST(compute):COMPARE_COMPUTE: -cpu //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; + interface IBase { associatedtype V; diff --git a/tests/compute/assoctype-func-param.slang b/tests/compute/assoctype-func-param.slang index fb3875d60..573016e4b 100644 --- a/tests/compute/assoctype-func-param.slang +++ b/tests/compute/assoctype-func-param.slang @@ -1,8 +1,9 @@ +//TEST(compute):COMPARE_COMPUTE:-cpu //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out // Test type checking of associatedtype and typedef +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; interface IBase @@ -41,7 +42,6 @@ U.RetT test<U:IBase>(U.RetT val) return obj.getVal(sb); } - [numthreads(4, 1, 1)] void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { diff --git a/tests/compute/assoctype-generic-arg.slang b/tests/compute/assoctype-generic-arg.slang index dd183ea5d..ae14380f4 100644 --- a/tests/compute/assoctype-generic-arg.slang +++ b/tests/compute/assoctype-generic-arg.slang @@ -1,8 +1,9 @@ +//TEST(compute):COMPARE_COMPUTE:-cpu //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out -//TEST_INPUT:type AssocImpl +//TEST_INPUT:type AssocImpl +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; interface IBase diff --git a/tests/compute/assoctype-nested.slang b/tests/compute/assoctype-nested.slang index b3d96306b..6f267a780 100644 --- a/tests/compute/assoctype-nested.slang +++ b/tests/compute/assoctype-nested.slang @@ -2,6 +2,7 @@ // Confirm that an associated type can be declared nested in its parent. +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -cpu //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute @@ -48,7 +49,7 @@ int test(int val) return helper(strategy, val); } -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=gOutputBuffer RWStructuredBuffer<int> gOutputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/assoctype-simple.slang b/tests/compute/assoctype-simple.slang index d12c29620..6edf46f33 100644 --- a/tests/compute/assoctype-simple.slang +++ b/tests/compute/assoctype-simple.slang @@ -1,8 +1,10 @@ +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out + // Confirm that generics syntax can be used in user // code and generates valid output. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; interface ISimple diff --git a/tests/compute/bit-cast-double.slang b/tests/compute/bit-cast-double.slang index 27d0b48cf..69c93ba4f 100644 --- a/tests/compute/bit-cast-double.slang +++ b/tests/compute/bit-cast-double.slang @@ -1,9 +1,9 @@ +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -cpu //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out - +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/break-stmt.slang b/tests/compute/break-stmt.slang index 02f5f9fa9..283593ee5 100644 --- a/tests/compute/break-stmt.slang +++ b/tests/compute/break-stmt.slang @@ -1,5 +1,5 @@ +//TEST(compute):COMPARE_COMPUTE:-cpu //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out // Test that `break` from a loop works. @@ -15,6 +15,7 @@ int test(int inVal) return -ii; } +//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer : register(u0); [numthreads(4, 1, 1)] diff --git a/tests/compute/buffer-layout.slang b/tests/compute/buffer-layout.slang index 145da99c8..9e4a63722 100644 --- a/tests/compute/buffer-layout.slang +++ b/tests/compute/buffer-layout.slang @@ -6,9 +6,9 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -cpu - -//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; struct A @@ -103,10 +103,10 @@ struct S int d; } -//TEST_INPUT:cbuffer(data=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32]):dxbinding(0),glbinding(0) +//TEST_INPUT:cbuffer(data=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32]):dxbinding(0),glbinding(0),name=cb ConstantBuffer<S> cb; -//TEST_INPUT:ubuffer(data=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32],stride=4):dxbinding(0),glbinding(1) +//TEST_INPUT:ubuffer(data=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32],stride=4):dxbinding(0),glbinding(1),name=sb RWStructuredBuffer<S> sb; int test(int val) diff --git a/tests/compute/buffer-layout.slang.3.expected.txt b/tests/compute/buffer-layout.slang.3.expected.txt new file mode 100644 index 000000000..4fcded8c6 --- /dev/null +++ b/tests/compute/buffer-layout.slang.3.expected.txt @@ -0,0 +1,4 @@ +13080308 +23080308 +33080308 +43080308 diff --git a/tests/compute/buffer-type-splitting.slang b/tests/compute/buffer-type-splitting.slang index c7577a0b2..f4a05c8f8 100644 --- a/tests/compute/buffer-type-splitting.slang +++ b/tests/compute/buffer-type-splitting.slang @@ -1,9 +1,11 @@ +//TEST(compute):COMPARE_COMPUTE:-cpu //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out -//TEST_INPUT:ubuffer(data=[0 2 3 3]):dxbinding(1),glbinding(1) -//TEST_INPUT:ubuffer(data=[4 5 6 7]):dxbinding(2),glbinding(2) -//TEST_INPUT:ubuffer(data=[8 9 10 11]):dxbinding(3),glbinding(3) -//TEST_INPUT:ubuffer(data=[12 13 14 15]):dxbinding(4),glbinding(4) + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer +//TEST_INPUT:ubuffer(data=[0 2 3 3]):dxbinding(1),glbinding(1),name=s[0].a +//TEST_INPUT:ubuffer(data=[4 5 6 7]):dxbinding(2),glbinding(2),name=s[1].a +//TEST_INPUT:ubuffer(data=[8 9 10 11]):dxbinding(3),glbinding(3),name=s[0].b +//TEST_INPUT:ubuffer(data=[12 13 14 15]):dxbinding(4),glbinding(4),name=s[1].b RWStructuredBuffer<int> outputBuffer; diff --git a/tests/compute/byte-address-buffer.slang b/tests/compute/byte-address-buffer.slang index 2efbeb630..851e06214 100644 --- a/tests/compute/byte-address-buffer.slang +++ b/tests/compute/byte-address-buffer.slang @@ -1,5 +1,6 @@ // byte-address-buffer.slang +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-d3d12 -compute @@ -9,10 +10,10 @@ // TODO: I'm only using `RWByteAddressBuffer` for now because I don't // know if `render-test` supports the non-UAV case. -//TEST_INPUT:ubuffer(data=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]):dxbinding(0),glbinding(0) +//TEST_INPUT:ubuffer(data=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]):dxbinding(0),glbinding(0),name=inputBuffer RWByteAddressBuffer inputBuffer; -//TEST_INPUT:ubuffer(data=[0 0 0 0]):dxbinding(1),glbinding(1),out +//TEST_INPUT:ubuffer(data=[0 0 0 0]):dxbinding(1),glbinding(1),out,name=outputBuffer RWByteAddressBuffer outputBuffer; void test(int val) diff --git a/tests/compute/cast-zero-to-struct.slang b/tests/compute/cast-zero-to-struct.slang index c2ed8fb6d..41bc299e5 100644 --- a/tests/compute/cast-zero-to-struct.slang +++ b/tests/compute/cast-zero-to-struct.slang @@ -4,6 +4,7 @@ // to a `struct` type works. //TEST(compute):COMPARE_COMPUTE: +//TEST(compute):COMPARE_COMPUTE:-cpu struct S { @@ -24,7 +25,7 @@ int test(int val) return t.x + t.y*16; } -//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=gOutputBuffer RWStructuredBuffer<int> gOutputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/continue-stmt.slang b/tests/compute/continue-stmt.slang index 9adb5a4a6..f21592ecc 100644 --- a/tests/compute/continue-stmt.slang +++ b/tests/compute/continue-stmt.slang @@ -1,5 +1,5 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // Test that `break` from a loop works. @@ -20,6 +20,7 @@ int test(int inVal) return -ii; } +//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer : register(u0); [numthreads(4, 1, 1)] diff --git a/tests/compute/default-parameter.slang b/tests/compute/default-parameter.slang index 6e6631bb4..cc960f2e5 100644 --- a/tests/compute/default-parameter.slang +++ b/tests/compute/default-parameter.slang @@ -1,8 +1,8 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-cpu -compute -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out - +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; int helper(int val, int a = 16) diff --git a/tests/compute/empty-struct.slang b/tests/compute/empty-struct.slang index 51094fad5..5e000b723 100644 --- a/tests/compute/empty-struct.slang +++ b/tests/compute/empty-struct.slang @@ -1,8 +1,10 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu + // Confirm that generics syntax can be used in user // code and generates valid output. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; struct Simple diff --git a/tests/compute/empty-struct2.slang b/tests/compute/empty-struct2.slang index 17cbb6ab4..2ec7bbc3f 100644 --- a/tests/compute/empty-struct2.slang +++ b/tests/compute/empty-struct2.slang @@ -1,7 +1,9 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu + // This is a basic test for Slang compute shader. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<uint> outputBuffer; interface IInterface diff --git a/tests/compute/enum-tag-conversion.slang b/tests/compute/enum-tag-conversion.slang index 5758cc3c1..869b1c3af 100644 --- a/tests/compute/enum-tag-conversion.slang +++ b/tests/compute/enum-tag-conversion.slang @@ -2,6 +2,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute // Confirm that a value of `enum` type can have an initializer // that includes basic operations like type conversion. @@ -16,7 +17,7 @@ int test(int val) return val + int(RoseColors.Red); } -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/enum.slang b/tests/compute/enum.slang index c10cedc25..cbe940f30 100644 --- a/tests/compute/enum.slang +++ b/tests/compute/enum.slang @@ -1,6 +1,7 @@ // enum.slang //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute // Confirm that basic `enum` declarations are supported. @@ -51,7 +52,7 @@ int test(int val) return (val << 4) + int(c); } -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/explicit-this-expr.slang b/tests/compute/explicit-this-expr.slang index 7179d046d..02f744662 100644 --- a/tests/compute/explicit-this-expr.slang +++ b/tests/compute/explicit-this-expr.slang @@ -1,5 +1,6 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu + // Access fields of a `struct` type from within a "method" by // using an explicit `this` expression. @@ -14,6 +15,7 @@ struct A } }; +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer : register(u0); diff --git a/tests/compute/extension-multi-interface.slang b/tests/compute/extension-multi-interface.slang index e29baf3b5..f13769f56 100644 --- a/tests/compute/extension-multi-interface.slang +++ b/tests/compute/extension-multi-interface.slang @@ -1,6 +1,7 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; interface IAdd diff --git a/tests/compute/extension-on-interface.slang b/tests/compute/extension-on-interface.slang index 0034cc43a..4f516092d 100644 --- a/tests/compute/extension-on-interface.slang +++ b/tests/compute/extension-on-interface.slang @@ -1,6 +1,7 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; interface IOp diff --git a/tests/compute/func-cbuffer-param.slang b/tests/compute/func-cbuffer-param.slang index 1fe7d2a38..a0784e21e 100644 --- a/tests/compute/func-cbuffer-param.slang +++ b/tests/compute/func-cbuffer-param.slang @@ -8,19 +8,20 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute, vulkan, compatibility-issue):COMPARE_COMPUTE_EX:-dx12 -compute -use-dxil //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-cpu -compute struct Data { int4 val[4]; } -//TEST_INPUT:cbuffer(data=[0 1 2 3 16 17 18 19 32 33 34 35 48 49 50 51]):dxbinding(0),glbinding(0) +//TEST_INPUT:cbuffer(data=[0 1 2 3 16 17 18 19 32 33 34 35 48 49 50 51]):dxbinding(0),glbinding(0),name=a ConstantBuffer<Data> a; -//TEST_INPUT:cbuffer(data=[16 17 18 19 32 33 34 35 48 49 50 51 64 65 66 67]):dxbinding(1),glbinding(1) +//TEST_INPUT:cbuffer(data=[16 17 18 19 32 33 34 35 48 49 50 51 64 65 66 67]):dxbinding(1),glbinding(1),name=b ConstantBuffer<Data> b; -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(2),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(2),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; int helper(ConstantBuffer<Data> buffer, int index) diff --git a/tests/compute/func-param-legalize.slang b/tests/compute/func-param-legalize.slang index f3177a1b1..a68766389 100644 --- a/tests/compute/func-param-legalize.slang +++ b/tests/compute/func-param-legalize.slang @@ -1,7 +1,4 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:Texture2D(size=4, content = one) : dxbinding(0),glbinding(0) -//TEST_INPUT: Sampler : dxbinding(0),glbinding(0,1,2,3,4,5,6) -//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out struct Param { @@ -10,8 +7,11 @@ struct Param float base; }; +//TEST_INPUT:Texture2D(size=4, content = one) : dxbinding(0),glbinding(0),name=diffuseMap Texture2D diffuseMap; +//TEST_INPUT: Sampler : dxbinding(0),glbinding(0,1,2,3,4,5,6),name=samplerState SamplerState samplerState; +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; float4 run(Param p) diff --git a/tests/compute/func-resource-param.slang b/tests/compute/func-resource-param.slang index 19784b108..2f6668dce 100644 --- a/tests/compute/func-resource-param.slang +++ b/tests/compute/func-resource-param.slang @@ -7,13 +7,14 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-dx12 -compute //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-cpu -compute //NO_TEST:SIMPLE:-target glsl -entry computeMain -stage compute -validate-ir -dump-ir -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; -//TEST_INPUT:ubuffer(data=[0 16 32 48], stride=4):dxbinding(1),glbinding(1) +//TEST_INPUT:ubuffer(data=[0 16 32 48], stride=4):dxbinding(1),glbinding(1),name=inputBuffer RWStructuredBuffer<int> inputBuffer; int helper(RWStructuredBuffer<int> buffer, int index) diff --git a/tests/compute/generic-closer.slang b/tests/compute/generic-closer.slang index f3bb643de..a40d520cc 100644 --- a/tests/compute/generic-closer.slang +++ b/tests/compute/generic-closer.slang @@ -1,8 +1,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute - -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute interface IGetter { @@ -18,7 +17,9 @@ struct Gen1<TGetter : IGetter> : IGetter int get() { return g.get(); } }; +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; + void writeArray(inout float3 a[4]) { a[0] = float3(1, 1, 1); diff --git a/tests/compute/generic-interface-method-simple.slang b/tests/compute/generic-interface-method-simple.slang index 2af6da969..a8b2fcd8a 100644 --- a/tests/compute/generic-interface-method-simple.slang +++ b/tests/compute/generic-interface-method-simple.slang @@ -1,6 +1,7 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; interface IVertexInterpolant diff --git a/tests/compute/generic-interface-method.slang b/tests/compute/generic-interface-method.slang index 38babdf7c..16d891636 100644 --- a/tests/compute/generic-interface-method.slang +++ b/tests/compute/generic-interface-method.slang @@ -1,6 +1,7 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; struct DisneyBRDFPattern diff --git a/tests/compute/generic-list.slang b/tests/compute/generic-list.slang index 118cbaed6..8b88a35ac 100644 --- a/tests/compute/generic-list.slang +++ b/tests/compute/generic-list.slang @@ -1,8 +1,10 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu + // Confirm that generics syntax can be used in user // code and generates valid output. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float4> outputBuffer; interface IElement diff --git a/tests/compute/generic-struct-with-constraint.slang b/tests/compute/generic-struct-with-constraint.slang index 1c2fdf4f3..5468cce80 100644 --- a/tests/compute/generic-struct-with-constraint.slang +++ b/tests/compute/generic-struct-with-constraint.slang @@ -1,8 +1,10 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu + // Confirm that generics syntax can be used in user // code and generates valid output. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float4> outputBuffer; interface IElement diff --git a/tests/compute/generic-struct.slang b/tests/compute/generic-struct.slang index b13a7bf77..8c97ef76d 100644 --- a/tests/compute/generic-struct.slang +++ b/tests/compute/generic-struct.slang @@ -1,9 +1,10 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // Check that user code can declare and use a generic // `struct` type. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; __generic<T> diff --git a/tests/compute/generics-constrained.slang b/tests/compute/generics-constrained.slang index ba42b303c..eb3df321a 100644 --- a/tests/compute/generics-constrained.slang +++ b/tests/compute/generics-constrained.slang @@ -1,5 +1,5 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu // Use interface constraints on a generic parameter @@ -27,6 +27,7 @@ float testHelp(T helper) return helper.getHelp(); } +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer : register(u0); diff --git a/tests/compute/generics-constructor.slang b/tests/compute/generics-constructor.slang index 59368b47c..d36f72a59 100644 --- a/tests/compute/generics-constructor.slang +++ b/tests/compute/generics-constructor.slang @@ -1,6 +1,7 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; __generic<T:__BuiltinFloatingPointType> diff --git a/tests/compute/generics-overload.slang b/tests/compute/generics-overload.slang index 45d0deb2b..8d30666c3 100644 --- a/tests/compute/generics-overload.slang +++ b/tests/compute/generics-overload.slang @@ -1,8 +1,10 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu + // Confirm that generics syntax can be used in user // code and generates valid output. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; diff --git a/tests/compute/generics-simple.slang b/tests/compute/generics-simple.slang index 653ccfd0a..f7b73a5e6 100644 --- a/tests/compute/generics-simple.slang +++ b/tests/compute/generics-simple.slang @@ -1,8 +1,10 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu + // Confirm that generics syntax can be used in user // code and generates valid output. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; diff --git a/tests/compute/generics-syntax-2.slang b/tests/compute/generics-syntax-2.slang index 56ace573c..f57ccb9ed 100644 --- a/tests/compute/generics-syntax-2.slang +++ b/tests/compute/generics-syntax-2.slang @@ -1,8 +1,10 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu + // Confirm that generics syntax can be used in user // code and generates valid output. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; struct GenStruct<T> diff --git a/tests/compute/generics-syntax.slang b/tests/compute/generics-syntax.slang index 194d860f5..2d1adea44 100644 --- a/tests/compute/generics-syntax.slang +++ b/tests/compute/generics-syntax.slang @@ -1,8 +1,10 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu + // Confirm that generics syntax can be used in user // code and generates valid output. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; struct GenStruct<T> diff --git a/tests/compute/global-init.slang b/tests/compute/global-init.slang index 1fc4ae0a8..db99d1f2f 100644 --- a/tests/compute/global-init.slang +++ b/tests/compute/global-init.slang @@ -1,5 +1,5 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // Test that a global variable (not a shader parameter) // with an initializer works. @@ -11,6 +11,7 @@ int test(int inVal) return inVal + gVar; } +//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer : register(u0); [numthreads(4, 1, 1)] diff --git a/tests/compute/global-type-param.slang b/tests/compute/global-type-param.slang index 7621f8961..ed0591064 100644 --- a/tests/compute/global-type-param.slang +++ b/tests/compute/global-type-param.slang @@ -1,7 +1,8 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0], stride=4):dxbinding(0),glbinding(0),out + //TEST_INPUT:type Wrapper<Impl> +//TEST_INPUT:ubuffer(data=[0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; interface IBase diff --git a/tests/compute/implicit-generic-app.slang b/tests/compute/implicit-generic-app.slang index b6fcbd434..53edefc66 100644 --- a/tests/compute/implicit-generic-app.slang +++ b/tests/compute/implicit-generic-app.slang @@ -1,5 +1,5 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // Testing that we can implicitly specialize a generic // that has a constrained type parameter. @@ -29,7 +29,9 @@ int test(int val) return doIt(simple); } +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer : register(u0); + [numthreads(4, 1, 1)] void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { diff --git a/tests/compute/implicit-this-expr.slang b/tests/compute/implicit-this-expr.slang index 2d074f677..2197cde10 100644 --- a/tests/compute/implicit-this-expr.slang +++ b/tests/compute/implicit-this-expr.slang @@ -1,5 +1,5 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // Access fields of a `struct` type from within a "method" by // using an implicit `this` expression. @@ -14,9 +14,9 @@ struct A } }; +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer : register(u0); - float test(float inVal) { A a; diff --git a/tests/compute/init-list-defaults.slang b/tests/compute/init-list-defaults.slang index d8eb72b5b..9ed54ffaa 100644 --- a/tests/compute/init-list-defaults.slang +++ b/tests/compute/init-list-defaults.slang @@ -1,5 +1,6 @@ // init-list-defaults.slang //TEST(compute):COMPARE_COMPUTE: +//TEST(compute):COMPARE_COMPUTE:-cpu // Confirm that initializer lists correctly default-initialize elements past those specified. @@ -22,7 +23,7 @@ int test(int inVal) + (inVal+1)*4096; } -//TEST_INPUT:ubuffer(data=[9 9 9 9], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[9 9 9 9], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer : register(u0); [numthreads(4, 1, 1)] diff --git a/tests/compute/initializer-list.slang b/tests/compute/initializer-list.slang index de94d6c25..7d0af700e 100644 --- a/tests/compute/initializer-list.slang +++ b/tests/compute/initializer-list.slang @@ -1,6 +1,5 @@ //TEST(compute):COMPARE_COMPUTE: - -//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu struct Test { @@ -16,6 +15,7 @@ uint test(uint val) return val + t.b; } +//TEST_INPUT: ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<uint> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/inout.slang b/tests/compute/inout.slang index a11050055..b7c64d57f 100644 --- a/tests/compute/inout.slang +++ b/tests/compute/inout.slang @@ -1,5 +1,5 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // Test that we correctly support both `out` // and `inout` function parameters. @@ -35,6 +35,7 @@ int test(int inVal) return x3; } +//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer : register(u0); [numthreads(4, 1, 1)] diff --git a/tests/compute/int-generic.slang b/tests/compute/int-generic.slang index d9eb85f82..c62ecf3d7 100644 --- a/tests/compute/int-generic.slang +++ b/tests/compute/int-generic.slang @@ -1,6 +1,8 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out + //TEST_INPUT:type Material<1,2> + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; interface IBRDF diff --git a/tests/compute/interface-local.slang b/tests/compute/interface-local.slang index d3ee88062..0a3d1c85f 100644 --- a/tests/compute/interface-local.slang +++ b/tests/compute/interface-local.slang @@ -13,6 +13,8 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute + interface IHelper { @@ -35,7 +37,7 @@ int test(int val) return existentialHelper.getVal(); } -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=gOutputBuffer RWStructuredBuffer<int> gOutputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/interface-param.slang b/tests/compute/interface-param.slang index 1c16d2e9b..6e0a735f4 100644 --- a/tests/compute/interface-param.slang +++ b/tests/compute/interface-param.slang @@ -7,6 +7,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute interface IHelper { @@ -31,7 +32,7 @@ int test(int val) return doTheThing(helperImpl); } -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=gOutputBuffer RWStructuredBuffer<int> gOutputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/interface-shader-param.slang b/tests/compute/interface-shader-param.slang index b8968b225..75788ee9a 100644 --- a/tests/compute/interface-shader-param.slang +++ b/tests/compute/interface-shader-param.slang @@ -6,6 +6,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//DISABLE_TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute // First we will define some fake interfaces for testing. // Let's pretend we are doing some kind of random number @@ -74,7 +75,7 @@ int test( // // We'll start with the buffer for writing the test output. -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=gOutputBuffer RWStructuredBuffer<int> gOutputBuffer; // Now we'll define a global shader parameter for the diff --git a/tests/compute/interface-static-method.slang b/tests/compute/interface-static-method.slang index 4747c8a8a..f10e00783 100644 --- a/tests/compute/interface-static-method.slang +++ b/tests/compute/interface-static-method.slang @@ -3,6 +3,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute interface IHideout { @@ -45,7 +46,7 @@ int test(int val) } -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/matrix-layout-structured-buffer.slang b/tests/compute/matrix-layout-structured-buffer.slang index fc46d7815..68b591f1b 100644 --- a/tests/compute/matrix-layout-structured-buffer.slang +++ b/tests/compute/matrix-layout-structured-buffer.slang @@ -17,8 +17,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -xslang -matrix-layout-row-major //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -xslang -matrix-layout-column-major - -//TEST_INPUT:ubuffer(data=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23], stride=48):dxbinding(0),glbinding(0) +//TEST_INPUT:ubuffer(data=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23], stride=48):dxbinding(0),glbinding(0),name=gMatrices RWStructuredBuffer<int3x4> gMatrices; int test(int val) diff --git a/tests/compute/matrix-layout.hlsl b/tests/compute/matrix-layout.hlsl index 034ac512c..64d863eb3 100644 --- a/tests/compute/matrix-layout.hlsl +++ b/tests/compute/matrix-layout.hlsl @@ -60,7 +60,7 @@ int test(int val) return ((a*N + b) * N + c) * N + d; } -//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0], stride=4):dxbinding(0),glbinding(2),out +//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0 0 0], stride=4):dxbinding(0),glbinding(2),out,name=buffer RWStructuredBuffer<int> buffer; [numthreads(12, 1, 1)] diff --git a/tests/compute/modern-syntax.slang b/tests/compute/modern-syntax.slang index c0a1f1442..cf5f89370 100644 --- a/tests/compute/modern-syntax.slang +++ b/tests/compute/modern-syntax.slang @@ -1,5 +1,6 @@ // modern-syntax.slang //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -slang -compute // This file exists to confirm that declarations using "modern" // syntax are handled correctly by the compiler front-end. @@ -14,7 +15,7 @@ func test(val: MyInt) -> MyInt return tmp; } -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/multi-interface.slang b/tests/compute/multi-interface.slang index f2115f1fc..f3c18ba42 100644 --- a/tests/compute/multi-interface.slang +++ b/tests/compute/multi-interface.slang @@ -1,6 +1,7 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; interface IAdd diff --git a/tests/compute/multiple-continue-sites.slang b/tests/compute/multiple-continue-sites.slang index 5a5b78d0c..afab66a95 100644 --- a/tests/compute/multiple-continue-sites.slang +++ b/tests/compute/multiple-continue-sites.slang @@ -1,5 +1,5 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // Test that a loop with multiple `continue` sites works. // @@ -27,6 +27,7 @@ int test(int inVal) return ii; } +//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer : register(u0); [numthreads(4, 1, 1)] diff --git a/tests/compute/mutating-methods.slang b/tests/compute/mutating-methods.slang index 8192acd82..bb3bdeb7e 100644 --- a/tests/compute/mutating-methods.slang +++ b/tests/compute/mutating-methods.slang @@ -2,6 +2,7 @@ //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -xslang -serial-ir //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -dx12 -xslang -serial-ir //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -xslang -serial-ir +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -xslang -serial-ir interface IAccumulator { @@ -40,7 +41,7 @@ int test(int x) return a.state; } -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/nested-generics.slang b/tests/compute/nested-generics.slang index 8996b2574..de1e52991 100644 --- a/tests/compute/nested-generics.slang +++ b/tests/compute/nested-generics.slang @@ -1,8 +1,9 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // test specialization of nested generic functions +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; interface IGetF diff --git a/tests/compute/nested-generics2.slang b/tests/compute/nested-generics2.slang index 1f6d4a50a..855f97a11 100644 --- a/tests/compute/nested-generics2.slang +++ b/tests/compute/nested-generics2.slang @@ -1,8 +1,9 @@ //TEST(compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(compute):COMPARE_COMPUTE:-cpu // test specialization of nested generic functions +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; interface IBRDF diff --git a/tests/compute/scope-operator.slang b/tests/compute/scope-operator.slang index c50d95965..2afb642ab 100644 --- a/tests/compute/scope-operator.slang +++ b/tests/compute/scope-operator.slang @@ -1,10 +1,11 @@ // scope.slang //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute //TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute // Confirm that scoping on enums and types works -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; enum Color diff --git a/tests/compute/select-expr.slang b/tests/compute/select-expr.slang index d90708ab9..ae5375e42 100644 --- a/tests/compute/select-expr.slang +++ b/tests/compute/select-expr.slang @@ -1,6 +1,5 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out - +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu // Test IR code generation for the `?:` "select" operator @@ -9,6 +8,7 @@ int test(int input) return input > 1 ? -input : input; } +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/simple.slang b/tests/compute/simple.slang index 8f53a79b2..67ed67a6c 100644 --- a/tests/compute/simple.slang +++ b/tests/compute/simple.slang @@ -1,7 +1,9 @@ //TEST(smoke,compute):COMPARE_COMPUTE: -//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out +//TEST(smoke,compute):COMPARE_COMPUTE:-cpu + // This is a basic test for Slang compute shader. +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):dxbinding(0),glbinding(0),out,name=outputBuffer RWStructuredBuffer<float> outputBuffer; [numthreads(4, 1, 1)] diff --git a/tests/compute/ssa-reduce-bug.slang b/tests/compute/ssa-reduce-bug.slang index fe53f2ab0..15af36f9f 100644 --- a/tests/compute/ssa-reduce-bug.slang +++ b/tests/compute/ssa-reduce-bug.slang @@ -1,10 +1,10 @@ // ssa-reduce-bug.slang //TEST(compute):COMPARE_COMPUTE_EX:-slang -compute +//TEST(compute):COMPARE_COMPUTE_EX:-cpu -slang -compute -//TEST_INPUT:ubuffer(data=[0 3 1 2 6 4 7 6], stride=4):dxbinding(0),glbinding(0) -//TEST_INPUT:ubuffer(data=[8 8 8 8 8 8 8 8], stride=4):dxbinding(1),glbinding(1),out - +//TEST_INPUT:ubuffer(data=[0 3 1 2 6 4 7 6], stride=4):dxbinding(0),glbinding(0),name=inputBuffer RWStructuredBuffer<int> inputBuffer; +//TEST_INPUT:ubuffer(data=[8 8 8 8 8 8 8 8], stride=4):dxbinding(1),glbinding(1),out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; int2 reduce(int2 val) diff --git a/tools/render-test/render-test-main.cpp b/tools/render-test/render-test-main.cpp index e8170be40..3bd257340 100644 --- a/tools/render-test/render-test-main.cpp +++ b/tools/render-test/render-test-main.cpp @@ -15,6 +15,8 @@ #include "../source/core/slang-io.h" +#include "core/slang-token-reader.h" + #include "shader-input-layout.h" #include <stdio.h> #include <stdlib.h> @@ -320,72 +322,35 @@ static SlangResult _compile(SlangSession* session, const String& sourcePath, Opt return ShaderCompilerUtil::compileProgram(session, input, compileRequest, output.compileOutput); } -static SlangResult _handleResource(slang::TypeReflection* type, ShaderInputLayoutEntry& src, void* dst) +struct MemoryInfo { - auto shape = type->getResourceShape(); - auto access = type->getResourceAccess(); + MemoryInfo() :data(nullptr), size(0) {} + uint8_t* data; + size_t size; +}; - switch (shape & SLANG_RESOURCE_BASE_SHAPE_MASK) - { - default: - assert(!"unhandled case"); - break; - case SLANG_TEXTURE_1D: - case SLANG_TEXTURE_2D: - case SLANG_TEXTURE_3D: - case SLANG_TEXTURE_CUBE: - case SLANG_TEXTURE_BUFFER: - { - return SLANG_FAIL; - } - case SLANG_STRUCTURED_BUFFER: - { - // TODO(JS): I guess this is questionable - because sizeof(unsigned int) != sizeof(uint32_t) necessarily - CPPPrelude::StructuredBuffer<uint32_t>& dstBuf = *(CPPPrelude::StructuredBuffer<uint32_t>*)dst; - dstBuf.data = src.bufferData.getBuffer(); - dstBuf.count = src.bufferData.getCount(); - break; - } - case SLANG_BYTE_ADDRESS_BUFFER: - { - CPPPrelude::ByteAddressBuffer& dstBuf = *(CPPPrelude::ByteAddressBuffer*)dst; - dstBuf.data = src.bufferData.getBuffer(); - dstBuf.sizeInBytes = src.bufferData.getCount() * sizeof(unsigned int); +static MemoryInfo _allocateMemory(MemoryArena& arena, size_t size, List<unsigned int>& initialContents) +{ + MemoryInfo info; - break; - } - } - if (shape & SLANG_TEXTURE_ARRAY_FLAG) - { - - } - if (shape & SLANG_TEXTURE_MULTISAMPLE_FLAG) - { - - } + // Use 16 byte alignment so works for all common types including typical simd + void* data = arena.allocateAligned(size, 16); + ::memset(data, 0, size); - if (access != SLANG_RESOURCE_ACCESS_READ) + if (initialContents.getCount() > 0) { - switch (access) - { - default: - assert(!"unhandled case"); - break; + size_t initialSize = initialContents.getCount() * sizeof(unsigned int); + initialSize = (initialSize > size) ? size : initialSize; - case SLANG_RESOURCE_ACCESS_READ: - break; - - case SLANG_RESOURCE_ACCESS_READ_WRITE: break; - case SLANG_RESOURCE_ACCESS_RASTER_ORDERED: break; - case SLANG_RESOURCE_ACCESS_APPEND: break; - case SLANG_RESOURCE_ACCESS_CONSUME: break; - } - + ::memcpy(data, initialContents.getBuffer(), initialSize); } - return SLANG_OK; + + info.data = (uint8_t*)data; + info.size = size; + return info; } -static SlangResult _writeBindings(const ShaderInputLayout& layout, const String& fileName) +static SlangResult _writeBindings(const ShaderInputLayout& layout, const List<MemoryInfo>& infos, const String& fileName) { FILE * f = fopen(fileName.getBuffer(), "wb"); if (!f) @@ -393,15 +358,26 @@ static SlangResult _writeBindings(const ShaderInputLayout& layout, const String& return SLANG_FAIL; } - for (auto entry : layout.entries) + const auto& entries = layout.entries; + + for (int i = 0; i < entries.getCount(); ++i) { + const auto& entry = entries[i]; if (entry.isOutput) { - auto ptr = entry.bufferData.getBuffer(); + const auto& info = infos[i]; + + unsigned int* ptr = (unsigned int*)info.data; + const int size = int(entry.bufferData.getCount()); + // Must be the same size or less thatn allocated buffer + SLANG_ASSERT(size * sizeof(unsigned int) <= info.size); + for (int i = 0; i < size; ++i) { - fprintf(f, "%X\n", ptr[i]); + unsigned int v = ptr[i]; + + fprintf(f, "%X\n", v); } } } @@ -409,6 +385,22 @@ static SlangResult _writeBindings(const ShaderInputLayout& layout, const String& return SLANG_OK; } + +static slang::VariableLayoutReflection* _getParameterByName(slang::ShaderReflection* reflection, const char* name) +{ + const int parameterCount = reflection->getParameterCount(); + for (int i = 0; i < parameterCount; ++i) + { + auto parameter = reflection->getParameterByIndex(i); + const char* paramName = parameter->getName(); + if (strcmp(name, paramName) == 0) + { + return parameter; + } + } + return nullptr; +} + static SlangResult _doCPUCompute(SlangSession* session, const String& sourcePath, Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input) { CompileOutput output; @@ -428,7 +420,6 @@ static SlangResult _doCPUCompute(SlangSession* session, const String& sourcePath slang::EntryPointReflection* entryPoint = nullptr; Func func = nullptr; { - auto entryPointCount = reflection->getEntryPointCount(); SLANG_ASSERT(entryPointCount == 1); @@ -448,53 +439,118 @@ static SlangResult _doCPUCompute(SlangSession* session, const String& sourcePath // For general storage MemoryArena arena; - arena.init(1024); + // 1k blocks with minimum 16 byte alignment + arena.init(1024, 16); + + // We have a memory info for each of the layouts + List<MemoryInfo> memoryInfos; + memoryInfos.setCount(layout.entries.getCount()); + List<void*> uniformState; { - int parameterCount = reflection->getParameterCount(); + auto& outStream = StdWriters::getOut(); + + auto& entries = layout.entries; - for (int i = 0; i < parameterCount; ++i) + for (int entryIndex = 0; entryIndex < entries.getCount(); ++entryIndex) { - auto parameter = reflection->getParameterByIndex(i); + auto& entry = entries[entryIndex]; - const char* paramName = parameter->getName(); - - const Index entryIndex = layout.findEntryIndexByName(paramName); - if (entryIndex < 0) + if (entry.name.getLength() == 0) { - auto& outStream = StdWriters::getOut(); + outStream.print("No 'name' specified for resources in '%s'\n", sourcePath.getBuffer()); + return SLANG_FAIL; + } - int numNamed = 0; - for (const auto& entry : layout.entries) - { - numNamed += int(entry.name.getLength() > 0); - } + // We will parse the 'name' as may be path to a resource + TokenReader parser(entry.name); - if (layout.entries.getCount() > 0 && numNamed == 0) + size_t offset = 0; + slang::TypeLayoutReflection* typeLayout = nullptr; + { + Token nameToken = parser.ReadToken(); + if (nameToken.Type != TokenType::Identifier) { - outStream.print("No 'name' specified for resources in '%s'\n", sourcePath.getBuffer()); + outStream.print("Invalid input syntax at line %d", int(parser.NextToken().Position.Line)); + return SLANG_FAIL; } - else + auto parameter = _getParameterByName(reflection, nameToken.Content.getBuffer()); + if (!parameter) { - outStream.print("Unable to find entry in '%s' for '%s' (for CPU name must be specified) \n", sourcePath.getBuffer(), paramName); + outStream.print("Unable to find entry in '%s' for '%s' (for CPU name must be specified) \n", sourcePath.getBuffer(), entry.name.getBuffer()); + return SLANG_FAIL; } - return SLANG_FAIL; + + typeLayout = parameter->getTypeLayout(); + offset = parameter->getOffset(); } - auto stage = parameter->getStage(); + while (!parser.IsEnd()) + { + Token token = parser.NextToken(0); + + if (token.Type == TokenType::LBracket) + { + parser.ReadToken(); + int index = parser.ReadInt(); + SLANG_ASSERT(index >= 0); + parser.ReadMatchingToken(TokenType::RBracket); + + auto elementTypeLayout = typeLayout->getElementTypeLayout(); + auto elementCount = int(typeLayout->getElementCount()); - auto typeLayout = parameter->getTypeLayout(); - auto categoryCount = parameter->getCategoryCount(); + SLANG_ASSERT(index < elementCount); - SLANG_ASSERT(categoryCount == 1); + typeLayout = elementTypeLayout; + offset += elementTypeLayout->getSize() * index; + } + else if (token.Type == TokenType::Dot) + { + parser.ReadToken(); + Token identifierToken = parser.ReadMatchingToken(TokenType::Identifier); + + if (typeLayout->getKind() == slang::TypeReflection::Kind::Struct) + { + slang::VariableLayoutReflection* varLayout = nullptr; + auto fieldCount = typeLayout->getFieldCount(); + for (uint32_t ff = 0; ff < fieldCount; ++ff) + { + auto field = typeLayout->getFieldByIndex(ff); + if (identifierToken.Content == field->getName()) + { + varLayout = field; + break; + } + } - // Only dealing one category per item right now - auto category = parameter->getCategoryByIndex(0); + if (varLayout == nullptr) + { + outStream.print("Couldn't field %s\n", identifierToken.Content.getBuffer()); + return SLANG_FAIL; + } + + offset += varLayout->getOffset(); + typeLayout = varLayout->getTypeLayout(); + } + else + { + outStream.print("Couldn't field %s\n", identifierToken.Content.getBuffer()); + return SLANG_FAIL; + } + } + else if (token.Type == TokenType::Comma) + { + // Break out + break; + } + else + { + throw TextFormatException("Invalid input syntax at line " + parser.NextToken().Position.Line); + } + } - auto offset = parameter->getOffset(category); - auto space = parameter->getBindingSpace(category); - auto count = typeLayout->getSize(category); + auto count = typeLayout->getSize(); size_t end = offset + count; if (uniformState.getCount() * sizeof(void*) < end) @@ -543,8 +599,13 @@ static SlangResult _doCPUCompute(SlangSession* session, const String& sourcePath } case slang::TypeReflection::Kind::ConstantBuffer: { + SLANG_ASSERT(typeLayout->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM) == sizeof(void*)); auto elementTypeLayout = typeLayout->getElementTypeLayout(); - SLANG_UNUSED(elementTypeLayout); + const size_t elementSize = elementTypeLayout->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM); + + const MemoryInfo info = _allocateMemory(arena, elementSize, srcEntry.bufferData); + memoryInfos[entryIndex] = info; + *(void**)dstEntry = info.data; break; } case slang::TypeReflection::Kind::ParameterBlock: @@ -579,23 +640,70 @@ static SlangResult _doCPUCompute(SlangSession* session, const String& sourcePath } case slang::TypeReflection::Kind::Resource: { - // Some resource types (notably structured buffers) - // encode layout information for their result/element - // type, but others don't. We need to check for - // the relevant cases here. - // auto type = typeLayout->getType(); auto shape = type->getResourceShape(); - if ((shape & SLANG_RESOURCE_BASE_SHAPE_MASK) == SLANG_STRUCTURED_BUFFER) + //auto access = type->getResourceAccess(); + + switch (shape & SLANG_RESOURCE_BASE_SHAPE_MASK) { - _handleResource(typeLayout->getType(), srcEntry, dstEntry); + default: + assert(!"unhandled case"); + break; + case SLANG_TEXTURE_1D: + case SLANG_TEXTURE_2D: + case SLANG_TEXTURE_3D: + case SLANG_TEXTURE_CUBE: + case SLANG_TEXTURE_BUFFER: + { + return SLANG_FAIL; + } + case SLANG_STRUCTURED_BUFFER: + { + auto elementTypeLayout = typeLayout->getElementTypeLayout(); + size_t elementSize = elementTypeLayout->getSize(SLANG_PARAMETER_CATEGORY_UNIFORM); + + // We don't know the size of the buffer, but we can work it out, based on what is initialized + + size_t srcBufferSize = srcEntry.bufferData.getCount() * sizeof(unsigned int); + const int numElements = int((srcBufferSize + elementSize - 1) / elementSize); + + size_t bufferSize = numElements * elementSize; + SLANG_ASSERT(bufferSize >= srcBufferSize); + + const MemoryInfo info = _allocateMemory(arena, bufferSize, srcEntry.bufferData); + memoryInfos[entryIndex] = info; + // TODO(JS): I guess this is questionable - because sizeof(unsigned int) != sizeof(uint32_t) necessarily + CPPPrelude::StructuredBuffer<uint32_t>& dstBuf = *(CPPPrelude::StructuredBuffer<uint32_t>*)dstEntry; + dstBuf.data = (uint32_t*)info.data; + dstBuf.count = numElements; + break; + } + case SLANG_BYTE_ADDRESS_BUFFER: + { + CPPPrelude::ByteAddressBuffer& dstBuf = *(CPPPrelude::ByteAddressBuffer*)dstEntry; + + Index numElements = srcEntry.bufferData.getCount(); + size_t bufferSize = sizeof(uint32_t) * numElements; + + const MemoryInfo info = _allocateMemory(arena, bufferSize, srcEntry.bufferData); + memoryInfos[entryIndex] = info; + + dstBuf.data = (uint32_t*)info.data; + dstBuf.sizeInBytes = bufferSize; + break; + } } - else + if (shape & SLANG_TEXTURE_ARRAY_FLAG) + { + + } + if (shape & SLANG_TEXTURE_MULTISAMPLE_FLAG) { - //emitReflectionTypeInfoJSON(writer, typeLayout->getType()); + } + break; } } @@ -609,13 +717,13 @@ static SlangResult _doCPUCompute(SlangSession* session, const String& sourcePath CPPPrelude::ComputeVaryingInput varying; varying.groupID = {}; - for (int z = 0; z < numThreadsPerAxis[2]; ++z) + for (int z = 0; z < int(numThreadsPerAxis[2]); ++z) { varying.groupThreadID.z = z; - for (int y = 0; y < numThreadsPerAxis[1]; ++y) + for (int y = 0; y < int(numThreadsPerAxis[1]); ++y) { varying.groupThreadID.y = y; - for (int x = 0; x < numThreadsPerAxis[0]; ++x) + for (int x = 0; x < int(numThreadsPerAxis[0]); ++x) { varying.groupThreadID.x = x; @@ -626,7 +734,7 @@ static SlangResult _doCPUCompute(SlangSession* session, const String& sourcePath } // Dump everything out that was write (we wrote in place!) - return _writeBindings(layout, gOptions.outputPath); + return _writeBindings(layout, memoryInfos, gOptions.outputPath); } SlangResult RenderTestApp::initialize(SlangSession* session, Renderer* renderer, Options::ShaderProgramType shaderType, const ShaderCompilerUtil::Input& input) diff --git a/tools/render-test/shader-input-layout.cpp b/tools/render-test/shader-input-layout.cpp index e555ee6ca..a59f30a24 100644 --- a/tools/render-test/shader-input-layout.cpp +++ b/tools/render-test/shader-input-layout.cpp @@ -286,13 +286,54 @@ namespace renderer_test else if (parser.LookAhead("name")) { parser.ReadToken(); - Token nameToken = parser.ReadToken(); + // Optionally consume '=' + if (parser.NextToken().Type == TokenType::OpAssign) + { + parser.ReadToken(); + } + + StringBuilder builder; + + Token nameToken = parser.ReadToken(); if (nameToken.Type != TokenType::Identifier) { throw TextFormatException("Invalid input syntax at line " + parser.NextToken().Position.Line); } - entry.name = nameToken.Content; + builder << nameToken.Content; + + while (!parser.IsEnd()) + { + Token token = parser.NextToken(0); + + if (token.Type == TokenType::LBracket) + { + parser.ReadToken(); + int index = parser.ReadInt(); + SLANG_ASSERT(index >= 0); + parser.ReadMatchingToken(TokenType::RBracket); + + builder << "[" << index << "]"; + } + else if (token.Type == TokenType::Dot) + { + parser.ReadToken(); + Token identifierToken = parser.ReadMatchingToken(TokenType::Identifier); + + builder << "." << identifierToken.Content; + } + else if (token.Type == TokenType::Comma) + { + // Break out + break; + } + else + { + throw TextFormatException("Invalid input syntax at line " + parser.NextToken().Position.Line); + } + } + + entry.name = builder; } if (parser.LookAhead(",")) |
