diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0abb43692d..4da50ca0b0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2400,7 +2400,7 @@ void Application::initializeGL() { DependencyManager::get()->initializeShapePipelines(); }); - _gameWorkload.startup(_main3DScene); + _gameWorkload.startup(_workloadSpace, _main3DScene); _offscreenContext = new OffscreenGLCanvas(); _offscreenContext->setObjectName("MainThreadContext"); diff --git a/interface/src/Application.h b/interface/src/Application.h index e04421cb6c..2af1d4678a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -619,6 +619,7 @@ private: gpu::ContextPointer _gpuContext; // initialized during window creation GameWorkload _gameWorkload; + workload::SpacePointer _workloadSpace{ new workload::Space() }; mutable QMutex _renderArgsMutex{ QMutex::Recursive }; struct AppRenderArgs { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index f9a0bfa360..0113e0568d 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -8,8 +8,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "GameWorkload.h" +#include "GameWorkloadRenderer.h" -GameWorkloadContext::GameWorkloadContext(const render::ScenePointer& scene) : WorkloadContext(), _scene(scene) { +GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene) : WorkloadContext(space), _scene(scene) { } GameWorkloadContext::~GameWorkloadContext() { @@ -23,8 +24,8 @@ GameWorkload::~GameWorkload() { shutdown(); } -void GameWorkload::startup(const render::ScenePointer& scene) { - _engine.reset(new workload::Engine(std::make_shared(scene))); +void GameWorkload::startup(const workload::SpacePointer& space, const render::ScenePointer& scene) { + _engine.reset(new workload::Engine(std::make_shared(space, scene))); _engine->addJob("SpaceToRender"); } @@ -35,78 +36,3 @@ void GameWorkload::shutdown() { - - -class GameWorkloadRenderItem { -public: - using Payload = render::Payload; - 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; } - -protected: - render::Item::Bound _bound; - - 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); -} - -namespace render { - template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) { - auto builder = ItemKey::Builder().withTypeShape(); - 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 GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) { - auto gameWorkloadContext = std::dynamic_pointer_cast(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(); - renderItem->editBound().expandedContains(glm::vec3(0.0), 32000.0); - transaction.resetItem(_spaceRenderItemID, std::make_shared(std::make_shared())); - } - - scene->enqueueTransaction(transaction); - - auto space = gameWorkloadContext->_space; - if (!space) { - return; - } - - -} \ No newline at end of file diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 1647056d60..fe48d0fe92 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -15,21 +15,9 @@ #include "render/Scene.h" -class GameSpaceToRender { -public: - using Outputs = render::Transaction; - using JobModel = workload::Job::ModelO; - - GameSpaceToRender() {} - void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); - -protected: - render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; -}; - class GameWorkloadContext : public workload::WorkloadContext { public: - GameWorkloadContext(const render::ScenePointer& scene); + GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene); virtual ~GameWorkloadContext(); render::ScenePointer _scene; @@ -40,7 +28,7 @@ public: GameWorkload(); ~GameWorkload(); - void startup(const render::ScenePointer& scene); + void startup(const workload::SpacePointer& space, const render::ScenePointer& scene); void shutdown(); workload::EnginePointer _engine; diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp new file mode 100644 index 0000000000..dcc55e54b3 --- /dev/null +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -0,0 +1,121 @@ +// +// 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 + + +#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(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(); + renderItem->editBound().expandedContains(glm::vec3(0.0), 32000.0); + transaction.resetItem(_spaceRenderItemID, std::make_shared(std::make_shared())); + } + + scene->enqueueTransaction(transaction); + + auto space = gameWorkloadContext->_space; + if (!space) { + return; + } + + space->getNumObjects(); + +} + +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& proxies) { + static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy); + if (!_allProxiesBuffer) { + _allProxiesBuffer = std::make_shared(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(); + 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); + }); + +} + + + diff --git a/interface/src/workload/GameWorkloadRenderer.h b/interface/src/workload/GameWorkloadRenderer.h new file mode 100644 index 0000000000..969c85a195 --- /dev/null +++ b/interface/src/workload/GameWorkloadRenderer.h @@ -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() {} + void run(const workload::WorkloadContextPointer& renderContext, Outputs& outputs); + +protected: + render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID }; +}; + + +class GameWorkloadRenderItem { +public: + using Payload = render::Payload; + 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& 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 \ No newline at end of file diff --git a/libraries/render-utils/src/drawWorkloadProxy.slf b/libraries/render-utils/src/drawWorkloadProxy.slf new file mode 100644 index 0000000000..84c47d0933 --- /dev/null +++ b/libraries/render-utils/src/drawWorkloadProxy.slf @@ -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); + } + +} diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv new file mode 100644 index 0000000000..0bb2b795bd --- /dev/null +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -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)); + +} \ No newline at end of file diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index e209fbf5d5..3cf31bd879 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -36,7 +36,7 @@ namespace workload { } }; - WorkloadContext::WorkloadContext() : task::JobContext(trace_workload()) {} + WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} using EngineModel = Task::Model; diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index 1e69f555c7..365461a4a3 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -29,7 +29,7 @@ namespace workload { // (1) Derive class C from task::JobContext class WorkloadContext : public task::JobContext { public: - WorkloadContext(); + WorkloadContext(const SpacePointer& space); virtual ~WorkloadContext() {} SpacePointer _space; @@ -66,12 +66,7 @@ namespace workload { // (6) The Engine's Context is passed to its Jobs when they are run() void run() { assert(_context); Task::run(_context); } - // Register the Space - void registerSpace(const SpacePointer& space) { _context->_space = space; } - 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); } private: WorkloadContextPointer _context; diff --git a/libraries/workload/src/workload/Space.cpp b/libraries/workload/src/workload/Space.cpp index 2c38ec9f8b..e37211b611 100644 --- a/libraries/workload/src/workload/Space.cpp +++ b/libraries/workload/src/workload/Space.cpp @@ -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()) { diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index c4e89cda60..fb288a060c 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -70,6 +70,8 @@ public: void categorizeAndGetChanges(std::vector& changes); + uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies); + private: void deleteProxy(int32_t proxyId); void updateProxy(int32_t proxyId, const Sphere& sphere);