diff options
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 5 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 114 | ||||
| -rw-r--r-- | tests/bugs/gh-6380-atomic-in-struct.slang | 15 |
3 files changed, 96 insertions, 38 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 1659a161b..f12d11bdf 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -12441,10 +12441,13 @@ bool SemanticsDeclAttributesVisitor::_synthesizeCtorSignature(StructDecl* struct { auto member = resultMembers[i]; auto parentAggDecl = getParentAggTypeDecl(member); - ; auto ctorParam = m_astBuilder->create<ParamDecl>(); ctorParam->type = (TypeExp)member->type; + if (auto atomicType = as<AtomicType>(ctorParam->type)) + { + ctorParam->type.type = atomicType->getElementType(); + } if (!stopProcessingDefaultValues) ctorParam->initExpr = _getParamDefaultValue(this, member); diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index bc90e3ac4..e0367be89 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -3407,6 +3407,25 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex return emitOpBitcast(parent, inst, inst->getDataType(), vec); } + bool isAtomicableAddressSpace(IRInst* type) + { + auto ptrType = as<IRPtrTypeBase>(type); + if (!ptrType) + return false; + switch (ptrType->getAddressSpace()) + { + case AddressSpace::Global: + case AddressSpace::StorageBuffer: + case AddressSpace::UserPointer: + case AddressSpace::GroupShared: + case AddressSpace::Image: + case AddressSpace::TaskPayloadWorkgroup: + return true; + default: + return false; + } + } + // The instructions that appear inside the basic blocks of // functions are what we will call "local" instructions. // @@ -3862,53 +3881,74 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex case kIROp_AtomicLoad: { IRBuilder builder{inst}; - const auto memoryScope = - emitIntConstant(IRIntegerValue{SpvScopeDevice}, builder.getUIntType()); - const auto memorySemantics = - emitMemorySemanticMask(inst->getOperand(1), inst->getOperand(0)); - result = emitOpAtomicLoad( - parent, - inst, - inst->getFullType(), - inst->getOperand(0), - memoryScope, - memorySemantics); - ensureAtomicCapability(inst, SpvOpAtomicLoad); + if (isAtomicableAddressSpace(inst->getOperand(0)->getDataType())) + { + const auto memoryScope = + emitIntConstant(IRIntegerValue{SpvScopeDevice}, builder.getUIntType()); + const auto memorySemantics = + emitMemorySemanticMask(inst->getOperand(1), inst->getOperand(0)); + result = emitOpAtomicLoad( + parent, + inst, + inst->getFullType(), + inst->getOperand(0), + memoryScope, + memorySemantics); + ensureAtomicCapability(inst, SpvOpAtomicLoad); + } + else + { + result = emitOpLoad(parent, inst, inst->getFullType(), inst->getOperand(0)); + } } break; case kIROp_AtomicStore: { IRBuilder builder{inst}; - const auto memoryScope = - emitIntConstant(IRIntegerValue{SpvScopeDevice}, builder.getUIntType()); - const auto memorySemantics = - emitMemorySemanticMask(inst->getOperand(2), inst->getOperand(0)); - result = emitOpAtomicStore( - parent, - inst, - inst->getOperand(0), - memoryScope, - memorySemantics, - inst->getOperand(1)); - ensureAtomicCapability(inst, SpvOpAtomicStore); + if (isAtomicableAddressSpace(inst->getOperand(0)->getDataType())) + { + const auto memoryScope = + emitIntConstant(IRIntegerValue{SpvScopeDevice}, builder.getUIntType()); + const auto memorySemantics = + emitMemorySemanticMask(inst->getOperand(2), inst->getOperand(0)); + result = emitOpAtomicStore( + parent, + inst, + inst->getOperand(0), + memoryScope, + memorySemantics, + inst->getOperand(1)); + ensureAtomicCapability(inst, SpvOpAtomicStore); + } + else + { + result = emitOpStore(parent, inst, inst->getOperand(0), inst->getOperand(1)); + } } break; case kIROp_AtomicExchange: { IRBuilder builder{inst}; - const auto memoryScope = - emitIntConstant(IRIntegerValue{SpvScopeDevice}, builder.getUIntType()); - const auto memorySemantics = - emitMemorySemanticMask(inst->getOperand(2), inst->getOperand(0)); - result = emitOpAtomicExchange( - parent, - inst, - inst->getFullType(), - inst->getOperand(0), - memoryScope, - memorySemantics, - inst->getOperand(1)); - ensureAtomicCapability(inst, SpvOpAtomicExchange); + if (isAtomicableAddressSpace(inst->getOperand(0)->getDataType())) + { + const auto memoryScope = + emitIntConstant(IRIntegerValue{SpvScopeDevice}, builder.getUIntType()); + const auto memorySemantics = + emitMemorySemanticMask(inst->getOperand(2), inst->getOperand(0)); + result = emitOpAtomicExchange( + parent, + inst, + inst->getFullType(), + inst->getOperand(0), + memoryScope, + memorySemantics, + inst->getOperand(1)); + ensureAtomicCapability(inst, SpvOpAtomicExchange); + } + else + { + result = emitOpStore(parent, inst, inst->getOperand(0), inst->getOperand(1)); + } } break; case kIROp_AtomicCompareExchange: diff --git a/tests/bugs/gh-6380-atomic-in-struct.slang b/tests/bugs/gh-6380-atomic-in-struct.slang new file mode 100644 index 000000000..7eda02418 --- /dev/null +++ b/tests/bugs/gh-6380-atomic-in-struct.slang @@ -0,0 +1,15 @@ +//TEST:SIMPLE(filecheck=CHECK): -target spirv +//CHECK: OpEntryPoint + +struct Test { + Atomic<int> test; +} + +RWStructuredBuffer<Test> data; + +[shader("compute")] +[numthreads(1,1,1)] +public void main() { + Test t = Test(1); + data[0].test.increment(); +}
\ No newline at end of file |
