Merging with master

This commit is contained in:
samcake 2018-02-21 12:16:33 -08:00
commit 0a920fcfc5
14 changed files with 441 additions and 16 deletions

View file

@ -2276,7 +2276,8 @@ Application::~Application() {
// shutdown render engine
_main3DScene = nullptr;
_renderEngine = nullptr;
_infinityEngine = nullptr;
_gameWorkload.shutdown();
DependencyManager::destroy<Preferences>();
@ -2399,6 +2400,8 @@ void Application::initializeGL() {
DependencyManager::get<GeometryCache>()->initializeShapePipelines();
});
_gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene);
_offscreenContext = new OffscreenGLCanvas();
_offscreenContext->setObjectName("MainThreadContext");
_offscreenContext->create(_glWidget->qglContext());
@ -4166,7 +4169,7 @@ void Application::idle() {
}
{
_infinityEngine->run();
_gameWorkload._engine->run();
}
{
PerformanceTimer perfTimer("update");

View file

@ -69,7 +69,8 @@
#include "ui/OverlayConductor.h"
#include "ui/overlays/Overlays.h"
#include "UndoStackScriptingInterface.h"
#include "workload/Engine.h"
#include "workload/GameWorkload.h"
#include <procedural/ProceduralSkybox.h>
#include <graphics/Skybox.h>
@ -613,7 +614,8 @@ private:
render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
render::EnginePointer _renderEngine{ new render::Engine() };
gpu::ContextPointer _gpuContext; // initialized during window creation
workload::EnginePointer _infinityEngine{ new workload::Engine() };
GameWorkload _gameWorkload;
mutable QMutex _renderArgsMutex{ QMutex::Recursive };
struct AppRenderArgs {

View file

@ -0,0 +1,38 @@
//
// GameWorkload.cpp
//
// Created by Sam Gateau on 2/16/2018.
// Copyright 2018 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 "GameWorkload.h"
#include "GameWorkloadRenderer.h"
GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene) : WorkloadContext(space), _scene(scene) {
}
GameWorkloadContext::~GameWorkloadContext() {
}
GameWorkload::GameWorkload() {
}
GameWorkload::~GameWorkload() {
shutdown();
}
void GameWorkload::startup(const workload::SpacePointer& space, const render::ScenePointer& scene) {
_engine.reset(new workload::Engine(std::make_shared<GameWorkloadContext>(space, scene)));
_engine->addJob<GameSpaceToRender>("SpaceToRender");
}
void GameWorkload::shutdown() {
_engine.reset();
}

View file

@ -0,0 +1,37 @@
//
// GameWorkload.h
//
// Created by Sam Gateau on 2/16/2018.
// Copyright 2018 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
//
#ifndef hifi_GameWorkload_h
#define hifi_GameWorkload_h
#include "workload/Space.h"
#include "workload/Engine.h"
#include "render/Scene.h"
class GameWorkloadContext : public workload::WorkloadContext {
public:
GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene);
virtual ~GameWorkloadContext();
render::ScenePointer _scene;
};
class GameWorkload {
public:
GameWorkload();
~GameWorkload();
void startup(const workload::SpacePointer& space, const render::ScenePointer& scene);
void shutdown();
workload::EnginePointer _engine;
};
#endif

View file

@ -0,0 +1,128 @@
//
// GameWorkloadRender.cpp
//
// Created by Sam Gateau on 2/20/2018.
// Copyright 2018 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 "GameWorkloadRenderer.h"
#include <cstring>
#include <gpu/Context.h>
#include "render-utils/drawWorkloadProxy_vert.h"
#include "render-utils/drawWorkloadProxy_frag.h"
void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) {
auto gameWorkloadContext = std::dynamic_pointer_cast<GameWorkloadContext>(runContext);
if (!gameWorkloadContext) {
return;
}
auto scene = gameWorkloadContext->_scene;
// Valid space, let's display its content
render::Transaction transaction;
if (!render::Item::isValidID(_spaceRenderItemID)) {
_spaceRenderItemID = scene->allocateID();
auto renderItem = std::make_shared<GameWorkloadRenderItem>();
renderItem->editBound().expandedContains(glm::vec3(0.0f), 32000.0f);
transaction.resetItem(_spaceRenderItemID, std::make_shared<GameWorkloadRenderItem::Payload>(std::make_shared<GameWorkloadRenderItem>()));
scene->enqueueTransaction(transaction);
}
auto space = gameWorkloadContext->_space;
if (!space) {
return;
}
std::vector<workload::Space::Proxy> proxies(space->getNumAllocatedProxies());
space->copyProxyValues(proxies.data(), (uint32_t) proxies.size());
transaction.updateItem<GameWorkloadRenderItem>(_spaceRenderItemID, [proxies](GameWorkloadRenderItem& item) {
item.setAllProxies(proxies);
});
scene->enqueueTransaction(transaction);
}
namespace render {
template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) {
auto builder = ItemKey::Builder().opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1);
return builder.build();
}
template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) {
if (payload) {
return payload->getBound();
}
return Item::Bound();
}
template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args) {
if (payload) {
payload->render(args);
}
}
}
void GameWorkloadRenderItem::setAllProxies(const std::vector<workload::Space::Proxy>& proxies) {
static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy);
if (!_allProxiesBuffer) {
_allProxiesBuffer = std::make_shared<gpu::Buffer>(sizeOfProxy);
}
_allProxiesBuffer->setData(proxies.size() * sizeOfProxy, (const gpu::Byte*) proxies.data());
_numAllProxies = (uint32_t) proxies.size();
}
const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() {
if (!_drawAllProxiesPipeline) {
auto vs = drawWorkloadProxy_vert::getShader();
auto ps = drawWorkloadProxy_frag::getShader();
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
gpu::Shader::BindingSet slotBindings;
gpu::Shader::makeProgram(*program, slotBindings);
auto state = std::make_shared<gpu::State>();
state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);
_drawAllProxiesPipeline = gpu::Pipeline::create(program, state);
}
return _drawAllProxiesPipeline;
}
void GameWorkloadRenderItem::render(RenderArgs* args) {
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;
// Setup projection
glm::mat4 projMat;
Transform viewMat;
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
batch.setModelTransform(Transform());
// Bind program
batch.setPipeline(getPipeline());
batch.setResourceBuffer(0, _allProxiesBuffer);
static const int NUM_VERTICES_PER_QUAD = 4;
batch.draw(gpu::LINES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0);
});
}

View file

@ -0,0 +1,64 @@
//
// GameWorkloadRender.h
//
// Created by Sam Gateau on 2/20/2018.
// Copyright 2018 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
//
#ifndef hifi_GameWorkloadRenderer_h
#define hifi_GameWorkloadRenderer_h
#include "GameWorkload.h"
class GameSpaceToRender {
public:
using Outputs = render::Transaction;
using JobModel = workload::Job::ModelO<GameSpaceToRender, Outputs>;
GameSpaceToRender() {}
void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs);
protected:
render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID };
};
class GameWorkloadRenderItem {
public:
using Payload = render::Payload<GameWorkloadRenderItem>;
using Pointer = Payload::DataPointer;
GameWorkloadRenderItem() {}
~GameWorkloadRenderItem() {}
void render(RenderArgs* args);
render::Item::Bound& editBound() { _needUpdate = true; return _bound; }
const render::Item::Bound& getBound() { return _bound; }
void setVisible(bool visible) { _isVisible = visible; }
bool isVisible() const { return _isVisible; }
void setAllProxies(const std::vector<workload::Space::Proxy>& proxies);
protected:
render::Item::Bound _bound;
gpu::BufferPointer _allProxiesBuffer;
uint32_t _numAllProxies{ 0 };
gpu::PipelinePointer _drawAllProxiesPipeline;
const gpu::PipelinePointer getPipeline();
bool _needUpdate{ true };
bool _isVisible{ true };
};
namespace render {
template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload);
template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload);
template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args);
}
#endif

View file

@ -281,7 +281,7 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
if (entity->getSpaceIndex() == -1) {
std::unique_lock<std::mutex> lock(_spaceLock);
workload::Space::Sphere sphere(entity->getWorldPosition(), entity->getBoundingRadius());
int32_t spaceIndex = _space.createProxy(sphere);
int32_t spaceIndex = _space->createProxy(sphere);
entity->setSpaceIndex(spaceIndex);
connect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate, Qt::QueuedConnection);
}
@ -428,7 +428,7 @@ void EntityTreeRenderer::update(bool simulate) {
}
{ // update proxies in the workload::Space
std::unique_lock<std::mutex> lock(_spaceLock);
_space.updateProxies(_spaceUpdates);
_space->updateProxies(_spaceUpdates);
_spaceUpdates.clear();
}
{ // flush final EntityTree references to removed entities
@ -442,7 +442,7 @@ void EntityTreeRenderer::update(bool simulate) {
disconnect(entity.get(), &EntityItem::spaceUpdate, this, &EntityTreeRenderer::handleSpaceUpdate);
deadProxies.push_back(spaceIndex);
}
_space.deleteProxies(deadProxies);
_space->deleteProxies(deadProxies);
}
}

View file

@ -120,6 +120,9 @@ public:
static void setRenderDebugHullsOperator(std::function<bool()> renderDebugHullsOperator) { _renderDebugHullsOperator = renderDebugHullsOperator; }
static bool shouldRenderDebugHulls() { return _renderDebugHullsOperator(); }
// Access the workload Space
const workload::SpacePointer getWorkloadSpace() const { return _space; }
signals:
void enterEntity(const EntityItemID& entityItemID);
void leaveEntity(const EntityItemID& entityItemID);
@ -266,7 +269,7 @@ private:
static std::function<bool()> _renderDebugHullsOperator;
mutable std::mutex _spaceLock;
workload::Space _space;
workload::SpacePointer _space{ new workload::Space() };
std::vector<workload::Space::ProxyUpdate> _spaceUpdates;
};

View file

@ -0,0 +1,28 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// drawItemBounds.frag
// fragment shader
//
// Created by Sam Gateau on 6/29/15.
// Copyright 2015 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
//
in vec4 varColor;
in vec2 varTexcoord;
out vec4 outFragColor;
void main(void) {
float var = step(fract(varTexcoord.x * varTexcoord.y * 1.0), 0.5);
if (varColor.a == 0.0) {
outFragColor = vec4(mix(vec3(0.0), varColor.xyz, var), mix(0.0, 1.0, var));
} else {
outFragColor = vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a);
}
}

View file

@ -0,0 +1,102 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// drawItemBounds.slv
// vertex shader
//
// Created by Sam Gateau on 6/29/2015.
// Copyright 2015 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 gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include gpu/Color.slh@>
<$declareColorWheel()$>
uniform vec4 inColor;
struct ItemBound {
vec4 id_boundPos;
vec4 boundDim_s;
};
#if defined(GPU_GL410)
uniform samplerBuffer ssbo0Buffer;
ItemBound getItemBound(int i) {
int offset = 2 * i;
ItemBound bound;
bound.id_boundPos = texelFetch(ssbo0Buffer, offset);
bound.boundDim_s = texelFetch(ssbo0Buffer, offset + 1);
return bound;
}
#else
layout(std140) buffer ssbo0Buffer {
ItemBound bounds[];
};
ItemBound getItemBound(int i) {
ItemBound bound = bounds[i];
return bound;
}
#endif
out vec4 varColor;
out vec2 varTexcoord;
void main(void) {
const vec4 UNIT_BOX[8] = vec4[8](
vec4(0.0, 0.0, 0.0, 0.0),
vec4(1.0, 0.0, 0.0, 1.0),
vec4(0.0, 1.0, 0.0, 1.0),
vec4(1.0, 1.0, 0.0, 2.0),
vec4(0.0, 0.0, 1.0, 1.0),
vec4(1.0, 0.0, 1.0, 2.0),
vec4(0.0, 1.0, 1.0, 2.0),
vec4(1.0, 1.0, 1.0, 3.0)
);
const int UNIT_BOX_LINE_INDICES[24] = int[24](
0, 1,
1, 3,
3, 2,
2, 0,
4, 5,
5, 7,
7, 6,
6, 4,
2, 6,
3, 7,
0, 4,
1, 5
);
int boundID = gl_VertexID / 24;
int vertexID = gl_VertexID - boundID * 24;
vec4 cubeVec = UNIT_BOX[UNIT_BOX_LINE_INDICES[vertexID]];
ItemBound bound = getItemBound(boundID);
vec3 boundPos = bound.id_boundPos.yzw;
vec3 boundDim = bound.boundDim_s.xyz;
vec4 pos = vec4(boundPos + boundDim * cubeVec.xyz, 1.0);
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, pos, gl_Position)$>
if (inColor.w < 0.0) {
varColor = vec4(colorWheel(float(boundID)/(-inColor.w)), 1.0);
} else {
varColor = vec4(colorWheel(float(inColor.w)), 1.0);
}
varTexcoord = vec2(cubeVec.w, length(boundDim));
}

View file

@ -38,7 +38,7 @@ namespace workload {
}
};
WorkloadContext::WorkloadContext() : task::JobContext(trace_workload()) {}
WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {}
using EngineModel = Task::Model<class HelloWorldBuilder>;
@ -54,8 +54,8 @@ namespace workload {
}
};
Engine::Engine() : Task("Engine", EngineModel::create()),
_context(std::make_shared<WorkloadContext>()) {
Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineModel::create()),
_context(context) {
}
} // namespace workload

View file

@ -20,6 +20,8 @@
#include <task/Task.h>
#include "Space.h"
namespace workload {
// How to make an Engine under the task::Task<C> paradigm...
@ -27,8 +29,10 @@ namespace workload {
// (1) Derive class C from task::JobContext
class WorkloadContext : public task::JobContext {
public:
WorkloadContext();
WorkloadContext(const SpacePointer& space);
virtual ~WorkloadContext() {}
SpacePointer _space;
};
using WorkloadContextPointer = std::shared_ptr<WorkloadContext>;
@ -56,15 +60,15 @@ namespace workload {
// (5) Engine derives from task::Task<C> and will run all the Job<C>'s
class Engine : public Task {
public:
Engine();
Engine(const WorkloadContextPointer& context = std::make_shared<WorkloadContext>());
~Engine() = default;
// (6) The Engine's Context is passed to its Jobs when they are run()
void run() { assert(_context); Task::run(_context); }
void run() { assert(_context); run(_context); }
protected:
// (6) Again, the Engine's Context is passed to its Jobs when they are run()
void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); }
void run(const WorkloadContextPointer& context) override { assert(_context); Task::run(_context); }
private:
WorkloadContextPointer _context;

View file

@ -13,7 +13,7 @@
//
#include "Space.h"
#include <cstring>
#include <algorithm>
#include <glm/gtx/quaternion.hpp>
@ -101,6 +101,15 @@ void Space::deleteProxy(int32_t proxyId) {
}
}
uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) {
auto numCopied = std::min(numDestProxies, (uint32_t)_proxies.size());
memcpy(proxies, _proxies.data(), numCopied * sizeof(Proxy));
return numCopied;
}
// private
void Space::updateProxy(int32_t proxyId, const Space::Sphere& newSphere) {
if (proxyId > -1 && proxyId < (int32_t)_proxies.size()) {

View file

@ -15,9 +15,11 @@
#ifndef hifi_workload_Space_h
#define hifi_workload_Space_h
#include <memory>
#include <vector>
#include <glm/glm.hpp>
namespace workload {
class Space {
@ -33,6 +35,7 @@ public:
class Proxy {
public:
Proxy() : sphere(0.0f) {}
Proxy(const Sphere& s) : sphere(s) {}
Sphere sphere;
uint8_t region { REGION_UNKNOWN };
@ -66,9 +69,12 @@ public:
void setViews(const std::vector<View>& views);
uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); }
uint32_t getNumAllocatedProxies() const { return (uint32_t)(_proxies.size()); }
void categorizeAndGetChanges(std::vector<Change>& changes);
uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies);
private:
void deleteProxy(int32_t proxyId);
void updateProxy(int32_t proxyId, const Sphere& sphere);
@ -78,6 +84,7 @@ private:
std::vector<int32_t> _freeIndices;
};
using SpacePointer = std::shared_ptr<Space>;
using Classifications = std::vector<Space::Change>;
} // namespace workload