mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-09 01:22:21 +02:00
Pass an explicit pipeline to render.*Instance calls
This commit is contained in:
parent
2af6c08057
commit
d14ce8a9fe
8 changed files with 103 additions and 67 deletions
|
@ -73,10 +73,12 @@ public:
|
|||
BufferPointers buffers;
|
||||
Function function;
|
||||
DrawCallInfoBuffer drawCallInfos;
|
||||
Pipeline::Pointer pipeline;
|
||||
|
||||
size_t count() const { return drawCallInfos.size(); }
|
||||
|
||||
void process(Batch& batch) {
|
||||
batch.setPipeline(pipeline);
|
||||
if (function) {
|
||||
function(batch, *this);
|
||||
}
|
||||
|
|
|
@ -494,10 +494,22 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
|
|||
return INSTANCED_SOLID_STREAM_FORMAT;
|
||||
}
|
||||
|
||||
render::ShapePipelinePointer GeometryCache::_simplePipeline;
|
||||
|
||||
GeometryCache::GeometryCache() :
|
||||
_nextID(0)
|
||||
{
|
||||
buildShapes();
|
||||
GeometryCache::_simplePipeline =
|
||||
std::make_shared<render::ShapePipeline>(getSimplePipeline(), nullptr,
|
||||
[](const render::ShapePipeline&, gpu::Batch& batch) {
|
||||
// Set the defaults needed for a simple program
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP,
|
||||
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
|
||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
GeometryCache::~GeometryCache() {
|
||||
|
@ -1781,7 +1793,23 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) {
|
|||
return a.getRaw() == b.getRaw();
|
||||
}
|
||||
|
||||
gpu::PipelinePointer GeometryCache::getPipeline(SimpleProgramKey config) {
|
||||
void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool emissive, bool depthBiased) {
|
||||
batch.setPipeline(getSimplePipeline(textured, culled, emissive, depthBiased));
|
||||
|
||||
// If not textured, set a default diffuse map
|
||||
if (!textured) {
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP,
|
||||
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
}
|
||||
// Set a default normal map
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
|
||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
|
||||
gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool emissive, bool depthBiased) {
|
||||
SimpleProgramKey config{textured, culled, emissive, depthBiased};
|
||||
|
||||
// Compile the shaders
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&]() {
|
||||
auto VS = gpu::Shader::createVertex(std::string(simple_vert));
|
||||
|
@ -1796,13 +1824,14 @@ gpu::PipelinePointer GeometryCache::getPipeline(SimpleProgramKey config) {
|
|||
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
|
||||
gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
|
||||
});
|
||||
|
||||
|
||||
|
||||
// If the pipeline already exists, return it
|
||||
auto it = _simplePrograms.find(config);
|
||||
if (it != _simplePrograms.end()) {
|
||||
return it.value();
|
||||
}
|
||||
|
||||
|
||||
// If the pipeline did not exist, make it
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
if (config.isCulled()) {
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
|
@ -1815,33 +1844,15 @@ gpu::PipelinePointer GeometryCache::getPipeline(SimpleProgramKey config) {
|
|||
state->setDepthBiasSlopeScale(1.0f);
|
||||
}
|
||||
state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
|
||||
gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state);
|
||||
_simplePrograms.insert(config, pipeline);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
gpu::PipelinePointer GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled,
|
||||
bool emissive, bool depthBias) {
|
||||
SimpleProgramKey config{textured, culled, emissive, depthBias};
|
||||
gpu::PipelinePointer pipeline = getPipeline(config);
|
||||
batch.setPipeline(pipeline);
|
||||
|
||||
gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader;
|
||||
|
||||
if (!config.isTextured()) {
|
||||
// If it is not textured, bind white texture and keep using textured pipeline
|
||||
batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
}
|
||||
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
|
||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
uint32_t toCompactColor(const glm::vec4& color) {
|
||||
uint32_t compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
||||
((int(color.y * 255.0f) & 0xFF) << 8) |
|
||||
|
@ -1853,30 +1864,30 @@ uint32_t toCompactColor(const glm::vec4& color) {
|
|||
static const size_t INSTANCE_COLOR_BUFFER = 0;
|
||||
|
||||
template <typename F>
|
||||
void renderInstances(const std::string& name, gpu::Batch& batch, const glm::vec4& color, F f) {
|
||||
void renderInstances(const std::string& name, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline, F f) {
|
||||
{
|
||||
gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(name, INSTANCE_COLOR_BUFFER);
|
||||
auto compactColor = toCompactColor(color);
|
||||
instanceColorBuffer->append(compactColor);
|
||||
}
|
||||
|
||||
batch.setupNamedCalls(name, [f](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||
batch.setupNamedCalls(name, [f, pipeline](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
batch.setPipeline(pipeline->get(batch));
|
||||
f(batch, data);
|
||||
});
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color) {
|
||||
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, GeometryCache::Sphere, data.count(),
|
||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
||||
});
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color) {
|
||||
void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, GeometryCache::Sphere, data.count(),
|
||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
||||
});
|
||||
|
@ -1886,12 +1897,12 @@ void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4&
|
|||
// available shape types, both solid and wireframes
|
||||
//#define DEBUG_SHAPES
|
||||
|
||||
void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color) {
|
||||
void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
|
||||
#ifdef DEBUG_SHAPES
|
||||
static auto startTime = usecTimestampNow();
|
||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
|
||||
auto usecs = usecTimestampNow();
|
||||
usecs -= startTime;
|
||||
|
@ -1924,18 +1935,17 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4&
|
|||
}
|
||||
});
|
||||
#else
|
||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
DependencyManager::get<GeometryCache>()->renderCubeInstances(batch, data.count(),
|
||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color) {
|
||||
void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
renderInstances(INSTANCE_NAME, batch, color, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
DependencyManager::get<GeometryCache>()->renderWireCubeInstances(batch, data.count(),
|
||||
data.buffers[INSTANCE_COLOR_BUFFER]);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -150,31 +150,44 @@ public:
|
|||
static const int UNKNOWN_ID;
|
||||
|
||||
|
||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
||||
gpu::PipelinePointer bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||
bool emissive = false, bool depthBias = false);
|
||||
// Bind the pipeline and get the state to render static geometry
|
||||
void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true,
|
||||
bool emissive = false, bool depthBias = false);
|
||||
// Get the pipeline to render static geometry
|
||||
gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true,
|
||||
bool emissive = false, bool depthBias = false);
|
||||
render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; }
|
||||
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color);
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color) {
|
||||
renderSolidSphereInstance(batch, glm::vec4(color, 1.0));
|
||||
// Static geometry
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
renderSolidSphereInstance(batch, glm::vec4(color, 1.0), pipeline);
|
||||
}
|
||||
|
||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color);
|
||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color) {
|
||||
renderWireSphereInstance(batch, glm::vec4(color, 1.0));
|
||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
renderWireSphereInstance(batch, glm::vec4(color, 1.0), pipeline);
|
||||
}
|
||||
|
||||
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color);
|
||||
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color) {
|
||||
renderSolidCubeInstance(batch, glm::vec4(color, 1.0));
|
||||
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
renderSolidCubeInstance(batch, glm::vec4(color, 1.0), pipeline);
|
||||
}
|
||||
|
||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color);
|
||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color) {
|
||||
renderWireCubeInstance(batch, glm::vec4(color, 1.0));
|
||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
renderWireCubeInstance(batch, glm::vec4(color, 1.0), pipeline);
|
||||
}
|
||||
|
||||
|
||||
// Dynamic geometry
|
||||
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||
void renderShape(gpu::Batch& batch, Shape shape);
|
||||
|
@ -364,11 +377,9 @@ private:
|
|||
|
||||
QHash<QUrl, QWeakPointer<NetworkGeometry> > _networkGeometry;
|
||||
|
||||
|
||||
gpu::PipelinePointer getPipeline(SimpleProgramKey config);
|
||||
|
||||
gpu::ShaderPointer _simpleShader;
|
||||
gpu::ShaderPointer _emissiveShader;
|
||||
static render::ShapePipelinePointer _simplePipeline;
|
||||
QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;
|
||||
};
|
||||
|
||||
|
|
|
@ -58,6 +58,15 @@ void initStencilPipeline(gpu::PipelinePointer& pipeline) {
|
|||
pipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
|
||||
// Set a default diffuse map
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP,
|
||||
DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
// Set a default normal map
|
||||
batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP,
|
||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
|
||||
void initOverlay3DPipelines(ShapePlumber& plumber) {
|
||||
auto vs = gpu::Shader::createVertex(std::string(overlay3D_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(overlay3D_frag));
|
||||
|
@ -67,14 +76,7 @@ void initOverlay3DPipelines(ShapePlumber& plumber) {
|
|||
opaqueState->setDepthTest(false);
|
||||
opaqueState->setBlendFunction(false);
|
||||
|
||||
plumber.addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState);
|
||||
}
|
||||
|
||||
void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
|
||||
if (pipeline.locations->normalFittingMapUnit > -1) {
|
||||
batch.setResourceTexture(pipeline.locations->normalFittingMapUnit,
|
||||
DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
plumber.addPipeline(ShapeKey::Filter::Builder().withOpaque(), program, opaqueState, &batchSetter);
|
||||
}
|
||||
|
||||
void initDeferredPipelines(render::ShapePlumber& plumber) {
|
||||
|
@ -97,7 +99,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
|||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader);
|
||||
plumber.addPipeline(key, program, state, &pipelineBatchSetter);
|
||||
plumber.addPipeline(key, program, state, &batchSetter);
|
||||
|
||||
// Add a wireframe version
|
||||
if (!key.isWireFrame()) {
|
||||
|
@ -106,7 +108,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber) {
|
|||
|
||||
wireFrameState->setFillMode(gpu::State::FILL_LINE);
|
||||
|
||||
plumber.addPipeline(wireFrameKey, program, wireFrameState, &pipelineBatchSetter);
|
||||
plumber.addPipeline(wireFrameKey, program, wireFrameState, &batchSetter);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -143,6 +143,7 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons
|
|||
if (args->_pipeline) {
|
||||
item.render(args);
|
||||
}
|
||||
args->_pipeline = nullptr;
|
||||
} else if (key.hasOwnPipeline()) {
|
||||
item.render(args);
|
||||
} else {
|
||||
|
|
|
@ -22,6 +22,11 @@ ShapeKey::Filter::Builder::Builder() {
|
|||
_mask.set(INVALID);
|
||||
}
|
||||
|
||||
gpu::PipelinePointer ShapePipeline::get(gpu::Batch& batch) {
|
||||
batchSetter(*this, batch);
|
||||
return this->pipeline;
|
||||
}
|
||||
|
||||
void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit, const PipelinePointer& pipeline) {
|
||||
// Iterate over all keys
|
||||
if (bit < (int)ShapeKey::FlagBit::NUM_FLAGS) {
|
||||
|
|
|
@ -209,6 +209,10 @@ public:
|
|||
ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter) :
|
||||
pipeline(pipeline), locations(locations), batchSetter(batchSetter) {}
|
||||
|
||||
// Normally, a pipeline is accessed thorugh pickPipeline. If it needs to be accessed manually,
|
||||
// this method preps the pipeline with defaults set by its batchSetter and returns only the gpu::Pipeline.
|
||||
gpu::PipelinePointer get(gpu::Batch& batch);
|
||||
|
||||
gpu::PipelinePointer pipeline;
|
||||
std::shared_ptr<Locations> locations;
|
||||
|
||||
|
|
|
@ -239,6 +239,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
auto pipeline = geometryCache->getSimplePipeline();
|
||||
for (auto& transform : transforms) {
|
||||
batch.setModelTransform(transform);
|
||||
batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
|
|
Loading…
Reference in a new issue