summaryrefslogtreecommitdiffstats
path: root/source/slang
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 /source/slang
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.
Diffstat (limited to 'source/slang')
-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
5 files changed, 274 insertions, 52 deletions
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,