mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:44:02 +02:00
Adding the State to gpu and wiring the pipeline in glBackend to potentially make it work soon :)
This commit is contained in:
parent
69667fb5ca
commit
19a96c4815
12 changed files with 578 additions and 94 deletions
|
@ -82,6 +82,15 @@ public:
|
|||
return reinterpret_cast<T*>(pipeline.getGPUObject());
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
static void setGPUObject(const State& state, T* so) {
|
||||
state.setGPUObject(so);
|
||||
}
|
||||
template< typename T >
|
||||
static T* getGPUObject(const State& state) {
|
||||
return reinterpret_cast<T*>(state.getGPUObject());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
|
||||
namespace gpu {
|
||||
|
||||
class GPUObject;
|
||||
|
||||
typedef int Stamp;
|
||||
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
typedef unsigned short uint16;
|
||||
|
|
|
@ -79,18 +79,61 @@ public:
|
|||
public:
|
||||
class Command {
|
||||
public:
|
||||
typedef void *GlFunction(GLenum);
|
||||
|
||||
GlFunction _glFunction;
|
||||
GLenum _enum;
|
||||
|
||||
void run() { _glFunction(_enum); }
|
||||
virtual void run() = 0;
|
||||
|
||||
Command() {}
|
||||
virtual ~Command() {};
|
||||
};
|
||||
|
||||
typedef std::vector< Command > Commands;
|
||||
template <class T> class Command1 : public Command {
|
||||
public:
|
||||
typedef void (*GLFunction)(typename T);
|
||||
|
||||
void run() { (_func)(_param); }
|
||||
|
||||
Command1(GLFunction func, T param) : _func(func), _param(param) {};
|
||||
|
||||
GLFunction _func;
|
||||
T _param;
|
||||
};
|
||||
template <class T, class U> class Command2 : public Command {
|
||||
public:
|
||||
typedef void (*GLFunction)(typename T, typename U);
|
||||
|
||||
void run() { (_func)(_param0, _param1); }
|
||||
|
||||
Command2(GLFunction func, T param0, U param1) : _func(func), _param0(param0), _param1(param1) {};
|
||||
|
||||
GLFunction _func;
|
||||
T _param0;
|
||||
U _param1;
|
||||
};
|
||||
|
||||
template <class T, class U, class V, class W> class Command4 : public Command {
|
||||
public:
|
||||
typedef void (*GLFunction)(typename T, typename U, typename V, typename W);
|
||||
|
||||
void run() { (_func)(_param0, _param1, _param2, _param3); }
|
||||
|
||||
Command4(GLFunction func, T param0, U param1, V param2, W param3) :
|
||||
_func(func),
|
||||
_param0(param0),
|
||||
_param1(param1),
|
||||
_param2(param2),
|
||||
_param3(param3) {};
|
||||
|
||||
GLFunction _func;
|
||||
T _param0;
|
||||
U _param1;
|
||||
V _param2;
|
||||
W _param3;
|
||||
};
|
||||
typedef std::shared_ptr< Command > CommandPointer;
|
||||
typedef std::vector< CommandPointer > Commands;
|
||||
|
||||
Commands _commands;
|
||||
|
||||
Stamp _stamp;
|
||||
|
||||
GLState();
|
||||
~GLState();
|
||||
|
@ -100,6 +143,7 @@ public:
|
|||
class GLPipeline : public GPUObject {
|
||||
public:
|
||||
GLShader* _program;
|
||||
GLState* _state;
|
||||
|
||||
GLPipeline();
|
||||
~GLPipeline();
|
||||
|
@ -203,14 +247,19 @@ protected:
|
|||
GLuint _program;
|
||||
bool _invalidProgram;
|
||||
|
||||
State _state;
|
||||
GLState::Commands _stateCommands;
|
||||
bool _invalidState;
|
||||
|
||||
PipelineStageState() :
|
||||
_pipeline(),
|
||||
_program(0),
|
||||
_invalidProgram(false)
|
||||
_invalidProgram(false),
|
||||
_state(),
|
||||
_invalidState(false)
|
||||
{}
|
||||
} _pipeline;
|
||||
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
using namespace gpu;
|
||||
|
||||
GLBackend::GLPipeline::GLPipeline() :
|
||||
_program(nullptr)
|
||||
_program(nullptr),
|
||||
_state(nullptr)
|
||||
{}
|
||||
|
||||
GLBackend::GLPipeline::~GLPipeline() {
|
||||
_program = nullptr;
|
||||
_state = nullptr;
|
||||
}
|
||||
|
||||
GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) {
|
||||
|
@ -30,7 +32,29 @@ GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) {
|
|||
return object;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
// No object allocated yet, let's see if it's worth it...
|
||||
ShaderPointer shader = pipeline.getProgram();
|
||||
GLShader* programObject = GLBackend::syncGPUObject((*shader));
|
||||
if (programObject == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StatePointer state = pipeline.getState();
|
||||
GLState* stateObject = GLBackend::syncGPUObject((*state));
|
||||
if (stateObject == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Program and state are valid, we can create the pipeline object
|
||||
if (!object) {
|
||||
object = new GLPipeline();
|
||||
Backend::setGPUObject(pipeline, object);
|
||||
}
|
||||
|
||||
object->_program = programObject;
|
||||
object->_state = stateObject;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
|
||||
|
@ -46,8 +70,15 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) {
|
|||
}
|
||||
|
||||
_pipeline._pipeline = pipeline;
|
||||
_pipeline._program = pipelineObject->_program->_program;
|
||||
_pipeline._invalidProgram = true;
|
||||
|
||||
if (_pipeline._program != pipelineObject->_program->_program) {
|
||||
_pipeline._program = pipelineObject->_program->_program;
|
||||
_pipeline._invalidProgram = true;
|
||||
}
|
||||
|
||||
_pipeline._stateCommands = pipelineObject->_state->_commands;
|
||||
_pipeline._invalidState = true;
|
||||
|
||||
}
|
||||
|
||||
void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {
|
||||
|
@ -86,8 +117,15 @@ void GLBackend::updatePipeline() {
|
|||
if (_pipeline._invalidProgram) {
|
||||
glUseProgram(_pipeline._program);
|
||||
CHECK_GL_ERROR();
|
||||
_pipeline._invalidProgram = false;
|
||||
}
|
||||
|
||||
_pipeline._invalidProgram = true;
|
||||
if (_pipeline._invalidState) {
|
||||
for (auto command: _pipeline._stateCommands) {
|
||||
command->run();
|
||||
}
|
||||
CHECK_GL_ERROR();
|
||||
_pipeline._invalidState = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
356
libraries/gpu/src/gpu/GLBackendState.cpp
Normal file
356
libraries/gpu/src/gpu/GLBackendState.cpp
Normal file
|
@ -0,0 +1,356 @@
|
|||
//
|
||||
// GLBackendState.cpp
|
||||
// libraries/gpu/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 3/22/2015.
|
||||
// Copyright 2014 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "GLBackendShared.h"
|
||||
|
||||
#include "Format.h"
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
GLBackend::GLState::GLState()
|
||||
{}
|
||||
|
||||
GLBackend::GLState::~GLState() {
|
||||
}
|
||||
|
||||
|
||||
typedef GLBackend::GLState::Command Command;
|
||||
typedef GLBackend::GLState::CommandPointer CommandPointer;
|
||||
typedef GLBackend::GLState::Command1<GLenum> Command1E;
|
||||
typedef GLBackend::GLState::Command2<GLenum, GLenum> Command2E;
|
||||
typedef GLBackend::GLState::Command2<GLfloat, GLfloat> Command2F;
|
||||
typedef GLBackend::GLState::Command4<GLenum, GLenum, GLenum, GLenum> Command4E;
|
||||
typedef GLBackend::GLState::Command4<GLfloat, GLfloat, GLfloat, GLfloat> Command4F;
|
||||
typedef GLBackend::GLState::Command4<GLboolean, GLboolean, GLboolean, GLboolean> Command4B;
|
||||
|
||||
static GLenum GL_COMPARISON_FUNCTIONS[] = {
|
||||
GL_NEVER,
|
||||
GL_LESS,
|
||||
GL_EQUAL,
|
||||
GL_LEQUAL,
|
||||
GL_GREATER,
|
||||
GL_NOTEQUAL,
|
||||
GL_GEQUAL,
|
||||
GL_ALWAYS };
|
||||
|
||||
void glBackend_glPolygonMode(GLenum fillMode) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, fillMode);
|
||||
}
|
||||
|
||||
void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) {
|
||||
static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL };
|
||||
commands.push_back(CommandPointer(new Command1E(glBackend_glPolygonMode, GL_FILL_MODES[fillMode])));
|
||||
}
|
||||
|
||||
void generateCullMode(GLBackend::GLState::Commands& commands, State::CullMode cullMode) {
|
||||
static GLenum CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK };
|
||||
if (cullMode == State::CULL_NONE) {
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_CULL_FACE))));
|
||||
} else {
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_CULL_FACE))));
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glCullFace, CULL_MODES[cullMode])));
|
||||
}
|
||||
}
|
||||
|
||||
void generateDepthBias(GLBackend::GLState::Commands& commands, const State& state) {
|
||||
if ((state.getDepthBias() == 0) && (state.getDepthBiasSlopeScale() == 0.0f)) {
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_FILL))));
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_LINE))));
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_POINT))));
|
||||
} else {
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_FILL))));
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_LINE))));
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_POINT))));
|
||||
commands.push_back(CommandPointer(new Command2F((Command2F::GLFunction)glPolygonOffset,
|
||||
state.getDepthBiasSlopeScale(),
|
||||
state.getDepthBias())));
|
||||
}
|
||||
}
|
||||
|
||||
void generateFrontClockwise(GLBackend::GLState::Commands& commands, bool frontClockwise) {
|
||||
static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW };
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glFrontFace, GL_FRONT_FACES[frontClockwise])));
|
||||
}
|
||||
|
||||
#define ADD_ENABLE_DISABLE_COMMAND( NAME ) if (enable) {\
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, NAME)));\
|
||||
} else {\
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, NAME)));\
|
||||
}
|
||||
|
||||
void generateDepthClipEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_DEPTH_CLAMP);
|
||||
}
|
||||
|
||||
void generateScissorEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
void generateMultisampleEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_MULTISAMPLE);
|
||||
}
|
||||
|
||||
void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_POINT_SMOOTH);
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
void generateDepthEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void generateDepthWriteMask(GLBackend::GLState::Commands& commands, bool write) {
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthMask, write)));
|
||||
}
|
||||
|
||||
void generateDepthFunc(GLBackend::GLState::Commands& commands, State::ComparisonFunction function) {
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthFunc, GL_COMPARISON_FUNCTIONS[function])));
|
||||
}
|
||||
|
||||
void generateStencilEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
void generateStencilWriteMask(GLBackend::GLState::Commands& commands, uint32 mask) {
|
||||
commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glStencilMask, mask)));
|
||||
}
|
||||
|
||||
void generateStencilState(GLBackend::GLState::Commands& commands, const State& state) {
|
||||
auto frontTest(state.getStencilTestFront());
|
||||
auto backTest(state.getStencilTestBack());
|
||||
|
||||
commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glBlendEquationSeparate,
|
||||
GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest._function], state.getStencilReference(), state.getStencilReadMask())));
|
||||
commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glBlendEquationSeparate,
|
||||
GL_BACK, GL_COMPARISON_FUNCTIONS[backTest._function], state.getStencilReference(), state.getStencilReadMask())));
|
||||
|
||||
static GLenum STENCIL_OPS[] = {
|
||||
GL_KEEP,
|
||||
GL_ZERO,
|
||||
GL_REPLACE,
|
||||
GL_INCR_WRAP,
|
||||
GL_DECR_WRAP,
|
||||
GL_INVERT,
|
||||
GL_INCR,
|
||||
GL_DECR };
|
||||
|
||||
commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glStencilOpSeparate,
|
||||
GL_FRONT, STENCIL_OPS[frontTest._failOp], STENCIL_OPS[frontTest._passOp], STENCIL_OPS[frontTest._depthFailOp])));
|
||||
commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glStencilOpSeparate,
|
||||
GL_BACK, STENCIL_OPS[backTest._failOp], STENCIL_OPS[backTest._passOp], STENCIL_OPS[backTest._depthFailOp])));
|
||||
}
|
||||
|
||||
void generateAlphaToCoverageEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||
}
|
||||
|
||||
void generateBlendEnable(GLBackend::GLState::Commands& commands, bool enable) {
|
||||
ADD_ENABLE_DISABLE_COMMAND(GL_BLEND);
|
||||
}
|
||||
|
||||
void generateBlendFunction(GLBackend::GLState::Commands& commands, const State& state) {
|
||||
static GLenum GL_BLEND_OPS[] = {
|
||||
GL_FUNC_ADD,
|
||||
GL_FUNC_SUBTRACT,
|
||||
GL_FUNC_REVERSE_SUBTRACT,
|
||||
GL_MIN,
|
||||
GL_MAX };
|
||||
|
||||
auto colorFunction = state.getBlendFunctionColor();
|
||||
auto alphaFunction = state.getBlendFunctionColor();
|
||||
|
||||
commands.push_back(CommandPointer(new Command2E((Command2E::GLFunction)glBlendEquationSeparate,
|
||||
GL_BLEND_OPS[colorFunction._operation],
|
||||
GL_BLEND_OPS[alphaFunction._operation])));
|
||||
|
||||
static GLenum BLEND_ARGS[] = {
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_SRC_COLOR,
|
||||
GL_ONE_MINUS_SRC_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA,
|
||||
GL_DST_ALPHA,
|
||||
GL_ONE_MINUS_DST_ALPHA,
|
||||
GL_DST_COLOR,
|
||||
GL_ONE_MINUS_DST_COLOR,
|
||||
GL_SRC_ALPHA_SATURATE,
|
||||
GL_CONSTANT_COLOR,
|
||||
GL_ONE_MINUS_CONSTANT_COLOR
|
||||
};
|
||||
|
||||
commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glBlendFuncSeparate,
|
||||
BLEND_ARGS[colorFunction._source],
|
||||
BLEND_ARGS[colorFunction._destination],
|
||||
BLEND_ARGS[alphaFunction._source],
|
||||
BLEND_ARGS[alphaFunction._destination])));
|
||||
}
|
||||
|
||||
void generateBlendFactor(GLBackend::GLState::Commands& commands, const Vec4& factor) {
|
||||
commands.push_back(CommandPointer(new Command4F((Command4F::GLFunction)glBlendColor,
|
||||
factor.x, factor.y, factor.z, factor.w)));
|
||||
}
|
||||
|
||||
void generateColorWriteMask(GLBackend::GLState::Commands& commands, State::ColorMask mask) {
|
||||
commands.push_back(CommandPointer(new Command4B((Command4B::GLFunction)glColorMask,
|
||||
mask & State::ColorMask::WRITE_RED,
|
||||
mask & State::ColorMask::WRITE_GREEN,
|
||||
mask & State::ColorMask::WRITE_BLUE,
|
||||
mask & State::ColorMask::WRITE_ALPHA )));
|
||||
}
|
||||
|
||||
GLBackend::GLState* GLBackend::syncGPUObject(const State& state) {
|
||||
GLState* object = Backend::getGPUObject<GLBackend::GLState>(state);
|
||||
|
||||
// If GPU object already created then good
|
||||
if (object) {
|
||||
if (object->_stamp == state.getStamp()) {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
// Else allocate and create the GLState
|
||||
if (!object) {
|
||||
object = new GLState();
|
||||
Backend::setGPUObject(state, object);
|
||||
}
|
||||
|
||||
// here, we need to regenerate something so let's do it all
|
||||
object->_commands.clear();
|
||||
object->_stamp = state.getStamp();
|
||||
|
||||
bool depthBias = false;
|
||||
|
||||
bool depthEnabled = false;
|
||||
bool depthState = false;
|
||||
|
||||
bool stencilEnabled = false;
|
||||
bool stencilState = false;
|
||||
|
||||
bool blendEnabled = false;
|
||||
bool blendFunction = false;
|
||||
bool blendFactor = false;
|
||||
|
||||
// go thorugh the list of state fields in the State and record the corresponding gl command
|
||||
for (auto field: state.getFields()) {
|
||||
switch(field.first) {
|
||||
case State::FILL_MODE: {
|
||||
generateFillMode(object->_commands, State::FillMode(field.second._integer));
|
||||
break;
|
||||
}
|
||||
case State::CULL_MODE: {
|
||||
generateCullMode(object->_commands, State::CullMode(field.second._integer));
|
||||
break;
|
||||
}
|
||||
case State::DEPTH_BIAS:
|
||||
case State::DEPTH_BIAS_SLOPE_SCALE: {
|
||||
depthBias = true;
|
||||
break;
|
||||
}
|
||||
case State::FRONT_CLOCKWISE: {
|
||||
generateFrontClockwise(object->_commands, bool(field.second._integer));
|
||||
break;
|
||||
}
|
||||
case State::DEPTH_CLIP_ENABLE: {
|
||||
generateDepthClipEnable(object->_commands, bool(field.second._integer));
|
||||
break;
|
||||
}
|
||||
case State::SCISSOR_ENABLE: {
|
||||
generateScissorEnable(object->_commands, bool(field.second._integer));
|
||||
break;
|
||||
}
|
||||
case State::MULTISAMPLE_ENABLE: {
|
||||
generateMultisampleEnable(object->_commands, bool(field.second._integer));
|
||||
break;
|
||||
}
|
||||
case State::ANTIALISED_LINE_ENABLE: {
|
||||
generateAntialiasedLineEnable(object->_commands, bool(field.second._integer));
|
||||
break;
|
||||
}
|
||||
|
||||
case State::DEPTH_ENABLE: {
|
||||
depthEnabled = bool(field.second._integer);
|
||||
generateDepthEnable(object->_commands, depthEnabled);
|
||||
break;
|
||||
}
|
||||
case State::DEPTH_WRITE_MASK:
|
||||
case State::DEPTH_FUNC: {
|
||||
depthState = true;
|
||||
break;
|
||||
}
|
||||
case State::STENCIL_ENABLE: {
|
||||
stencilEnabled = bool(field.second._integer);
|
||||
generateStencilEnable(object->_commands, stencilEnabled);
|
||||
break;
|
||||
}
|
||||
case State::STENCIL_WRITE_MASK:
|
||||
case State::STENCIL_READ_MASK:
|
||||
case State::STENCIL_REFERENCE:
|
||||
case State::STENCIL_TEST_FRONT:
|
||||
case State::STENCIL_TEST_BACK: {
|
||||
stencilState = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case State::SAMPLE_MASK: {
|
||||
break;
|
||||
}
|
||||
case State::ALPHA_TO_COVERAGE_ENABLE: {
|
||||
generateAlphaToCoverageEnable(object->_commands, bool(field.second._integer));
|
||||
break;
|
||||
}
|
||||
|
||||
case State::BLEND_ENABLE: {
|
||||
blendEnabled = field.second._integer;
|
||||
generateBlendEnable(object->_commands, blendEnabled);
|
||||
break;
|
||||
}
|
||||
case State::BLEND_FUNCTION_COLOR:
|
||||
case State::BLEND_FUNCTION_ALPHA: {
|
||||
blendFunction = true;
|
||||
break;
|
||||
}
|
||||
case State::BLEND_FACTOR_X:
|
||||
case State::BLEND_FACTOR_Y:
|
||||
case State::BLEND_FACTOR_Z:
|
||||
case State::BLEND_FACTOR_W: {
|
||||
blendFactor = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case State::COLOR_WRITE_MASK: {
|
||||
generateColorWriteMask(object->_commands, State::ColorMask(field.second._integer));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (depthBias) {
|
||||
generateDepthBias(object->_commands, state);
|
||||
}
|
||||
|
||||
if (depthEnabled) {
|
||||
generateDepthWriteMask(object->_commands, state.getDepthWriteMask());
|
||||
generateDepthFunc(object->_commands, state.getDepthFunc());
|
||||
}
|
||||
|
||||
if (stencilEnabled) {
|
||||
generateStencilState(object->_commands, state);
|
||||
generateStencilWriteMask(object->_commands, state.getStencilWriteMask());
|
||||
}
|
||||
|
||||
if (blendEnabled) {
|
||||
generateBlendFunction(object->_commands, state);
|
||||
generateBlendFactor(object->_commands, state.getBlendFactor());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
|
@ -17,7 +17,7 @@ using namespace gpu;
|
|||
|
||||
Pipeline::Pipeline():
|
||||
_program(),
|
||||
_states()
|
||||
_state()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,10 @@ Pipeline::~Pipeline()
|
|||
{
|
||||
}
|
||||
|
||||
Pipeline* Pipeline::create(const ShaderPointer& program, const States& states) {
|
||||
Pipeline* Pipeline::create(const ShaderPointer& program, const StatePointer& state) {
|
||||
Pipeline* pipeline = new Pipeline();
|
||||
pipeline->_program = program;
|
||||
pipeline->_states = states;
|
||||
pipeline->_state = state;
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
|
|
@ -22,16 +22,16 @@ namespace gpu {
|
|||
|
||||
class Pipeline {
|
||||
public:
|
||||
static Pipeline* create(const ShaderPointer& program, const States& states);
|
||||
static Pipeline* create(const ShaderPointer& program, const StatePointer& state);
|
||||
~Pipeline();
|
||||
|
||||
const ShaderPointer& getProgram() const { return _program; }
|
||||
|
||||
const States& getStates() const { return _states; }
|
||||
const StatePointer& getState() const { return _state; }
|
||||
|
||||
protected:
|
||||
ShaderPointer _program;
|
||||
States _states;
|
||||
StatePointer _state;
|
||||
|
||||
Pipeline();
|
||||
Pipeline(const Pipeline& pipeline); // deep copy of the sysmem shader
|
||||
|
|
|
@ -24,10 +24,6 @@
|
|||
|
||||
namespace gpu {
|
||||
|
||||
class GPUObject;
|
||||
|
||||
typedef int Stamp;
|
||||
|
||||
class Resource {
|
||||
public:
|
||||
typedef unsigned char Byte;
|
||||
|
|
|
@ -22,21 +22,25 @@ State::~State()
|
|||
void State::set(Field field, bool value) {
|
||||
auto found = _fields.at(field);
|
||||
found._integer = value;
|
||||
_stamp++;
|
||||
}
|
||||
|
||||
void State::set(Field field, uint32 value) {
|
||||
auto found = _fields.at(field);
|
||||
found._unsigned_integer = value;
|
||||
_stamp++;
|
||||
}
|
||||
|
||||
void State::set(Field field, int32 value) {
|
||||
auto found = _fields.at(field);
|
||||
found._integer = value;
|
||||
_stamp++;
|
||||
}
|
||||
|
||||
void State::set(Field field, float value) {
|
||||
auto found = _fields.at(field);
|
||||
found._float = value;
|
||||
_stamp++;
|
||||
}
|
||||
|
||||
State::Value State::get(Field field) const {
|
||||
|
|
|
@ -26,12 +26,14 @@ public:
|
|||
State() {}
|
||||
virtual ~State();
|
||||
|
||||
const Stamp getStamp() const { return _stamp; }
|
||||
|
||||
// All the possible fields
|
||||
enum Field {
|
||||
FILL_MODE,
|
||||
CULL_MODE,
|
||||
|
||||
DEPTH_BIAS,
|
||||
DEPTH_BIAS_CLAMP,
|
||||
DEPTH_BIAS_SLOPE_SCALE,
|
||||
|
||||
FRONT_CLOCKWISE,
|
||||
|
@ -47,37 +49,22 @@ public:
|
|||
STENCIL_ENABLE,
|
||||
STENCIL_READ_MASK,
|
||||
STENCIL_WRITE_MASK,
|
||||
|
||||
STENCIL_FUNC_FRONT,
|
||||
STENCIL_FRONT_FUNC,
|
||||
STENCIL_FRONT_FAIL_OP,
|
||||
STENCIL_FRONT_DEPTH_FAIL_OP,
|
||||
STENCIL_FRONT_PASS_OP,
|
||||
|
||||
STENCIL_BACK_FUNC,
|
||||
STENCIL_BACK_FAIL_OP,
|
||||
STENCIL_BACK_DEPTH_FAIL_OP,
|
||||
STENCIL_BACK_PASS_OP,
|
||||
STENCIL_FUNC_BACK,
|
||||
|
||||
STENCIL_TEST_FRONT,
|
||||
STENCIL_TEST_BACK,
|
||||
STENCIL_REFERENCE,
|
||||
|
||||
SAMPLE_MASK,
|
||||
ALPHA_TO_COVERAGE_ENABLE,
|
||||
|
||||
BLEND_ENABLE,
|
||||
BLEND_FUNCTION_COLOR,
|
||||
BLEND_FUNCTION_ALPHA,
|
||||
BLEND_FACTOR_X,
|
||||
BLEND_FACTOR_Y,
|
||||
BLEND_FACTOR_Z,
|
||||
BLEND_FACTOR_W,
|
||||
|
||||
BLEND_INDEPENDANT_ENABLE,
|
||||
BLEND_ENABLE,
|
||||
BLEND_SOURCE,
|
||||
BLEND_DESTINATION,
|
||||
BLEND_OPERATION,
|
||||
BLEND_SOURCE_ALPHA,
|
||||
BLEND_DESTINATION_ALPHA,
|
||||
BLEND_OPERATION_ALPHA,
|
||||
BLEND_WRITE_MASK,
|
||||
|
||||
COLOR_WRITE_MASK,
|
||||
|
||||
NUM_FIELDS, // not a valid field, just the count
|
||||
};
|
||||
|
@ -138,10 +125,6 @@ public:
|
|||
SRC_ALPHA_SAT,
|
||||
BLEND_FACTOR,
|
||||
INV_BLEND_FACTOR,
|
||||
SRC1_COLOR,
|
||||
INV_SRC1_COLOR,
|
||||
SRC1_ALPHA,
|
||||
INV_SRC1_ALPHA,
|
||||
|
||||
NUM_BLEND_ARGS,
|
||||
};
|
||||
|
@ -166,6 +149,33 @@ public:
|
|||
WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ),
|
||||
};
|
||||
|
||||
class StencilTest {
|
||||
public:
|
||||
int8 _failOp = STENCIL_OP_KEEP;
|
||||
int8 _depthFailOp = STENCIL_OP_KEEP;
|
||||
int8 _passOp = STENCIL_OP_KEEP;
|
||||
int8 _function = ALWAYS;
|
||||
|
||||
StencilTest(StencilOp failOp, StencilOp depthFailOp, StencilOp passOp, ComparisonFunction func) :
|
||||
_failOp(failOp), _depthFailOp(depthFailOp), _passOp(passOp), _function(func) {}
|
||||
|
||||
int32 raw() const { return *(reinterpret_cast<const int32*>(this)); }
|
||||
StencilTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
|
||||
};
|
||||
|
||||
class BlendFunction {
|
||||
public:
|
||||
int8 _source = ONE;
|
||||
int8 _operation = BLEND_OP_ADD;
|
||||
int8 _destination = ZERO;
|
||||
int8 _spare = 0;
|
||||
|
||||
BlendFunction(BlendArg source, BlendOp operation, BlendArg destination) :
|
||||
_source(source), _operation(operation), _destination(destination) {}
|
||||
|
||||
int32 raw() const { return *(reinterpret_cast<const int32*>(this)); }
|
||||
BlendFunction(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
|
||||
};
|
||||
|
||||
class Value {
|
||||
public:
|
||||
|
@ -177,6 +187,8 @@ public:
|
|||
};
|
||||
typedef std::unordered_map<Field, Value> FieldMap;
|
||||
|
||||
const FieldMap& getFields() const { return _fields; }
|
||||
|
||||
void set(Field field, bool value);
|
||||
void set(Field field, uint32 value);
|
||||
void set(Field field, int32 value);
|
||||
|
@ -189,11 +201,9 @@ public:
|
|||
FillMode getFillMode() const { return FillMode(get(FILL_MODE)._integer); }
|
||||
CullMode getCullMode() const { return CullMode(get(CULL_MODE)._integer); }
|
||||
|
||||
void setDepthBias(int32 bias) { set(DEPTH_BIAS, bias); }
|
||||
void setDepthBiasClamp(float clamp) { set(DEPTH_BIAS_CLAMP, clamp); }
|
||||
void setDepthBias(float bias) { set(DEPTH_BIAS, bias); }
|
||||
void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, scale); }
|
||||
int32 getDepthBias() const { return get(DEPTH_BIAS)._integer; }
|
||||
float getDepthBiasClamp() const { return get(DEPTH_BIAS_CLAMP)._float; }
|
||||
float getDepthBias() const { return get(DEPTH_BIAS)._integer; }
|
||||
float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE)._float; }
|
||||
|
||||
void setFrontClockwise(bool enable) { set(FRONT_CLOCKWISE, enable); }
|
||||
|
@ -221,23 +231,10 @@ public:
|
|||
uint8 getStencilReadMask() const { return get(STENCIL_READ_MASK)._unsigned_integer; }
|
||||
uint8 getStencilWriteMask() const { return get(STENCIL_WRITE_MASK)._unsigned_integer; }
|
||||
|
||||
void setStencilFrontFailOp(StencilOp op) { set(STENCIL_FRONT_FAIL_OP, op); }
|
||||
void setStencilFrontDepthFailOp(StencilOp op) { set(STENCIL_FRONT_DEPTH_FAIL_OP, op); }
|
||||
void setStencilFrontPassOp(StencilOp op) { set(STENCIL_FRONT_PASS_OP, op); }
|
||||
void setStencilFrontFunc(ComparisonFunction func) { set(STENCIL_FRONT_FUNC, func); }
|
||||
StencilOp getStencilFrontFailOp() const { return StencilOp(get(STENCIL_FRONT_FAIL_OP)._integer); }
|
||||
StencilOp getStencilFrontDepthFailOp() const { return StencilOp(get(STENCIL_FRONT_DEPTH_FAIL_OP)._integer); }
|
||||
StencilOp getStencilFrontPassOp() const { return StencilOp(get(STENCIL_FRONT_PASS_OP)._integer); }
|
||||
ComparisonFunction getStencilFrontFunc() const { return ComparisonFunction(get(STENCIL_FRONT_FUNC)._integer); }
|
||||
|
||||
void setStencilBackFailOp(StencilOp op) { set(STENCIL_BACK_FAIL_OP, op); }
|
||||
void setStencilBackDepthFailOp(StencilOp op) { set(STENCIL_BACK_DEPTH_FAIL_OP, op); }
|
||||
void setStencilBackPassOp(StencilOp op) { set(STENCIL_BACK_PASS_OP, op); }
|
||||
void setStencilBackFunc(ComparisonFunction func) { set(STENCIL_BACK_FUNC, func); }
|
||||
StencilOp getStencilBackFailOp() const { return StencilOp(get(STENCIL_BACK_FAIL_OP)._integer); }
|
||||
StencilOp getStencilBackDepthFailOp() const { return StencilOp(get(STENCIL_BACK_DEPTH_FAIL_OP)._integer); }
|
||||
StencilOp getStencilBackPassOp() const { return StencilOp(get(STENCIL_BACK_PASS_OP)._integer); }
|
||||
ComparisonFunction getStencilBackFunc() const { return ComparisonFunction(get(STENCIL_BACK_FUNC)._integer); }
|
||||
void setStencilTestFront(StencilTest test) { set(STENCIL_TEST_FRONT, test.raw()); }
|
||||
void setStencilTestBack(StencilTest test) { set(STENCIL_TEST_BACK, test.raw()); }
|
||||
StencilTest getStencilTestFront() const { return StencilTest(get(STENCIL_TEST_FRONT)._integer); }
|
||||
StencilTest getStencilTestBack() const { return StencilTest(get(STENCIL_TEST_BACK)._integer); }
|
||||
|
||||
void setStencilReference(uint32 ref) { set(STENCIL_REFERENCE, ref); }
|
||||
uint32 getStencilReference() const { return get(STENCIL_REFERENCE)._unsigned_integer; }
|
||||
|
@ -247,39 +244,30 @@ public:
|
|||
|
||||
void setSampleMask(uint32 mask) { set(SAMPLE_MASK, mask); }
|
||||
uint32 getSampleMask() const { return get(SAMPLE_MASK)._unsigned_integer; }
|
||||
|
||||
// void setBlendIndependantEnable(bool enable) { set(BLEND_INDEPENDANT_ENABLE, enable); }
|
||||
// bool getBlendIndependantEnable() const { return get(BLEND_INDEPENDANT_ENABLE)._integer; }
|
||||
|
||||
void setBlendEnable(bool enable) { set(BLEND_ENABLE, enable); }
|
||||
bool getBlendEnable() const { return get(BLEND_ENABLE)._integer; }
|
||||
|
||||
void setBlendSource(BlendArg source) { set(BLEND_SOURCE, source); }
|
||||
void setBlendDestination(BlendArg destination) { set(BLEND_DESTINATION, destination); }
|
||||
void setBlendOperation(BlendOp operation) { set(BLEND_OPERATION, operation); }
|
||||
BlendArg getBlendSource() const { return BlendArg(get(BLEND_SOURCE)._integer); }
|
||||
BlendArg getBlendDestination() const { return BlendArg(get(BLEND_DESTINATION)._integer); }
|
||||
BlendOp getBlendOperation() const { return BlendOp(get(BLEND_OPERATION)._integer); }
|
||||
|
||||
void setBlendSourceAlpha(BlendArg source) { set(BLEND_SOURCE_ALPHA, source); }
|
||||
void setBlendDestinationAlpha(BlendArg destination) { set(BLEND_DESTINATION_ALPHA, destination); }
|
||||
void setBlendOperationAlpha(BlendOp operation) { set(BLEND_OPERATION_ALPHA, operation); }
|
||||
BlendArg getBlendSourceAlpha() const { return BlendArg(get(BLEND_SOURCE_ALPHA)._integer); }
|
||||
BlendArg getBlendDestinationAlpha() const { return BlendArg(get(BLEND_DESTINATION_ALPHA)._integer); }
|
||||
BlendOp getBlendOperationAlpha() const { return BlendOp(get(BLEND_OPERATION_ALPHA)._integer); }
|
||||
|
||||
void setBlendWriteMask(ColorMask mask) { set(BLEND_WRITE_MASK, mask); }
|
||||
ColorMask getBlendWriteMask() const { return ColorMask(get(BLEND_WRITE_MASK)._integer); }
|
||||
|
||||
void setBlendFunctionColor(BlendFunction function) { set(BLEND_FUNCTION_COLOR, function.raw()); }
|
||||
BlendFunction getBlendFunctionColor() const { return BlendFunction(get(BLEND_FUNCTION_COLOR)._integer); }
|
||||
void setBlendFunctionAlpha(BlendFunction function) { set(BLEND_FUNCTION_ALPHA, function.raw()); }
|
||||
BlendFunction getBlendFunctionAlpha() const { return BlendFunction(get(BLEND_FUNCTION_ALPHA)._integer); }
|
||||
|
||||
void setBlendFactor(const Vec4& factor) { set(BLEND_FACTOR_X, factor.x); set(BLEND_FACTOR_Y, factor.y); set(BLEND_FACTOR_Z, factor.z); set(BLEND_FACTOR_W, factor.w); }
|
||||
Vec4 getBlendFactor() const { return Vec4(get(BLEND_FACTOR_X)._float, get(BLEND_FACTOR_Y)._float, get(BLEND_FACTOR_Z)._float, get(BLEND_FACTOR_W)._float); }
|
||||
|
||||
|
||||
void setColorWriteMask(ColorMask mask) { set(COLOR_WRITE_MASK, mask); }
|
||||
ColorMask getColorWriteMask() const { return ColorMask(get(COLOR_WRITE_MASK)._integer); }
|
||||
|
||||
protected:
|
||||
State(const State& state);
|
||||
State& operator=(const State& state);
|
||||
|
||||
FieldMap _fields;
|
||||
|
||||
Stamp _stamp;
|
||||
|
||||
// This shouldn't be used by anything else than the Backend class with the proper casting.
|
||||
mutable GPUObject* _gpuObject = NULL;
|
||||
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
|
||||
|
|
|
@ -215,7 +215,13 @@ SunSkyStage::SunSkyStage() :
|
|||
auto skyFromAtmosphereVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(SkyFromAtmosphere_vert)));
|
||||
auto skyFromAtmosphereFragment = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(SkyFromAtmosphere_frag)));
|
||||
auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyFromAtmosphereVertex, skyFromAtmosphereFragment));
|
||||
_skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, gpu::States()));
|
||||
|
||||
auto skyState = gpu::StatePointer(new gpu::State());
|
||||
skyState->setDepthEnable(false);
|
||||
skyState->setStencilEnable(false);
|
||||
skyState->setBlendEnable(false);
|
||||
|
||||
_skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -318,6 +318,29 @@ private:
|
|||
int _blendNumber;
|
||||
int _appliedBlendNumber;
|
||||
|
||||
/*
|
||||
static gpu::PipelinePointer _program;
|
||||
static gpu::PipelinePointer _normalMapProgram;
|
||||
static gpu::PipelinePointer _specularMapProgram;
|
||||
static gpu::PipelinePointer _normalSpecularMapProgram;
|
||||
static gpu::PipelinePointer _translucentProgram;
|
||||
|
||||
static gpu::PipelinePointer _lightmapProgram;
|
||||
static gpu::PipelinePointer _lightmapNormalMapProgram;
|
||||
static gpu::PipelinePointer _lightmapSpecularMapProgram;
|
||||
static gpu::PipelinePointer _lightmapNormalSpecularMapProgram;
|
||||
|
||||
static gpu::PipelinePointer _shadowProgram;
|
||||
|
||||
static gpu::PipelinePointer _skinProgram;
|
||||
static gpu::PipelinePointer _skinNormalMapProgram;
|
||||
static gpu::PipelinePointer _skinSpecularMapProgram;
|
||||
static gpu::PipelinePointer _skinNormalSpecularMapProgram;
|
||||
static gpu::PipelinePointer _skinTranslucentProgram;
|
||||
|
||||
static gpu::PipelinePointer _skinShadowProgram;
|
||||
*/
|
||||
|
||||
static gpu::ShaderPointer _program;
|
||||
static gpu::ShaderPointer _normalMapProgram;
|
||||
static gpu::ShaderPointer _specularMapProgram;
|
||||
|
@ -473,6 +496,17 @@ private:
|
|||
|
||||
static AbstractViewStateInterface* _viewState;
|
||||
|
||||
/* class RenderKey {
|
||||
public:
|
||||
enum Flag {
|
||||
TRANSLUCENT = 0,
|
||||
HAS_LIGHTMAP,
|
||||
};
|
||||
|
||||
RenderMode mode;
|
||||
|
||||
};
|
||||
*/
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QPointer<Model>)
|
||||
|
|
Loading…
Reference in a new issue