diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/hlsl.meta.slang | 31 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-emit-glsl.cpp | 22 | ||||
| -rw-r--r-- | source/slang/slang-emit-metal.cpp | 41 | ||||
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 18 | ||||
| -rw-r--r-- | source/slang/slang-emit.cpp | 19 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.cpp | 142 | ||||
| -rw-r--r-- | source/slang/slang-ir-glsl-legalize.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 28 | ||||
| -rw-r--r-- | source/slang/slang-ir-legalize-image-subscript.cpp | 203 | ||||
| -rw-r--r-- | source/slang/slang-ir-legalize-image-subscript.h | 11 | ||||
| -rw-r--r-- | source/slang/slang-ir-util.cpp | 13 | ||||
| -rw-r--r-- | source/slang/slang-ir-util.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 11 |
14 files changed, 365 insertions, 181 deletions
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 597e4dc06..94a5208b0 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -2416,11 +2416,12 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,form __intrinsic_asm "$c$0.read(vec<uint,3>(($1).xyz), uint(($1).w))$z"; break; case $(SLANG_TEXTURE_CUBE): + static_assert(isArray == 0, "Unsupported 'Load' of 'texture cube array' for 'metal' target"); if (isShadow == 1) { if (isArray == 1) // T read(uint2 coord, uint face, uint array, uint lod = 0) const - __intrinsic_asm "$0.read(vec<uint,2>(($1).xy), uint(($1).z), uint(($1).w))"; + __intrinsic_asm "<invalid intrinsics>"; else // T read(uint2 coord, uint face, uint lod = 0) const __intrinsic_asm "$c$0.read(vec<uint,2>(($1).xy), uint(($1).z), uint(($1).w))$z"; @@ -2429,14 +2430,14 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,0,isShadow,isCombined,form { if (isArray == 1) // Tv read(uint2 coord, uint face, uint array, uint lod = 0) const - __intrinsic_asm "$0.read(vec<uint,2>(($1).xy), uint(($1).z), uint(($1).w))"; + __intrinsic_asm "<invalid intrinsics>"; else // Tv read(uint2 coord, uint face, uint lod = 0) const __intrinsic_asm "$c$0.read(vec<uint,2>(($1).xy), uint(($1).z), uint(($1).w))$z"; } break; } - // TODO: This needs to be handled by the capability system + static_assert(false, "Unsupported 'Load' of 'texture' for 'metal' target"); __intrinsic_asm "<invalid intrinsics>"; case glsl: __intrinsic_asm "$ctexelFetch($0, ($1).$w1b, ($1).$w1e)$z"; @@ -2819,6 +2820,7 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,form __intrinsic_asm "$c$0.read(vec<uint,3>(($1).xyz))$z"; break; case $(SLANG_TEXTURE_CUBE): + static_assert(isArray == 0, "Unsupported 'Load' of 'texture cube array' for 'metal' target"); if (isShadow == 1) { if (isArray == 1) @@ -2839,7 +2841,7 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,form } break; } - // TODO: This needs to be handled by the capability system + static_assert(false, "Unsupported 'Load' of 'texture' for 'metal' target"); __intrinsic_asm "<invalid intrinsics>"; } } @@ -2960,10 +2962,10 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,form // lod is not supported for 1D texture if (isArray == 1) // void write(Tv color, uint coord, uint array, uint lod = 0) const - __intrinsic_asm "$0.write($2, uint(($1).x))"; + __intrinsic_asm "$0.write($2, uint(($1).x), uint(($1).y))"; else // void write(Tv color, uint coord, uint lod = 0) const - __intrinsic_asm "$0.write($2, uint(($1).x))"; + __intrinsic_asm "$0.write($2, uint($1))"; break; case $(SLANG_TEXTURE_2D): if (isShadow == 1) @@ -2991,23 +2993,16 @@ extension __TextureImpl<T,Shape,isArray,0,sampleCount,$(access),isShadow, 0,form __intrinsic_asm "$0.write($2, vec<uint,3>(($1).xyz))"; break; case $(SLANG_TEXTURE_CUBE): + static_assert(isArray == 0, "Unsupported 'Store' of 'texture cube array' for 'metal' target"); if (isShadow == 1) { - if (isArray == 1) - // void write(Tv color, uint2 coord, uint face, uint array, uint lod = 0) const - __intrinsic_asm "$0.write($2, vec<uint,2>(($1).xy), uint(($1).z)%6, uint(($1).z)/6)"; - else - // void write(Tv color, uint2 coord, uint face, uint lod = 0) const - __intrinsic_asm "$0.write($2, vec<uint,2>(($1).xy), uint(($1).z))"; + // void write(Tv color, uint2 coord, uint face, uint lod = 0) const + __intrinsic_asm "$0.write($2, vec<uint,2>(($1).xy), uint(($1).z), uint(($1).w))"; } else { - if (isArray == 1) - // void write(Tv color, uint2 coord, uint face, uint array, uint lod = 0) const - __intrinsic_asm "$0.write($2, vec<uint,2>(($1).xy), uint(($1).z)%6, uint(($1).z)/6)"; - else - // void write(Tv color, uint2 coord, uint face, uint lod = 0) const - __intrinsic_asm "$0.write($2, vec<uint,2>(($1).xy), uint(($1).z))"; + // void write(Tv color, uint2 coord, uint face, uint lod = 0) const + __intrinsic_asm "$0.write($2, vec<uint,2>(($1).xy), uint(($1).z), uint(($1).w))"; } break; } diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index e27e40c59..5b9c3e65a 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -774,6 +774,8 @@ DIAGNOSTIC(41400, Error, staticAssertionFailure, "static assertion failed, $0") DIAGNOSTIC(41401, Error, staticAssertionFailureWithoutMessage, "static assertion failed.") DIAGNOSTIC(41402, Error, staticAssertionConditionNotConstant, "condition for static assertion cannot be evaluated at the compile-time.") +DIAGNOSTIC(41402, Error, multiSampledTextureDoesNotAllowWrites, "cannot write to a multisampled texture with target '$0'.") + // // 5xxxx - Target code generation. // diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index 2a7f22905..b6c3c0d67 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -2021,21 +2021,33 @@ bool GLSLSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inOu } case kIROp_ImageLoad: { + auto imageOp = as<IRImageLoad>(inst); m_writer->emit("imageLoad("); - emitOperand(inst->getOperand(0), getInfo(EmitOp::General)); + emitOperand(imageOp->getImage(), getInfo(EmitOp::General)); m_writer->emit(","); - emitOperand(inst->getOperand(1), getInfo(EmitOp::General)); + emitOperand(imageOp->getCoord(), getInfo(EmitOp::General)); + if (imageOp->hasAuxCoord1()) + { + m_writer->emit(","); + emitOperand(imageOp->getAuxCoord1(), getInfo(EmitOp::General)); + } m_writer->emit(")"); return true; } case kIROp_ImageStore: { + auto imageOp = as<IRImageStore>(inst); m_writer->emit("imageStore("); - emitOperand(inst->getOperand(0), getInfo(EmitOp::General)); + emitOperand(imageOp->getImage(), getInfo(EmitOp::General)); m_writer->emit(","); - emitOperand(inst->getOperand(1), getInfo(EmitOp::General)); + emitOperand(imageOp->getCoord(), getInfo(EmitOp::General)); + if (imageOp->hasAuxCoord1()) + { + m_writer->emit(","); + emitOperand(imageOp->getAuxCoord1(), getInfo(EmitOp::General)); + } m_writer->emit(","); - emitOperand(inst->getOperand(2), getInfo(EmitOp::General)); + emitOperand(imageOp->getValue(), getInfo(EmitOp::General)); m_writer->emit(")"); return true; } diff --git a/source/slang/slang-emit-metal.cpp b/source/slang/slang-emit-metal.cpp index d38c3de9b..e7df29e0c 100644 --- a/source/slang/slang-emit-metal.cpp +++ b/source/slang/slang-emit-metal.cpp @@ -451,6 +451,47 @@ bool MetalSourceEmitter::tryEmitInstExprImpl(IRInst* inst, const EmitOpInfo& inO emitOperand(inst->getOperand(2), getInfo(EmitOp::General)); return true; } + case kIROp_ImageLoad: + { + auto imageOp = as<IRImageLoad>(inst); + emitOperand(imageOp->getImage(), getInfo(EmitOp::General)); + m_writer->emit(".read("); + emitOperand(imageOp->getCoord(), getInfo(EmitOp::General)); + if(imageOp->hasAuxCoord1()) + { + m_writer->emit(","); + emitOperand(imageOp->getAuxCoord1(), getInfo(EmitOp::General)); + } + if(imageOp->hasAuxCoord2()) + { + m_writer->emit(","); + emitOperand(imageOp->getAuxCoord2(), getInfo(EmitOp::General)); + } + m_writer->emit(")"); + return true; + } + case kIROp_ImageStore: + { + + auto imageOp = as<IRImageStore>(inst); + emitOperand(imageOp->getImage(), getInfo(EmitOp::General)); + m_writer->emit(".write("); + emitOperand(imageOp->getValue(), getInfo(EmitOp::General)); + m_writer->emit(","); + emitOperand(imageOp->getCoord(), getInfo(EmitOp::General)); + if(imageOp->hasAuxCoord1()) + { + m_writer->emit(","); + emitOperand(imageOp->getAuxCoord1(), getInfo(EmitOp::General)); + } + if(imageOp->hasAuxCoord2()) + { + m_writer->emit(","); + emitOperand(imageOp->getAuxCoord2(), getInfo(EmitOp::General)); + } + m_writer->emit(")"); + return true; + } default: break; } // Not handled diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index 3ee0d9241..51a71d65c 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -2989,12 +2989,26 @@ struct SPIRVEmitContext SpvInst* emitImageLoad(SpvInstParent* parent, IRImageLoad* load) { - return emitInst(parent, load, SpvOpImageRead, load->getDataType(), kResultID, load->getImage(), load->getCoord()); + if (load->hasAuxCoord1()) + { + return emitInst(parent, load, SpvOpImageRead, load->getDataType(), kResultID, load->getImage(), load->getCoord(), SpvImageOperandsSampleMask, load->getAuxCoord1()); + } + else + { + return emitInst(parent, load, SpvOpImageRead, load->getDataType(), kResultID, load->getImage(), load->getCoord()); + } } SpvInst* emitImageStore(SpvInstParent* parent, IRImageStore* store) { - return emitInst(parent, store, SpvOpImageWrite, store->getImage(), store->getCoord(), store->getValue()); + if (store->hasAuxCoord1()) + { + return emitInst(parent, store, SpvOpImageWrite, store->getImage(), store->getCoord(), store->getValue(), SpvImageOperandsSampleMask, store->getAuxCoord1()); + } + else + { + return emitInst(parent, store, SpvOpImageWrite, store->getImage(), store->getCoord(), store->getValue()); + } } SpvInst* emitImageSubscript(SpvInstParent* parent, IRImageSubscript* subscript) diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 0f53f74cd..bb6bab0ab 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -50,6 +50,7 @@ #include "slang-ir-lower-l-value-cast.h" #include "slang-ir-lower-reinterpret.h" #include "slang-ir-loop-unroll.h" +#include "slang-ir-legalize-image-subscript.h" #include "slang-ir-legalize-vector-types.h" #include "slang-ir-metadata.h" #include "slang-ir-optix-entry-point-uniforms.h" @@ -1153,14 +1154,28 @@ Result linkAndOptimizeIR( if(isD3DTarget(targetRequest)) legalizeNonStructParameterToStructForHLSL(irModule); - // Legalize `ImageSubscript` and constant buffer loads for GLSL. + // Legalize `ImageSubscript` loads. + switch (target) + { + case CodeGenTarget::Metal: + case CodeGenTarget::GLSL: + case CodeGenTarget::SPIRV: + case CodeGenTarget::SPIRVAssembly: + { + legalizeImageSubscript(targetRequest, irModule, sink); + } + break; + default: + break; + } + + // Legalize constant buffer loads. switch (target) { case CodeGenTarget::GLSL: case CodeGenTarget::SPIRV: case CodeGenTarget::SPIRVAssembly: { - legalizeImageSubscriptForGLSL(irModule); legalizeConstantBufferLoadForGLSL(irModule); legalizeDispatchMeshPayloadForGLSL(irModule); } diff --git a/source/slang/slang-ir-glsl-legalize.cpp b/source/slang/slang-ir-glsl-legalize.cpp index be222c87f..0e23460ce 100644 --- a/source/slang/slang-ir-glsl-legalize.cpp +++ b/source/slang/slang-ir-glsl-legalize.cpp @@ -15,148 +15,6 @@ namespace Slang { -int getIRVectorElementSize(IRType* type) -{ - if (type->getOp() != kIROp_VectorType) - return 1; - return (int)(as<IRIntLit>(as<IRVectorType>(type)->getElementCount())->value.intVal); -} -IRType* getIRVectorBaseType(IRType* type) -{ - if (type->getOp() != kIROp_VectorType) - return type; - return as<IRVectorType>(type)->getElementType(); -} - -void legalizeImageSubscriptStoreForGLSL(IRBuilder& builder, IRInst* storeInst) -{ - builder.setInsertBefore(storeInst); - auto getElementPtr = as<IRGetElementPtr>(storeInst->getOperand(0)); - IRImageSubscript* imageSubscript = nullptr; - if (getElementPtr) - imageSubscript = as<IRImageSubscript>(getElementPtr->getBase()); - else - imageSubscript = as<IRImageSubscript>(storeInst->getOperand(0)); - assert(imageSubscript); - auto imageElementType = cast<IRPtrTypeBase>(imageSubscript->getDataType())->getValueType(); - auto coordType = imageSubscript->getCoord()->getDataType(); - auto coordVectorSize = getIRVectorElementSize(coordType); - if (coordVectorSize != 1) - { - coordType = builder.getVectorType( - builder.getIntType(), builder.getIntValue(builder.getIntType(), coordVectorSize)); - } - else - { - coordType = builder.getIntType(); - } - auto legalizedCoord = imageSubscript->getCoord(); - if (coordType != imageSubscript->getCoord()->getDataType()) - { - legalizedCoord = builder.emitCast(coordType, legalizedCoord); - } - switch (storeInst->getOp()) - { - case kIROp_Store: - { - IRInst* newValue = nullptr; - if (getElementPtr) - { - auto vectorBaseType = getIRVectorBaseType(imageElementType); - IRType* vector4Type = builder.getVectorType(vectorBaseType, 4); - auto originalValue = builder.emitImageLoad(vector4Type, imageSubscript->getImage(), legalizedCoord); - auto index = getElementPtr->getIndex(); - newValue = builder.emitSwizzleSet(vector4Type, originalValue, storeInst->getOperand(1), 1, &index); - } - else - { - newValue = storeInst->getOperand(1); - if (getIRVectorElementSize(imageElementType) != 4) - { - auto vectorBaseType = getIRVectorBaseType(imageElementType); - newValue = builder.emitVectorReshape( - builder.getVectorType( - vectorBaseType, builder.getIntValue(builder.getIntType(), 4)), - newValue); - } - } - auto imageStore = builder.emitImageStore( - builder.getVoidType(), - imageSubscript->getImage(), - legalizedCoord, - newValue); - storeInst->replaceUsesWith(imageStore); - storeInst->removeAndDeallocate(); - if (!imageSubscript->hasUses()) - { - imageSubscript->removeAndDeallocate(); - } - } - break; - case kIROp_SwizzledStore: - { - auto swizzledStore = cast<IRSwizzledStore>(storeInst); - // Here we assume the imageElementType is already lowered into float4/uint4 types from any - // user-defined type. - assert(imageElementType->getOp() == kIROp_VectorType); - auto vectorBaseType = getIRVectorBaseType(imageElementType); - IRType* vector4Type = builder.getVectorType(vectorBaseType, 4); - auto originalValue = builder.emitImageLoad(vector4Type, imageSubscript->getImage(), legalizedCoord); - Array<IRInst*, 4> indices; - for (UInt i = 0; i < swizzledStore->getElementCount(); i++) - { - indices.add(swizzledStore->getElementIndex(i)); - } - auto newValue = builder.emitSwizzleSet( - vector4Type, - originalValue, - swizzledStore->getSource(), - swizzledStore->getElementCount(), - indices.getBuffer()); - auto imageStore = builder.emitImageStore( - builder.getVoidType(), imageSubscript->getImage(), legalizedCoord, newValue); - storeInst->replaceUsesWith(imageStore); - storeInst->removeAndDeallocate(); - if (!imageSubscript->hasUses()) - { - imageSubscript->removeAndDeallocate(); - } - } - break; - default: - break; - } -} - -void legalizeImageSubscriptForGLSL(IRModule* module) -{ - IRBuilder builder(module); - for (auto globalInst : module->getModuleInst()->getChildren()) - { - auto func = as<IRFunc>(globalInst); - if (!func) - continue; - for (auto block : func->getBlocks()) - { - auto inst = block->getFirstInst(); - IRInst* next; - for ( ; inst; inst = next) - { - next = inst->getNextInst(); - switch (inst->getOp()) - { - case kIROp_Store: - case kIROp_SwizzledStore: - if (getRootAddr(inst->getOperand(0))->getOp() == kIROp_ImageSubscript) - { - legalizeImageSubscriptStoreForGLSL(builder, inst); - } - } - } - } - } -} - // // Legalization of entry points for GLSL: // diff --git a/source/slang/slang-ir-glsl-legalize.h b/source/slang/slang-ir-glsl-legalize.h index 6fd0b642e..8ec164a96 100644 --- a/source/slang/slang-ir-glsl-legalize.h +++ b/source/slang/slang-ir-glsl-legalize.h @@ -21,8 +21,6 @@ void legalizeEntryPointsForGLSL( CodeGenContext* context, GLSLExtensionTracker* glslExtensionTracker); -void legalizeImageSubscriptForGLSL(IRModule* module); - void legalizeConstantBufferLoadForGLSL(IRModule* module); void legalizeDispatchMeshPayloadForGLSL(IRModule* module); diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 4781ea2c3..a63cc5c22 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -2440,6 +2440,8 @@ struct IRImageSubscript : IRInst IR_LEAF_ISA(ImageSubscript); IRInst* getImage() { return getOperand(0); } IRInst* getCoord() { return getOperand(1); } + bool hasSampleCoord() { return getOperandCount() > 2 && getOperand(2) != nullptr; } + IRInst* getSampleCoord() { return getOperand(2); } }; struct IRImageLoad : IRInst @@ -2447,6 +2449,16 @@ struct IRImageLoad : IRInst IR_LEAF_ISA(ImageLoad); IRInst* getImage() { return getOperand(0); } IRInst* getCoord() { return getOperand(1); } + + /// If GLSL/SPIR-V, Sample coord + /// If Metal, Array or Sample coord + bool hasAuxCoord1() { return getOperandCount() > 2 && getOperand(2) != nullptr; } + IRInst* getAuxCoord1() { return getOperand(2); } + + /// If Metal, Sample coord + bool hasAuxCoord2() { return getOperandCount() > 3 && getOperand(3) != nullptr; } + IRInst* getAuxCoord2() { return getOperand(3); } + }; struct IRImageStore : IRInst @@ -2455,6 +2467,15 @@ struct IRImageStore : IRInst IRInst* getImage() { return getOperand(0); } IRInst* getCoord() { return getOperand(1); } IRInst* getValue() { return getOperand(2); } + + /// If GLSL/SPIR-V, Sample coord + /// If Metal, Array or Sample coord + bool hasAuxCoord1() { return getOperandCount() > 3 && getOperand(3) != nullptr; } + IRInst* getAuxCoord1() { return getOperand(3); } + + /// If Metal, Sample coord + bool hasAuxCoord2() { return getOperandCount() > 4 && getOperand(4) != nullptr; } + IRInst* getAuxCoord2() { return getOperand(4); } }; // Terminators @@ -4048,14 +4069,11 @@ public: IRInst* emitImageLoad( IRType* type, - IRInst* image, - IRInst* coord); + ShortList<IRInst*> params); IRInst* emitImageStore( IRType* type, - IRInst* image, - IRInst* coord, - IRInst* value); + ShortList<IRInst*> params); IRInst* emitIsType(IRInst* value, IRInst* witness, IRInst* typeOperand, IRInst* targetWitness); diff --git a/source/slang/slang-ir-legalize-image-subscript.cpp b/source/slang/slang-ir-legalize-image-subscript.cpp new file mode 100644 index 000000000..b5b240675 --- /dev/null +++ b/source/slang/slang-ir-legalize-image-subscript.cpp @@ -0,0 +1,203 @@ +#include "slang-ir-legalize-image-subscript.h" + +#include "slang-ir.h" +#include "slang-ir-insts.h" +#include "slang-ir-util.h" +#include "slang-ir-clone.h" +#include "slang-ir-specialize-address-space.h" +#include "slang-parameter-binding.h" +#include "slang-ir-legalize-varying-params.h" + +namespace Slang +{ + void legalizeStore(TargetRequest* target, IRBuilder& builder, IRInst* storeInst, DiagnosticSink* sink) + { + SLANG_ASSERT(storeInst); + + builder.setInsertBefore(storeInst); + IRImageSubscript* imageSubscript = nullptr; + auto getElementPtr = as<IRGetElementPtr>(storeInst->getOperand(0)); + if(getElementPtr) + { + imageSubscript = as<IRImageSubscript>(getElementPtr->getBase()); + } + else + { + imageSubscript = as<IRImageSubscript>(storeInst->getOperand(0)); + } + SLANG_ASSERT(imageSubscript); + SLANG_ASSERT(imageSubscript->getImage()); + IRTextureType* textureType = as<IRTextureType>(imageSubscript->getImage()->getFullType()); + SLANG_ASSERT(textureType); + auto imageElementType = cast<IRPtrTypeBase>(imageSubscript->getDataType())->getValueType(); + auto vectorBaseType = getIRVectorBaseType(imageElementType); + IRType* vector4Type = builder.getVectorType(vectorBaseType, 4); + IRType* coordType = imageSubscript->getCoord()->getDataType(); + int coordVectorSize = getIRVectorElementSize(coordType); + + bool seperateArrayCoord = (isMetalTarget(target) && textureType->isArray()); // seperate array param + bool seperateSampleCoord = (textureType->isMultisample()); // seperate sample param + + if(seperateSampleCoord && isMetalTarget(target)) + sink->diagnose(imageSubscript->getImage(), Diagnostics::multiSampledTextureDoesNotAllowWrites, target->getTarget()); + + IRType* indexingType = builder.getIntType(); + if(isMetalTarget(target)) + indexingType = builder.getUIntType(); + + if (coordVectorSize != 1) + { + coordType = builder.getVectorType( + indexingType, builder.getIntValue(builder.getIntType(), coordVectorSize)); + } + else + { + coordType = indexingType; + } + + auto legalizedCoord = imageSubscript->getCoord(); + if (coordType != imageSubscript->getCoord()->getDataType()) + { + legalizedCoord = builder.emitCast(coordType, legalizedCoord); + } + + const Index kCoordParamIndex = 1; + const Index kValueParamIndex = 2; + + ShortList<IRInst*> loadParams; + loadParams.reserveOverflowBuffer(4); + loadParams.add(imageSubscript->getImage()); // image + loadParams.add(legalizedCoord); // coord + + ShortList<IRInst*> storeParams; + storeParams.reserveOverflowBuffer(5); + storeParams.add(imageSubscript->getImage()); // image + storeParams.add(legalizedCoord); // coord + storeParams.add(nullptr); // value + + if (seperateArrayCoord) + { + + UInt paramIndexToFetch = coordVectorSize - 1; + + auto seperatedParam = builder.emitSwizzle(indexingType, legalizedCoord, 1, ¶mIndexToFetch); + loadParams.add(seperatedParam); + storeParams.add(seperatedParam); + + coordVectorSize -= 1; + ShortList<UInt> paramToFetch; + paramToFetch.reserveOverflowBuffer(coordVectorSize); + for (int i = 0; i < coordVectorSize; i++) + { + paramToFetch.add(i); + } + auto newCoord = builder.emitSwizzle(builder.getVectorType(indexingType, builder.getIntValue(builder.getIntType(), coordVectorSize)), legalizedCoord, coordVectorSize, paramToFetch.getArrayView().getBuffer()); + storeParams[kCoordParamIndex] = newCoord; + loadParams[kCoordParamIndex] = newCoord; + } + if (seperateSampleCoord) + { + loadParams.add(imageSubscript->getSampleCoord()); + storeParams.add(imageSubscript->getSampleCoord()); + } + + IRInst* legalizedStore = storeInst->getOperand(1); + switch (storeInst->getOp()) + { + case kIROp_Store: + { + IRInst* newValue = nullptr; + if (getElementPtr) + { + auto originalValue = builder.emitImageLoad(vector4Type, loadParams); + auto index = getElementPtr->getIndex(); + newValue = builder.emitSwizzleSet(vector4Type, originalValue, legalizedStore, 1, &index); + } + else + { + newValue = legalizedStore; + if (getIRVectorElementSize(imageElementType) != 4) + { + newValue = builder.emitVectorReshape( + builder.getVectorType( + vectorBaseType, builder.getIntValue(builder.getIntType(), 4)), + newValue); + } + } + + storeParams[kValueParamIndex] = newValue; + auto imageStore = builder.emitImageStore( + builder.getVoidType(), + storeParams); + storeInst->replaceUsesWith(imageStore); + storeInst->removeAndDeallocate(); + if (!imageSubscript->hasUses()) + { + imageSubscript->removeAndDeallocate(); + } + } + break; + case kIROp_SwizzledStore: + { + auto swizzledStore = cast<IRSwizzledStore>(storeInst); + // Here we assume the imageElementType is already lowered into float4/uint4 types from any + // user-defined type. + assert(imageElementType->getOp() == kIROp_VectorType); + auto originalValue = builder.emitImageLoad(vector4Type, loadParams); + Array<IRInst*, 4> indices; + for (UInt i = 0; i < swizzledStore->getElementCount(); i++) + { + indices.add(swizzledStore->getElementIndex(i)); + } + auto newValue = builder.emitSwizzleSet( + vector4Type, + originalValue, + swizzledStore->getSource(), + swizzledStore->getElementCount(), + indices.getBuffer()); + storeParams[kValueParamIndex] = newValue; + auto imageStore = builder.emitImageStore( + builder.getVoidType(), + storeParams); + storeInst->replaceUsesWith(imageStore); + storeInst->removeAndDeallocate(); + if (!imageSubscript->hasUses()) + { + imageSubscript->removeAndDeallocate(); + } + } + break; + default: + break; + } + } + void legalizeImageSubscript(TargetRequest* target, IRModule* module, DiagnosticSink* sink) + { + IRBuilder builder(module); + for (auto globalInst : module->getModuleInst()->getChildren()) + { + auto func = as<IRFunc>(globalInst); + if (!func) + continue; + for (auto block : func->getBlocks()) + { + auto inst = block->getFirstInst(); + IRInst* next; + for ( ; inst; inst = next) + { + next = inst->getNextInst(); + switch (inst->getOp()) + { + case kIROp_Store: + case kIROp_SwizzledStore: + if (getRootAddr(inst->getOperand(0))->getOp() == kIROp_ImageSubscript) + { + legalizeStore(target, builder, inst, sink); + } + } + } + } + } + } +} + diff --git a/source/slang/slang-ir-legalize-image-subscript.h b/source/slang/slang-ir-legalize-image-subscript.h new file mode 100644 index 000000000..71d20b32d --- /dev/null +++ b/source/slang/slang-ir-legalize-image-subscript.h @@ -0,0 +1,11 @@ +#pragma once + +#include "slang-ir.h" +#include "slang-compiler.h" + +namespace Slang +{ + class DiagnosticSink; + + void legalizeImageSubscript(TargetRequest* target, IRModule* module, DiagnosticSink* sink); +} diff --git a/source/slang/slang-ir-util.cpp b/source/slang/slang-ir-util.cpp index 40d169c48..10c7bfea6 100644 --- a/source/slang/slang-ir-util.cpp +++ b/source/slang/slang-ir-util.cpp @@ -1783,4 +1783,17 @@ void verifyComputeDerivativeGroupModifiers( } } +int getIRVectorElementSize(IRType* type) +{ + if (type->getOp() != kIROp_VectorType) + return 1; + return (int)(as<IRIntLit>(as<IRVectorType>(type)->getElementCount())->value.intVal); +} +IRType* getIRVectorBaseType(IRType* type) +{ + if (type->getOp() != kIROp_VectorType) + return type; + return as<IRVectorType>(type)->getElementType(); +} + } diff --git a/source/slang/slang-ir-util.h b/source/slang/slang-ir-util.h index d78ceaaf8..855046c04 100644 --- a/source/slang/slang-ir-util.h +++ b/source/slang/slang-ir-util.h @@ -345,6 +345,9 @@ inline bool isSPIRV(CodeGenTarget codeGenTarget) || codeGenTarget == CodeGenTarget::SPIRVAssembly; } +int getIRVectorElementSize(IRType* type); +IRType* getIRVectorBaseType(IRType* type); + } #endif diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index c0541f4c4..a4ea100dc 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -4841,17 +4841,18 @@ namespace Slang return inst; } - IRInst* IRBuilder::emitImageLoad(IRType* type, IRInst* image, IRInst* coord) + /// @param params An ordered list of imageLoad parameters { image, coord, [optional] seperateArrayCoord, [optional] seperateSampleCoord } + IRInst* IRBuilder::emitImageLoad(IRType* type, ShortList<IRInst*> params) { - auto inst = createInst<IRImageLoad>(this, kIROp_ImageLoad, type, image, coord); + auto inst = createInst<IRImageLoad>(this, kIROp_ImageLoad, type, params.getCount(), params.getArrayView().getBuffer()); addInst(inst); return inst; } - IRInst* IRBuilder::emitImageStore(IRType* type, IRInst* image, IRInst* coord, IRInst* value) + /// @param params An ordered list of imageStore parameters { image, coord, value, [optional] seperateArrayCoord, [optional] seperateSampleCoord } + IRInst* IRBuilder::emitImageStore(IRType* type, ShortList<IRInst*> params) { - IRInst* args[] = {image, coord, value}; - auto inst = createInst<IRImageStore>(this, kIROp_ImageStore, type, 3, args); + auto inst = createInst<IRImageStore>(this, kIROp_ImageStore, type, params.getCount(), params.getArrayView().getBuffer()); addInst(inst); return inst; } |
