blob: 4b964718ff0f5ecca6849b621ea212a949d59784 [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_Renderer_hpp
#define sw_Renderer_hpp
#include "VertexProcessor.hpp"
#include "PixelProcessor.hpp"
#include "SetupProcessor.hpp"
#include "Plane.hpp"
#include "Primitive.hpp"
#include "Blitter.hpp"
#include "Device/Config.hpp"
#include "Vulkan/VkDescriptorSet.hpp"
#include "Yarn/Pool.hpp"
#include "Yarn/Finally.hpp"
#include "Yarn/Ticket.hpp"
#include <atomic>
#include <list>
#include <mutex>
#include <thread>
namespace vk
{
class DescriptorSet;
class Device;
class Query;
}
namespace sw
{
struct DrawCall;
class PixelShader;
class VertexShader;
struct Task;
class TaskEvents;
class Resource;
struct Constants;
static constexpr int MaxBatchSize = 128;
static constexpr int MaxBatchCount = 16;
static constexpr int MaxClusterCount = 16;
static constexpr int MaxDrawCount = 16;
using TriangleBatch = std::array<Triangle, MaxBatchSize>;
using PrimitiveBatch = std::array<Primitive, MaxBatchSize>;
struct DrawData
{
const Constants *constants;
vk::DescriptorSet::Bindings descriptorSets = {};
vk::DescriptorSet::DynamicOffsets descriptorDynamicOffsets = {};
const void *input[MAX_INTERFACE_COMPONENTS / 4];
unsigned int stride[MAX_INTERFACE_COMPONENTS / 4];
const void *indices;
int instanceID;
int baseVertex;
float lineWidth;
int viewID;
PixelProcessor::Stencil stencil[2]; // clockwise, counterclockwise
PixelProcessor::Factor factor;
unsigned int occlusion[MaxClusterCount]; // Number of pixels passing depth test
float4 Wx16;
float4 Hx16;
float4 X0x16;
float4 Y0x16;
float4 halfPixelX;
float4 halfPixelY;
float viewportHeight;
float slopeDepthBias;
float depthRange;
float depthNear;
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;
PushConstantStorage pushConstants;
};
struct DrawCall
{
struct BatchData
{
using Pool = yarn::BoundedPool<BatchData, MaxBatchCount, yarn::PoolPolicy::Preserve>;
TriangleBatch triangles;
PrimitiveBatch primitives;
VertexTask vertexTask;
unsigned int id;
unsigned int firstPrimitive;
unsigned int numPrimitives;
int numVisible;
yarn::Ticket clusterTickets[MaxClusterCount];
};
using Pool = yarn::BoundedPool<DrawCall, MaxDrawCount, yarn::PoolPolicy::Preserve>;
using SetupFunction = int(*)(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count);
DrawCall();
~DrawCall();
static void run(const yarn::Loan<DrawCall>& draw, yarn::Ticket::Queue* tickets, yarn::Ticket::Queue clusterQueues[MaxClusterCount]);
static void processVertices(DrawCall* draw, BatchData* batch);
static void processPrimitives(DrawCall* draw, BatchData* batch);
static void processPixels(const yarn::Loan<DrawCall>& draw, const yarn::Loan<BatchData>& batch, const std::shared_ptr<yarn::Finally>& finally);
void setup();
void teardown();
int id;
BatchData::Pool *batchDataPool;
unsigned int numPrimitives;
unsigned int numPrimitivesPerBatch;
unsigned int numBatches;
VkPrimitiveTopology topology;
VkIndexType indexType;
std::shared_ptr<Routine> vertexRoutine;
std::shared_ptr<Routine> setupRoutine;
std::shared_ptr<Routine> pixelRoutine;
VertexProcessor::RoutinePointer vertexPointer;
SetupProcessor::RoutinePointer setupPointer;
PixelProcessor::RoutinePointer pixelPointer;
SetupFunction setupPrimitives;
SetupProcessor::State setupState;
vk::ImageView *renderTarget[RENDERTARGETS];
vk::ImageView *depthBuffer;
vk::ImageView *stencilBuffer;
TaskEvents *events;
vk::Query* occlusionQuery;
DrawData *data;
static void processPrimitiveVertices(
unsigned int triangleIndicesOut[MaxBatchSize + 1][3],
const void *primitiveIndices,
VkIndexType indexType,
unsigned int start,
unsigned int triangleCount,
VkPrimitiveTopology topology);
static int setupSolidTriangles(Triangle* triangles, Primitive* primitives, const DrawCall* drawCall, int count);
static int setupWireframeTriangles(Triangle* triangles, Primitive* primitives, const DrawCall* drawCall, int count);
static int setupPointTriangles(Triangle* triangles, Primitive* primitives, const DrawCall* drawCall, int count);
static int setupLines(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count);
static int setupPoints(Triangle *triangles, Primitive *primitives, const DrawCall *drawCall, int count);
static bool setupLine(Primitive &primitive, Triangle &triangle, const DrawCall &draw);
static bool setupPoint(Primitive &primitive, Triangle &triangle, const DrawCall &draw);
};
class Renderer : public VertexProcessor, public PixelProcessor, public SetupProcessor
{
public:
Renderer(vk::Device* device);
virtual ~Renderer();
bool hasOcclusionQuery() const { return occlusionQuery != nullptr; }
void draw(const sw::Context* context, VkIndexType indexType, unsigned int count, int baseVertex,
TaskEvents *events, int instanceID, int viewID, void *indexBuffer,
PushConstantStorage const & pushConstants, bool update = true);
// Viewport & Clipper
void setViewport(const VkViewport &viewport);
void setScissor(const VkRect2D &scissor);
void addQuery(vk::Query *query);
void removeQuery(vk::Query *query);
void advanceInstanceAttributes(Stream* inputs);
void synchronize();
private:
VkViewport viewport;
VkRect2D scissor;
DrawCall::Pool drawCallPool;
DrawCall::BatchData::Pool batchDataPool;
std::atomic<int> nextDrawID = {0};
vk::Query *occlusionQuery = nullptr;
yarn::Ticket::Queue drawTickets;
yarn::Ticket::Queue clusterQueues[MaxClusterCount];
VertexProcessor::State vertexState;
SetupProcessor::State setupState;
PixelProcessor::State pixelState;
std::shared_ptr<Routine> vertexRoutine;
std::shared_ptr<Routine> setupRoutine;
std::shared_ptr<Routine> pixelRoutine;
vk::Device* device;
};
}
#endif // sw_Renderer_hpp