|  | // 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; | 
|  |  | 
|  | std::shared_ptr<Routine> vertexRoutine; | 
|  | std::shared_ptr<Routine> setupRoutine; | 
|  | std::shared_ptr<Routine> pixelRoutine; | 
|  | }; | 
|  |  | 
|  | struct DrawCall | 
|  | { | 
|  | DrawCall(); | 
|  |  | 
|  | ~DrawCall(); | 
|  |  | 
|  | AtomicInt drawType; | 
|  | AtomicInt batchSize; | 
|  |  | 
|  | std::shared_ptr<Routine> vertexRoutine; | 
|  | std::shared_ptr<Routine> setupRoutine; | 
|  | std::shared_ptr<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 |