diff --git a/interface/src/scripting/RenderScriptingInterface.cpp b/interface/src/scripting/RenderScriptingInterface.cpp index 338a5ab883..f23dc598a9 100644 --- a/interface/src/scripting/RenderScriptingInterface.cpp +++ b/interface/src/scripting/RenderScriptingInterface.cpp @@ -54,7 +54,7 @@ void RenderScriptingInterface::forceRenderMethod(RenderMethod renderMethod) { _renderMethod = (int)renderMethod; _renderMethodSetting.set((int)renderMethod); - auto config = dynamic_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DeferredForwardSwitch")); + auto config = dynamic_cast(qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DeferredForwardSwitch")); if (config) { config->setBranch((int)renderMethod); } diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 6cdc25d7b3..1c3e755c7b 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -52,12 +52,14 @@ void PolyLineEntityRenderer::buildPipelines() { gpu::ShaderPointer program = gpu::Shader::createProgram(key.first == render::Args::DEFERRED ? shader::entities_renderer::program::paintStroke : shader::entities_renderer::program::paintStroke_forward); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setCullMode(gpu::State::CullMode::CULL_NONE); state->setDepthTest(true, !key.second, gpu::LESS_EQUAL); PrepareStencil::testMask(*state); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + + state->setBlendFunction(true, 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); + _pipelines[key] = gpu::Pipeline::create(program, state); } } diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 837291efe6..4ae242655c 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -31,7 +31,7 @@ layout(location=3) in float _distanceFromCenter; void main(void) { vec4 texel = texture(_texture, _texCoord); texel *= _color; - texel.a *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y); + texel.a *= mix(1.0, pow(1.0 - min(1.0, abs(_distanceFromCenter)), 10.0), _polylineData.faceCameraGlow.y); <@if not HIFI_USE_FORWARD@> packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index ffd0466b79..2532de31b0 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -584,6 +584,7 @@ protected: friend class GLState; friend class GLTexture; friend class GLShader; + friend class GLPipeline; }; }} // namespace gpu::gl diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendShader.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendShader.cpp index f737842ec0..10b573276e 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendShader.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendShader.cpp @@ -202,7 +202,7 @@ GLint GLBackend::getRealUniformLocation(GLint location) const { void GLBackend::postLinkProgram(ShaderObject& shaderObject, const Shader& program) const { const auto& glprogram = shaderObject.glprogram; - const auto& expectedUniforms = program.getReflection().uniforms; + auto expectedUniforms = program.getReflection(getShaderDialect(), getShaderVariant()).uniforms; auto& uniformRemap = shaderObject.uniformRemap; // initialize all the uniforms with an invalid location diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLPipeline.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLPipeline.cpp index e00dc9fc25..52e10eb417 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLPipeline.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLPipeline.cpp @@ -52,7 +52,8 @@ GLPipeline* GLPipeline::sync(GLBackend& backend, const Pipeline& pipeline) { // Special case for view correction matrices, any pipeline that declares the correction buffer // uniform will automatically have it provided without any client code necessary. // Required for stable lighting in the HMD. - object->_cameraCorrection = shader->getReflection().validUniformBuffer(gpu::slot::buffer::CameraCorrection); + auto reflection = shader->getReflection(backend.getShaderDialect(), backend.getShaderVariant()); + object->_cameraCorrection = reflection.validUniformBuffer(gpu::slot::buffer::CameraCorrection); object->_program = programObject; object->_state = stateObject; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendShader.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendShader.cpp index f33dd91d03..227bad787b 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendShader.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendShader.cpp @@ -15,7 +15,7 @@ using namespace gpu::gl41; void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& program) const { Parent::postLinkProgram(programObject, program); const auto& glprogram = programObject.glprogram; - const auto& reflection = program.getReflection(); + auto reflection = program.getReflection(getShaderDialect(), getShaderVariant()); // For the UBOs, use glUniformBlockBinding to fixup the locations based on the reflection { const auto& expectedUbos = reflection.uniformBuffers; @@ -43,25 +43,23 @@ void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& pro } // For the resource buffers, do the same as for the textures, since in GL 4.1 that's how they're implemented + static const std::string TRANSFORM_OBJECT_BUFFER = "transformObjectBuffer"; { const auto& expectedResourceBuffers = reflection.resourceBuffers; const auto names = Shader::Reflection::getNames(expectedResourceBuffers); const auto resourceBufferUniforms = ::gl::Uniform::loadByName(glprogram, names); for (const auto& resourceBuffer : resourceBufferUniforms) { + + // Special case for the transformObjectBuffer, which is filtered out of the reflection data at shader load time + if (resourceBuffer.name == TRANSFORM_OBJECT_BUFFER) { + glProgramUniform1i(glprogram, resourceBuffer.binding, ::gpu::slot::texture::ObjectTransforms); + continue; + } const auto& targetBinding = expectedResourceBuffers.at(resourceBuffer.name); glProgramUniform1i(glprogram, resourceBuffer.binding, targetBinding); } } - // Special case for the transformObjectBuffer, which is filtered out of the reflection data at shader load time - // - { - static const std::string TRANSFORM_OBJECT_BUFFER = "transformObjectBuffer"; - const auto uniform = ::gl::Uniform::loadByName(glprogram, TRANSFORM_OBJECT_BUFFER); - if (-1 != uniform.binding) { - glProgramUniform1i(glprogram, uniform.binding, ::gpu::slot::texture::ObjectTransforms); - } - } } diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index d4236ac66c..6a1ea53cda 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -43,17 +43,34 @@ Shader::Shader(Type type, const Pointer& vertex, const Pointer& geometry, const shaders[VERTEX] = vertex; shaders[PIXEL] = pixel; } +} - auto& reflection = const_cast(getReflection()); - for (const auto& subShader : _shaders) { - reflection.merge(subShader->getReflection()); - } - if (_shaders[VERTEX]) { - reflection.inputs = _shaders[VERTEX]->getReflection().inputs; - } - if (_shaders[PIXEL]) { - reflection.outputs = _shaders[PIXEL]->getReflection().outputs; +Shader::Reflection Shader::getReflection(shader::Dialect dialect, shader::Variant variant) const { + if (_type == Shader::Type::PROGRAM) { + Reflection reflection; + for (const auto& subShader : _shaders) { + reflection.merge(subShader->getReflection(dialect, variant)); + } + if (_shaders[VERTEX]) { + reflection.inputs = _shaders[VERTEX]->getReflection(dialect, variant).inputs; + } + if (_shaders[PIXEL]) { + reflection.outputs = _shaders[PIXEL]->getReflection(dialect, variant).outputs; + } + + return reflection; } + + return _source.getReflection(dialect, variant); +} + + +Shader::Reflection Shader::getReflection() const { + // For sake of convenience i would like to be able to use a "default" dialect that represents the reflection + // of the source of the shader + // What i really want, is a reflection that is designed for the gpu lib interface but we don't have that yet (glsl45 is the closest to that) + // Until we have an implementation for this, we will return such default reflection from the one available and platform specific + return getReflection(shader::DEFAULT_DIALECT, shader::Variant::Mono); } Shader::~Shader() diff --git a/libraries/gpu/src/gpu/Shader.h b/libraries/gpu/src/gpu/Shader.h index 987e632025..f4f37b1815 100755 --- a/libraries/gpu/src/gpu/Shader.h +++ b/libraries/gpu/src/gpu/Shader.h @@ -91,7 +91,8 @@ public: const Shaders& getShaders() const { return _shaders; } - const Reflection& getReflection() const { return _source.reflection; } + Reflection getReflection(shader::Dialect dialect, shader::Variant variant) const; + Reflection getReflection() const; // get the default version of the reflection // Compilation Handler can be passed while compiling a shader (in the makeProgram call) to be able to give the hand to // the caller thread if the compilation fails and to provide a different version of the source for it diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index dbdf9cc7d1..ce4fbb2a38 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -264,12 +264,24 @@ void Procedural::prepare(gpu::Batch& batch, fragmentSource.replacements[PROCEDURAL_VERSION] = "#define PROCEDURAL_V" + std::to_string(_data.version); fragmentSource.replacements[PROCEDURAL_BLOCK] = _shaderSource.toStdString(); - // Set any userdata specified uniforms - int customSlot = procedural::slot::uniform::Custom; - for (const auto& key : _data.uniforms.keys()) { - std::string uniformName = key.toLocal8Bit().data(); - fragmentSource.reflection.uniforms[uniformName] = customSlot; - ++customSlot; + // Set any userdata specified uniforms (if any) + if (!_data.uniforms.empty()) { + // First grab all the possible dialect/variant/Reflections + std::vector allReflections; + for (auto dialectIt = fragmentSource.dialectSources.begin(); dialectIt != fragmentSource.dialectSources.end(); ++dialectIt) { + for (auto variantIt = (*dialectIt).second.variantSources.begin(); variantIt != (*dialectIt).second.variantSources.end(); ++variantIt) { + allReflections.push_back(&(*variantIt).second.reflection); + } + } + // Then fill in every reflections the new custom bindings + int customSlot = procedural::slot::uniform::Custom; + for (const auto& key : _data.uniforms.keys()) { + std::string uniformName = key.toLocal8Bit().data(); + for (auto reflection : allReflections) { + reflection->uniforms[uniformName] = customSlot; + } + ++customSlot; + } } // Leave this here for debugging diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 14f2e51697..e34db755b7 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -48,6 +48,17 @@ using namespace render; extern void initForwardPipelines(ShapePlumber& plumber); +void PreparePrimaryFramebufferMSAAConfig::setResolutionScale(float scale) { + const float SCALE_RANGE_MIN = 0.1f; + const float SCALE_RANGE_MAX = 2.0f; + resolutionScale = std::max(SCALE_RANGE_MIN, std::min(SCALE_RANGE_MAX, scale)); +} + +void PreparePrimaryFramebufferMSAAConfig::setNumSamples(int num) { + numSamples = std::max(1, std::min(32, num)); + emit dirty(); +} + void RenderForwardTask::configure(const Config& config) { // Propagate resolution scale to sub jobs who need it auto preparePrimaryBufferConfig = config.getConfig("PreparePrimaryBufferForward"); diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index dd0abbc9ab..6833e42449 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -42,22 +42,14 @@ public: class PreparePrimaryFramebufferMSAAConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale) - Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples) + Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale NOTIFY dirty) + Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples NOTIFY dirty) public: float getResolutionScale() const { return resolutionScale; } - void setResolutionScale(float scale) { - const float SCALE_RANGE_MIN = 0.1f; - const float SCALE_RANGE_MAX = 2.0f; - resolutionScale = std::max(SCALE_RANGE_MIN, std::min(SCALE_RANGE_MAX, scale)); - //emit dirty(); - } + void setResolutionScale(float scale); int getNumSamples() const { return numSamples; } - void setNumSamples(int num) { - numSamples = std::max(1, std::min(32, num)); - emit dirty(); - } + void setNumSamples(int num); signals: void dirty(); diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 130ed6533f..f1d59727d3 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -70,7 +70,7 @@ namespace render { GPUTaskConfig() = default; - GPUTaskConfig(bool enabled) : TaskConfig(enabled) {} + GPUTaskConfig(bool enabled) : render::TaskConfig(enabled) {} // Running Time measurement on GPU and for Batch execution void setGPUBatchRunTime(double msGpuTime, double msBatchTime) { _msGPURunTime = msGpuTime; _msBatchRunTime = msBatchTime; } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 12947f5291..048e08e959 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -86,7 +86,7 @@ void ShapePlumber::addPipeline(const Key& key, const gpu::ShaderPointer& program void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& program, const gpu::StatePointer& state, BatchSetter batchSetter, ItemSetter itemSetter) { ShapeKey key{ filter._flags }; - const auto& reflection = program->getReflection(); + auto reflection = program->getReflection(); auto locations = std::make_shared(); locations->albedoTextureUnit = reflection.validTexture(graphics::slot::texture::MaterialAlbedo); locations->roughnessTextureUnit = reflection.validTexture(graphics::slot::texture::MaterialRoughness); diff --git a/libraries/shaders/src/shaders/Shaders.cpp b/libraries/shaders/src/shaders/Shaders.cpp index a074c2f0c9..ef67842f84 100644 --- a/libraries/shaders/src/shaders/Shaders.cpp +++ b/libraries/shaders/src/shaders/Shaders.cpp @@ -32,7 +32,7 @@ namespace shader { #if defined(USE_GLES) -static const Dialect DEFAULT_DIALECT = Dialect::glsl310es; +const Dialect DEFAULT_DIALECT = Dialect::glsl310es; const std::vector& allDialects() { static const std::vector ALL_DIALECTS{ { Dialect::glsl310es } }; @@ -41,7 +41,7 @@ const std::vector& allDialects() { #elif defined(Q_OS_MAC) -static const Dialect DEFAULT_DIALECT = Dialect::glsl410; +const Dialect DEFAULT_DIALECT = Dialect::glsl410; const std::vector& allDialects() { static const std::vector ALL_DIALECTS{ Dialect::glsl410 }; @@ -50,7 +50,7 @@ const std::vector& allDialects() { #else -static const Dialect DEFAULT_DIALECT = Dialect::glsl450; +const Dialect DEFAULT_DIALECT = Dialect::glsl450; const std::vector & allDialects() { static const std::vector ALL_DIALECTS{ { Dialect::glsl450, Dialect::glsl410 } }; @@ -131,7 +131,6 @@ Source::Pointer Source::loadSource(uint32_t shaderId) { for (const auto& dialect : dialects) { result->dialectSources[dialect] = loadDialectSource(dialect, shaderId); } - result->reflection = result->dialectSources[DEFAULT_DIALECT].variantSources[Variant::Mono].reflection; return result; } @@ -140,7 +139,6 @@ Source& Source::operator=(const Source& other) { name = other.name; dialectSources = other.dialectSources; replacements = other.replacements; - reflection = other.reflection; return *this; } diff --git a/libraries/shaders/src/shaders/Shaders.h b/libraries/shaders/src/shaders/Shaders.h index 134b2bdcf8..701695c3a8 100644 --- a/libraries/shaders/src/shaders/Shaders.h +++ b/libraries/shaders/src/shaders/Shaders.h @@ -42,6 +42,8 @@ enum class Dialect #endif }; +extern const Dialect DEFAULT_DIALECT; + const std::vector& allDialects(); const std::string& dialectPath(Dialect dialect); @@ -140,9 +142,6 @@ struct Source { // The name of the shader file, with extension, i.e. DrawColor.frag std::string name; - // Generic reflection, copied from the 450 dialect / mono variant - Reflection reflection; - // Map of platforms to their specific shaders std::unordered_map dialectSources; diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index 79e0b9f7fb..bcf5eb7d1f 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -79,8 +79,8 @@ void JobConfig::refresh() { _jobConcept->applyConfiguration(); } -TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& jobName) const { - TaskConfig* root = const_cast (this); +JobConfig* JobConfig::getRootConfig(const std::string& jobPath, std::string& jobName) const { + JobConfig* root = const_cast (this); std::list tokens; std::size_t pos = 0, sepPos; @@ -105,7 +105,7 @@ TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& j while (tokens.size() > 1) { auto taskName = tokens.front(); tokens.pop_front(); - root = root->findChild((taskName.empty() ? QString() : QString(taskName.c_str()))); + root = root->findChild((taskName.empty() ? QString() : QString(taskName.c_str()))); if (!root) { return nullptr; } @@ -115,7 +115,7 @@ TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& j return root; } -JobConfig* TaskConfig::getJobConfig(const std::string& jobPath) const { +JobConfig* JobConfig::getJobConfig(const std::string& jobPath) const { std::string jobName; auto root = getRootConfig(jobPath, jobName); @@ -134,10 +134,10 @@ JobConfig* TaskConfig::getJobConfig(const std::string& jobPath) const { } } -void SwitchConfig::setBranch(uint8_t branch) { +void JobConfig::setBranch(uint8_t branch) { if (_branch != branch) { _branch = branch; // We can re-use this signal here emit dirtyEnabled(); } -} \ No newline at end of file +} diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 75cecb5f18..8accba9e1f 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -83,11 +83,19 @@ protected: Setting::Handle _preset; }; +class JobConfig; + +class TConfigProxy { +public: + using Config = JobConfig; +}; + // A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) class JobConfig : public QObject { Q_OBJECT Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled()) + Q_PROPERTY(int branch READ getBranch WRITE setBranch NOTIFY dirtyEnabled) double _msCPURunTime{ 0.0 }; @@ -96,7 +104,11 @@ protected: bool _isEnabled{ true }; + uint8_t _branch { 0 }; public: + bool _isTask{ false }; + bool _isSwitch{ false }; + using Persistent = PersistentConfig; JobConfig() = default; @@ -121,44 +133,83 @@ public: */ Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); } - Q_INVOKABLE QObject* getConfig(const QString& name) { return nullptr; } - // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } - // Describe the node graph data connections of the associated Job/Task /**jsdoc - * @function Workload.isTask + * @function Render.getConfig + * @param {string} name + * @returns {object} + */ + // Get a sub job config through task.getConfig(path) + // where path can be: + // - search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root) + // - .[.] + // Allowing to first look for the parent_name job (from this task as root) and then search from there for the + // optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path were found) + // + // getter for qml integration, prefer the templated getter + Q_INVOKABLE QObject* getConfig(const QString& name) { return getConfig(name.toStdString()); } + + // getter for cpp (strictly typed), prefer this getter + JobConfig* getRootConfig(const std::string& jobPath, std::string& jobName) const; + JobConfig* getJobConfig(const std::string& jobPath) const; + template typename T::Config* getConfig(std::string jobPath = "") const { + return dynamic_cast(getJobConfig(jobPath)); + } + + // Describe the node graph data connections of the associated Job/Task + /**jsdoc + * @function JobConfig.isTask + * @returns {boolean} + */ + Q_INVOKABLE bool isTask() const { return _isTask; } + + /**jsdoc + * @function JobConfig.isSwitch * @returns {boolean} */ - Q_INVOKABLE virtual bool isTask() const { return false; } + Q_INVOKABLE bool isSwitch() const { return _isSwitch; } /**jsdoc - * @function Workload.getSubConfigs + * @function JobConfig.getSubConfigs * @returns {object[]} */ - Q_INVOKABLE virtual QObjectList getSubConfigs() const { return QObjectList(); } + Q_INVOKABLE QObjectList getSubConfigs() const { + auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); + QObjectList returned; + for (int i = 0; i < list.size(); i++) { + returned.push_back(list[i]); + } + return returned; + } /**jsdoc - * @function Workload.getNumSubs + * @function JobConfig.getNumSubs * @returns {number} */ - Q_INVOKABLE virtual int getNumSubs() const { return 0; } + Q_INVOKABLE int getNumSubs() const { return getSubConfigs().size(); } /**jsdoc - * @function Workload.getSubConfig + * @function JobConfig.getSubConfig * @param {number} index * @returns {object} */ - Q_INVOKABLE virtual QObject* getSubConfig(int i) const { return nullptr; } - + Q_INVOKABLE QObject* getSubConfig(int i) const { + auto subs = getSubConfigs(); + return ((i < 0 || i >= subs.size()) ? nullptr : subs[i]); + } + void connectChildConfig(std::shared_ptr childConfig, const std::string& name); void transferChildrenConfigs(std::shared_ptr source); JobConcept* _jobConcept; + uint8_t getBranch() const { return _branch; } + void setBranch(uint8_t index); + public slots: /**jsdoc @@ -195,82 +246,6 @@ signals: using QConfigPointer = std::shared_ptr; -class TConfigProxy { -public: - using Config = JobConfig; -}; - - -/**jsdoc - * @namespace Workload - * - * @hifi-interface - * @hifi-client-entity - * @hifi-avatar - * - * @property {number} cpuRunTime - Read-only. - * @property {boolean} enabled - */ -class TaskConfig : public JobConfig { - Q_OBJECT - -public: - using Persistent = PersistentConfig; - - TaskConfig() = default; - TaskConfig(bool enabled) : JobConfig(enabled) {} - - /**jsdoc - * @function Workload.getConfig - * @param {string} name - * @returns {object} - */ - // Get a sub job config through task.getConfig(path) - // where path can be: - // - search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root) - // - .[.] - // Allowing to first look for the parent_name job (from this task as root) and then search from there for the - // optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path were found) - // - // getter for qml integration, prefer the templated getter - Q_INVOKABLE QObject* getConfig(const QString& name) { return getConfig(name.toStdString()); } - - // getter for cpp (strictly typed), prefer this getter - TaskConfig* getRootConfig(const std::string& jobPath, std::string& jobName) const; - JobConfig* getJobConfig(const std::string& jobPath) const; - - template typename T::Config* getConfig(std::string jobPath = "") const { - return dynamic_cast(getJobConfig(jobPath)); - } - - Q_INVOKABLE bool isTask() const override { return true; } - Q_INVOKABLE QObjectList getSubConfigs() const override { - auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); - QObjectList returned; - for (int i = 0; i < list.size(); i++) { - returned.push_back(list[i]); - } - return returned; - } - Q_INVOKABLE int getNumSubs() const override { return getSubConfigs().size(); } - Q_INVOKABLE QObject* getSubConfig(int i) const override { - auto subs = getSubConfigs(); - return ((i < 0 || i >= subs.size()) ? nullptr : subs[i]); - } -}; - -class SwitchConfig : public JobConfig { - Q_OBJECT - Q_PROPERTY(int branch READ getBranch WRITE setBranch NOTIFY dirtyEnabled) - -public: - uint8_t getBranch() const { return _branch; } - void setBranch(uint8_t index); - -protected: - uint8_t _branch { 0 }; -}; - } #endif // hifi_task_Config_h diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index cdc279ff36..0ee458f3ea 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -69,7 +69,7 @@ class JobConcept { public: using Config = JobConfig; - JobConcept(const std::string& name, QConfigPointer config) : _config(config), _name(name) {} + JobConcept(const std::string& name, QConfigPointer config) : _config(config), _name(name) { config->_jobConcept = this; } virtual ~JobConcept() = default; const std::string& getName() const { return _name; } @@ -80,7 +80,7 @@ public: virtual QConfigPointer& getConfiguration() { return _config; } virtual void applyConfiguration() = 0; - void setCPURunTime(const std::chrono::nanoseconds& runtime) { std::static_pointer_cast(_config)->setCPURunTime(runtime); } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { (_config)->setCPURunTime(runtime); } QConfigPointer _config; protected: @@ -94,9 +94,6 @@ template void jobConfigure(T& data, const C& configuration) { template void jobConfigure(T&, const JobConfig&) { // nop, as the default JobConfig was used, so the data does not need a configure method } -template void jobConfigure(T&, const TaskConfig&) { - // nop, as the default TaskConfig was used, so the data does not need a configure method -} template void jobRun(T& data, const JC& jobContext, const JobNoIO& input, JobNoIO& output) { data.run(jobContext); @@ -158,7 +155,17 @@ public: return std::make_shared(name, input, std::make_shared(), std::forward(args)...); } - + void createConfiguration() { + // A brand new config + auto config = std::make_shared(); + // Make sure we transfer the former children configs to the new config + config->transferChildrenConfigs(Concept::_config); + // swap + Concept::_config = config; + // Capture this + Concept::_config->_jobConcept = this; + } + void applyConfiguration() override { TimeProfiler probe(("configure::" + JobConcept::getName())); @@ -228,7 +235,7 @@ public: using Context = JC; using TimeProfiler = TP; using ContextPointer = std::shared_ptr; - using Config = TaskConfig; + using Config = JobConfig; //TaskConfig; using JobType = Job; using None = typename JobType::None; using Concept = typename JobType::Concept; @@ -247,14 +254,14 @@ public: const Varying getOutput() const override { return _output; } Varying& editInput() override { return _input; } - TaskConcept(const std::string& name, const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) {} + TaskConcept(const std::string& name, const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) {config->_isTask = true;} // Create a new job in the container's queue; returns the job's output template const Varying addJob(std::string name, const Varying& input, NA&&... args) { _jobs.emplace_back((NT::JobModel::create(name, input, std::forward(args)...))); // Conect the child config to this task's config - std::static_pointer_cast(Concept::getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name); + std::static_pointer_cast(Concept::getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name); return _jobs.back().getOutput(); } @@ -284,9 +291,6 @@ public: TimeProfiler probe("build::" + model->getName()); model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); } - // Recreate the Config to use the templated type - model->createConfiguration(); - model->applyConfiguration(); return model; } @@ -369,7 +373,7 @@ public: using Context = JC; using TimeProfiler = TP; using ContextPointer = std::shared_ptr; - using Config = SwitchConfig; + using Config = JobConfig; //SwitchConfig; using JobType = Job; using None = typename JobType::None; using Concept = typename JobType::Concept; @@ -388,14 +392,15 @@ public: const Varying getOutput() const override { return _output; } Varying& editInput() override { return _input; } - SwitchConcept(const std::string& name, const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) {} + SwitchConcept(const std::string& name, const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) + {config->_isTask = true; config->_isSwitch = true; } template const Varying addBranch(std::string name, uint8_t index, const Varying& input, NA&&... args) { auto& branch = _branches[index]; branch = JobType(NT::JobModel::create(name, input, std::forward(args)...)); // Conect the child config to this task's config - std::static_pointer_cast(Concept::getConfiguration())->connectChildConfig(branch.getConfiguration(), name); + std::static_pointer_cast(Concept::getConfiguration())->connectChildConfig(branch.getConfiguration(), name); return branch.getOutput(); } @@ -405,7 +410,7 @@ public: } }; - template class SwitchModel : public SwitchConcept { + template class SwitchModel : public SwitchConcept { public: using Data = T; using Input = I; @@ -426,9 +431,6 @@ public: TimeProfiler probe("build::" + model->getName()); model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); } - // Recreate the Config to use the templated type - model->createConfiguration(); - model->applyConfiguration(); return model; } @@ -475,8 +477,8 @@ public: } } }; - template using Model = SwitchModel; - template using ModelI = SwitchModel; + template using Model = SwitchModel; + template using ModelI = SwitchModel; // TODO: Switches don't support Outputs yet //template using ModelO = SwitchModel; //template using ModelIO = SwitchModel; @@ -500,7 +502,7 @@ class Engine : public Task { public: using Context = JC; using ContextPointer = std::shared_ptr; - using Config = TaskConfig; + using Config = JobConfig; //TaskConfig; using TaskType = Task; using ConceptPointer = typename TaskType::ConceptPointer; @@ -526,10 +528,11 @@ protected: } + #define Task_DeclareTypeAliases(ContextType, TimeProfiler) \ using JobConfig = task::JobConfig; \ - using TaskConfig = task::TaskConfig; \ - using SwitchConfig = task::SwitchConfig; \ + using TaskConfig = task::JobConfig; \ + using SwitchConfig = task::JobConfig; \ template using PersistentConfig = task::PersistentConfig; \ using Job = task::Job; \ using Switch = task::Switch; \ diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index 52c13c5279..4c3188a5cf 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -18,7 +18,7 @@ // @param depth: the depth of the recurse loop since the initial call. function task_traverse(root, functor, depth) { if (root.isTask()) { - depth++; + depth++; for (var i = 0; i