Merge pull request #16053 from samcake/toulouse

BUGZ-1173, BUGZ-1175: On Windows, Fix black edges on whiteboard lines in Forward and more issues in GL41Backend
This commit is contained in:
Shannon Romano 2019-08-15 09:34:03 -07:00 committed by GitHub
commit d9f78499ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 301 additions and 299 deletions

View file

@ -54,7 +54,7 @@ void RenderScriptingInterface::forceRenderMethod(RenderMethod renderMethod) {
_renderMethod = (int)renderMethod; _renderMethod = (int)renderMethod;
_renderMethodSetting.set((int)renderMethod); _renderMethodSetting.set((int)renderMethod);
auto config = dynamic_cast<task::SwitchConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DeferredForwardSwitch")); auto config = dynamic_cast<render::SwitchConfig*>(qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DeferredForwardSwitch"));
if (config) { if (config) {
config->setBranch((int)renderMethod); config->setBranch((int)renderMethod);
} }

View file

@ -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::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()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setCullMode(gpu::State::CullMode::CULL_NONE); state->setCullMode(gpu::State::CullMode::CULL_NONE);
state->setDepthTest(true, !key.second, gpu::LESS_EQUAL); state->setDepthTest(true, !key.second, gpu::LESS_EQUAL);
PrepareStencil::testMask(*state); 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); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
_pipelines[key] = gpu::Pipeline::create(program, state); _pipelines[key] = gpu::Pipeline::create(program, state);
} }
} }

View file

@ -31,7 +31,7 @@ layout(location=3) in float _distanceFromCenter;
void main(void) { void main(void) {
vec4 texel = texture(_texture, _texCoord); vec4 texel = texture(_texture, _texCoord);
texel *= _color; 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@> <@if not HIFI_USE_FORWARD@>
packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS); packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS);

View file

@ -584,6 +584,7 @@ protected:
friend class GLState; friend class GLState;
friend class GLTexture; friend class GLTexture;
friend class GLShader; friend class GLShader;
friend class GLPipeline;
}; };
}} // namespace gpu::gl }} // namespace gpu::gl

View file

@ -202,7 +202,7 @@ GLint GLBackend::getRealUniformLocation(GLint location) const {
void GLBackend::postLinkProgram(ShaderObject& shaderObject, const Shader& program) const { void GLBackend::postLinkProgram(ShaderObject& shaderObject, const Shader& program) const {
const auto& glprogram = shaderObject.glprogram; const auto& glprogram = shaderObject.glprogram;
const auto& expectedUniforms = program.getReflection().uniforms; auto expectedUniforms = program.getReflection(getShaderDialect(), getShaderVariant()).uniforms;
auto& uniformRemap = shaderObject.uniformRemap; auto& uniformRemap = shaderObject.uniformRemap;
// initialize all the uniforms with an invalid location // initialize all the uniforms with an invalid location

View file

@ -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 // Special case for view correction matrices, any pipeline that declares the correction buffer
// uniform will automatically have it provided without any client code necessary. // uniform will automatically have it provided without any client code necessary.
// Required for stable lighting in the HMD. // 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->_program = programObject;
object->_state = stateObject; object->_state = stateObject;

View file

@ -15,7 +15,7 @@ using namespace gpu::gl41;
void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& program) const { void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& program) const {
Parent::postLinkProgram(programObject, program); Parent::postLinkProgram(programObject, program);
const auto& glprogram = programObject.glprogram; 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 // For the UBOs, use glUniformBlockBinding to fixup the locations based on the reflection
{ {
const auto& expectedUbos = reflection.uniformBuffers; 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 // 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& expectedResourceBuffers = reflection.resourceBuffers;
const auto names = Shader::Reflection::getNames(expectedResourceBuffers); const auto names = Shader::Reflection::getNames(expectedResourceBuffers);
const auto resourceBufferUniforms = ::gl::Uniform::loadByName(glprogram, names); const auto resourceBufferUniforms = ::gl::Uniform::loadByName(glprogram, names);
for (const auto& resourceBuffer : resourceBufferUniforms) { 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); const auto& targetBinding = expectedResourceBuffers.at(resourceBuffer.name);
glProgramUniform1i(glprogram, resourceBuffer.binding, targetBinding); 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);
}
}
} }

View file

@ -43,17 +43,34 @@ Shader::Shader(Type type, const Pointer& vertex, const Pointer& geometry, const
shaders[VERTEX] = vertex; shaders[VERTEX] = vertex;
shaders[PIXEL] = pixel; shaders[PIXEL] = pixel;
} }
}
auto& reflection = const_cast<Reflection&>(getReflection()); Shader::Reflection Shader::getReflection(shader::Dialect dialect, shader::Variant variant) const {
for (const auto& subShader : _shaders) { if (_type == Shader::Type::PROGRAM) {
reflection.merge(subShader->getReflection()); Reflection reflection;
} for (const auto& subShader : _shaders) {
if (_shaders[VERTEX]) { reflection.merge(subShader->getReflection(dialect, variant));
reflection.inputs = _shaders[VERTEX]->getReflection().inputs; }
} if (_shaders[VERTEX]) {
if (_shaders[PIXEL]) { reflection.inputs = _shaders[VERTEX]->getReflection(dialect, variant).inputs;
reflection.outputs = _shaders[PIXEL]->getReflection().outputs; }
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() Shader::~Shader()

View file

@ -91,7 +91,8 @@ public:
const Shaders& getShaders() const { return _shaders; } 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 // 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 // the caller thread if the compilation fails and to provide a different version of the source for it

View file

@ -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_VERSION] = "#define PROCEDURAL_V" + std::to_string(_data.version);
fragmentSource.replacements[PROCEDURAL_BLOCK] = _shaderSource.toStdString(); fragmentSource.replacements[PROCEDURAL_BLOCK] = _shaderSource.toStdString();
// Set any userdata specified uniforms // Set any userdata specified uniforms (if any)
int customSlot = procedural::slot::uniform::Custom; if (!_data.uniforms.empty()) {
for (const auto& key : _data.uniforms.keys()) { // First grab all the possible dialect/variant/Reflections
std::string uniformName = key.toLocal8Bit().data(); std::vector<shader::Reflection*> allReflections;
fragmentSource.reflection.uniforms[uniformName] = customSlot; for (auto dialectIt = fragmentSource.dialectSources.begin(); dialectIt != fragmentSource.dialectSources.end(); ++dialectIt) {
++customSlot; 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 // Leave this here for debugging

View file

@ -48,6 +48,17 @@ using namespace render;
extern void initForwardPipelines(ShapePlumber& plumber); 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) { void RenderForwardTask::configure(const Config& config) {
// Propagate resolution scale to sub jobs who need it // Propagate resolution scale to sub jobs who need it
auto preparePrimaryBufferConfig = config.getConfig<PreparePrimaryFramebufferMSAA>("PreparePrimaryBufferForward"); auto preparePrimaryBufferConfig = config.getConfig<PreparePrimaryFramebufferMSAA>("PreparePrimaryBufferForward");

View file

@ -42,22 +42,14 @@ public:
class PreparePrimaryFramebufferMSAAConfig : public render::Job::Config { class PreparePrimaryFramebufferMSAAConfig : public render::Job::Config {
Q_OBJECT Q_OBJECT
Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale) Q_PROPERTY(float resolutionScale WRITE setResolutionScale READ getResolutionScale NOTIFY dirty)
Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples) Q_PROPERTY(int numSamples WRITE setNumSamples READ getNumSamples NOTIFY dirty)
public: public:
float getResolutionScale() const { return resolutionScale; } float getResolutionScale() const { return resolutionScale; }
void setResolutionScale(float scale) { 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();
}
int getNumSamples() const { return numSamples; } int getNumSamples() const { return numSamples; }
void setNumSamples(int num) { void setNumSamples(int num);
numSamples = std::max(1, std::min(32, num));
emit dirty();
}
signals: signals:
void dirty(); void dirty();

View file

@ -70,7 +70,7 @@ namespace render {
GPUTaskConfig() = default; GPUTaskConfig() = default;
GPUTaskConfig(bool enabled) : TaskConfig(enabled) {} GPUTaskConfig(bool enabled) : render::TaskConfig(enabled) {}
// Running Time measurement on GPU and for Batch execution // Running Time measurement on GPU and for Batch execution
void setGPUBatchRunTime(double msGpuTime, double msBatchTime) { _msGPURunTime = msGpuTime; _msBatchRunTime = msBatchTime; } void setGPUBatchRunTime(double msGpuTime, double msBatchTime) { _msGPURunTime = msGpuTime; _msBatchRunTime = msBatchTime; }

View file

@ -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, void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& program, const gpu::StatePointer& state,
BatchSetter batchSetter, ItemSetter itemSetter) { BatchSetter batchSetter, ItemSetter itemSetter) {
ShapeKey key{ filter._flags }; ShapeKey key{ filter._flags };
const auto& reflection = program->getReflection(); auto reflection = program->getReflection();
auto locations = std::make_shared<Locations>(); auto locations = std::make_shared<Locations>();
locations->albedoTextureUnit = reflection.validTexture(graphics::slot::texture::MaterialAlbedo); locations->albedoTextureUnit = reflection.validTexture(graphics::slot::texture::MaterialAlbedo);
locations->roughnessTextureUnit = reflection.validTexture(graphics::slot::texture::MaterialRoughness); locations->roughnessTextureUnit = reflection.validTexture(graphics::slot::texture::MaterialRoughness);

View file

@ -32,7 +32,7 @@ namespace shader {
#if defined(USE_GLES) #if defined(USE_GLES)
static const Dialect DEFAULT_DIALECT = Dialect::glsl310es; const Dialect DEFAULT_DIALECT = Dialect::glsl310es;
const std::vector<Dialect>& allDialects() { const std::vector<Dialect>& allDialects() {
static const std::vector<Dialect> ALL_DIALECTS{ { Dialect::glsl310es } }; static const std::vector<Dialect> ALL_DIALECTS{ { Dialect::glsl310es } };
@ -41,7 +41,7 @@ const std::vector<Dialect>& allDialects() {
#elif defined(Q_OS_MAC) #elif defined(Q_OS_MAC)
static const Dialect DEFAULT_DIALECT = Dialect::glsl410; const Dialect DEFAULT_DIALECT = Dialect::glsl410;
const std::vector<Dialect>& allDialects() { const std::vector<Dialect>& allDialects() {
static const std::vector<Dialect> ALL_DIALECTS{ Dialect::glsl410 }; static const std::vector<Dialect> ALL_DIALECTS{ Dialect::glsl410 };
@ -50,7 +50,7 @@ const std::vector<Dialect>& allDialects() {
#else #else
static const Dialect DEFAULT_DIALECT = Dialect::glsl450; const Dialect DEFAULT_DIALECT = Dialect::glsl450;
const std::vector<Dialect> & allDialects() { const std::vector<Dialect> & allDialects() {
static const std::vector<Dialect> ALL_DIALECTS{ { Dialect::glsl450, Dialect::glsl410 } }; static const std::vector<Dialect> ALL_DIALECTS{ { Dialect::glsl450, Dialect::glsl410 } };
@ -131,7 +131,6 @@ Source::Pointer Source::loadSource(uint32_t shaderId) {
for (const auto& dialect : dialects) { for (const auto& dialect : dialects) {
result->dialectSources[dialect] = loadDialectSource(dialect, shaderId); result->dialectSources[dialect] = loadDialectSource(dialect, shaderId);
} }
result->reflection = result->dialectSources[DEFAULT_DIALECT].variantSources[Variant::Mono].reflection;
return result; return result;
} }
@ -140,7 +139,6 @@ Source& Source::operator=(const Source& other) {
name = other.name; name = other.name;
dialectSources = other.dialectSources; dialectSources = other.dialectSources;
replacements = other.replacements; replacements = other.replacements;
reflection = other.reflection;
return *this; return *this;
} }

View file

@ -42,6 +42,8 @@ enum class Dialect
#endif #endif
}; };
extern const Dialect DEFAULT_DIALECT;
const std::vector<Dialect>& allDialects(); const std::vector<Dialect>& allDialects();
const std::string& dialectPath(Dialect dialect); const std::string& dialectPath(Dialect dialect);
@ -140,9 +142,6 @@ struct Source {
// The name of the shader file, with extension, i.e. DrawColor.frag // The name of the shader file, with extension, i.e. DrawColor.frag
std::string name; std::string name;
// Generic reflection, copied from the 450 dialect / mono variant
Reflection reflection;
// Map of platforms to their specific shaders // Map of platforms to their specific shaders
std::unordered_map<Dialect, DialectSource, EnumClassHash> dialectSources; std::unordered_map<Dialect, DialectSource, EnumClassHash> dialectSources;

View file

@ -79,8 +79,8 @@ void JobConfig::refresh() {
_jobConcept->applyConfiguration(); _jobConcept->applyConfiguration();
} }
TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& jobName) const { JobConfig* JobConfig::getRootConfig(const std::string& jobPath, std::string& jobName) const {
TaskConfig* root = const_cast<TaskConfig*> (this); JobConfig* root = const_cast<JobConfig*> (this);
std::list<std::string> tokens; std::list<std::string> tokens;
std::size_t pos = 0, sepPos; std::size_t pos = 0, sepPos;
@ -105,7 +105,7 @@ TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& j
while (tokens.size() > 1) { while (tokens.size() > 1) {
auto taskName = tokens.front(); auto taskName = tokens.front();
tokens.pop_front(); tokens.pop_front();
root = root->findChild<TaskConfig*>((taskName.empty() ? QString() : QString(taskName.c_str()))); root = root->findChild<JobConfig*>((taskName.empty() ? QString() : QString(taskName.c_str())));
if (!root) { if (!root) {
return nullptr; return nullptr;
} }
@ -115,7 +115,7 @@ TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& j
return root; return root;
} }
JobConfig* TaskConfig::getJobConfig(const std::string& jobPath) const { JobConfig* JobConfig::getJobConfig(const std::string& jobPath) const {
std::string jobName; std::string jobName;
auto root = getRootConfig(jobPath, 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) { if (_branch != branch) {
_branch = branch; _branch = branch;
// We can re-use this signal here // We can re-use this signal here
emit dirtyEnabled(); emit dirtyEnabled();
} }
} }

View file

@ -83,11 +83,19 @@ protected:
Setting::Handle<QString> _preset; Setting::Handle<QString> _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) // A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled)
class JobConfig : public QObject { class JobConfig : public QObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled()) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled())
Q_PROPERTY(int branch READ getBranch WRITE setBranch NOTIFY dirtyEnabled)
double _msCPURunTime{ 0.0 }; double _msCPURunTime{ 0.0 };
@ -96,7 +104,11 @@ protected:
bool _isEnabled{ true }; bool _isEnabled{ true };
uint8_t _branch { 0 };
public: public:
bool _isTask{ false };
bool _isSwitch{ false };
using Persistent = PersistentConfig<JobConfig>; using Persistent = PersistentConfig<JobConfig>;
JobConfig() = default; JobConfig() = default;
@ -121,44 +133,83 @@ public:
*/ */
Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); } 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 // Running Time measurement
// The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated // 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<double, std::milli>(runtime).count(); emit newStats(); } void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration<double, std::milli>(runtime).count(); emit newStats(); }
double getCPURunTime() const { return _msCPURunTime; } double getCPURunTime() const { return _msCPURunTime; }
// Describe the node graph data connections of the associated Job/Task
/**jsdoc /**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:
// - <job_name> search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root)
// - <parent_name>.[<sub_parent_names>.]<job_name>
// 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<TConfigProxy>(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 <class T> typename T::Config* getConfig(std::string jobPath = "") const {
return dynamic_cast<typename T::Config*>(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} * @returns {boolean}
*/ */
Q_INVOKABLE virtual bool isTask() const { return false; } Q_INVOKABLE bool isSwitch() const { return _isSwitch; }
/**jsdoc /**jsdoc
* @function Workload.getSubConfigs * @function JobConfig.getSubConfigs
* @returns {object[]} * @returns {object[]}
*/ */
Q_INVOKABLE virtual QObjectList getSubConfigs() const { return QObjectList(); } Q_INVOKABLE QObjectList getSubConfigs() const {
auto list = findChildren<JobConfig*>(QRegExp(".*"), Qt::FindDirectChildrenOnly);
QObjectList returned;
for (int i = 0; i < list.size(); i++) {
returned.push_back(list[i]);
}
return returned;
}
/**jsdoc /**jsdoc
* @function Workload.getNumSubs * @function JobConfig.getNumSubs
* @returns {number} * @returns {number}
*/ */
Q_INVOKABLE virtual int getNumSubs() const { return 0; } Q_INVOKABLE int getNumSubs() const { return getSubConfigs().size(); }
/**jsdoc /**jsdoc
* @function Workload.getSubConfig * @function JobConfig.getSubConfig
* @param {number} index * @param {number} index
* @returns {object} * @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<JobConfig> childConfig, const std::string& name); void connectChildConfig(std::shared_ptr<JobConfig> childConfig, const std::string& name);
void transferChildrenConfigs(std::shared_ptr<JobConfig> source); void transferChildrenConfigs(std::shared_ptr<JobConfig> source);
JobConcept* _jobConcept; JobConcept* _jobConcept;
uint8_t getBranch() const { return _branch; }
void setBranch(uint8_t index);
public slots: public slots:
/**jsdoc /**jsdoc
@ -195,82 +246,6 @@ signals:
using QConfigPointer = std::shared_ptr<JobConfig>; using QConfigPointer = std::shared_ptr<JobConfig>;
class TConfigProxy {
public:
using Config = JobConfig;
};
/**jsdoc
* @namespace Workload
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*
* @property {number} cpuRunTime - <em>Read-only.</em>
* @property {boolean} enabled
*/
class TaskConfig : public JobConfig {
Q_OBJECT
public:
using Persistent = PersistentConfig<TaskConfig>;
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:
// - <job_name> search for the first job named job_name traversing the the sub graph of task and jobs (from this task as root)
// - <parent_name>.[<sub_parent_names>.]<job_name>
// 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<TConfigProxy>(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 <class T> typename T::Config* getConfig(std::string jobPath = "") const {
return dynamic_cast<typename T::Config*>(getJobConfig(jobPath));
}
Q_INVOKABLE bool isTask() const override { return true; }
Q_INVOKABLE QObjectList getSubConfigs() const override {
auto list = findChildren<JobConfig*>(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 #endif // hifi_task_Config_h

View file

@ -69,7 +69,7 @@ class JobConcept {
public: public:
using Config = JobConfig; 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; virtual ~JobConcept() = default;
const std::string& getName() const { return _name; } const std::string& getName() const { return _name; }
@ -80,7 +80,7 @@ public:
virtual QConfigPointer& getConfiguration() { return _config; } virtual QConfigPointer& getConfiguration() { return _config; }
virtual void applyConfiguration() = 0; virtual void applyConfiguration() = 0;
void setCPURunTime(const std::chrono::nanoseconds& runtime) { std::static_pointer_cast<Config>(_config)->setCPURunTime(runtime); } void setCPURunTime(const std::chrono::nanoseconds& runtime) { (_config)->setCPURunTime(runtime); }
QConfigPointer _config; QConfigPointer _config;
protected: protected:
@ -94,9 +94,6 @@ template <class T, class C> void jobConfigure(T& data, const C& configuration) {
template<class T> void jobConfigure(T&, const JobConfig&) { template<class T> void jobConfigure(T&, const JobConfig&) {
// nop, as the default JobConfig was used, so the data does not need a configure method // nop, as the default JobConfig was used, so the data does not need a configure method
} }
template<class T> void jobConfigure(T&, const TaskConfig&) {
// nop, as the default TaskConfig was used, so the data does not need a configure method
}
template <class T, class JC> void jobRun(T& data, const JC& jobContext, const JobNoIO& input, JobNoIO& output) { template <class T, class JC> void jobRun(T& data, const JC& jobContext, const JobNoIO& input, JobNoIO& output) {
data.run(jobContext); data.run(jobContext);
@ -158,7 +155,17 @@ public:
return std::make_shared<Model>(name, input, std::make_shared<C>(), std::forward<A>(args)...); return std::make_shared<Model>(name, input, std::make_shared<C>(), std::forward<A>(args)...);
} }
void createConfiguration() {
// A brand new config
auto config = std::make_shared<C>();
// 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 { void applyConfiguration() override {
TimeProfiler probe(("configure::" + JobConcept::getName())); TimeProfiler probe(("configure::" + JobConcept::getName()));
@ -228,7 +235,7 @@ public:
using Context = JC; using Context = JC;
using TimeProfiler = TP; using TimeProfiler = TP;
using ContextPointer = std::shared_ptr<Context>; using ContextPointer = std::shared_ptr<Context>;
using Config = TaskConfig; using Config = JobConfig; //TaskConfig;
using JobType = Job<JC, TP>; using JobType = Job<JC, TP>;
using None = typename JobType::None; using None = typename JobType::None;
using Concept = typename JobType::Concept; using Concept = typename JobType::Concept;
@ -247,14 +254,14 @@ public:
const Varying getOutput() const override { return _output; } const Varying getOutput() const override { return _output; }
Varying& editInput() override { return _input; } 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 // Create a new job in the container's queue; returns the job's output
template <class NT, class... NA> const Varying addJob(std::string name, const Varying& input, NA&&... args) { template <class NT, class... NA> const Varying addJob(std::string name, const Varying& input, NA&&... args) {
_jobs.emplace_back((NT::JobModel::create(name, input, std::forward<NA>(args)...))); _jobs.emplace_back((NT::JobModel::create(name, input, std::forward<NA>(args)...)));
// Conect the child config to this task's config // Conect the child config to this task's config
std::static_pointer_cast<TaskConfig>(Concept::getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name); std::static_pointer_cast<JobConfig>(Concept::getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name);
return _jobs.back().getOutput(); return _jobs.back().getOutput();
} }
@ -284,9 +291,6 @@ public:
TimeProfiler probe("build::" + model->getName()); TimeProfiler probe("build::" + model->getName());
model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...); model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...);
} }
// Recreate the Config to use the templated type
model->createConfiguration();
model->applyConfiguration();
return model; return model;
} }
@ -369,7 +373,7 @@ public:
using Context = JC; using Context = JC;
using TimeProfiler = TP; using TimeProfiler = TP;
using ContextPointer = std::shared_ptr<Context>; using ContextPointer = std::shared_ptr<Context>;
using Config = SwitchConfig; using Config = JobConfig; //SwitchConfig;
using JobType = Job<JC, TP>; using JobType = Job<JC, TP>;
using None = typename JobType::None; using None = typename JobType::None;
using Concept = typename JobType::Concept; using Concept = typename JobType::Concept;
@ -388,14 +392,15 @@ public:
const Varying getOutput() const override { return _output; } const Varying getOutput() const override { return _output; }
Varying& editInput() override { return _input; } 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 <class NT, class... NA> const Varying addBranch(std::string name, uint8_t index, const Varying& input, NA&&... args) { template <class NT, class... NA> const Varying addBranch(std::string name, uint8_t index, const Varying& input, NA&&... args) {
auto& branch = _branches[index]; auto& branch = _branches[index];
branch = JobType(NT::JobModel::create(name, input, std::forward<NA>(args)...)); branch = JobType(NT::JobModel::create(name, input, std::forward<NA>(args)...));
// Conect the child config to this task's config // Conect the child config to this task's config
std::static_pointer_cast<SwitchConfig>(Concept::getConfiguration())->connectChildConfig(branch.getConfiguration(), name); std::static_pointer_cast<JobConfig>(Concept::getConfiguration())->connectChildConfig(branch.getConfiguration(), name);
return branch.getOutput(); return branch.getOutput();
} }
@ -405,7 +410,7 @@ public:
} }
}; };
template <class T, class C = SwitchConfig, class I = None, class O = None> class SwitchModel : public SwitchConcept { template <class T, class C = Config, class I = None, class O = None> class SwitchModel : public SwitchConcept {
public: public:
using Data = T; using Data = T;
using Input = I; using Input = I;
@ -426,9 +431,6 @@ public:
TimeProfiler probe("build::" + model->getName()); TimeProfiler probe("build::" + model->getName());
model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...); model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...);
} }
// Recreate the Config to use the templated type
model->createConfiguration();
model->applyConfiguration();
return model; return model;
} }
@ -475,8 +477,8 @@ public:
} }
} }
}; };
template <class T, class C = SwitchConfig> using Model = SwitchModel<T, C, None, None>; template <class T, class C = Config> using Model = SwitchModel<T, C, None, None>;
template <class T, class I, class C = SwitchConfig> using ModelI = SwitchModel<T, C, I, None>; template <class T, class I, class C = Config> using ModelI = SwitchModel<T, C, I, None>;
// TODO: Switches don't support Outputs yet // TODO: Switches don't support Outputs yet
//template <class T, class O, class C = SwitchConfig> using ModelO = SwitchModel<T, C, None, O>; //template <class T, class O, class C = SwitchConfig> using ModelO = SwitchModel<T, C, None, O>;
//template <class T, class I, class O, class C = SwitchConfig> using ModelIO = SwitchModel<T, C, I, O>; //template <class T, class I, class O, class C = SwitchConfig> using ModelIO = SwitchModel<T, C, I, O>;
@ -500,7 +502,7 @@ class Engine : public Task<JC, TP> {
public: public:
using Context = JC; using Context = JC;
using ContextPointer = std::shared_ptr<Context>; using ContextPointer = std::shared_ptr<Context>;
using Config = TaskConfig; using Config = JobConfig; //TaskConfig;
using TaskType = Task<JC, TP>; using TaskType = Task<JC, TP>;
using ConceptPointer = typename TaskType::ConceptPointer; using ConceptPointer = typename TaskType::ConceptPointer;
@ -526,10 +528,11 @@ protected:
} }
#define Task_DeclareTypeAliases(ContextType, TimeProfiler) \ #define Task_DeclareTypeAliases(ContextType, TimeProfiler) \
using JobConfig = task::JobConfig; \ using JobConfig = task::JobConfig; \
using TaskConfig = task::TaskConfig; \ using TaskConfig = task::JobConfig; \
using SwitchConfig = task::SwitchConfig; \ using SwitchConfig = task::JobConfig; \
template <class T> using PersistentConfig = task::PersistentConfig<T>; \ template <class T> using PersistentConfig = task::PersistentConfig<T>; \
using Job = task::Job<ContextType, TimeProfiler>; \ using Job = task::Job<ContextType, TimeProfiler>; \
using Switch = task::Switch<ContextType, TimeProfiler>; \ using Switch = task::Switch<ContextType, TimeProfiler>; \

View file

@ -18,7 +18,7 @@
// @param depth: the depth of the recurse loop since the initial call. // @param depth: the depth of the recurse loop since the initial call.
function task_traverse(root, functor, depth) { function task_traverse(root, functor, depth) {
if (root.isTask()) { if (root.isTask()) {
depth++; depth++;
for (var i = 0; i <root.getNumSubs(); i++) { for (var i = 0; i <root.getNumSubs(); i++) {
var sub = root.getSubConfig(i); var sub = root.getSubConfig(i);
if (functor(sub, depth, i)) { if (functor(sub, depth, i)) {
@ -41,15 +41,19 @@ function task_traverseTree(root, functor) {
function job_propKeys(job) { function job_propKeys(job) {
var keys = Object.keys(job) var keys = Object.keys(job)
var propKeys = []; var propKeys = [];
if (job.isSwitch()) {
propKeys.push("branch")
}
for (var k=0; k < keys.length;k++) { for (var k=0; k < keys.length;k++) {
// Filter for relevant property // Filter for relevant property
var key = keys[k] var key = keys[k]
if ((typeof job[key]) !== "function") { if ((typeof job[key]) !== "function") {
if ((key !== "objectName") && (key !== "cpuRunTime") && (key !== "enabled")) { if ((key !== "objectName") && (key !== "cpuRunTime") && (key !== "enabled") && (key !== "branch")) {
propKeys.push(keys[k]); propKeys.push(keys[k]);
} }
} }
} }
return propKeys; return propKeys;
} }

View file

@ -12,9 +12,6 @@ import QtQuick 2.7
import QtQuick.Controls 1.4 as Original import QtQuick.Controls 1.4 as Original
import QtQuick.Controls.Styles 1.4 import QtQuick.Controls.Styles 1.4
import stylesUit 1.0
import controlsUit 1.0 as HifiControls
import "../../prop" as Prop import "../../prop" as Prop
import "../jet.js" as Jet import "../jet.js" as Jet
@ -23,6 +20,8 @@ Prop.PropGroup {
id: root; id: root;
Prop.Global { id: global;}
property var rootConfig : Render property var rootConfig : Render
property var jobPath: "" property var jobPath: ""
property alias label: root.label property alias label: root.label
@ -30,7 +29,7 @@ Prop.PropGroup {
property var showProps: true property var showProps: true
property var showSubs: true property var showSubs: true
property var jobEnabled: rootConfig.getConfig(jobPath).enabled property bool jobEnabled: rootConfig.getConfig(jobPath).enabled
property var jobCpuTime: pullCpuTime() property var jobCpuTime: pullCpuTime()
function pullCpuTime() { function pullCpuTime() {
@ -72,8 +71,8 @@ Prop.PropGroup {
id: enabledIcon id: enabledIcon
anchors.right:parent.right anchors.right:parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
filled: root.jobEnabled filled: true
fillColor: (root.jobEnabled ? global.colorGreenHighlight : global.colorOrangeAccent) fillColor: (root.jobEnabled ? global.colorGreenHighlight : global.colorRedAccent)
icon: 5 icon: 5
MouseArea{ MouseArea{
@ -92,7 +91,7 @@ Prop.PropGroup {
// console.log(JSON.stringify(props)); // console.log(JSON.stringify(props));
if (showProps) { if (showProps) {
for (var p in props) { for (var p in props) {
propsModel.push({"object": rootConfig.getConfig(jobPath), "property":props[p] }) propsModel.push({"object": rootConfig.getConfig(jobPath), "property":props[p]})
} }
root.updatePropItems(root.propItemsPanel, propsModel); root.updatePropItems(root.propItemsPanel, propsModel);
} }

View file

@ -68,7 +68,7 @@ PropFolderPanel {
"min": (proItem["min"] !== undefined ? proItem.min : 0.0), "min": (proItem["min"] !== undefined ? proItem.min : 0.0),
"max": (proItem["max"] !== undefined ? proItem.max : 1.0), "max": (proItem["max"] !== undefined ? proItem.max : 1.0),
"integer": (proItem["integral"] !== undefined ? proItem.integral : false), "integer": (proItem["integral"] !== undefined ? proItem.integral : false),
"readOnly": (proItem["readOnly"] !== undefined ? proItem["readOnly"] : false), "readOnly": (proItem["readOnly"] !== undefined ? proItem["readOnly"] : true),
}) })
} break; } break;
case 'PropEnum': { case 'PropEnum': {
@ -136,30 +136,32 @@ PropFolderPanel {
function populateFromObjectProps(object) { function populateFromObjectProps(object) {
var propsModel = [] var propsModel = []
var props = Object.keys(object); if (object !== undefined) {
for (var p in props) { var props = Object.keys(object);
var o = {}; for (var p in props) {
o["object"] = object var o = {};
o["property"] = props[p]; o["object"] = object
// o["readOnly"] = true; o["property"] = props[p];
// o["readOnly"] = true;
var thePropThing = object[props[p]];
if ((thePropThing !== undefined) && (thePropThing !== null)) {
var theType = typeof(thePropThing)
switch(theType) {
case 'object': {
o["type"] = "object";
propsModel.push(o)
} break;
default: {
o["type"] = "string";
propsModel.push(o)
} break;
}
} else { var thePropThing = object[props[p]];
o["type"] = "string"; if ((thePropThing !== undefined) && (thePropThing !== null)) {
propsModel.push(o) var theType = typeof(thePropThing)
switch(theType) {
case 'object': {
o["type"] = "object";
propsModel.push(o)
} break;
default: {
o["type"] = "string";
propsModel.push(o)
} break;
}
} else {
o["type"] = "string";
propsModel.push(o)
}
} }
} }

View file

@ -44,8 +44,8 @@ Item {
property alias labelControl: labelControl property alias labelControl: labelControl
property alias label: labelControl.text property alias label: labelControl.text
property var labelAreaWidth: root.width * global.splitterRightWidthScale - global.splitterWidth property var labelAreaWidth: root.width * global.splitterLeftWidthScale - global.splitterWidth
PropText { PropText {
id: labelControl id: labelControl
text: root.label text: root.label

View file

@ -1,5 +1,5 @@
// //
// PropItem.qml // PropScalar.qml
// //
// Created by Sam Gateau on 3/2/2019 // Created by Sam Gateau on 3/2/2019
// Copyright 2019 High Fidelity, Inc. // Copyright 2019 High Fidelity, Inc.
@ -42,8 +42,8 @@ PropItem {
enabled: root.showValue enabled: root.showValue
anchors.left: root.splitter.right anchors.left: root.splitter.right
anchors.right: (root.readOnly ? root.right : sliderControl.left)
anchors.verticalCenter: root.verticalCenter anchors.verticalCenter: root.verticalCenter
width: root.width * (root.readOnly ? 1.0 : global.valueAreaWidthScale)
horizontalAlignment: global.valueTextAlign horizontalAlignment: global.valueTextAlign
height: global.slimHeight height: global.slimHeight
@ -55,17 +55,25 @@ PropItem {
border.width: global.valueBorderWidth border.width: global.valueBorderWidth
radius: global.valueBorderRadius radius: global.valueBorderRadius
} }
MouseArea{
id: mousearea
anchors.fill: parent
onDoubleClicked: { sliderControl.visible = !sliderControl.visible }
}
} }
HifiControls.Slider { HifiControls.Slider {
id: sliderControl id: sliderControl
visible: !root.readOnly visible: !root.readOnly
stepSize: root.integral ? 1.0 : 0.0 stepSize: root.integral ? 1.0 : 0.0
anchors.left: valueLabel.right
anchors.right: root.right
anchors.verticalCenter: root.verticalCenter
value: root.sourceValueVar value: root.sourceValueVar
onValueChanged: { applyValueVarFromWidgets(value) } onValueChanged: { applyValueVarFromWidgets(value) }
width: root.width * (root.readOnly ? 0.0 : global.handleAreaWidthScale)
anchors.right: root.right
anchors.verticalCenter: root.verticalCnter
} }

View file

@ -31,16 +31,17 @@ Item {
readonly property color colorBorderHighight: hifi.colors.blueHighlight readonly property color colorBorderHighight: hifi.colors.blueHighlight
readonly property color colorBorderLighter: hifi.colors.faintGray readonly property color colorBorderLighter: hifi.colors.faintGray
readonly property color colorOrangeAccent: "#FF6309" readonly property color colorOrangeAccent: hifi.colors.orangeAccent
readonly property color colorRedAccent: "#C62147" readonly property color colorRedAccent: hifi.colors.redAccent
readonly property color colorGreenHighlight: "#1ac567" readonly property color colorGreenHighlight: hifi.colors.greenHighlight
readonly property real fontSize: 12 readonly property real fontSize: 12
readonly property var fontFamily: "Raleway" readonly property var fontFamily: "Raleway"
readonly property var fontWeight: Font.DemiBold readonly property var fontWeight: Font.DemiBold
readonly property color fontColor: hifi.colors.faintGray readonly property color fontColor: hifi.colors.faintGray
readonly property var splitterRightWidthScale: 0.45 readonly property var splitterLeftWidthScale: 0.45
readonly property var splitterRightWidthScale: 1.0 - splitterLeftWidthScale
readonly property real splitterWidth: 8 readonly property real splitterWidth: 8
readonly property real iconWidth: fontSize readonly property real iconWidth: fontSize
@ -49,8 +50,9 @@ Item {
readonly property var labelTextAlign: Text.AlignRight readonly property var labelTextAlign: Text.AlignRight
readonly property var labelTextElide: Text.ElideMiddle readonly property var labelTextElide: Text.ElideMiddle
readonly property var valueAreaWidthScale: 0.3 * (1.0 - splitterRightWidthScale) readonly property var valueAreaWidthScale: 0.3 * (splitterRightWidthScale)
readonly property var handleAreaWidthScale: 0.7 * (splitterRightWidthScale)
readonly property var valueTextAlign: Text.AlignHCenter readonly property var valueTextAlign: Text.AlignHCenter
readonly property real valueBorderWidth: 1 readonly property real valueBorderWidth: 1
readonly property real valueBorderRadius: 2 readonly property real valueBorderRadius: 2
} }

View file

@ -1,57 +1,5 @@
(function() { var window = Desktop.createWindow(Script.resolvePath('./engineInspector.qml'), {
var TABLET_BUTTON_NAME = "Inspector"; title: "Render Engine Inspector",
var QMLAPP_URL = Script.resolvePath("./engineInspector.qml"); presentationMode: Desktop.PresentationMode.NATIVE,
var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); size: {x: 350, y: 700}
var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); });
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var button = tablet.addButton({
text: TABLET_BUTTON_NAME,
icon: ICON_URL,
activeIcon: ACTIVE_ICON_URL
});
Script.scriptEnding.connect(function () {
killWindow()
button.clicked.disconnect(onClicked);
tablet.removeButton(button);
});
button.clicked.connect(onClicked);
var onScreen = false;
var window;
function onClicked() {
if (onScreen) {
killWindow()
} else {
createWindow()
}
}
function createWindow() {
var qml = Script.resolvePath(QMLAPP_URL);
window = new OverlayWindow({
title: 'Render Engine Inspector',
source: qml,
width: 250,
height: 500
});
window.setPosition(200, 50);
window.closed.connect(killWindow);
onScreen = true
button.editProperties({isActive: true});
}
function killWindow() {
if (window !== undefined) {
window.closed.disconnect(killWindow);
window.close()
window = undefined
}
onScreen = false
button.editProperties({isActive: false})
}
}());

View file

@ -8,23 +8,32 @@
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
// //
import QtQuick 2.7 import QtQuick 2.7
import QtQuick.Controls 1.4 import QtQuick.Controls 2.5
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import stylesUit 1.0
import controlsUit 1.0 as HifiControls
import "../lib/jet/qml" as Jet import "../lib/jet/qml" as Jet
Item { Item {
HifiConstants { id: hifi;} anchors.fill: parent
id: root; id: root;
anchors.fill: parent
property var rootConfig: Render.getConfig("") property var rootConfig: Render.getConfig("")
Jet.TaskListView { ScrollView {
rootConfig: root.rootConfig id: scrollView
anchors.fill: root anchors.fill: parent
contentWidth: parent.width
clip: true
Column {
anchors.left: parent.left
anchors.right: parent.right
Jet.TaskPropView {
rootConfig: root.rootConfig
anchors.fill: root
}
}
} }
} }

View file

@ -1,13 +1,5 @@
function openEngineTaskView() { var window = Desktop.createWindow(Script.resolvePath('./engineList.qml'), {
// Set up the qml ui title: "Render Engine Inspector",
var qml = Script.resolvePath('engineList.qml'); presentationMode: Desktop.PresentationMode.NATIVE,
var window = new OverlayWindow({ size: {x: 350, y: 700}
title: 'Render Engine', });
source: qml,
width: 300,
height: 400
});
window.setPosition(200, 50);
//window.closed.connect(function() { Script.stop(); });
}
openEngineTaskView();

View file

@ -24,7 +24,7 @@ Item {
property var mainViewTask: Render.getConfig("RenderMainView") property var mainViewTask: Render.getConfig("RenderMainView")
Jet.TaskList { Jet.TaskList {
rootConfig: Render rootConfig: Render.getConfig("")
anchors.fill: render anchors.fill: render
} }
} }

View file

@ -32,7 +32,16 @@ Rectangle {
clip: true clip: true
Column { Column {
id: column
width: parent.width width: parent.width
Prop.PropFolderPanel {
label: "Render Settings"
isUnfold: false
panelFrameData: Component {
RenderSettings {
}
}
}
Prop.PropFolderPanel { Prop.PropFolderPanel {
label: "Shading Model" label: "Shading Model"
panelFrameData: Component { panelFrameData: Component {
@ -73,17 +82,26 @@ Rectangle {
label: "Tools" label: "Tools"
panelFrameData: Component { panelFrameData: Component {
Row { Row {
HifiControls.Button {
text: "Engine"
onClicked: {
sendToScript({method: "openEngineInspectorView"});
}
width:column.width / 3
}
HifiControls.Button { HifiControls.Button {
text: "LOD" text: "LOD"
onClicked: { onClicked: {
sendToScript({method: "openEngineLODView"}); sendToScript({method: "openEngineLODView"});
} }
width:column.width / 3
} }
HifiControls.Button { HifiControls.Button {
text: "Material" text: "Material"
onClicked: { onClicked: {
sendToScript({method: "openMaterialInspectorView"}); sendToScript({method: "openMaterialInspectorView"});
} }
width:column.width / 3
} }
} }
} }

View file

@ -18,6 +18,8 @@ import controlsUit 1.0 as HifiControls
import "../configSlider" import "../configSlider"
import "../../lib/plotperf" import "../../lib/plotperf"
import "../../lib/prop" as Prop
Column{ Column{
HifiConstants { id: hifi; } HifiConstants { id: hifi; }
@ -28,7 +30,14 @@ Column{
anchors.right: parent.right anchors.right: parent.right
spacing: 10 spacing: 10
Prop.PropScalar {
label: "MSAA"
object: Render.getConfig("RenderMainView.PreparePrimaryBufferForward")
property: "numSamples"
min: 1
max: 32
integral: true
}
Row { Row {
spacing: 10 spacing: 10
id: fxaaOnOff id: fxaaOnOff

View file

@ -69,6 +69,7 @@ function openView() {
} }
pages.addPage('Luci', 'Luci', '../luci.qml', 300, 420, openLuciWindow, closeLuciWindow); pages.addPage('Luci', 'Luci', '../luci.qml', 300, 420, openLuciWindow, closeLuciWindow);
pages.addPage('openEngineInspectorView', 'Render Engine Inspector', '../engineInspector.qml', 300, 400);
pages.addPage('openEngineLODView', 'Render LOD', '../lod.qml', 300, 400); pages.addPage('openEngineLODView', 'Render LOD', '../lod.qml', 300, 400);
pages.addPage('openMaterialInspectorView', 'Material Inspector', '../materialInspector.qml', 300, 400, MaterialInspector.setWindow, MaterialInspector.setWindow); pages.addPage('openMaterialInspectorView', 'Material Inspector', '../materialInspector.qml', 300, 400, MaterialInspector.setWindow, MaterialInspector.setWindow);