mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-11-04 12:34:39 +08:00 
			
		
		
		
	shader: Implement ImageGradient
This commit is contained in:
		
							parent
							
								
									be3e94ae55
								
							
						
					
					
						commit
						d5bfc63088
					
				@ -363,6 +363,7 @@ Id EmitBindlessImageGatherDref(EmitContext&);
 | 
			
		||||
Id EmitBindlessImageFetch(EmitContext&);
 | 
			
		||||
Id EmitBindlessImageQueryDimensions(EmitContext&);
 | 
			
		||||
Id EmitBindlessImageQueryLod(EmitContext&);
 | 
			
		||||
Id EmitBindlessImageGradient(EmitContext&);
 | 
			
		||||
Id EmitBoundImageSampleImplicitLod(EmitContext&);
 | 
			
		||||
Id EmitBoundImageSampleExplicitLod(EmitContext&);
 | 
			
		||||
Id EmitBoundImageSampleDrefImplicitLod(EmitContext&);
 | 
			
		||||
@ -372,6 +373,7 @@ Id EmitBoundImageGatherDref(EmitContext&);
 | 
			
		||||
Id EmitBoundImageFetch(EmitContext&);
 | 
			
		||||
Id EmitBoundImageQueryDimensions(EmitContext&);
 | 
			
		||||
Id EmitBoundImageQueryLod(EmitContext&);
 | 
			
		||||
Id EmitBoundImageGradient(EmitContext&);
 | 
			
		||||
Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
 | 
			
		||||
                              Id bias_lc, Id offset);
 | 
			
		||||
Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
 | 
			
		||||
@ -388,6 +390,8 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
 | 
			
		||||
                  Id lod, Id ms);
 | 
			
		||||
Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod);
 | 
			
		||||
Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
 | 
			
		||||
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
 | 
			
		||||
                     Id derivates, Id offset, Id lod_clamp);
 | 
			
		||||
Id EmitVoteAll(EmitContext& ctx, Id pred);
 | 
			
		||||
Id EmitVoteAny(EmitContext& ctx, Id pred);
 | 
			
		||||
Id EmitVoteEqual(EmitContext& ctx, Id pred);
 | 
			
		||||
 | 
			
		||||
@ -69,12 +69,44 @@ public:
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivates, u32 num_derivates,
 | 
			
		||||
                           Id offset, Id lod_clamp) {
 | 
			
		||||
        if (Sirit::ValidId(derivates)) {
 | 
			
		||||
            boost::container::static_vector<Id, 3> deriv_x_accum;
 | 
			
		||||
            boost::container::static_vector<Id, 3> deriv_y_accum;
 | 
			
		||||
            for (size_t i = 0; i < num_derivates; i++) {
 | 
			
		||||
                deriv_x_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2));
 | 
			
		||||
                deriv_y_accum.push_back(ctx.OpCompositeExtract(ctx.F32[1], derivates, i * 2 + 1));
 | 
			
		||||
            }
 | 
			
		||||
            Id derivates_X = ctx.OpCompositeConstruct(
 | 
			
		||||
                ctx.F32[num_derivates], std::span{deriv_x_accum.data(), deriv_x_accum.size()});
 | 
			
		||||
            Id derivates_Y = ctx.OpCompositeConstruct(
 | 
			
		||||
                ctx.F32[num_derivates], std::span{deriv_y_accum.data(), deriv_y_accum.size()});
 | 
			
		||||
            Add(spv::ImageOperandsMask::Grad, derivates_X, derivates_Y);
 | 
			
		||||
        } else {
 | 
			
		||||
            throw LogicError("Derivates must be present");
 | 
			
		||||
        }
 | 
			
		||||
        if (Sirit::ValidId(offset)) {
 | 
			
		||||
            Add(spv::ImageOperandsMask::Offset, offset);
 | 
			
		||||
        }
 | 
			
		||||
        if (has_lod_clamp) {
 | 
			
		||||
            Add(spv::ImageOperandsMask::MinLod, lod_clamp);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Add(spv::ImageOperandsMask new_mask, Id value) {
 | 
			
		||||
        mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) |
 | 
			
		||||
                                                   static_cast<unsigned>(new_mask));
 | 
			
		||||
        operands.push_back(value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Add(spv::ImageOperandsMask new_mask, Id value, Id value_2) {
 | 
			
		||||
        mask = static_cast<spv::ImageOperandsMask>(static_cast<unsigned>(mask) |
 | 
			
		||||
                                                   static_cast<unsigned>(new_mask));
 | 
			
		||||
        operands.push_back(value);
 | 
			
		||||
        operands.push_back(value_2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::span<const Id> Span() const noexcept {
 | 
			
		||||
        return std::span{operands.data(), operands.size()};
 | 
			
		||||
    }
 | 
			
		||||
@ -84,7 +116,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    boost::container::static_vector<Id, 3> operands;
 | 
			
		||||
    boost::container::static_vector<Id, 4> operands;
 | 
			
		||||
    spv::ImageOperandsMask mask{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -165,6 +197,10 @@ Id EmitBindlessImageQueryLod(EmitContext&) {
 | 
			
		||||
    throw LogicError("Unreachable instruction");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Id EmitBindlessImageGradient(EmitContext&) {
 | 
			
		||||
    throw LogicError("Unreachable instruction");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Id EmitBoundImageSampleImplicitLod(EmitContext&) {
 | 
			
		||||
    throw LogicError("Unreachable instruction");
 | 
			
		||||
}
 | 
			
		||||
@ -201,6 +237,10 @@ Id EmitBoundImageQueryLod(EmitContext&) {
 | 
			
		||||
    throw LogicError("Unreachable instruction");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Id EmitBoundImageGradient(EmitContext&) {
 | 
			
		||||
    throw LogicError("Unreachable instruction");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
 | 
			
		||||
                              Id bias_lc, Id offset) {
 | 
			
		||||
    const auto info{inst->Flags<IR::TextureInstInfo>()};
 | 
			
		||||
@ -302,4 +342,13 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst*, const IR::Value& index, Id coo
 | 
			
		||||
                                    zero, zero);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
 | 
			
		||||
                     Id derivates, Id offset, Id lod_clamp) {
 | 
			
		||||
    const auto info{inst->Flags<IR::TextureInstInfo>()};
 | 
			
		||||
    const ImageOperands operands(ctx, info.has_lod_clamp != 0, derivates, info.num_derivates, offset, lod_clamp);
 | 
			
		||||
    return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
 | 
			
		||||
                &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, index),
 | 
			
		||||
                coords, operands.Mask(), operands.Span());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Shader::Backend::SPIRV
 | 
			
		||||
 | 
			
		||||
@ -1573,6 +1573,13 @@ Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, Texture
 | 
			
		||||
    return Inst(op, Flags{info}, handle, coords);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Value IREmitter::ImageGradient(const Value& handle, const Value& coords, const Value& derivates,
 | 
			
		||||
                               const Value& offset, const F32& lod_clamp, TextureInstInfo info) {
 | 
			
		||||
    const Opcode op{handle.IsImmediate() ? Opcode::BoundImageGradient
 | 
			
		||||
                                         : Opcode::BindlessImageGradient};
 | 
			
		||||
    return Inst(op, Flags{info}, handle, coords, derivates, offset, lod_clamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
U1 IREmitter::VoteAll(const U1& value) {
 | 
			
		||||
    return Inst<U1>(Opcode::VoteAll, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -268,6 +268,10 @@ public:
 | 
			
		||||
    [[nodiscard]] Value ImageFetch(const Value& handle, const Value& coords, const Value& offset,
 | 
			
		||||
                                   const U32& lod, const U32& multisampling, TextureInstInfo info);
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords,
 | 
			
		||||
                                      const Value& derivates, const Value& offset,
 | 
			
		||||
                                      const F32& lod_clamp, TextureInstInfo info);
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] U1 VoteAll(const U1& value);
 | 
			
		||||
    [[nodiscard]] U1 VoteAny(const U1& value);
 | 
			
		||||
    [[nodiscard]] U1 VoteEqual(const U1& value);
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@ union TextureInstInfo {
 | 
			
		||||
    BitField<9, 1, u32> has_lod_clamp;
 | 
			
		||||
    BitField<10, 1, u32> relaxed_precision;
 | 
			
		||||
    BitField<11, 2, u32> gather_component;
 | 
			
		||||
    BitField<13, 2, u32> num_derivates;
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(TextureInstInfo) <= sizeof(u32));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -381,6 +381,7 @@ OPCODE(BindlessImageGatherDref,                             F32x4,          U32,
 | 
			
		||||
OPCODE(BindlessImageFetch,                                  F32x4,          U32,            Opaque,         Opaque,         Opaque,         Opaque,         )
 | 
			
		||||
OPCODE(BindlessImageQueryDimensions,                        U32x4,          U32,            U32,                                                            )
 | 
			
		||||
OPCODE(BindlessImageQueryLod,                               F32x4,          U32,            Opaque,                                                         )
 | 
			
		||||
OPCODE(BindlessImageGradient,                               F32x4,          U32,            Opaque,         Opaque,         Opaque,         Opaque,         )
 | 
			
		||||
 | 
			
		||||
OPCODE(BoundImageSampleImplicitLod,                         F32x4,          U32,            Opaque,         Opaque,         Opaque,                         )
 | 
			
		||||
OPCODE(BoundImageSampleExplicitLod,                         F32x4,          U32,            Opaque,         Opaque,         Opaque,                         )
 | 
			
		||||
@ -391,6 +392,7 @@ OPCODE(BoundImageGatherDref,                                F32x4,          U32,
 | 
			
		||||
OPCODE(BoundImageFetch,                                     F32x4,          U32,            Opaque,         Opaque,         Opaque,         Opaque,         )
 | 
			
		||||
OPCODE(BoundImageQueryDimensions,                           U32x4,          U32,            U32,                                                            )
 | 
			
		||||
OPCODE(BoundImageQueryLod,                                  F32x4,          U32,            Opaque,                                                         )
 | 
			
		||||
OPCODE(BoundImageGradient,                                  F32x4,          U32,            Opaque,         Opaque,         Opaque,         Opaque,         )
 | 
			
		||||
 | 
			
		||||
OPCODE(ImageSampleImplicitLod,                              F32x4,          U32,            Opaque,         Opaque,         Opaque,                         )
 | 
			
		||||
OPCODE(ImageSampleExplicitLod,                              F32x4,          U32,            Opaque,         Opaque,         Opaque,                         )
 | 
			
		||||
@ -401,6 +403,7 @@ OPCODE(ImageGatherDref,                                     F32x4,          U32,
 | 
			
		||||
OPCODE(ImageFetch,                                          F32x4,          U32,            Opaque,         Opaque,         Opaque,         Opaque,         )
 | 
			
		||||
OPCODE(ImageQueryDimensions,                                U32x4,          U32,            U32,                                                            )
 | 
			
		||||
OPCODE(ImageQueryLod,                                       F32x4,          U32,            Opaque,                                                         )
 | 
			
		||||
OPCODE(ImageGradient,                                       F32x4,          U32,            Opaque,         Opaque,         Opaque,         F32,            )
 | 
			
		||||
 | 
			
		||||
// Warp operations
 | 
			
		||||
OPCODE(VoteAll,                                             U1,             U1,                                                                             )
 | 
			
		||||
 | 
			
		||||
@ -370,12 +370,20 @@ void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
    case IR::Opcode::BindlessImageSampleDrefExplicitLod:
 | 
			
		||||
    case IR::Opcode::BindlessImageGather:
 | 
			
		||||
    case IR::Opcode::BindlessImageGatherDref:
 | 
			
		||||
    case IR::Opcode::BindlessImageFetch:
 | 
			
		||||
    case IR::Opcode::BindlessImageQueryDimensions:
 | 
			
		||||
    case IR::Opcode::BindlessImageQueryLod:
 | 
			
		||||
    case IR::Opcode::BindlessImageGradient:
 | 
			
		||||
    case IR::Opcode::BoundImageSampleImplicitLod:
 | 
			
		||||
    case IR::Opcode::BoundImageSampleExplicitLod:
 | 
			
		||||
    case IR::Opcode::BoundImageSampleDrefImplicitLod:
 | 
			
		||||
    case IR::Opcode::BoundImageSampleDrefExplicitLod:
 | 
			
		||||
    case IR::Opcode::BoundImageGather:
 | 
			
		||||
    case IR::Opcode::BoundImageGatherDref:
 | 
			
		||||
    case IR::Opcode::BoundImageFetch:
 | 
			
		||||
    case IR::Opcode::BoundImageQueryDimensions:
 | 
			
		||||
    case IR::Opcode::BoundImageQueryLod:
 | 
			
		||||
    case IR::Opcode::BoundImageGradient:
 | 
			
		||||
    case IR::Opcode::ImageSampleImplicitLod:
 | 
			
		||||
    case IR::Opcode::ImageSampleExplicitLod:
 | 
			
		||||
    case IR::Opcode::ImageSampleDrefImplicitLod:
 | 
			
		||||
@ -384,7 +392,8 @@ void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
    case IR::Opcode::ImageGatherDref:
 | 
			
		||||
    case IR::Opcode::ImageFetch:
 | 
			
		||||
    case IR::Opcode::ImageQueryDimensions:
 | 
			
		||||
    case IR::Opcode::ImageQueryLod: {
 | 
			
		||||
    case IR::Opcode::ImageQueryLod:
 | 
			
		||||
    case IR::Opcode::ImageGradient: {
 | 
			
		||||
        const TextureType type{inst.Flags<IR::TextureInstInfo>().type};
 | 
			
		||||
        info.uses_sampled_1d |= type == TextureType::Color1D || type == TextureType::ColorArray1D ||
 | 
			
		||||
                                type == TextureType::Shadow1D || type == TextureType::ShadowArray1D;
 | 
			
		||||
 | 
			
		||||
@ -60,6 +60,9 @@ IR::Opcode IndexedInstruction(const IR::Inst& inst) {
 | 
			
		||||
    case IR::Opcode::BoundImageQueryLod:
 | 
			
		||||
    case IR::Opcode::BindlessImageQueryLod:
 | 
			
		||||
        return IR::Opcode::ImageQueryLod;
 | 
			
		||||
    case IR::Opcode::BoundImageGradient:
 | 
			
		||||
    case IR::Opcode::BindlessImageGradient:
 | 
			
		||||
        return IR::Opcode::ImageGradient;
 | 
			
		||||
    default:
 | 
			
		||||
        return IR::Opcode::Void;
 | 
			
		||||
    }
 | 
			
		||||
@ -76,6 +79,7 @@ bool IsBindless(const IR::Inst& inst) {
 | 
			
		||||
    case IR::Opcode::BindlessImageFetch:
 | 
			
		||||
    case IR::Opcode::BindlessImageQueryDimensions:
 | 
			
		||||
    case IR::Opcode::BindlessImageQueryLod:
 | 
			
		||||
    case IR::Opcode::BindlessImageGradient:
 | 
			
		||||
        return true;
 | 
			
		||||
    case IR::Opcode::BoundImageSampleImplicitLod:
 | 
			
		||||
    case IR::Opcode::BoundImageSampleExplicitLod:
 | 
			
		||||
@ -86,6 +90,7 @@ bool IsBindless(const IR::Inst& inst) {
 | 
			
		||||
    case IR::Opcode::BoundImageFetch:
 | 
			
		||||
    case IR::Opcode::BoundImageQueryDimensions:
 | 
			
		||||
    case IR::Opcode::BoundImageQueryLod:
 | 
			
		||||
    case IR::Opcode::BoundImageGradient:
 | 
			
		||||
        return false;
 | 
			
		||||
    default:
 | 
			
		||||
        throw InvalidArgument("Invalid opcode {}", inst.Opcode());
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user