shader: Implement ImageGradient
This commit is contained in:
parent
be3e94ae55
commit
d5bfc63088
8 changed files with 84 additions and 2 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue