blob: 00d2c35e746280dc8b8ac37f73e80209de6cb522 [file] [log] [blame]
// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef sw_PixelProcessor_hpp
#define sw_PixelProcessor_hpp
#include "Context.hpp"
#include "Memset.hpp"
#include "RoutineCache.hpp"
#include "Vulkan/VkFormat.hpp"
#include <memory>
namespace sw {
struct DrawData;
struct Primitive;
class SpirvShader;
using RasterizerFunction = FunctionT<void(const vk::Device *device, const Primitive *primitive, int count, int cluster, int clusterCount, DrawData *draw)>;
class PixelProcessor
{
public:
struct States : Memset<States>
{
// Same as VkStencilOpState, but with no reference, as it's not part of the state
// (it doesn't require a different program to be generated)
struct StencilOpState
{
VkStencilOp failOp;
VkStencilOp passOp;
VkStencilOp depthFailOp;
VkCompareOp compareOp;
bool useCompareMask;
bool useWriteMask;
bool writeEnabled;
void operator=(const VkStencilOpState &rhs)
{
failOp = rhs.failOp;
passOp = rhs.passOp;
depthFailOp = rhs.depthFailOp;
compareOp = rhs.compareOp;
useCompareMask = (rhs.compareMask != 0xff);
useWriteMask = ((rhs.writeMask & 0xFF) != 0xFF);
writeEnabled = (rhs.writeMask != 0);
}
};
States()
: Memset(this, 0)
{}
uint32_t computeHash();
uint64_t shaderID;
uint32_t pipelineLayoutIdentifier;
unsigned int numClipDistances;
unsigned int numCullDistances;
VkCompareOp depthCompareMode;
bool depthWriteEnable;
bool robustBufferAccess;
bool stencilActive;
StencilOpState frontStencil;
StencilOpState backStencil;
bool depthTestActive;
bool depthBoundsTestActive;
bool occlusionEnabled;
bool perspective;
vk::BlendState blendState[MAX_COLOR_BUFFERS];
unsigned int colorWriteMask;
vk::Format colorFormat[MAX_COLOR_BUFFERS];
unsigned int multiSampleCount;
unsigned int multiSampleMask;
bool enableMultiSampling;
bool alphaToCoverage;
bool centroid;
bool sampleShadingEnabled;
float minSampleShading;
float minDepthBounds;
float maxDepthBounds;
VkFrontFace frontFace;
vk::Format depthFormat;
bool depthBias;
bool depthClamp;
float minDepthClamp;
float maxDepthClamp;
};
struct State : States
{
bool operator==(const State &state) const;
int colorWriteActive(int index) const
{
return (colorWriteMask >> (index * 4)) & 0xF;
}
uint32_t hash;
};
struct Stencil
{
int64_t testMaskQ;
int64_t referenceMaskedQ;
int64_t referenceMaskedSignedQ;
int64_t writeMaskQ;
int64_t invWriteMaskQ;
int64_t referenceQ;
void set(int reference, int testMask, int writeMask)
{
referenceQ = replicate(reference);
testMaskQ = replicate(testMask);
writeMaskQ = replicate(writeMask);
invWriteMaskQ = ~writeMaskQ;
referenceMaskedQ = referenceQ & testMaskQ;
referenceMaskedSignedQ = replicate(((reference & testMask) + 0x80) & 0xFF);
}
static int64_t replicate(int b)
{
int64_t w = b & 0xFF;
return (w << 0) | (w << 8) | (w << 16) | (w << 24) | (w << 32) | (w << 40) | (w << 48) | (w << 56);
}
};
struct Factor
{
float4 blendConstantF; // Unclamped for floating-point attachment formats.
float4 invBlendConstantF; // Unclamped for floating-point attachment formats.
float4 blendConstantU; // Clamped to [0,1] for unsigned fixed-point attachment formats.
float4 invBlendConstantU; // Clamped to [0,1] for unsigned fixed-point attachment formats.
float4 blendConstantS; // Clamped to [-1,1] for signed fixed-point attachment formats.
float4 invBlendConstantS; // Clamped to [-1,1] for signed fixed-point attachment formats.
};
public:
using RoutineType = RasterizerFunction::RoutineType;
PixelProcessor();
void setBlendConstant(const float4 &blendConstant);
const State update(const vk::GraphicsState &pipelineState, const sw::SpirvShader *fragmentShader, const sw::SpirvShader *vertexShader, const vk::Attachments &attachments, bool occlusionEnabled) const;
RoutineType routine(const State &state, const vk::PipelineLayout *pipelineLayout,
const SpirvShader *pixelShader, const vk::DescriptorSet::Bindings &descriptorSets);
void setRoutineCacheSize(int routineCacheSize);
// Other semi-constants
Factor factor;
private:
using RoutineCacheType = RoutineCache<State, RasterizerFunction::CFunctionType>;
std::unique_ptr<RoutineCacheType> routineCache;
};
} // namespace sw
namespace std {
template<>
struct hash<sw::PixelProcessor::State>
{
uint64_t operator()(const sw::PixelProcessor::State &state) const
{
return state.hash;
}
};
} // namespace std
#endif // sw_PixelProcessor_hpp