GL_EXT_buffer_reference
This commit is contained in:
@@ -194,6 +194,40 @@ Id Builder::makePointer(StorageClass storageClass, Id pointee)
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::makeForwardPointer(StorageClass storageClass)
|
||||
{
|
||||
// Caching/uniquifying doesn't work here, because we don't know the
|
||||
// pointee type and there can be multiple forward pointers of the same
|
||||
// storage type. Somebody higher up in the stack must keep track.
|
||||
Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeForwardPointer);
|
||||
type->addImmediateOperand(storageClass);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee)
|
||||
{
|
||||
// try to find it
|
||||
Instruction* type;
|
||||
for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
|
||||
type = groupedTypes[OpTypePointer][t];
|
||||
if (type->getImmediateOperand(0) == (unsigned)storageClass &&
|
||||
type->getIdOperand(1) == pointee)
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
type = new Instruction(forwardPointerType, NoType, OpTypePointer);
|
||||
type->addImmediateOperand(storageClass);
|
||||
type->addIdOperand(pointee);
|
||||
groupedTypes[OpTypePointer].push_back(type);
|
||||
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::makeIntegerType(int width, bool hasSign)
|
||||
{
|
||||
// try to find it
|
||||
@@ -576,6 +610,7 @@ int Builder::getNumTypeConstituents(Id typeId) const
|
||||
case OpTypeBool:
|
||||
case OpTypeInt:
|
||||
case OpTypeFloat:
|
||||
case OpTypePointer:
|
||||
return 1;
|
||||
case OpTypeVector:
|
||||
case OpTypeMatrix:
|
||||
@@ -669,17 +704,36 @@ bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case OpTypePointer:
|
||||
return false;
|
||||
case OpTypeVector:
|
||||
case OpTypeMatrix:
|
||||
case OpTypeArray:
|
||||
case OpTypeRuntimeArray:
|
||||
case OpTypePointer:
|
||||
return containsType(getContainedTypeId(typeId), typeOp, width);
|
||||
default:
|
||||
return typeClass == typeOp;
|
||||
}
|
||||
}
|
||||
|
||||
// return true if the type is a pointer to PhysicalStorageBufferEXT or an
|
||||
// array of such pointers. These require restrict/aliased decorations.
|
||||
bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const
|
||||
{
|
||||
const Instruction& instr = *module.getInstruction(typeId);
|
||||
|
||||
Op typeClass = instr.getOpCode();
|
||||
switch (typeClass)
|
||||
{
|
||||
case OpTypePointer:
|
||||
return getTypeStorageClass(typeId) == StorageClassPhysicalStorageBufferEXT;
|
||||
case OpTypeArray:
|
||||
return containsPhysicalStorageBufferOrArray(getContainedTypeId(typeId));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// See if a scalar constant of this type has already been created, so it
|
||||
// can be reused rather than duplicated. (Required by the specification).
|
||||
Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value)
|
||||
@@ -1252,15 +1306,39 @@ Id Builder::createUndefined(Id type)
|
||||
return inst->getResultId();
|
||||
}
|
||||
|
||||
// av/vis/nonprivate are unnecessary and illegal for some storage classes.
|
||||
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
|
||||
{
|
||||
switch (sc) {
|
||||
case spv::StorageClassUniform:
|
||||
case spv::StorageClassWorkgroup:
|
||||
case spv::StorageClassStorageBuffer:
|
||||
case spv::StorageClassPhysicalStorageBufferEXT:
|
||||
break;
|
||||
default:
|
||||
memoryAccess = spv::MemoryAccessMask(memoryAccess &
|
||||
~(spv::MemoryAccessMakePointerAvailableKHRMask |
|
||||
spv::MemoryAccessMakePointerVisibleKHRMask |
|
||||
spv::MemoryAccessNonPrivatePointerKHRMask));
|
||||
break;
|
||||
}
|
||||
return memoryAccess;
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
|
||||
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
|
||||
{
|
||||
Instruction* store = new Instruction(OpStore);
|
||||
store->addIdOperand(lValue);
|
||||
store->addIdOperand(rValue);
|
||||
|
||||
memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
|
||||
|
||||
if (memoryAccess != MemoryAccessMaskNone) {
|
||||
store->addImmediateOperand(memoryAccess);
|
||||
if (memoryAccess & spv::MemoryAccessAlignedMask) {
|
||||
store->addImmediateOperand(alignment);
|
||||
}
|
||||
if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) {
|
||||
store->addIdOperand(makeUintConstant(scope));
|
||||
}
|
||||
@@ -1270,13 +1348,18 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
|
||||
Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
|
||||
{
|
||||
Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
|
||||
load->addIdOperand(lValue);
|
||||
|
||||
memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
|
||||
|
||||
if (memoryAccess != MemoryAccessMaskNone) {
|
||||
load->addImmediateOperand(memoryAccess);
|
||||
if (memoryAccess & spv::MemoryAccessAlignedMask) {
|
||||
load->addImmediateOperand(alignment);
|
||||
}
|
||||
if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) {
|
||||
load->addIdOperand(makeUintConstant(scope));
|
||||
}
|
||||
@@ -2118,7 +2201,8 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
|
||||
// Go through the source arguments, each one could have either
|
||||
// a single or multiple components to contribute.
|
||||
for (unsigned int i = 0; i < sources.size(); ++i) {
|
||||
if (isScalar(sources[i]))
|
||||
|
||||
if (isScalar(sources[i]) || isPointer(sources[i]))
|
||||
latchResult(sources[i]);
|
||||
else if (isVector(sources[i]))
|
||||
accumulateVectorConstituents(sources[i]);
|
||||
@@ -2433,11 +2517,15 @@ void Builder::clearAccessChain()
|
||||
accessChain.preSwizzleBaseType = NoType;
|
||||
accessChain.isRValue = false;
|
||||
accessChain.coherentFlags.clear();
|
||||
accessChain.alignment = 0;
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType)
|
||||
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
|
||||
{
|
||||
accessChain.coherentFlags |= coherentFlags;
|
||||
accessChain.alignment |= alignment;
|
||||
|
||||
// swizzles can be stacked in GLSL, but simplified to a single
|
||||
// one here; the base type doesn't change
|
||||
if (accessChain.preSwizzleBaseType == NoType)
|
||||
@@ -2459,7 +2547,7 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
|
||||
void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
|
||||
{
|
||||
assert(accessChain.isRValue == false);
|
||||
|
||||
@@ -2477,11 +2565,17 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
|
||||
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
|
||||
}
|
||||
|
||||
createStore(source, base, memoryAccess, scope);
|
||||
// take LSB of alignment
|
||||
alignment = alignment & ~(alignment & (alignment-1));
|
||||
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
|
||||
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
|
||||
}
|
||||
|
||||
createStore(source, base, memoryAccess, scope, alignment);
|
||||
}
|
||||
|
||||
// Comments in header
|
||||
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
|
||||
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
|
||||
{
|
||||
Id id;
|
||||
|
||||
@@ -2524,8 +2618,15 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
|
||||
id = accessChain.base; // no precision, it was set when this was defined
|
||||
} else {
|
||||
transferAccessChainSwizzle(true);
|
||||
|
||||
// take LSB of alignment
|
||||
alignment = alignment & ~(alignment & (alignment-1));
|
||||
if (getStorageClass(accessChain.base) == StorageClassPhysicalStorageBufferEXT) {
|
||||
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
|
||||
}
|
||||
|
||||
// load through the access chain
|
||||
id = createLoad(collapseAccessChain(), memoryAccess, scope);
|
||||
id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
|
||||
setPrecision(id, precision);
|
||||
addDecoration(id, nonUniform);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user