| // 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 |