summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-08-22 15:58:28 -0400
committerGitHub <noreply@github.com>2019-08-22 15:58:28 -0400
commit06a0e3980fd04fa265bd20eb11f2abc18bd6a215 (patch)
treeea664d7f0ecfa4b6948319d4fcfb0bbd1e3af888
parentbc392f9dbfb8cb6c359bb890fb85b831e49bfd55 (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.
-rw-r--r--prelude/slang-cpp-scalar-intrinsics.h45
-rw-r--r--source/core/slang-memory-arena.cpp35
-rw-r--r--source/core/slang-token-reader.h9
-rw-r--r--source/slang/slang-compiler.cpp5
-rw-r--r--source/slang/slang-emit-cpp.cpp213
-rw-r--r--source/slang/slang-emit-cpp.h13
-rw-r--r--source/slang/slang-ir-insts.h7
-rw-r--r--source/slang/slang-ir.cpp88
-rw-r--r--tests/compute/assoctype-complex.slang4
-rw-r--r--tests/compute/assoctype-func-param.slang4
-rw-r--r--tests/compute/assoctype-generic-arg.slang5
-rw-r--r--tests/compute/assoctype-nested.slang3
-rw-r--r--tests/compute/assoctype-simple.slang4
-rw-r--r--tests/compute/bit-cast-double.slang4
-rw-r--r--tests/compute/break-stmt.slang3
-rw-r--r--tests/compute/buffer-layout.slang8
-rw-r--r--tests/compute/buffer-layout.slang.3.expected.txt4
-rw-r--r--tests/compute/buffer-type-splitting.slang12
-rw-r--r--tests/compute/byte-address-buffer.slang5
-rw-r--r--tests/compute/cast-zero-to-struct.slang3
-rw-r--r--tests/compute/continue-stmt.slang3
-rw-r--r--tests/compute/default-parameter.slang4
-rw-r--r--tests/compute/empty-struct.slang4
-rw-r--r--tests/compute/empty-struct2.slang4
-rw-r--r--tests/compute/enum-tag-conversion.slang3
-rw-r--r--tests/compute/enum.slang3
-rw-r--r--tests/compute/explicit-this-expr.slang4
-rw-r--r--tests/compute/extension-multi-interface.slang3
-rw-r--r--tests/compute/extension-on-interface.slang3
-rw-r--r--tests/compute/func-cbuffer-param.slang7
-rw-r--r--tests/compute/func-param-legalize.slang6
-rw-r--r--tests/compute/func-resource-param.slang5
-rw-r--r--tests/compute/generic-closer.slang5
-rw-r--r--tests/compute/generic-interface-method-simple.slang3
-rw-r--r--tests/compute/generic-interface-method.slang3
-rw-r--r--tests/compute/generic-list.slang4
-rw-r--r--tests/compute/generic-struct-with-constraint.slang4
-rw-r--r--tests/compute/generic-struct.slang3
-rw-r--r--tests/compute/generics-constrained.slang3
-rw-r--r--tests/compute/generics-constructor.slang3
-rw-r--r--tests/compute/generics-overload.slang4
-rw-r--r--tests/compute/generics-simple.slang4
-rw-r--r--tests/compute/generics-syntax-2.slang4
-rw-r--r--tests/compute/generics-syntax.slang4
-rw-r--r--tests/compute/global-init.slang3
-rw-r--r--tests/compute/global-type-param.slang3
-rw-r--r--tests/compute/implicit-generic-app.slang4
-rw-r--r--tests/compute/implicit-this-expr.slang4
-rw-r--r--tests/compute/init-list-defaults.slang3
-rw-r--r--tests/compute/initializer-list.slang4
-rw-r--r--tests/compute/inout.slang3
-rw-r--r--tests/compute/int-generic.slang4
-rw-r--r--tests/compute/interface-local.slang4
-rw-r--r--tests/compute/interface-param.slang3
-rw-r--r--tests/compute/interface-shader-param.slang3
-rw-r--r--tests/compute/interface-static-method.slang3
-rw-r--r--tests/compute/matrix-layout-structured-buffer.slang3
-rw-r--r--tests/compute/matrix-layout.hlsl2
-rw-r--r--tests/compute/modern-syntax.slang3
-rw-r--r--tests/compute/multi-interface.slang3
-rw-r--r--tests/compute/multiple-continue-sites.slang3
-rw-r--r--tests/compute/mutating-methods.slang3
-rw-r--r--tests/compute/nested-generics.slang3
-rw-r--r--tests/compute/nested-generics2.slang3
-rw-r--r--tests/compute/scope-operator.slang3
-rw-r--r--tests/compute/select-expr.slang4
-rw-r--r--tests/compute/simple.slang4
-rw-r--r--tests/compute/ssa-reduce-bug.slang6
-rw-r--r--tools/render-test/render-test-main.cpp314
-rw-r--r--tools/render-test/shader-input-layout.cpp45
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(","))