Commit 125dba0b by Nicolas Capens Committed by Nicolas Capens

Implement OpImageSampleExplicitLod

Emit a call to a different trampoline function for generating the sampler code, which unifies the implementation with OpImageSampleExplicitLod's by using a common EmitImageSample which takes a sampler 'method' enum. This is then passed at shader execution time to emitSamplerFunction. The lod parameter is parsed from the instruction stream in EmitImageSample. Other (optional) image operands are left unimplemented for now. Bug: b/129523279 Test: dEQP-VK.binding_model.shader_access.primary_cmd_buf.combined_image_sampler_mutable.fragment.single_descriptor.2d Change-Id: I265b81d953fe5a0496d029704a0f5eeff4229823 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/29774Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarChris Forbes <chrisforbes@google.com>
parent a94ca189
......@@ -16,7 +16,6 @@
#define sw_PixelProgram_hpp
#include "PixelRoutine.hpp"
#include "SamplerCore.hpp"
namespace sw
{
......
......@@ -14,6 +14,7 @@
#include "SamplerCore.hpp"
#include "PixelRoutine.hpp"
#include "Constants.hpp"
#include "Vulkan/VkDebug.hpp"
......
......@@ -15,11 +15,18 @@
#ifndef sw_SamplerCore_hpp
#define sw_SamplerCore_hpp
#include "PixelRoutine.hpp"
#include "ShaderCore.hpp"
#include "Device/Sampler.hpp"
#include "Reactor/Reactor.hpp"
#ifdef None
#undef None // b/127920555
#endif
namespace sw
{
using namespace rr;
enum SamplerMethod
{
Implicit, // Compute gradients (pixel shader only).
......
......@@ -333,7 +333,9 @@ namespace sw
for (auto insn : *this)
{
switch (insn.opcode())
spv::Op opcode = insn.opcode();
switch (opcode)
{
case spv::OpExecutionMode:
ProcessExecutionMode(insn);
......@@ -444,7 +446,7 @@ namespace sw
blocks[currentBlock] = Block(blockStart, blockEnd);
currentBlock = Block::ID(0);
if (insn.opcode() == spv::OpKill)
if (opcode == spv::OpKill)
{
modes.ContainsKill = true;
}
......@@ -639,7 +641,7 @@ namespace sw
case spv::OpSpecConstantTrue:
// These should have all been removed by preprocessing passes. If we see them here,
// our assumptions are wrong and we will probably generate wrong code.
UNIMPLEMENTED("%s should have already been lowered.", OpcodeName(insn.opcode()).c_str());
UNIMPLEMENTED("%s should have already been lowered.", OpcodeName(opcode).c_str());
break;
case spv::OpFConvert:
......@@ -667,7 +669,7 @@ namespace sw
DefineResult(insn);
if (insn.opcode() == spv::OpAccessChain || insn.opcode() == spv::OpInBoundsAccessChain)
if (opcode == spv::OpAccessChain || opcode == spv::OpInBoundsAccessChain)
{
Decorations dd{};
ApplyDecorationsForAccessChain(&dd, pointerId, insn.wordCount() - 4, insn.wordPointer(4));
......@@ -787,6 +789,7 @@ namespace sw
case spv::OpAtomicCompareExchange:
case spv::OpPhi:
case spv::OpImageSampleImplicitLod:
case spv::OpImageSampleExplicitLod:
case spv::OpImageQuerySize:
case spv::OpImageRead:
case spv::OpImageTexelPointer:
......@@ -811,7 +814,7 @@ namespace sw
}
default:
UNIMPLEMENTED("%s", OpcodeName(insn.opcode()).c_str());
UNIMPLEMENTED("%s", OpcodeName(opcode).c_str());
}
}
......@@ -2316,6 +2319,9 @@ namespace sw
case spv::OpImageSampleImplicitLod:
return EmitImageSampleImplicitLod(insn, state);
case spv::OpImageSampleExplicitLod:
return EmitImageSampleExplicitLod(insn, state);
case spv::OpImageQuerySize:
return EmitImageQuerySize(insn, state);
......@@ -4364,6 +4370,16 @@ namespace sw
SpirvShader::EmitResult SpirvShader::EmitImageSampleImplicitLod(InsnIterator insn, EmitState *state) const
{
return EmitImageSample(getImageSamplerImplicitLod, insn, state);
}
SpirvShader::EmitResult SpirvShader::EmitImageSampleExplicitLod(InsnIterator insn, EmitState *state) const
{
return EmitImageSample(getImageSamplerExplicitLod, insn, state);
}
SpirvShader::EmitResult SpirvShader::EmitImageSample(GetImageSampler getImageSampler, InsnIterator insn, EmitState *state) const
{
Type::ID resultTypeId = insn.word(1);
Object::ID resultId = insn.word(2);
Object::ID sampledImageId = insn.word(3);
......@@ -4373,6 +4389,7 @@ namespace sw
auto &result = state->routine->createIntermediate(resultId, resultType.sizeInComponents);
auto &sampledImage = state->routine->getPointer(sampledImageId);
auto coordinate = GenericValue(this, state->routine, coordinateId);
auto &coordinateType = getType(coordinate.type);
Pointer<Byte> constants; // FIXME(b/129523279)
......@@ -4382,9 +4399,75 @@ namespace sw
auto samplerFunc = Call(getImageSampler, imageView, sampler);
Array<SIMD::Float> in(2);
in[0] = coordinate.Float(0);
in[1] = coordinate.Float(1);
uint32_t imageOperands = spv::ImageOperandsMaskNone;
bool bias = false;
bool lod = false;
Object::ID lodId = 0;
bool grad = false;
bool constOffset = false;
bool sample = false;
if(insn.wordCount() > 5)
{
imageOperands = static_cast<spv::ImageOperandsMask>(insn.word(5));
uint32_t operand = 6;
if(imageOperands & spv::ImageOperandsBiasMask)
{
UNIMPLEMENTED("Image operand %x", spv::ImageOperandsBiasMask); (void)bias;
bias = true;
imageOperands &= ~spv::ImageOperandsBiasMask;
}
if(imageOperands & spv::ImageOperandsLodMask)
{
lod = true;
lodId = insn.word(operand);
operand++;
imageOperands &= ~spv::ImageOperandsLodMask;
}
if(imageOperands & spv::ImageOperandsGradMask)
{
UNIMPLEMENTED("Image operand %x", spv::ImageOperandsGradMask); (void)grad;
grad = true;
imageOperands &= ~spv::ImageOperandsGradMask;
}
if(imageOperands & spv::ImageOperandsConstOffsetMask)
{
UNIMPLEMENTED("Image operand %x", spv::ImageOperandsConstOffsetMask); (void)constOffset;
constOffset = true;
imageOperands &= ~spv::ImageOperandsConstOffsetMask;
}
if(imageOperands & spv::ImageOperandsSampleMask)
{
UNIMPLEMENTED("Image operand %x", spv::ImageOperandsSampleMask); (void)sample;
sample = true;
imageOperands &= ~spv::ImageOperandsSampleMask;
}
if(imageOperands != 0)
{
UNIMPLEMENTED("Image operand %x", imageOperands);
}
}
Array<SIMD::Float> in(coordinateType.sizeInComponents + lod);
uint32_t i = 0;
for( ; i < coordinateType.sizeInComponents; i++)
{
in[i] = coordinate.Float(i);
}
if(lod)
{
auto lodValue = GenericValue(this, state->routine, lodId);
in[i] = lodValue.Float(0);
i++;
}
Array<SIMD::Float> out(4);
Call<ImageSampler>(samplerFunc, sampledImage.base, &in[0], &out[0]);
......
......@@ -16,6 +16,7 @@
#define sw_SpirvShader_hpp
#include "ShaderCore.hpp"
#include "SamplerCore.hpp"
#include "SpirvID.hpp"
#include "System/Types.hpp"
#include "Vulkan/VkDebug.hpp"
......@@ -256,6 +257,9 @@ namespace sw
using InsnStore = std::vector<uint32_t>;
InsnStore insns;
using ImageSampler = void(void* image, void* uvsIn, void* texelOut);
using GetImageSampler = ImageSampler*(const vk::ImageView *imageView, const vk::Sampler *sampler);
/* Pseudo-iterator over SPIRV instructions, designed to support range-based-for. */
class InsnIterator
{
......@@ -827,6 +831,8 @@ namespace sw
EmitResult EmitKill(InsnIterator insn, EmitState *state) const;
EmitResult EmitPhi(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageSampleImplicitLod(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageSampleExplicitLod(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageSample(GetImageSampler getImageSampler, InsnIterator insn, EmitState *state) const;
EmitResult EmitImageQuerySize(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageRead(InsnIterator insn, EmitState *state) const;
EmitResult EmitImageWrite(InsnIterator insn, EmitState *state) const;
......@@ -853,10 +859,11 @@ namespace sw
// Returns the pair <significand, exponent>
std::pair<SIMD::Float, SIMD::Int> Frexp(RValue<SIMD::Float> val) const;
using ImageSampler = void(void* image, void* uvsIn, void* texelOut);
static ImageSampler *getImageSampler(const vk::ImageView *imageView, const vk::Sampler *sampler);
static ImageSampler *getImageSamplerImplicitLod(const vk::ImageView *imageView, const vk::Sampler *sampler);
static ImageSampler *getImageSamplerExplicitLod(const vk::ImageView *imageView, const vk::Sampler *sampler);
static ImageSampler *getImageSampler(SamplerMethod samplerMethod, const vk::ImageView *imageView, const vk::Sampler *sampler);
static void emitSamplerFunction(
SamplerMethod samplerMethod,
const vk::ImageView *imageView, const vk::Sampler *sampler,
Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out);
......
......@@ -39,14 +39,23 @@
namespace sw {
SpirvShader::ImageSampler *SpirvShader::getImageSampler(const vk::ImageView *imageView, const vk::Sampler *sampler)
SpirvShader::ImageSampler *SpirvShader::getImageSamplerImplicitLod(const vk::ImageView *imageView, const vk::Sampler *sampler)
{
// TODO: Move somewhere sensible.
return getImageSampler(Implicit, imageView, sampler);
}
SpirvShader::ImageSampler *SpirvShader::getImageSamplerExplicitLod(const vk::ImageView *imageView, const vk::Sampler *sampler)
{
return getImageSampler(Lod, imageView, sampler);
}
SpirvShader::ImageSampler *SpirvShader::getImageSampler(SamplerMethod samplerMethod, const vk::ImageView *imageView, const vk::Sampler *sampler)
{
// TODO(b/129523279): Move somewhere sensible.
static std::unordered_map<uintptr_t, ImageSampler*> cache;
static std::mutex mutex;
// TODO: Don't use pointers they can be deleted and reused, combine some two
// unique ids.
// FIXME(b/129523279): Don't use pointers: they can be deleted and reused. Instead combine some two unique ids.
// FIXME(b/129523279): Take instruction opcode and optional parameters into acount (SamplerMethod / SamplerOption).
auto key = reinterpret_cast<uintptr_t>(imageView) ^ reinterpret_cast<uintptr_t>(sampler);
std::unique_lock<std::mutex> lock(mutex);
......@@ -58,13 +67,14 @@ SpirvShader::ImageSampler *SpirvShader::getImageSampler(const vk::ImageView *ima
Pointer<Byte> image = function.Arg<0>();
Pointer<SIMD::Float> in = function.Arg<1>();
Pointer<SIMD::Float> out = function.Arg<2>();
emitSamplerFunction(imageView, sampler, image, in, out);
emitSamplerFunction(samplerMethod, imageView, sampler, image, in, out);
auto fptr = reinterpret_cast<ImageSampler*>((void *)function("sampler")->getEntry());
cache.emplace(key, fptr);
return fptr;
}
void SpirvShader::emitSamplerFunction(
SamplerMethod samplerMethod,
const vk::ImageView *imageView, const vk::Sampler *sampler,
Pointer<Byte> image, Pointer<SIMD::Float> in, Pointer<Byte> out)
{
......@@ -102,11 +112,16 @@ void SpirvShader::emitSamplerFunction(
Pointer<Byte> texture = image + OFFSET(vk::SampledImageDescriptor, texture); // sw::Texture*
SIMD::Float w(0); // TODO(b/129523279)
SIMD::Float q(0); // TODO(b/129523279)
SIMD::Float bias(0); // TODO(b/129523279)
SIMD::Float bias(0);
Vector4f dsx; // TODO(b/129523279)
Vector4f dsy; // TODO(b/129523279)
Vector4f offset; // TODO(b/129523279)
SamplerFunction samplerFunction = { Implicit, None }; // ASSERT(insn.wordCount() == 5); // TODO(b/129523279)
SamplerFunction samplerFunction = { samplerMethod, None }; // TODO(b/129523279)
if(samplerMethod == Lod)
{
bias = in[2]; // TODO(b/129523279): Index depends on view dimensions and other optional operands.
}
Vector4f sample = s.sampleTexture(texture, u, v, w, q, bias, dsx, dsy, offset, samplerFunction);
......
......@@ -18,10 +18,6 @@
#include "VertexRoutine.hpp"
#include "ShaderCore.hpp"
#include "SamplerCore.hpp"
#include "Device/Stream.hpp"
#include "System/Types.hpp"
namespace sw
{
struct Stream;
......
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