// 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_Renderer_hpp
|
#define sw_Renderer_hpp
|
|
#include "VertexProcessor.hpp"
|
#include "PixelProcessor.hpp"
|
#include "SetupProcessor.hpp"
|
#include "Plane.hpp"
|
#include "Blitter.hpp"
|
#include "Common/MutexLock.hpp"
|
#include "Common/Thread.hpp"
|
#include "Main/Config.hpp"
|
|
#include <list>
|
|
namespace sw
|
{
|
class Clipper;
|
struct DrawCall;
|
class PixelShader;
|
class VertexShader;
|
class SwiftConfig;
|
struct Task;
|
class Resource;
|
struct Constants;
|
|
enum TranscendentalPrecision
|
{
|
APPROXIMATE,
|
PARTIAL, // 2^-10
|
ACCURATE,
|
WHQL, // 2^-21
|
IEEE // 2^-23
|
};
|
|
extern TranscendentalPrecision logPrecision;
|
extern TranscendentalPrecision expPrecision;
|
extern TranscendentalPrecision rcpPrecision;
|
extern TranscendentalPrecision rsqPrecision;
|
extern bool perspectiveCorrection;
|
|
struct Conventions
|
{
|
bool halfIntegerCoordinates;
|
bool symmetricNormalizedDepth;
|
bool booleanFaceRegister;
|
bool fullPixelPositionRegister;
|
bool leadingVertexFirst;
|
bool secondaryColor;
|
bool colorsDefaultToZero;
|
};
|
|
static const Conventions OpenGL =
|
{
|
true, // halfIntegerCoordinates
|
true, // symmetricNormalizedDepth
|
true, // booleanFaceRegister
|
true, // fullPixelPositionRegister
|
false, // leadingVertexFirst
|
false, // secondaryColor
|
true, // colorsDefaultToZero
|
};
|
|
static const Conventions Direct3D =
|
{
|
false, // halfIntegerCoordinates
|
false, // symmetricNormalizedDepth
|
false, // booleanFaceRegister
|
false, // fullPixelPositionRegister
|
true, // leadingVertexFirst
|
true, // secondardyColor
|
false, // colorsDefaultToZero
|
};
|
|
struct Query
|
{
|
enum Type { FRAGMENTS_PASSED, TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN };
|
|
Query(Type type);
|
|
void addRef();
|
void release();
|
|
inline void begin()
|
{
|
building = true;
|
data = 0;
|
}
|
|
inline void end()
|
{
|
building = false;
|
}
|
|
inline bool isReady() const
|
{
|
return (reference == 1);
|
}
|
|
bool building;
|
AtomicInt data;
|
|
const Type type;
|
private:
|
~Query() {} // Only delete a query within the release() function
|
|
AtomicInt reference;
|
};
|
|
struct DrawData
|
{
|
const Constants *constants;
|
|
const void *input[MAX_VERTEX_INPUTS];
|
unsigned int stride[MAX_VERTEX_INPUTS];
|
Texture mipmap[TOTAL_IMAGE_UNITS];
|
const void *indices;
|
|
struct VS
|
{
|
float4 c[VERTEX_UNIFORM_VECTORS + 1]; // One extra for indices out of range, c[VERTEX_UNIFORM_VECTORS] = {0, 0, 0, 0}
|
byte* u[MAX_UNIFORM_BUFFER_BINDINGS];
|
byte* t[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS];
|
unsigned int reg[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS]; // Offset used when reading from registers, in components
|
unsigned int row[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS]; // Number of rows to read
|
unsigned int col[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS]; // Number of columns to read
|
unsigned int str[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS]; // Number of components between each varying in output buffer
|
int4 i[16];
|
bool b[16];
|
};
|
|
struct PS
|
{
|
word4 cW[8][4];
|
float4 c[FRAGMENT_UNIFORM_VECTORS];
|
byte* u[MAX_UNIFORM_BUFFER_BINDINGS];
|
int4 i[16];
|
bool b[16];
|
};
|
|
union
|
{
|
VS vs;
|
VertexProcessor::FixedFunction ff;
|
};
|
|
PS ps;
|
|
int instanceID;
|
|
VertexProcessor::PointSprite point;
|
float lineWidth;
|
|
PixelProcessor::Stencil stencil[2]; // clockwise, counterclockwise
|
PixelProcessor::Fog fog;
|
PixelProcessor::Factor factor;
|
unsigned int occlusion[16]; // Number of pixels passing depth test
|
|
#if PERF_PROFILE
|
int64_t cycles[PERF_TIMERS][16];
|
#endif
|
|
TextureStage::Uniforms textureStage[8];
|
|
float4 Wx16;
|
float4 Hx16;
|
float4 X0x16;
|
float4 Y0x16;
|
float4 XXXX;
|
float4 YYYY;
|
float4 halfPixelX;
|
float4 halfPixelY;
|
float viewportHeight;
|
float slopeDepthBias;
|
float depthRange;
|
float depthNear;
|
Plane clipPlane[6];
|
|
unsigned int *colorBuffer[RENDERTARGETS];
|
int colorPitchB[RENDERTARGETS];
|
int colorSliceB[RENDERTARGETS];
|
float *depthBuffer;
|
int depthPitchB;
|
int depthSliceB;
|
unsigned char *stencilBuffer;
|
int stencilPitchB;
|
int stencilSliceB;
|
|
int scissorX0;
|
int scissorX1;
|
int scissorY0;
|
int scissorY1;
|
|
float4 a2c0;
|
float4 a2c1;
|
float4 a2c2;
|
float4 a2c3;
|
};
|
|
struct Viewport
|
{
|
float x0;
|
float y0;
|
float width;
|
float height;
|
float minZ;
|
float maxZ;
|
};
|
|
class Renderer : public VertexProcessor, public PixelProcessor, public SetupProcessor
|
{
|
struct Task
|
{
|
enum Type
|
{
|
PRIMITIVES,
|
PIXELS,
|
|
RESUME,
|
SUSPEND
|
};
|
|
AtomicInt type;
|
AtomicInt primitiveUnit;
|
AtomicInt pixelCluster;
|
};
|
|
struct PrimitiveProgress
|
{
|
void init()
|
{
|
drawCall = 0;
|
firstPrimitive = 0;
|
primitiveCount = 0;
|
visible = 0;
|
references = 0;
|
}
|
|
AtomicInt drawCall;
|
AtomicInt firstPrimitive;
|
AtomicInt primitiveCount;
|
AtomicInt visible;
|
AtomicInt references;
|
};
|
|
struct PixelProgress
|
{
|
void init()
|
{
|
drawCall = 0;
|
processedPrimitives = 0;
|
executing = false;
|
}
|
|
AtomicInt drawCall;
|
AtomicInt processedPrimitives;
|
AtomicInt executing;
|
};
|
|
public:
|
Renderer(Context *context, Conventions conventions, bool exactColorRounding);
|
|
virtual ~Renderer();
|
|
void *operator new(size_t size);
|
void operator delete(void * mem);
|
|
void draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update = true);
|
|
void clear(void *value, Format format, Surface *dest, const Rect &rect, unsigned int rgbaMask);
|
void blit(Surface *source, const SliceRectF &sRect, Surface *dest, const SliceRect &dRect, bool filter, bool isStencil = false, bool sRGBconversion = true);
|
void blit3D(Surface *source, Surface *dest);
|
|
void setIndexBuffer(Resource *indexBuffer);
|
|
void setMultiSampleMask(unsigned int mask);
|
void setTransparencyAntialiasing(TransparencyAntialiasing transparencyAntialiasing);
|
|
void setTextureResource(unsigned int sampler, Resource *resource);
|
void setTextureLevel(unsigned int sampler, unsigned int face, unsigned int level, Surface *surface, TextureType type);
|
|
void setTextureFilter(SamplerType type, int sampler, FilterType textureFilter);
|
void setMipmapFilter(SamplerType type, int sampler, MipmapType mipmapFilter);
|
void setGatherEnable(SamplerType type, int sampler, bool enable);
|
void setAddressingModeU(SamplerType type, int sampler, AddressingMode addressingMode);
|
void setAddressingModeV(SamplerType type, int sampler, AddressingMode addressingMode);
|
void setAddressingModeW(SamplerType type, int sampler, AddressingMode addressingMode);
|
void setReadSRGB(SamplerType type, int sampler, bool sRGB);
|
void setMipmapLOD(SamplerType type, int sampler, float bias);
|
void setBorderColor(SamplerType type, int sampler, const Color<float> &borderColor);
|
void setMaxAnisotropy(SamplerType type, int sampler, float maxAnisotropy);
|
void setHighPrecisionFiltering(SamplerType type, int sampler, bool highPrecisionFiltering);
|
void setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR);
|
void setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG);
|
void setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB);
|
void setSwizzleA(SamplerType type, int sampler, SwizzleType swizzleA);
|
void setCompareFunc(SamplerType type, int sampler, CompareFunc compare);
|
void setBaseLevel(SamplerType type, int sampler, int baseLevel);
|
void setMaxLevel(SamplerType type, int sampler, int maxLevel);
|
void setMinLod(SamplerType type, int sampler, float minLod);
|
void setMaxLod(SamplerType type, int sampler, float maxLod);
|
void setSyncRequired(SamplerType type, int sampler, bool syncRequired);
|
|
void setPointSpriteEnable(bool pointSpriteEnable);
|
void setPointScaleEnable(bool pointScaleEnable);
|
void setLineWidth(float width);
|
|
void setDepthBias(float bias);
|
void setSlopeDepthBias(float slopeBias);
|
|
void setRasterizerDiscard(bool rasterizerDiscard);
|
|
// Programmable pipelines
|
void setPixelShader(const PixelShader *shader);
|
void setVertexShader(const VertexShader *shader);
|
|
void setPixelShaderConstantF(unsigned int index, const float value[4], unsigned int count = 1);
|
void setPixelShaderConstantI(unsigned int index, const int value[4], unsigned int count = 1);
|
void setPixelShaderConstantB(unsigned int index, const int *boolean, unsigned int count = 1);
|
|
void setVertexShaderConstantF(unsigned int index, const float value[4], unsigned int count = 1);
|
void setVertexShaderConstantI(unsigned int index, const int value[4], unsigned int count = 1);
|
void setVertexShaderConstantB(unsigned int index, const int *boolean, unsigned int count = 1);
|
|
// Viewport & Clipper
|
void setViewport(const Viewport &viewport);
|
void setScissor(const Rect &scissor);
|
void setClipFlags(int flags);
|
void setClipPlane(unsigned int index, const float plane[4]);
|
|
// Partial transform
|
void setModelMatrix(const Matrix &M, int i = 0);
|
void setViewMatrix(const Matrix &V);
|
void setBaseMatrix(const Matrix &B);
|
void setProjectionMatrix(const Matrix &P);
|
|
void addQuery(Query *query);
|
void removeQuery(Query *query);
|
|
void synchronize();
|
|
#if PERF_HUD
|
// Performance timers
|
int getThreadCount();
|
int64_t getVertexTime(int thread);
|
int64_t getSetupTime(int thread);
|
int64_t getPixelTime(int thread);
|
void resetTimers();
|
#endif
|
|
static int getClusterCount() { return clusterCount; }
|
|
private:
|
static void threadFunction(void *parameters);
|
void threadLoop(int threadIndex);
|
void taskLoop(int threadIndex);
|
void findAvailableTasks();
|
void scheduleTask(int threadIndex);
|
void executeTask(int threadIndex);
|
void finishRendering(Task &pixelTask);
|
|
void processPrimitiveVertices(int unit, unsigned int start, unsigned int count, unsigned int loop, int thread);
|
|
int setupSolidTriangles(int batch, int count);
|
int setupWireframeTriangle(int batch, int count);
|
int setupVertexTriangle(int batch, int count);
|
int setupLines(int batch, int count);
|
int setupPoints(int batch, int count);
|
|
bool setupLine(Primitive &primitive, Triangle &triangle, const DrawCall &draw);
|
bool setupPoint(Primitive &primitive, Triangle &triangle, const DrawCall &draw);
|
|
bool isReadWriteTexture(int sampler);
|
void updateClipper();
|
void updateConfiguration(bool initialUpdate = false);
|
void initializeThreads();
|
void terminateThreads();
|
|
void loadConstants(const VertexShader *vertexShader);
|
void loadConstants(const PixelShader *pixelShader);
|
|
Context *context;
|
Clipper *clipper;
|
Blitter *blitter;
|
Viewport viewport;
|
Rect scissor;
|
int clipFlags;
|
|
Triangle *triangleBatch[16];
|
Primitive *primitiveBatch[16];
|
|
// User-defined clipping planes
|
Plane userPlane[MAX_CLIP_PLANES];
|
Plane clipPlane[MAX_CLIP_PLANES]; // Tranformed to clip space
|
bool updateClipPlanes;
|
|
AtomicInt exitThreads;
|
AtomicInt threadsAwake;
|
Thread *worker[16];
|
Event *resume[16]; // Events for resuming threads
|
Event *suspend[16]; // Events for suspending threads
|
Event *resumeApp; // Event for resuming the application thread
|
|
PrimitiveProgress primitiveProgress[16];
|
PixelProgress pixelProgress[16];
|
Task task[16]; // Current tasks for threads
|
|
enum {
|
DRAW_COUNT = 16, // Number of draw calls buffered (must be power of 2)
|
DRAW_COUNT_BITS = DRAW_COUNT - 1,
|
};
|
DrawCall *drawCall[DRAW_COUNT];
|
DrawCall *drawList[DRAW_COUNT];
|
|
AtomicInt currentDraw;
|
AtomicInt nextDraw;
|
|
enum {
|
TASK_COUNT = 32, // Size of the task queue (must be power of 2)
|
TASK_COUNT_BITS = TASK_COUNT - 1,
|
};
|
Task taskQueue[TASK_COUNT];
|
AtomicInt qHead;
|
AtomicInt qSize;
|
|
static AtomicInt unitCount;
|
static AtomicInt clusterCount;
|
|
MutexLock schedulerMutex;
|
|
#if PERF_HUD
|
int64_t vertexTime[16];
|
int64_t setupTime[16];
|
int64_t pixelTime[16];
|
#endif
|
|
VertexTask *vertexTask[16];
|
|
SwiftConfig *swiftConfig;
|
|
std::list<Query*> queries;
|
Resource *sync;
|
|
VertexProcessor::State vertexState;
|
SetupProcessor::State setupState;
|
PixelProcessor::State pixelState;
|
|
Routine *vertexRoutine;
|
Routine *setupRoutine;
|
Routine *pixelRoutine;
|
};
|
|
struct DrawCall
|
{
|
DrawCall();
|
|
~DrawCall();
|
|
AtomicInt drawType;
|
AtomicInt batchSize;
|
|
Routine *vertexRoutine;
|
Routine *setupRoutine;
|
Routine *pixelRoutine;
|
|
VertexProcessor::RoutinePointer vertexPointer;
|
SetupProcessor::RoutinePointer setupPointer;
|
PixelProcessor::RoutinePointer pixelPointer;
|
|
int (Renderer::*setupPrimitives)(int batch, int count);
|
SetupProcessor::State setupState;
|
|
Resource *vertexStream[MAX_VERTEX_INPUTS];
|
Resource *indexBuffer;
|
Surface *renderTarget[RENDERTARGETS];
|
Surface *depthBuffer;
|
Surface *stencilBuffer;
|
Resource *texture[TOTAL_IMAGE_UNITS];
|
Resource* pUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];
|
Resource* vUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];
|
Resource* transformFeedbackBuffers[MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS];
|
|
unsigned int vsDirtyConstF;
|
unsigned int vsDirtyConstI;
|
unsigned int vsDirtyConstB;
|
|
unsigned int psDirtyConstF;
|
unsigned int psDirtyConstI;
|
unsigned int psDirtyConstB;
|
|
std::list<Query*> *queries;
|
|
AtomicInt clipFlags;
|
|
AtomicInt primitive; // Current primitive to enter pipeline
|
AtomicInt count; // Number of primitives to render
|
AtomicInt references; // Remaining references to this draw call, 0 when done drawing, -1 when resources unlocked and slot is free
|
|
DrawData *data;
|
};
|
}
|
|
#endif // sw_Renderer_hpp
|