Commit 2a25ed8a by Nicolas Capens Committed by Nicolas Capens

Parse 'Sample' image instruction operand

OpImageFetch/Read/Write can have an optional 'Sample' operand which indicates the sample index to operate on. It is orthogonal to other operands so it is indicated by a new Boolean field in sw::SamplerFunction and SpirvShader::ImageInstruction. The offset operand was also turned into a Boolean field / component count. The sample index is not wired up to be taken into account by the Fetch sampling routine yet. OpImageRead already had support for the Sample operand, but OpImageWrite does not. Bug: b/135265531 Tests: dEQP-VK.pipeline.multisample.sampled_image.* Change-Id: I20f50a888436775b996221e8283a4c4ab7f28e17 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/32908Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
parent 8fd5330f
......@@ -1231,7 +1231,7 @@ namespace sw
void SamplerCore::computeIndices(UInt index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, Vector4f &offset, const Pointer<Byte> &mipmap, SamplerFunction function)
{
bool texelFetch = (function == Fetch);
bool hasOffset = (function.option == Offset);
bool hasOffset = (function.offset != 0);
if(!texelFetch)
{
......@@ -2088,7 +2088,7 @@ namespace sw
if(function == Fetch)
{
xyz0 = Min(Max(((function.option == Offset) && (addressingMode != ADDRESSING_LAYER)) ? As<Int4>(uvw) + As<Int4>(texOffset) : As<Int4>(uvw), Int4(0)), maxXYZ);
xyz0 = Min(Max(((function.offset != 0) && (addressingMode != ADDRESSING_LAYER)) ? As<Int4>(uvw) + As<Int4>(texOffset) : As<Int4>(uvw), Int4(0)), maxXYZ);
}
else if(addressingMode == ADDRESSING_LAYER) // Note: Offset does not apply to array layers
{
......@@ -2139,7 +2139,7 @@ namespace sw
Float4 floor = Floor(coord);
xyz0 = Int4(floor);
if(function.option == Offset)
if(function.offset != 0)
{
xyz0 += As<Int4>(texOffset);
}
......@@ -2153,7 +2153,7 @@ namespace sw
}
else
{
if(function.option != Offset)
if(function.offset == 0)
{
switch(addressingMode)
{
......@@ -2197,7 +2197,7 @@ namespace sw
if(state.textureFilter == FILTER_POINT)
{
if(addressingMode == ADDRESSING_BORDER || function.option == Offset)
if(addressingMode == ADDRESSING_BORDER || function.offset != 0)
{
xyz0 = Int4(Floor(coord));
}
......@@ -2223,7 +2223,7 @@ namespace sw
f = coord - floor;
}
if(function.option == Offset)
if(function.offset != 0)
{
xyz0 += As<Int4>(texOffset);
}
......@@ -2243,7 +2243,7 @@ namespace sw
xyz0 |= border0;
xyz1 |= border1;
}
else if(function.option == Offset)
else if(function.offset != 0)
{
switch(addressingMode)
{
......
......@@ -40,21 +40,18 @@ namespace sw
SAMPLER_METHOD_LAST = Gather,
};
enum SamplerOption
{
None,
Offset, // Offset sample location by provided integer coordinates.
SAMPLER_OPTION_LAST = Offset,
};
// TODO(b/129523279): Eliminate and use SpirvShader::ImageInstruction instead.
struct SamplerFunction
{
SamplerFunction(SamplerMethod method, SamplerOption option = None) : method(method), option(option) {}
SamplerFunction(SamplerMethod method, bool offset = false, bool sample = false)
: method(method), offset(offset), sample(sample)
{}
operator SamplerMethod() { return method; }
const SamplerMethod method;
const SamplerOption option;
const bool offset;
const bool sample;
};
class SamplerCore
......
......@@ -4783,6 +4783,7 @@ namespace sw
bool constOffset = false;
Object::ID offsetId = 0;
bool sample = false;
Object::ID sampleId = 0;
uint32_t operand = (instruction.isDref() || instruction.samplerMethod == Gather) ? 6 : 5;
......@@ -4829,14 +4830,17 @@ namespace sw
if(imageOperands & spv::ImageOperandsSampleMask)
{
UNIMPLEMENTED("Image operand %x", spv::ImageOperandsSampleMask); (void)sample;
sample = true;
sampleId = insn.word(operand);
imageOperands &= ~spv::ImageOperandsSampleMask;
ASSERT(instruction.samplerMethod == Fetch);
instruction.sample = true;
}
if(imageOperands != 0)
{
UNIMPLEMENTED("Image operand %x", imageOperands);
UNSUPPORTED("Image operand %x", imageOperands);
}
}
......@@ -4887,7 +4891,7 @@ namespace sw
auto &dxyType = getType(dxValue.type);
ASSERT(dxyType.sizeInComponents == getType(dyValue.type).sizeInComponents);
instruction.gradComponents = dxyType.sizeInComponents;
instruction.grad = dxyType.sizeInComponents;
for(uint32_t j = 0; j < dxyType.sizeInComponents; j++, i++)
{
......@@ -4913,8 +4917,7 @@ namespace sw
auto offsetValue = GenericValue(this, state->routine, offsetId);
auto &offsetType = getType(offsetValue.type);
instruction.samplerOption = Offset;
instruction.offsetComponents = offsetType.sizeInComponents;
instruction.offset = offsetType.sizeInComponents;
for(uint32_t j = 0; j < offsetType.sizeInComponents; j++, i++)
{
......@@ -4922,6 +4925,12 @@ namespace sw
}
}
if(sample)
{
auto sampleValue = GenericValue(this, state->routine, sampleId);
in[i] = sampleValue.Float(0);
}
auto samplerFunc = Call(getImageSampler, instruction.parameters, imageDescriptor, sampler);
Array<SIMD::Float> out(4);
......@@ -5455,7 +5464,7 @@ namespace sw
ASSERT(imageType.definition.opcode() == spv::OpTypeImage);
// Not handling any image operands yet.
// TODO(b/131171141): Not handling any image operands yet.
ASSERT(insn.wordCount() == 4);
auto coordinate = GenericValue(this, state->routine, insn.word(2));
......
......@@ -504,7 +504,7 @@ namespace sw
SamplerFunction getSamplerFunction() const
{
return { static_cast<SamplerMethod>(samplerMethod), static_cast<SamplerOption>(samplerOption) };
return { static_cast<SamplerMethod>(samplerMethod), offset != 0, sample != 0 };
}
bool isDref() const
......@@ -523,22 +523,22 @@ namespace sw
{
uint32_t variant : BITS(VARIANT_LAST);
uint32_t samplerMethod : BITS(SAMPLER_METHOD_LAST);
uint32_t samplerOption : BITS(SAMPLER_OPTION_LAST);
uint32_t gatherComponent : 2;
// Parameters are passed to the sampling routine in this order:
uint32_t coordinates : 3; // 1-4 (does not contain projection component)
// uint32_t dref : 1; // Indicated by Variant::ProjDref|Dref
// uint32_t lodOrBias : 1; // Indicated by SamplerMethod::Lod|Bias|Fetch
uint32_t gradComponents : 2; // 0-3 (for each of dx / dy)
uint32_t offsetComponents : 2; // 0-3
uint32_t grad : 2; // 0-3 components (for each of dx / dy)
uint32_t offset : 2; // 0-3 components
uint32_t sample : 1; // 0-1 scalar integer
};
uint32_t parameters;
};
};
static_assert(sizeof(ImageInstruction) == 4, "ImageInstruction must be 32-bit");
static_assert(sizeof(ImageInstruction) == sizeof(uint32_t), "ImageInstruction must be 32-bit");
int getSerialID() const
{
......
......@@ -164,25 +164,24 @@ SpirvShader::ImageSampler *SpirvShader::emitSamplerFunction(ImageInstruction ins
}
else if(instruction.samplerMethod == Grad)
{
for(uint32_t j = 0; j < instruction.gradComponents; j++, i++)
for(uint32_t j = 0; j < instruction.grad; j++, i++)
{
dsx[j] = in[i];
}
for(uint32_t j = 0; j < instruction.gradComponents; j++, i++)
for(uint32_t j = 0; j < instruction.grad; j++, i++)
{
dsy[j] = in[i];
}
}
if(instruction.samplerOption == Offset)
for(uint32_t j = 0; j < instruction.offset; j++, i++)
{
for(uint32_t j = 0; j < instruction.offsetComponents; j++, i++)
{
offset[j] = in[i];
}
offset[j] = in[i];
}
// TODO(b/133868964): Handle 'Sample' operand.
SamplerCore s(constants, samplerState);
// For explicit-lod instructions the LOD can be different per SIMD lane. SamplerCore currently assumes
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment