Example #1
0
bool
UsdSkelTopology::Validate(std::string* reason) const
{
    TRACE_FUNCTION();

    if(!TF_VERIFY(GetNumJoints() == 0 || _parentIndicesData))
        return false;

    for(size_t i = 0; i < GetNumJoints(); ++i) {
        int parent = _parentIndicesData[i];
        if(parent >= 0) {   
            if(ARCH_UNLIKELY(static_cast<size_t>(parent) >= i)) {
                if(static_cast<size_t>(parent) == i) {
                    if(reason) {
                        *reason = TfStringPrintf(
                            "Joint %zu has itself as its parent.", i);
                    }
                    return false;
                }

                if(reason) {
                    *reason = TfStringPrintf(
                        "Joint %zu has mis-ordered parent %d. Joints are "
                        "expected to be ordered with parent joints always "
                        "coming before children.", i, parent);

                    // XXX: Note that this ordering restriction is a schema
                    // requirement primarily because it simplifies hierarchy
                    // evaluation (see UsdSkelConcatJointTransforms)
                    // But a nice side effect for validation purposes is that
                    // it also ensures that topology is non-cyclic.
                }
                return false;
            }
        }
    }
    return true;
}
Example #2
0
UsdMayaGLBatchRenderer::TaskDelegate::TaskDelegate(
    HdRenderIndex *renderIndex, SdfPath const& delegateID)
    : HdSceneDelegate(renderIndex, delegateID)
{
    _lightingContext = GlfSimpleLightingContext::New();

    // populate tasks in renderindex

    // create an unique namespace
    _rootId = delegateID.AppendChild(
        TfToken(TfStringPrintf("_UsdImaging_%p", this)));

    _simpleLightTaskId          = _rootId.AppendChild(_tokens->simpleLightTask);
    _cameraId                   = _rootId.AppendChild(_tokens->camera);

    // camera
    {
        // Since we're hardcoded to use HdStRenderDelegate, we expect to
        // have camera Sprims.
        TF_VERIFY(renderIndex->IsSprimTypeSupported(HdPrimTypeTokens->camera));

        renderIndex->InsertSprim(HdPrimTypeTokens->camera, this, _cameraId);
        _ValueCache &cache = _valueCacheMap[_cameraId];
        cache[HdStCameraTokens->worldToViewMatrix] = VtValue(GfMatrix4d(1.0));
        cache[HdStCameraTokens->projectionMatrix] = VtValue(GfMatrix4d(1.0));
        cache[HdStCameraTokens->windowPolicy] = VtValue();  // no window policy.
    }

    // simple lighting task (for Hydra native)
    {
        renderIndex->InsertTask<HdxSimpleLightTask>(this, _simpleLightTaskId);
        _ValueCache &cache = _valueCacheMap[_simpleLightTaskId];
        HdxSimpleLightTaskParams taskParams;
        taskParams.cameraPath = _cameraId;
        cache[HdTokens->params] = VtValue(taskParams);
        cache[HdTokens->children] = VtValue(SdfPathVector());
    }
}
Example #3
0
bool 
UsdMtlxFileFormat::ReadFromString(
    const SdfLayerBasePtr& layerBase,
    const std::string& str) const
{
    TRACE_FUNCTION();

    SdfLayerHandle layer = TfDynamic_cast<SdfLayerHandle>(layerBase);
    if (!TF_VERIFY(layer)) {
        return false;
    }

    auto stage = UsdStage::CreateInMemory();
    if (!_Read(stage,
               [&str](mx::DocumentPtr d) {
                    mx::readFromXmlString(d, str);
               })) {
        return false;
    }

    layer->TransferContent(stage->GetRootLayer());
    return true;
}
Example #4
0
void 
Sdf_SubLayerListEditor::_OnEdit(
    SdfListOpType op,
    const std::vector<std::string>& oldValues,
    const std::vector<std::string>& newValues) const
{
    // When sublayer paths are added or removed, we need to keep the
    // sublayer offsets vector (stored in a separate field) in sync.
    const SdfLayerOffsetVector oldLayerOffsets = _GetOwner()->
        GetFieldAs<SdfLayerOffsetVector>(SdfFieldKeys->SubLayerOffsets);

    // If this is ever the case, bad things will probably happen as code
    // in SdfLayer assumes the two vectors are in sync.
    if (not TF_VERIFY(oldValues.size() == oldLayerOffsets.size(),
                      "Sublayer offsets do not match sublayer paths")) {
        return;
    }

    // Rebuild the layer offsets vector, retaining offsets.
    SdfLayerOffsetVector newLayerOffsets(newValues.size());
    for (size_t i = 0; i < newValues.size(); ++i) {
        const std::string& newLayer = newValues[i];

        std::vector<std::string>::const_iterator oldValuesIt = 
            std::find(oldValues.begin(), oldValues.end(), newLayer);
        if (oldValuesIt == oldValues.end()) {
            continue;
        }
        
        const size_t oldLayerOffsetIndex = 
            std::distance(oldValues.begin(), oldValuesIt);
        newLayerOffsets[i] = oldLayerOffsets[oldLayerOffsetIndex];
    }
    
    _GetOwner()->SetField(SdfFieldKeys->SubLayerOffsets, newLayerOffsets);
}
Example #5
0
void
Hd_TestDriver::_Init(HdReprSelector const &reprSelector)
{
    _renderIndex = HdRenderIndex::New(&_renderDelegate);
    TF_VERIFY(_renderIndex != nullptr);

    _sceneDelegate = new HdUnitTestDelegate(_renderIndex,
                                             SdfPath::AbsoluteRootPath());

    _reprSelector = reprSelector;

    GfMatrix4d viewMatrix = GfMatrix4d().SetIdentity();
    viewMatrix *= GfMatrix4d().SetTranslate(GfVec3d(0.0, 1000.0, 0.0));
    viewMatrix *= GfMatrix4d().SetRotate(GfRotation(GfVec3d(1.0, 0.0, 0.0), -90.0));

    GfFrustum frustum;
    frustum.SetPerspective(45, true, 1, 1.0, 10000.0);
    GfMatrix4d projMatrix = frustum.ComputeProjectionMatrix();

    SetCamera(viewMatrix, projMatrix, GfVec4d(0, 0, 512, 512));

    // set depthfunc to default
    _renderPassState->SetDepthFunc(HdCmpFuncLess);
}
Example #6
0
size_t
PcpPrimIndex_Graph::_CreateNodesForSubgraph(
    const PcpPrimIndex_Graph& subgraph, const PcpArc& arc)
{
    // The subgraph's root should never have a parent or origin node; we
    // rely on this invariant below.
    TF_VERIFY(!subgraph.GetRootNode().GetParentNode() &&
              !subgraph.GetRootNode().GetOriginNode());

    // Insert a copy of all of the node data in the given subgraph into our
    // node pool.
    const size_t oldNumNodes = _GetNumNodes();
    _data->finalized = false;
    _data->nodes.insert(
        _data->nodes.end(), 
        subgraph._data->nodes.begin(), subgraph._data->nodes.end());
    _nodeSitePaths.insert(
        _nodeSitePaths.end(), 
        subgraph._nodeSitePaths.begin(), subgraph._nodeSitePaths.end());
    _nodeHasSpecs.insert(
        _nodeHasSpecs.end(),
        subgraph._nodeHasSpecs.begin(), subgraph._nodeHasSpecs.end());        
    const size_t newNumNodes = _GetNumNodes();
    const size_t subgraphRootNodeIndex = oldNumNodes;

    // Set the arc connecting the root of the subgraph to the rest of the
    // graph.
    _Node& subgraphRoot = _data->nodes[subgraphRootNodeIndex];
    subgraphRoot.SetArc(arc);

    // XXX: This is very similar to code in _ApplyNodeIndexMapping that
    //      adjust node references. There must be a good way to factor
    //      all of that out...

    // Iterate over all of the newly-copied nodes and adjust references to
    // other nodes in the node pool.
    struct _ConvertOldToNewIndex {
        _ConvertOldToNewIndex(size_t base, size_t numNewNodes) :
            _base(base), _numNewNodes(numNewNodes) { }
        size_t operator()(size_t oldIndex) const
        {
            if (oldIndex != _Node::_invalidNodeIndex) {
                TF_VERIFY(oldIndex + _base < _numNewNodes);
                return oldIndex + _base;
            }
            else {
                return oldIndex;
            }
        }
        size_t _base;
        size_t _numNewNodes;
    };
    const _ConvertOldToNewIndex convertToNewIndex(subgraphRootNodeIndex,
                                                  newNumNodes);

    for (size_t i = oldNumNodes; i < newNumNodes; ++i) {
        _Node& newNode = _data->nodes[i];

        // Update the node's mapToRoot since it is now part of a new graph.
        if (i != subgraphRootNodeIndex) {
            newNode.mapToRoot =
                subgraphRoot.mapToRoot.Compose(newNode.mapToRoot);
        }

        // The parent and origin of the root of the newly-inserted subgraph 
        // don't need to be fixed up because it doesn't point to a node 
        // within the subgraph.
        if (i != subgraphRootNodeIndex) {
            PARENT(newNode) = convertToNewIndex(PARENT(newNode));
            ORIGIN(newNode) = convertToNewIndex(ORIGIN(newNode));
        }

        FIRST_CHILD(newNode)  = convertToNewIndex(FIRST_CHILD(newNode));
        LAST_CHILD(newNode)   = convertToNewIndex(LAST_CHILD(newNode));
        PREV_SIBLING(newNode) = convertToNewIndex(PREV_SIBLING(newNode));
        NEXT_SIBLING(newNode) = convertToNewIndex(NEXT_SIBLING(newNode));
    }

    return subgraphRootNodeIndex;
}
Example #7
0
bool
HdxIntersector::Query(HdxIntersector::Params const& params,
                      HdRprimCollection const& col,
                      HdEngine* engine,
                      HdxIntersector::Result* result)
{
    TRACE_FUNCTION();

    // Make sure we're in a sane GL state before attempting anything.
    if (GlfHasLegacyGraphics()) {
        TF_RUNTIME_ERROR("framebuffer object not supported");
        return false;
    }
    GlfGLContextSharedPtr context = GlfGLContext::GetCurrentGLContext();
    if (!TF_VERIFY(context)) {
        TF_RUNTIME_ERROR("Invalid GL context");
        return false;
    }
    if (!_drawTarget) {
        // Initialize the shared draw target late to ensure there is a valid GL
        // context, which may not be the case at constructon time.
        _Init(GfVec2i(128,128));
    }

    GfVec2i size(_drawTarget->GetSize());
    GfVec4i viewport(0, 0, size[0], size[1]);

    if (!TF_VERIFY(_renderPass)) {
        return false;
    }
    _renderPass->SetRprimCollection(col);

    // Setup state based on incoming params.
    _renderPassState->SetAlphaThreshold(params.alphaThreshold);
    _renderPassState->SetClipPlanes(params.clipPlanes);
    _renderPassState->SetCullStyle(params.cullStyle);
    _renderPassState->SetCamera(params.viewMatrix, params.projectionMatrix, viewport);
    _renderPassState->SetLightingEnabled(false);

    // Use a separate drawTarget (framebuffer object) for each GL context
    // that uses this renderer, but the drawTargets share attachments/textures.
    GlfDrawTargetRefPtr drawTarget = GlfDrawTarget::New(size);

    // Clone attachments into this context. Note that this will do a
    // light-weight copy of the textures, it does not produce a full copy of the
    // underlying images.
    drawTarget->Bind();
    drawTarget->CloneAttachments(_drawTarget);

    //
    // Setup GL raster state
    //

    GLenum drawBuffers[3] = { GL_COLOR_ATTACHMENT0,
                              GL_COLOR_ATTACHMENT1,
                              GL_COLOR_ATTACHMENT2 };
    glDrawBuffers(3, drawBuffers);
    
    glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
    glDisable(GL_BLEND);

    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glDepthFunc(GL_LEQUAL);  

    glClearColor(0,0,0,0);
    glClearStencil(0);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

    glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);

    GLF_POST_PENDING_GL_ERRORS();
    
    //
    // Execute the picking pass
    //
    {
        GLuint vao;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
        // Setup stencil state and prevent writes to color buffer.
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_ALWAYS, 1, 1);
        glStencilOp(GL_KEEP,     // stencil failed
                    GL_KEEP,     // stencil passed, depth failed
                    GL_REPLACE); // stencil passed, depth passed

        //
        // Condition the stencil buffer.
        //
        params.depthMaskCallback();
        // we expect any GL state changes are restored.

        // Disable stencil updates and setup the stencil test.
        glStencilFunc(GL_LESS, 0, 1);
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        // Clear depth incase the depthMaskCallback pollutes the depth buffer.
        glClear(GL_DEPTH_BUFFER_BIT);
        // Restore color outputs & setup state for rendering
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glDisable(GL_CULL_FACE);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glFrontFace(GL_CCW);

        //
        // Enable conservative rasterization, if available.
        //
        // XXX: This wont work until it's in the Glew build.
        bool convRstr = glewIsSupported("GL_NV_conservative_raster");
        if (convRstr) {
            // XXX: this should come from Glew
            #define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346
            glEnable(GL_CONSERVATIVE_RASTERIZATION_NV);
        }

        // 
        // Execute
        //
        // XXX: make intersector a Task
        HdTaskSharedPtrVector tasks;
        tasks.push_back(boost::make_shared<HdxIntersector_DrawTask>(_renderPass,
                                                               _renderPassState,
                                                            params.renderTags));
        engine->Execute(*_index, tasks);

        glDisable(GL_STENCIL_TEST);

        if (convRstr) {
            // XXX: this should come from Glew
            #define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346
            glDisable(GL_CONSERVATIVE_RASTERIZATION_NV);
        }

        // Restore
        glBindVertexArray(0);
        glDeleteVertexArrays(1, &vao);
    }

    GLF_POST_PENDING_GL_ERRORS();

    //
    // Capture the result buffers to be resolved later.
    //
    size_t len = size[0] * size[1];
    std::unique_ptr<unsigned char[]> primId(new unsigned char[len*4]);
    std::unique_ptr<unsigned char[]> instanceId(new unsigned char[len*4]);
    std::unique_ptr<unsigned char[]> elementId(new unsigned char[len*4]);
    std::unique_ptr<float[]> depths(new float[len]);

    glBindTexture(GL_TEXTURE_2D,
        drawTarget->GetAttachments().at("primId")->GetGlTextureName());
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &primId[0]);

    glBindTexture(GL_TEXTURE_2D,
        drawTarget->GetAttachments().at("instanceId")->GetGlTextureName());
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &instanceId[0]);

    glBindTexture(GL_TEXTURE_2D,
        drawTarget->GetAttachments().at("elementId")->GetGlTextureName());
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &elementId[0]);

    glBindTexture(GL_TEXTURE_2D,
        drawTarget->GetAttachments().at("depth")->GetGlTextureName());
    glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
                    &depths[0]);

    glBindTexture(GL_TEXTURE_2D, 0);

    GLF_POST_PENDING_GL_ERRORS();

    if (result) {
        *result = HdxIntersector::Result(
            std::move(primId), std::move(instanceId), std::move(elementId),
            std::move(depths), _index, params, viewport);
    }

    drawTarget->Unbind();
    GLF_POST_PENDING_GL_ERRORS();

    return true;
}
Example #8
0
HdSt_DrawBatch::_DrawingProgram &
HdSt_DrawBatch::_GetDrawingProgram(HdStRenderPassStateSharedPtr const &state,
                                 bool indirect,
                                 HdStResourceRegistrySharedPtr const &resourceRegistry)
{
    HD_TRACE_FUNCTION();
    HF_MALLOC_TAG_FUNCTION();

    HdStDrawItem const *firstDrawItem = _drawItemInstances[0]->GetDrawItem();

    // Calculate unique hash to detect if the shader (composed) has changed
    // recently and we need to recompile it.
    size_t shaderHash = state->GetShaderHash();
    boost::hash_combine(shaderHash,
                        firstDrawItem->GetGeometricShader()->ComputeHash());
    HdStShaderCodeSharedPtr overrideShader = state->GetOverrideShader();
    HdStShaderCodeSharedPtr surfaceShader  = overrideShader ? overrideShader
                                       : firstDrawItem->GetMaterialShader();
    boost::hash_combine(shaderHash, surfaceShader->ComputeHash());
    bool shaderChanged = (_shaderHash != shaderHash);
    
    // Set shaders (lighting and renderpass) to the program. 
    // We need to do this before checking if the shaderChanged because 
    // it is possible that the shader does not need to 
    // be recompiled but some of the parameters have changed.
    HdStShaderCodeSharedPtrVector shaders = state->GetShaders();
    _program.SetShaders(shaders);
    _program.SetGeometricShader(firstDrawItem->GetGeometricShader());

    // XXX: if this function appears to be expensive, we might consider caching
    //      programs by shaderHash.
    if (!_program.GetGLSLProgram() || shaderChanged) {
        
        _program.SetSurfaceShader(surfaceShader);

        // Try to compile the shader and if it fails to compile we go back
        // to use the specified fallback surface shader.
        if (!_program.CompileShader(firstDrawItem, indirect, resourceRegistry)){

            // While the code should gracefully handle shader compilation
            // failures, it is also undesirable for shaders to silently fail.
            TF_CODING_ERROR("Failed to compile shader for prim %s.",
                            firstDrawItem->GetRprimID().GetText());


            // If we failed to compile the surface shader, replace it with the
            // fallback surface shader and try again.
            // XXX: Note that we only say "surface shader" here because it is
            // currently the only one that we allow customization for.  We
            // expect all the other shaders to compile or else the shipping
            // code is broken and needs to be fixed.  When we open up more
            // shaders for customization, we will need to check them as well.
            
            typedef boost::shared_ptr<class HioGlslfx> HioGlslfxSharedPtr;

            HioGlslfxSharedPtr glslSurfaceFallback = 
                HioGlslfxSharedPtr(
                        new HioGlslfx(HdStPackageFallbackSurfaceShader()));

            HdStShaderCodeSharedPtr fallbackSurface =
                HdStShaderCodeSharedPtr(
                    new HdStGLSLFXShader(glslSurfaceFallback));

            _program.SetSurfaceShader(fallbackSurface);

            bool res = _program.CompileShader(firstDrawItem, 
                                              indirect, 
                                              resourceRegistry);
            // We expect the fallback shader to always compile.
            TF_VERIFY(res);
        }

        _shaderHash = shaderHash;
    }

    return _program;
}
Example #9
0
void 
PcpPrimIndex_Graph::_ApplyNodeIndexMapping(
    const std::vector<size_t>& nodeIndexMap)
{
    _NodePool& oldNodes = _data->nodes;
    SdfPathVector& oldSitePaths = _nodeSitePaths;
    std::vector<bool>& oldHasSpecs = _nodeHasSpecs;
    TF_VERIFY(oldNodes.size() == oldSitePaths.size() &&
              oldNodes.size() == oldHasSpecs.size());
    TF_VERIFY(nodeIndexMap.size() == oldNodes.size());

    const size_t numNodesToErase = 
        std::count(nodeIndexMap.begin(), nodeIndexMap.end(), 
                   _Node::_invalidNodeIndex);

    const size_t oldNumNodes = oldNodes.size();
    const size_t newNumNodes = oldNumNodes - numNodesToErase;
    TF_VERIFY(newNumNodes <= oldNumNodes);

    struct _ConvertOldToNewIndex {
        _ConvertOldToNewIndex(const std::vector<size_t>& table,
                              size_t numNewNodes) : _table(table)
        {
            for (size_t i = 0, n = _table.size(); i != n; ++i) {
                TF_VERIFY(_table[i] < numNewNodes || 
                          _table[i] == _Node::_invalidNodeIndex);
            }
        }

        size_t operator()(size_t oldIndex) const
        {
            if (oldIndex != _Node::_invalidNodeIndex) {
                return _table[oldIndex];
            }
            else {
                return oldIndex;
            }
        }
        const std::vector<size_t>& _table;

    };

    const _ConvertOldToNewIndex convertToNewIndex(nodeIndexMap, newNumNodes);

    // If this mapping causes nodes to be erased, it's much more convenient
    // to fix up node indices to accommodate those erasures in the old node
    // pool before moving nodes to their new position. 
    if (numNodesToErase > 0) {
        for (size_t i = 0; i < oldNumNodes; ++i) {
            const size_t oldNodeIndex = i;
            const size_t newNodeIndex = convertToNewIndex(oldNodeIndex);

            _Node& node = _data->nodes[oldNodeIndex];

            // Sanity-check: If this node isn't going to be erased, its parent
            // can't be erased either.
            const bool nodeWillBeErased = 
                (newNodeIndex == _Node::_invalidNodeIndex);
            if (!nodeWillBeErased) {
                const bool parentWillBeErased = 
                    PARENT(node) != _Node::_invalidNodeIndex &&
                    convertToNewIndex(PARENT(node)) == _Node::_invalidNodeIndex;
                TF_VERIFY(!parentWillBeErased);
                continue;
            }

            if (PREV_SIBLING(node) != _Node::_invalidNodeIndex) {
                _Node& prevNode = _data->nodes[PREV_SIBLING(node)];
                NEXT_SIBLING(prevNode) = NEXT_SIBLING(node);
            }
            if (NEXT_SIBLING(node) != _Node::_invalidNodeIndex) {
                _Node& nextNode = _data->nodes[NEXT_SIBLING(node)];
                PREV_SIBLING(nextNode) = PREV_SIBLING(node);
            }

            _Node& parentNode = _data->nodes[PARENT(node)];
            if (FIRST_CHILD(parentNode) == oldNodeIndex) {
                FIRST_CHILD(parentNode) = NEXT_SIBLING(node);
            }
            if (LAST_CHILD(parentNode) == oldNodeIndex) {
                LAST_CHILD(parentNode) = PREV_SIBLING(node);
            }
        }
    }

    // Swap nodes into their new position.
    _NodePool nodesAfterMapping(newNumNodes);
    SdfPathVector nodeSitePathsAfterMapping(newNumNodes);
    std::vector<bool> nodeHasSpecsAfterMapping(newNumNodes);

    for (size_t i = 0; i < oldNumNodes; ++i) {
        const size_t oldNodeIndex = i;
        const size_t newNodeIndex = convertToNewIndex(oldNodeIndex);
        if (newNodeIndex == _Node::_invalidNodeIndex) {
            continue;
        }

        // Swap the node from the old node pool into the new node pool at
        // the desired location.
        _Node& oldNode = oldNodes[oldNodeIndex];
        _Node& newNode = nodesAfterMapping[newNodeIndex];
        newNode.Swap(oldNode);

        PARENT(newNode)       = convertToNewIndex(PARENT(newNode));
        ORIGIN(newNode)       = convertToNewIndex(ORIGIN(newNode));
        FIRST_CHILD(newNode)  = convertToNewIndex(FIRST_CHILD(newNode));
        LAST_CHILD(newNode)   = convertToNewIndex(LAST_CHILD(newNode));
        PREV_SIBLING(newNode) = convertToNewIndex(PREV_SIBLING(newNode));
        NEXT_SIBLING(newNode) = convertToNewIndex(NEXT_SIBLING(newNode));

        // Copy the corresponding node site path.
        nodeSitePathsAfterMapping[newNodeIndex] = oldSitePaths[oldNodeIndex];
        nodeHasSpecsAfterMapping[newNodeIndex] = oldHasSpecs[oldNodeIndex];
    }

    _data->nodes.swap(nodesAfterMapping);
    _nodeSitePaths.swap(nodeSitePathsAfterMapping);
    _nodeHasSpecs.swap(nodeHasSpecsAfterMapping);
}
Example #10
0
SdfAttributeSpecHandle
SdfAttributeSpec::_New(
    const SdfRelationshipSpecHandle& owner,
    const SdfPath& path,
    const std::string& name,
    const SdfValueTypeName& typeName,
    SdfVariability variability,
    bool custom)
{
    if (not owner) {
        TF_CODING_ERROR("NULL owner");
        return TfNullPtr;
    }
    if (not typeName) {
        TF_CODING_ERROR("Cannot create attribute spec <%s> with invalid type",
                        owner->GetPath().AppendTarget(path).
                            AppendProperty(TfToken(name)).GetText());
	return TfNullPtr;
    }

    SdfChangeBlock block;

    // Determine the path of the relationship target
    SdfPath absPath = path.MakeAbsolutePath(owner->GetPath().GetPrimPath());
    SdfPath targetPath = owner->GetPath().AppendTarget(absPath);

    // Check to make sure that the name is valid
    if (not Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::IsValidName(name)) {
        TF_CODING_ERROR(
            "Cannot create attribute on %s with invalid name: %s",
            targetPath.GetText(), name.c_str());
        return TfNullPtr;
    }

    // Create the relationship target if it doesn't already exist. Note
    // that this does not automatically get added to the relationship's
    // target path list.
    SdfSpecHandle targetSpec = owner->_FindOrCreateTargetSpec(path);

    // AttributeSpecs are considered initially to have only required fields 
    // only if they are not custom.
    bool hasOnlyRequiredFields = (not custom);

    // Create the relational attribute spec
    SdfPath attrPath = targetPath.AppendRelationalAttribute(TfToken(name));
    if (not Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::CreateSpec(
            owner->GetLayer(), attrPath, SdfSpecTypeAttribute, 
            hasOnlyRequiredFields)) {
        return TfNullPtr;
    }

    SdfAttributeSpecHandle spec =
        owner->GetLayer()->GetAttributeAtPath(attrPath);
    
    // Avoid expensive dormancy checks in the case of binary-backed data.
    SdfAttributeSpec *specPtr = get_pointer(spec);
    if (TF_VERIFY(specPtr)) {
        specPtr->SetField(SdfFieldKeys->Custom, custom);
        specPtr->SetField(SdfFieldKeys->TypeName, typeName.GetAsToken());
        specPtr->SetField(SdfFieldKeys->Variability, variability);
    }

    return spec;
}
Example #11
0
void
UsdImagingGprimAdapter::_DiscoverPrimvarsDeprecated(UsdGeomGprim const& gprim,
                                          SdfPath const& cachePath, 
                                          UsdPrim const& shaderPrim,
                                          UsdTimeCode time,
                                          UsdImagingValueCache* valueCache)
{
    UsdImagingValueCache::PrimvarInfo primvar;
    std::vector<UsdProperty> const& props 
                                    = shaderPrim.GetProperties();
    TF_FOR_ALL(propIt, props) {
        UsdAttribute attr = propIt->As<UsdAttribute>();
        if (not attr) {
            continue;
        }
        if (attr.GetPath().IsNamespacedPropertyPath()) {
            continue;
        }
        // Ok this is a parameter, check source input.
        if (UsdAttribute texAttr = shaderPrim.GetAttribute(
                                TfToken(attr.GetPath().GetName() 
                                + ":texture"))) {
            TfToken t;
            SdfAssetPath ap;
            VtValue v;
            UsdGeomPrimvar primvarAttr;
            texAttr.Get(&ap, UsdTimeCode::Default());
            bool isPtex = GlfPtexTexture::IsPtexTexture(TfToken(ap.GetAssetPath()));
            if (isPtex) {
                t = UsdImagingTokens->ptexFaceIndex;
                // Allow the client to override this name
                texAttr.GetMetadata(UsdImagingTokens->faceIndexPrimvar, &t);
                primvarAttr = gprim.GetPrimvar(t);
                if (primvarAttr) {
                    if (primvarAttr.ComputeFlattened(&v, time)) {
                        primvar.name = t;
                        primvar.interpolation = primvarAttr.GetInterpolation();
                        valueCache->GetPrimvar(cachePath, t) = v;
                        _MergePrimvar(primvar, &valueCache->GetPrimvars(cachePath));
                    }
                }
                t = UsdImagingTokens->ptexFaceOffset;
                // Allow the client to override this name
                texAttr.GetMetadata(UsdImagingTokens->faceOffsetPrimvar, &t);
                primvarAttr = gprim.GetPrimvar(t);
                if (primvarAttr) {
                    primvar.name = t;
                    primvar.interpolation = primvarAttr.GetInterpolation();
                    if (primvarAttr.ComputeFlattened(&v, time)) {
                        valueCache->GetPrimvar(cachePath, t) = v;
                        _MergePrimvar(primvar, &valueCache->GetPrimvars(cachePath));
                    }
                }
            } else {
                texAttr.GetMetadata(UsdImagingTokens->uvPrimvar, &t);
                primvarAttr = gprim.GetPrimvar(t);
                if (TF_VERIFY(primvarAttr, "%s\n", t.GetText())) {
                    if (TF_VERIFY(primvarAttr.ComputeFlattened(&v, time))) {
                        primvar.name = t; // does not include primvars:
                        primvar.interpolation = primvarAttr.GetInterpolation();
                        // Convert double to float, we don't need double precision.
                        if (v.IsHolding<VtVec2dArray>()) {
                            v = VtValue::Cast<VtVec2fArray>(v);
                        }
                        valueCache->GetPrimvar(cachePath, t) = v;
                        _MergePrimvar(primvar, &valueCache->GetPrimvars(cachePath));
                    }
                }
            }
        } else if (UsdAttribute pvAttr = shaderPrim.GetAttribute(
                                        TfToken(attr.GetPath().GetName() 
                                                + ":primvar"))) {
            TfToken t;
            VtValue v;
            UsdGeomPrimvar primvarAttr;
            if (TF_VERIFY(pvAttr.Get(&t, UsdTimeCode::Default()))) {
                primvarAttr = gprim.GetPrimvar(t);
                if (TF_VERIFY(primvarAttr.ComputeFlattened(&v, time))) {
                    primvar.name = t; // does not include primvars:
                    primvar.interpolation = primvarAttr.GetInterpolation();
                    valueCache->GetPrimvar(cachePath, t) = v;
                   _MergePrimvar(primvar, &valueCache->GetPrimvars(cachePath));
                }
            }
        }
    }
bool
Hd_SmoothNormalsComputation::Resolve()
{
    // dependency check first
    if (_adjacencyBuilder) {
        if (!_adjacencyBuilder->IsResolved()) return false;
    }
    if (!_points->IsResolved()) return false;
    if (!_TryLock()) return false;

    HD_TRACE_FUNCTION();
    HF_MALLOC_TAG_FUNCTION();

    if (!TF_VERIFY(_adjacency)) return true;

    size_t numPoints = _points->GetNumElements();

    HdBufferSourceSharedPtr normals;

    switch (_points->GetTupleType().type) {
    case HdTypeFloatVec3:
        if (_packed) {
            normals = HdBufferSourceSharedPtr(
                new HdVtBufferSource(
                    _dstName, VtValue(
                        Hd_SmoothNormals::ComputeSmoothNormalsPacked(
                            _adjacency,
                            numPoints,
                            static_cast<const GfVec3f*>(_points->GetData())))));
        } else {
            normals = HdBufferSourceSharedPtr(
                new HdVtBufferSource(
                    _dstName, VtValue(
                        Hd_SmoothNormals::ComputeSmoothNormals(
                            _adjacency,
                            numPoints,
                            static_cast<const GfVec3f*>(_points->GetData())))));
        }
        break;
    case HdTypeDoubleVec3:
        if (_packed) {
            normals = HdBufferSourceSharedPtr(
                new HdVtBufferSource(
                    _dstName, VtValue(
                        Hd_SmoothNormals::ComputeSmoothNormalsPacked(
                            _adjacency,
                            numPoints,
                            static_cast<const GfVec3d*>(_points->GetData())))));
        } else {
            normals = HdBufferSourceSharedPtr(
                new HdVtBufferSource(
                    _dstName, VtValue(
                        Hd_SmoothNormals::ComputeSmoothNormals(
                            _adjacency,
                            numPoints,
                            static_cast<const GfVec3d*>(_points->GetData())))));
        }
        break;
    default:
        TF_CODING_ERROR("Unsupported points type for computing smooth normals");
        break;
    }

    _SetResult(normals);

    // call base class to mark as resolved.
    _SetResolved();
    return true;
}
Example #13
0
const std::string&
SdfFileFormat::GetPrimaryFileExtension() const
{
    static std::string emptyString;
    return TF_VERIFY(!_extensions.empty()) ? _extensions[0] : emptyString;
}
Example #14
0
void
HdStRenderContextCaps::_LoadCaps()
{
    // XXX: consider to move this class into glf

    // note that this function is called without GL context, in some unit tests.

    shaderStorageBufferEnabled   = false;
    bindlessTextureEnabled       = false;
    bindlessBufferEnabled        = false;
    multiDrawIndirectEnabled     = false;
    directStateAccessEnabled     = false;
    bufferStorageEnabled         = false;
    shadingLanguage420pack       = false;
    explicitUniformLocation      = false;
    maxUniformBlockSize          = 16*1024;      // GL spec minimum
    maxShaderStorageBlockSize    = 16*1024*1024; // GL spec minimum
    maxTextureBufferSize         = 64*1024;      // GL spec minimum
    uniformBufferOffsetAlignment = 0;

    const char *glVersionStr = (const char*)glGetString(GL_VERSION);

    // GL hasn't been initialized yet.
    if (glVersionStr == NULL) return;

    const char *dot = strchr(glVersionStr, '.');
    if (TF_VERIFY((dot && dot != glVersionStr),
                  "Can't parse GL_VERSION %s", glVersionStr)) {
        // GL_VERSION = "4.5.0 <vendor> <version>"
        //              "4.1 <vendor-os-ver> <version>"
        //              "4.1 <vendor-os-ver>"
        int major = std::max(0, std::min(9, *(dot-1) - '0'));
        int minor = std::max(0, std::min(9, *(dot+1) - '0'));
        glVersion = major * 100 + minor * 10;
    }

    if (glVersion >= 200) {
        const char *glslVersionStr =
            (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
        dot = strchr(glslVersionStr, '.');
        if (TF_VERIFY((dot && dot != glslVersionStr),
                      "Can't parse GL_SHADING_LANGUAGE_VERSION %s",
                      glslVersionStr)) {
            // GL_SHADING_LANGUAGE_VERSION = "4.10"
            //                               "4.50 <vendor>"
            int major = std::max(0, std::min(9, *(dot-1) - '0'));
            int minor = std::max(0, std::min(9, *(dot+1) - '0'));
            glslVersion = major * 100 + minor * 10;
        }
    } else {
        glslVersion = 0;
    }

    // initialize by Core versions
    if (glVersion >= 310) {
        glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE,
                      &maxUniformBlockSize);
        glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE,
                      &maxTextureBufferSize);
        glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT,
                      &uniformBufferOffsetAlignment);
    }
    if (glVersion >= 420) {
        shadingLanguage420pack = true;
    }
    if (glVersion >= 430) {
        shaderStorageBufferEnabled = true;
        explicitUniformLocation = true;
        glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE,
                      &maxShaderStorageBlockSize);
    }
    if (glVersion >= 440) {
        bufferStorageEnabled = true;
    }
    if (glVersion >= 450) {
        multiDrawIndirectEnabled = true;
        directStateAccessEnabled = true;
    }

    // initialize by individual extension.
    if (GLEW_ARB_bindless_texture && glMakeTextureHandleResidentNV) {
        bindlessTextureEnabled = true;
    }
    if (GLEW_NV_shader_buffer_load && glMakeNamedBufferResidentNV) {
        bindlessBufferEnabled = true;
    }
    if (GLEW_ARB_explicit_uniform_location) {
        explicitUniformLocation = true;
    }
    if (GLEW_ARB_shading_language_420pack) {
        shadingLanguage420pack = true;
    }
    if (GLEW_ARB_multi_draw_indirect) {
        multiDrawIndirectEnabled = true;
    }
#if defined(GLEW_VERSION_4_5)  // glew 1.11 or newer (usd requirement is 1.10)
    if (GLEW_ARB_direct_state_access) {
        directStateAccessEnabled = true;
    }
#endif
    if (GLEW_EXT_direct_state_access) {
        directStateAccessEnabled = true;
    }

    // Environment variable overrides (only downgrading is possible)
    if (!TfGetEnvSetting(HD_ENABLE_SHADER_STORAGE_BUFFER)) {
        shaderStorageBufferEnabled = false;
    }
    if (!TfGetEnvSetting(HD_ENABLE_BINDLESS_TEXTURE)) {
        bindlessTextureEnabled = false;
    }
    if (!TfGetEnvSetting(HD_ENABLE_BINDLESS_BUFFER)) {
        bindlessBufferEnabled = false;
    }
    if (!TfGetEnvSetting(HD_ENABLE_MULTI_DRAW_INDIRECT)) {
        multiDrawIndirectEnabled = false;
    }
    if (!TfGetEnvSetting(HD_ENABLE_DIRECT_STATE_ACCESS)) {
        directStateAccessEnabled = false;
    }

    // For debugging and unit testing
    if (TfGetEnvSetting(HD_GLSL_VERSION) > 0) {
        // GLSL version override
        glslVersion = std::min(glslVersion, TfGetEnvSetting(HD_GLSL_VERSION));

        // downgrade to the overriden GLSL version
        explicitUniformLocation    &= (glslVersion >= 430);
        bindlessTextureEnabled     &= (glslVersion >= 430);
        bindlessBufferEnabled      &= (glslVersion >= 430);
        shaderStorageBufferEnabled &= (glslVersion >= 430);

        shadingLanguage420pack     &= (glslVersion >= 420);
    }

    // For driver issues workaround
    if (!TfGetEnvSetting(HD_ENABLE_COPY_BUFFER)) {
        copyBufferEnabled = false;
    }

    // GPU Compute
    if (TfGetEnvSetting(HD_ENABLE_GPU_COMPUTE)) {
#if OPENSUBDIV_HAS_GLSL_COMPUTE
        if (glslVersion >= 430 && shaderStorageBufferEnabled) {
            gpuComputeEnabled = true;
        } else {
            TF_WARN("HD_ENABLE_GPU_COMPUTE can't be enabled "
                    "(OpenGL 4.3 required).\n");
        }
#else
        TF_WARN("HD_ENABLE_GPU_COMPUTE can't be enabled "
                "(OpenSubdiv hasn't been configured with GLSL compute).\n");
#endif
    }

    if (TfDebug::IsEnabled(HD_RENDER_CONTEXT_CAPS)) {
        std::cout
            << "HdStRenderContextCaps: \n"
            << "  GL version                         = "
            <<    glVersion << "\n"
            << "  GLSL version                       = "
            <<    glslVersion << "\n"

            << "  GL_MAX_UNIFORM_BLOCK_SIZE          = "
            <<    maxUniformBlockSize << "\n"
            << "  GL_MAX_SHADER_STORAGE_BLOCK_SIZE   = "
            <<    maxShaderStorageBlockSize << "\n"
            << "  GL_MAX_TEXTURE_BUFFER_SIZE         = "
            <<    maxTextureBufferSize << "\n"
            << "  GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = "
            <<    uniformBufferOffsetAlignment << "\n"

            << "  ARB_bindless_texture               = "
            <<    bindlessTextureEnabled << "\n"
            << "  ARB_explicit_uniform_location      = "
            <<    explicitUniformLocation << "\n"
            << "  ARB_multi_draw_indirect            = "
            <<    multiDrawIndirectEnabled << "\n"
            << "  ARB_direct_state_access            = "
            <<    directStateAccessEnabled << "\n"
            << "  ARB_shader_storage_buffer_object   = "
            <<    shaderStorageBufferEnabled << "\n"
            << "  ARB_shading_language_420pack       = "
            <<    shadingLanguage420pack << "\n"
            << "  NV_shader_buffer_load              = "
            <<    bindlessBufferEnabled << "\n"

            << "  GPU Compute                        = "
            <<    gpuComputeEnabled << "\n"
            ;

        if (!copyBufferEnabled) {
            std::cout << "  CopyBuffer : disabled\n";
        }
    }
}
Example #15
0
static VtVec3fArray
_GenerateCapsuleMeshPoints(float radius, float height, TfToken const & axis)
{
    // choose basis vectors aligned with the spine axis
    GfVec3f u, v, spine;
    if (axis == UsdGeomTokens->x) {
        u = GfVec3f::YAxis();
        v = GfVec3f::ZAxis();
        spine = GfVec3f::XAxis();
    } else if (axis == UsdGeomTokens->y) {
        u = GfVec3f::ZAxis();
        v = GfVec3f::XAxis();
        spine = GfVec3f::YAxis();
    } else { // (axis == UsdGeomTokens->z)
        u = GfVec3f::XAxis();
        v = GfVec3f::YAxis();
        spine = GfVec3f::ZAxis();
    }

    // compute a ring of points with unit radius in the uv plane
    std::vector<GfVec3f> ring(_slices);
    for (int i=0; i<_slices; ++i) {
        float a = float(2 * M_PI * i) / _slices;
        ring[i] = u * cosf(a) + v * sinf(a);
    }

    int numPoints = _slices * (_stacks + 1)                   // cylinder
                  + 2 * _slices * (_hemisphereStacks-1)       // hemispheres
                  + 2;                                        // end points

    // populate points
    VtVec3fArray pointsArray(numPoints);
    GfVec3f * p = pointsArray.data();

    // base hemisphere
    *p++ = spine * (-height/2-radius);
    for (int i=0; i<_hemisphereStacks-1; ++i) {
        float a = float(M_PI / 2) * (1.0f - float(i+1) / _hemisphereStacks);
        float r = radius * cosf(a);
        float w = radius * sinf(a);

        for (int j=0; j<_slices; ++j) {
            *p++ = r * ring[j] + spine * (-height/2-w);
        }
    }

    // middle
    for (int i=0; i<=_stacks; ++i) {
        float t = float(i) / _stacks;
        float w = height * (t - 0.5f);

        for (int j=0; j<_slices; ++j) {
            *p++ = radius * ring[j] + spine * w;
        }
    }

    // top hemisphere
    for (int i=0; i<_hemisphereStacks-1; ++i) {
        float a = float(M_PI / 2) * (float(i+1) / _hemisphereStacks);
        float r = radius * cosf(a);
        float w = radius * sinf(a);

        for (int j=0; j<_slices; ++j) {
            *p++ = r *  ring[j] + spine * (height/2+w);
        }
    }
    *p++ = spine * (height/2.0f+radius);

    TF_VERIFY(p - pointsArray.data() == numPoints);

    return pointsArray;
}
Example #16
0
const SdfPath&
PcpNodeRef::GetPath() const
{
    TF_VERIFY(_nodeIdx < _graph->_nodeSitePaths.size());
    return _graph->_nodeSitePaths[_nodeIdx];
}
Example #17
0
void
PcpNodeRef::SetHasSpecs(bool hasSpecs)
{
    TF_VERIFY(_nodeIdx < _graph->_nodeHasSpecs.size());
    _graph->_nodeHasSpecs[_nodeIdx] = hasSpecs;
}
Example #18
0
bool
PcpNodeRef::HasSpecs() const
{
    TF_VERIFY(_nodeIdx < _graph->_nodeHasSpecs.size());
    return _graph->_nodeHasSpecs[_nodeIdx];
}
Example #19
0
void 
GlfBaseTexture::_CreateTexture(GlfBaseTextureDataConstPtr texData,
                                bool const generateMipmap,
				int const unpackCropTop,
				int const unpackCropBottom,
				int const unpackCropLeft,
				int const unpackCropRight)
{
    TRACE_FUNCTION();
    
    if (texData and texData->HasRawBuffer()) {
        glBindTexture(
                GL_TEXTURE_2D,
               _textureName);

        glTexParameteri(
                GL_TEXTURE_2D,
                GL_GENERATE_MIPMAP,
                generateMipmap ? GL_TRUE
                               : GL_FALSE);

        if (not texData->IsCompressed()) {
            if (GlfGetNumElements(texData->GLFormat()) == 1) {
                GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE};
                glTexParameteriv(
                    GL_TEXTURE_2D,
                    GL_TEXTURE_SWIZZLE_RGBA, 
                    swizzleMask);
            }

            int texDataWidth = texData->ResizedWidth();
            int texDataHeight = texData->ResizedHeight();

            int unpackRowLength = texDataWidth;
            int unpackSkipPixels = 0;
            int unpackSkipRows = 0;

            if (unpackCropTop < 0 or unpackCropTop > texDataHeight) {
                return;
            } else if (unpackCropTop > 0) {
                unpackSkipRows = unpackCropTop;
                texDataHeight -= unpackCropTop;
            }
            if (unpackCropBottom < 0 or unpackCropBottom > texDataHeight) {
                return;
            } else if (unpackCropBottom) {
                texDataHeight -= unpackCropBottom;
            }
            if (unpackCropLeft < 0 or unpackCropLeft > texDataWidth) {
                return;
            } else {
                unpackSkipPixels = unpackCropLeft;
                texDataWidth -= unpackCropLeft;
            }
            if (unpackCropRight < 0 or unpackCropRight > texDataWidth) {
                return;
            } else if (unpackCropRight > 0) {
                texDataWidth -= unpackCropRight;
            }
        
            glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
            glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength);
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
            glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels);
            glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackSkipRows);

            glTexImage2D(
                    GL_TEXTURE_2D,
                    0,
                    texData->GLInternalFormat(),
                    texDataWidth,
                    texDataHeight,
                    0,
                    texData->GLFormat(),
                    texData->GLType(),
                    texData->GetRawBuffer());

            glPopClientAttrib();
        } else {
            // There should be no cropping when using compressed textures
            TF_VERIFY(unpackCropTop == 0 && unpackCropBottom == 0 &&
                      unpackCropLeft == 0 && unpackCropRight == 0);
            
            glCompressedTexImage2D(
                GL_TEXTURE_2D,
                0,
                texData->GLInternalFormat(),
                texData->ResizedWidth(),
                texData->ResizedHeight(),
                0,
                texData->ComputeBytesUsed(),
                texData->GetRawBuffer());
        }

        glBindTexture(
                GL_TEXTURE_2D,
                0);

        _SetMemoryUsed(texData->ComputeBytesUsed());
    }
}
HdSt_BasisCurvesShaderKey::HdSt_BasisCurvesShaderKey(
    TfToken const &type, TfToken const &basis, 
    DrawStyle drawStyle, NormalStyle normalStyle,
    bool basisWidthInterpolation,
    bool basisNormalInterpolation)
    : glslfx(_tokens->baseGLSLFX)
{
    bool drawThick = (drawStyle == HdSt_BasisCurvesShaderKey::HALFTUBE) || 
                     (drawStyle == HdSt_BasisCurvesShaderKey::RIBBON);
    bool cubic  = (type == HdTokens->cubic);
    bool linear = (type == HdTokens->linear);
    TF_VERIFY(cubic || linear);

    // The order of the clauses below matters!
    if (drawStyle == HdSt_BasisCurvesShaderKey::POINTS) {
        primType = HdSt_GeometricShader::PrimitiveType::PRIM_POINTS;
    } else if (cubic) {
        // cubic curves get drawn via isolines in a tessellation shader
        // even in wire mode.
        primType =
        HdSt_GeometricShader::PrimitiveType::PRIM_BASIS_CURVES_CUBIC_PATCHES;
    } else if (drawThick){
        primType =
        HdSt_GeometricShader::PrimitiveType::PRIM_BASIS_CURVES_LINEAR_PATCHES;
    } else {
        primType = HdSt_GeometricShader::PrimitiveType::PRIM_BASIS_CURVES_LINES;
    }

    bool isPrimTypePoints = HdSt_GeometricShader::IsPrimTypePoints(primType);

    bool oriented = normalStyle == HdSt_BasisCurvesShaderKey::ORIENTED;

    uint8_t vsIndex = 0;
    VS[vsIndex++]  = _tokens->instancing;
    VS[vsIndex++]  = drawThick ? _tokens->curvesVertexPatch 
                       : _tokens->curvesVertexWire;
    VS[vsIndex++]  = oriented ? _tokens->curvesVertexNormalOriented 
                      : _tokens->curvesVertexNormalImplicit;
    if (isPrimTypePoints) {
        // Add mixins that allow for picking and sel highlighting of points.
        // Even though these are more "render pass-ish", we do this here to
        // reduce the shader code generated when the points repr isn't used.
        VS[vsIndex++] = _tokens->pointIdVS;
        VS[vsIndex++] = _tokens->pointIdSelDecodeUtilsVS;
        VS[vsIndex++] = _tokens->pointIdSelPointSelVS;
    } else {
        VS[vsIndex++] = _tokens->pointIdNoneVS;
    }
    VS[vsIndex]  = TfToken();

    // Setup Tessellation
    if (linear) {
        switch(drawStyle) {
        case HdSt_BasisCurvesShaderKey::POINTS:
        case HdSt_BasisCurvesShaderKey::WIRE:
        {
            TCS[0] = TfToken();
            TES[0] = TfToken();
            break;
        }
        case HdSt_BasisCurvesShaderKey::RIBBON:
        {
            TCS[0] = _tokens->curvesTessControlShared;
            TCS[1] = _tokens->curvesTessControlLinearPatch; 
            TCS[2] = _tokens->curvesTessControlLinearRibbon;
            TCS[3] = TfToken();  

            TES[0] = _tokens->instancing;
            TES[1] = _tokens->curvesTessEvalPatch;
            TES[2] = _tokens->curvesFallback;
            TES[3] = _tokens->curvesTessEvalLinearPatch;
            TES[4] = oriented ? _tokens->curvesTessEvalRibbonOriented
                            : _tokens->curvesTessEvalRibbonImplicit;
            TES[5] = TfToken();
            break;
        }
        case HdSt_BasisCurvesShaderKey::HALFTUBE:
        {
            TCS[0] = _tokens->curvesTessControlShared;
            TCS[1] = _tokens->curvesTessControlLinearPatch; 
            TCS[2] = _tokens->curvesTessControlLinearHalfTube;
            TCS[3] = TfToken();  

            TES[0] = _tokens->instancing;
            TES[1] = _tokens->curvesTessEvalPatch;
            TES[2] = _tokens->curvesFallback;
            TES[3] = _tokens->curvesTessEvalLinearPatch;
            TES[4] = _tokens->curvesTessEvalHalfTube;
            TES[5] = TfToken();
            break;
        }
        default:
            TF_CODING_ERROR("Unhandled drawstyle for basis curves");
        }
    } else { // cubic
        switch(drawStyle) {
        case HdSt_BasisCurvesShaderKey::POINTS:
        {
            TCS[0] = TfToken();
            TES[0] = TfToken();
            break;
        }
        case HdSt_BasisCurvesShaderKey::WIRE:
        {
            TCS[0] = _tokens->curvesTessControlShared;
            TCS[1] = _tokens->curvesTessControlCubicWire;
            TCS[2] = TfToken();

            TES[0] = _tokens->instancing;
            TES[1] = _tokens->curvesTessEvalCubicWire;
            TES[2] = HdSt_BasisToShaderKey(basis);
            TES[3] = TfToken();
            break;
        }
        case HdSt_BasisCurvesShaderKey::RIBBON:
        {
            TCS[0] = _tokens->curvesTessControlShared;
            TCS[1] = _tokens->curvesTessControlCubicPatch;
            TCS[2] = _tokens->curvesTessControlCubicRibbon;
            TCS[3] = TfToken();


            TES[0] = _tokens->instancing;
            TES[1] = _tokens->curvesTessEvalPatch;
            TES[2] = _tokens->curvesTessEvalCubicPatch;
            TES[3] = HdSt_BasisToShaderKey(basis);
            TES[4] = oriented ? _tokens->curvesTessEvalRibbonOriented
                            : _tokens->curvesTessEvalRibbonImplicit;
            TES[5] = basisWidthInterpolation ? 
                        _tokens->curveCubicWidthsBasis 
                    : _tokens->curveCubicWidthsLinear;
            TES[6] = basisNormalInterpolation ?
                        _tokens->curveCubicNormalsBasis :
                        _tokens->curveCubicNormalsLinear;
            TES[7] = TfToken();
            break;
        }
        case HdSt_BasisCurvesShaderKey::HALFTUBE:
        {
            TCS[0] = _tokens->curvesTessControlShared;
            TCS[1] = _tokens->curvesTessControlCubicPatch;
            TCS[2] = _tokens->curvesTessControlCubicHalfTube;
            TCS[3] = TfToken();

            TES[0] = _tokens->instancing;
            TES[1] = _tokens->curvesTessEvalPatch;
            TES[2] = _tokens->curvesTessEvalCubicPatch;
            TES[3] = HdSt_BasisToShaderKey(basis);
            TES[4] = _tokens->curvesTessEvalHalfTube;
            TES[5] = basisWidthInterpolation ? 
                        _tokens->curveCubicWidthsBasis 
                    : _tokens->curveCubicWidthsLinear;
            TES[6] = basisNormalInterpolation ?
                        _tokens->curveCubicNormalsBasis :
                        _tokens->curveCubicNormalsLinear;
            TES[7] = TfToken();
            break;
        }
        default:
            TF_CODING_ERROR("Unhandled drawstyle for basis curves");
        }
    }

    // setup fragment shaders
    // Common must be first as it defines terminal interfaces
    uint8_t fsIndex = 0;
    FS[fsIndex++] = _tokens->commonFS;
    FS[fsIndex++] = _tokens->surfaceFS;
    FS[fsIndex++] = _tokens->scalarOverrideFS;

    // we don't currently ever set primType to PRIM_POINTS for curves, but
    // if we ever want to view them as just points, this allows point picking to
    // work.
    FS[fsIndex++] = isPrimTypePoints?
                        _tokens->pointIdFS : _tokens->pointIdFallbackFS;

    if (drawStyle == HdSt_BasisCurvesShaderKey::WIRE || 
        drawStyle == HdSt_BasisCurvesShaderKey::POINTS) {
        FS[fsIndex++] = _tokens->curvesFragmentWire;
        FS[fsIndex++] = TfToken();
    }
    else if (drawStyle == HdSt_BasisCurvesShaderKey::RIBBON &&
             normalStyle == HdSt_BasisCurvesShaderKey::ORIENTED){
        FS[fsIndex++] = _tokens->curvesFragmentPatch;
        FS[fsIndex++] = _tokens->curvesFragmentRibbonOriented;
        FS[fsIndex++] = TfToken();
    }
    else if (drawStyle == HdSt_BasisCurvesShaderKey::RIBBON &&
             normalStyle == HdSt_BasisCurvesShaderKey::ROUND){
        FS[fsIndex++] = _tokens->curvesFragmentPatch;
        FS[fsIndex++] = _tokens->curvesFragmentRibbonRound;
        FS[fsIndex++] = TfToken();
    }
    else if (drawStyle == HdSt_BasisCurvesShaderKey::RIBBON &&
             normalStyle == HdSt_BasisCurvesShaderKey::HAIR){
        FS[fsIndex++] = _tokens->curvesFragmentPatch;
        FS[fsIndex++] = _tokens->curvesFragmentHair;
        FS[fsIndex++] = TfToken();
    }
    else if (drawStyle == HdSt_BasisCurvesShaderKey::HALFTUBE &&
             normalStyle == HdSt_BasisCurvesShaderKey::ROUND){
        FS[fsIndex++] = _tokens->curvesFragmentPatch;
        FS[fsIndex++] = _tokens->curvesFragmentHalfTube;
        FS[fsIndex++] = TfToken();
    }
    else if (drawStyle == HdSt_BasisCurvesShaderKey::HALFTUBE &&
             normalStyle == HdSt_BasisCurvesShaderKey::HAIR){
        FS[fsIndex++] = _tokens->curvesFragmentPatch;
        FS[fsIndex++] = _tokens->curvesFragmentHair;
        FS[fsIndex++] = TfToken();
    }
    else{
        TF_WARN("Cannot setup fragment shaders for invalid combination of \
                 basis curves shader key settings.");
        FS[fsIndex++] = _tokens->curvesFragmentHair;
        FS[fsIndex++] = TfToken();
    }
}
Example #21
0
static void
_AddClipsFromNode(const PcpPrimIndex& primIndex, Usd_ClipCache::Clips* clips)
{
    Usd_ResolvedClipInfo clipInfo;
    auto node = Usd_ResolveClipInfo(primIndex, &clipInfo);

    // If we haven't found all of the required clip metadata we can just 
    // bail out. Note that clipTimes and clipManifestAssetPath are *not* 
    // required.
    if (!clipInfo.clipAssetPaths 
        || !clipInfo.clipPrimPath 
        || !clipInfo.clipActive) {
        return;
    }

    // The clip manifest is currently optional but can greatly improve
    // performance if specified. For debugging performance problems,
    // issue a message indicating if one hasn't been specified.
    if (!clipInfo.clipManifestAssetPath) {
        TF_DEBUG(USD_CLIPS).Msg(
            "No clip manifest specified for prim <%s>. " 
            "Performance may be improved if a manifest is specified.",
            primIndex.GetPath().GetString().c_str());
    }

    // XXX: Possibly want a better way to inform consumers of the error
    //      message..
    std::string error;
    if (!_ValidateClipFields(
            *clipInfo.clipAssetPaths, *clipInfo.clipPrimPath, 
            *clipInfo.clipActive, &error)) {

        TF_WARN(
            "Invalid clips specified for prim <%s> in LayerStack %s: %s",
            node.GetPath().GetString().c_str(),
            TfStringify(node.GetLayerStack()).c_str(),
            error.c_str());
        return;
    }

    // If a clip manifest has been specified, create a clip for it.
    if (clipInfo.clipManifestAssetPath) {
        const Usd_ClipRefPtr clip(new Usd_Clip(
            /* clipSourceNode       = */ node,
            /* clipSourceLayerIndex = */ 
                clipInfo.indexOfLayerWhereAssetPathsFound,
            /* clipAssetPath        = */ *clipInfo.clipManifestAssetPath,
            /* clipPrimPath         = */ SdfPath(*clipInfo.clipPrimPath),
            /* clipStartTime        = */ Usd_ClipTimesEarliest,
            /* clipEndTime          = */ Usd_ClipTimesLatest,
            /* clipTimes            = */ Usd_Clip::TimeMappings()));
        clips->manifestClip = clip;
    }

    // Generate a mapping of startTime -> clip entry. This allows us to
    // quickly determine the (startTime, endTime) for a given clip.
    typedef std::map<double, Usd_ClipEntry> _TimeToClipMap;
    _TimeToClipMap startTimeToClip;

    for (const auto& startFrameAndClipIndex : *clipInfo.clipActive) {
        const double startFrame = startFrameAndClipIndex[0];
        const int clipIndex = (int)(startFrameAndClipIndex[1]);
        const SdfAssetPath& assetPath = (*clipInfo.clipAssetPaths)[clipIndex];

        Usd_ClipEntry entry;
        entry.startTime = startFrame;
        entry.clipAssetPath = assetPath;
        entry.clipPrimPath = SdfPath(*clipInfo.clipPrimPath);

        // Validation should have caused us to bail out if there were any
        // conflicting clip activations set.
        TF_VERIFY(startTimeToClip.insert(
                std::make_pair(entry.startTime, entry)).second);
    }

    // Build up the final vector of clips.
    const _TimeToClipMap::const_iterator itBegin = startTimeToClip.begin();
    const _TimeToClipMap::const_iterator itEnd = startTimeToClip.end();

    _TimeToClipMap::const_iterator it = startTimeToClip.begin();
    while (it != itEnd) {
        const Usd_ClipEntry clipEntry = it->second;

        const Usd_Clip::ExternalTime clipStartTime = 
            (it == itBegin ? Usd_ClipTimesEarliest : it->first);
        ++it;
        const Usd_Clip::ExternalTime clipEndTime = 
            (it == itEnd ? Usd_ClipTimesLatest : it->first);

        // Generate the clip time mapping that applies to this clip.
        Usd_Clip::TimeMappings timeMapping;
        if (clipInfo.clipTimes) {
            for (const auto& clipTime : *clipInfo.clipTimes) {
                const Usd_Clip::ExternalTime extTime = clipTime[0];
                const Usd_Clip::InternalTime intTime = clipTime[1];
                
                if (clipStartTime <= extTime && extTime < clipEndTime) {
                    timeMapping.push_back(
                        Usd_Clip::TimeMapping(extTime, intTime));
                }
            }
        }

        const Usd_ClipRefPtr clip(new Usd_Clip(
            /* clipSourceNode = */ node,
            /* clipSourceLayerIndex = */ 
                clipInfo.indexOfLayerWhereAssetPathsFound,
            /* clipAssetPath = */ clipEntry.clipAssetPath,
            /* clipPrimPath = */ clipEntry.clipPrimPath,
            /* clipStartTime = */ clipStartTime,
            /* clipEndTime = */ clipEndTime,
            /* clipTimes = */ timeMapping));

        clips->valueClips.push_back(clip);
    }

    clips->sourceNode = node;
    clips->sourceLayerIndex = clipInfo.indexOfLayerWhereAssetPathsFound;    
}
// Walk the shader graph and emit nodes in topological order
// to avoid forward-references.
static
void _WalkGraph(UsdShadeShader const & shadeNode, 
               HdMaterialNetwork *materialNetwork,
               const TfTokenVector &shaderSourceTypes)
{
    // Store the path of the node
    HdMaterialNode node;
    node.path = shadeNode.GetPath();
    if (!TF_VERIFY(node.path != SdfPath::EmptyPath())) {
        return;
    }
    // If this node has already been found via another path, we do
    // not need to add it again.
    for (HdMaterialNode const& existingNode: materialNetwork->nodes) {
        if (existingNode.path == node.path) {
            return;
        }
    }

    // Visit the inputs of this node to ensure they are emitted first.
    const std::vector<UsdShadeInput> shadeNodeInputs = shadeNode.GetInputs();
    for (UsdShadeInput const& input: shadeNodeInputs) {
        // Check if this input is a connection and if so follow the path
        UsdShadeConnectableAPI source;
        TfToken sourceName;
        UsdShadeAttributeType sourceType;
        if (UsdShadeConnectableAPI::GetConnectedSource(input, 
                &source, &sourceName, &sourceType)) {
            // When we find a connection to a shading node output,
            // walk the upstream shading node.  Do not do this for
            // other sources (ex: a connection to a material
            // public interface parameter), since they are not
            // part of the shading node graph.
            if (sourceType == UsdShadeAttributeType::Output) {
                UsdShadeShader connectedNode(source);
                _WalkGraph(connectedNode, materialNetwork, shaderSourceTypes);
            }
        }
    }

    // Extract the identifier of the node
    TfToken id;
    if (!shadeNode.GetShaderId(&id)) {
        for (auto &sourceType : shaderSourceTypes) {
            if (SdrShaderNodeConstPtr n = 
                    shadeNode.GetShaderNodeForSourceType(sourceType)) {
                id = n->GetIdentifier();
                break;
            }
        }
    }

    if (!id.IsEmpty()) {
        node.identifier = id;

        // If a node is recognizable, we will try to extract the primvar 
        // names that is using since this can help render delegates 
        // optimize what what is needed from a prim when making data 
        // accessible for renderers.
        _ExtractPrimvarsFromNode(shadeNode, node, materialNetwork);
    } else {
        TF_WARN("UsdShade Shader without an id: %s.", node.path.GetText());
        node.identifier = TfToken("PbsNetworkMaterialStandIn_2");
    }

    // Add the parameters and the relationships of this node
    VtValue value;
    for (UsdShadeInput const& input: shadeNodeInputs) {
        // Check if this input is a connection and if so follow the path
        UsdShadeConnectableAPI source;
        TfToken sourceName;
        UsdShadeAttributeType sourceType;
        if (UsdShadeConnectableAPI::GetConnectedSource(input,
            &source, &sourceName, &sourceType)) {
            if (sourceType == UsdShadeAttributeType::Output) {
                // Store the relationship
                HdMaterialRelationship relationship;
                relationship.outputId = shadeNode.GetPath();
                relationship.outputName = input.GetBaseName();
                relationship.inputId = source.GetPath();
                relationship.inputName = sourceName;
                materialNetwork->relationships.push_back(relationship);
            } else if (sourceType == UsdShadeAttributeType::Input) {
                // Connected to an input on the public interface.
                // The source is not a node in the shader network, so
                // pull the value and pass it in as a parameter.
                if (UsdShadeInput connectedInput =
                    source.GetInput(sourceName)) {
                    if (connectedInput.Get(&value)) {
                        node.parameters[input.GetBaseName()] = value;
                    }
                }
            }
        } else {
            // Parameters detected, let's store it
            if (input.Get(&value)) {
                node.parameters[input.GetBaseName()] = value;
            }
        }
    }

    materialNetwork->nodes.push_back(node);
}
bool
HdxColorCorrectionTask::_CreateFramebufferResources(GLuint *texture)
{
    // If framebufferSize is not provided we use the viewport size.
    // This can be incorrect if the client/app has changed the viewport to
    // be different then the render window size. (E.g. UsdView CameraMask mode)
    GfVec2i fboSize = _framebufferSize;
    if (fboSize[0] <= 0 || fboSize[1] <= 0) {
        GLint res[4] = {0};
        glGetIntegerv(GL_VIEWPORT, res);
        fboSize = GfVec2i(res[2], res[3]);
    }

    bool createTexture = (_texture == 0 || fboSize != _textureSize);

    if (createTexture) {
        if (_texture != 0) {
            glDeleteTextures(1, &_texture);
            _texture = 0;
        }

        _textureSize = fboSize;

        GLint restoreTexture;
        glGetIntegerv(GL_TEXTURE_BINDING_2D, &restoreTexture);

        glGenTextures(1, texture);
        glBindTexture(GL_TEXTURE_2D, *texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        // XXX For step 1 we copy the client FBO texture, apply gamma to the
        // copy and write it back to the client texture.
        // A future step will likely create a 16F texture at the start of 
        // hydra rendering and use color-correction to render the results back
        // into the client FBO texture.

        // XXX For now we assume we always want R16F. We could perhaps expose
        //     this as client-API in HdxColorCorrectionTaskParams.
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, _textureSize[0], 
                     _textureSize[1], 0, GL_RGBA, GL_FLOAT, 0);

        glBindTexture(GL_TEXTURE_2D, restoreTexture);
    }

    bool switchedGLContext = !_owningContext || !_owningContext->IsCurrent();

    if (switchedGLContext) {
        // If we're rendering with a different context than the render pass
        // was created with, recreate the FBO because FB is not shared.
        // XXX we need this since we use a FBO in _CopyTexture(). Ideally we
        // use HdxCompositor to do the copy, but for that we need to know the
        // textureId currently bound to the default framebuffer. However
        // glGetFramebufferAttachmentParameteriv will return and error when
        // trying to query the texture name bound to GL_BACK_LEFT.
        if (_owningContext && _owningContext->IsValid()) {
            GlfGLContextScopeHolder contextHolder(_owningContext);
            glDeleteFramebuffers(1, &_framebuffer);
        }

        _owningContext = GlfGLContext::GetCurrentGLContext();
        if (!TF_VERIFY(_owningContext, "No valid GL context")) {
            return false;
        }

        if (_framebuffer == 0) {
            glGenFramebuffers(1, &_framebuffer);
        }
    }

    if (createTexture || switchedGLContext) {
        GLint restoreReadFB, restoreDrawFB;
        glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &restoreReadFB);
        glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &restoreDrawFB);
        glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
                               GL_TEXTURE_2D, _texture, 0);

        glBindFramebuffer(GL_READ_FRAMEBUFFER, restoreReadFB);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, restoreDrawFB);
    }

    GLF_POST_PENDING_GL_ERRORS();
    return true;
}
Example #24
0
File: light.cpp Project: MWDD/USD
/* virtual */
void
HdxLight::Sync(HdSceneDelegate *sceneDelegate,
               HdRenderParam   *renderParam,
               HdDirtyBits     *dirtyBits)
{
    HD_TRACE_FUNCTION();
    HF_MALLOC_TAG_FUNCTION();

    TF_UNUSED(renderParam);

    SdfPath const &id = GetID();

    if (!TF_VERIFY(sceneDelegate != nullptr)) {
        return;
    }

    // HdxLight communicates to the scene graph and caches all interesting
    // values within this class.

    // later on Get() is called from TaskState (RenderPass) to perform
    // aggregation/pre-computation, in order to make the shader execution
    // efficient.

    HdDirtyBits bits = *dirtyBits;

    // Change tracking

    // Transform
    if (bits & DirtyTransform) {
        VtValue transform = sceneDelegate->Get(id, HdxLightTokens->transform);
        if (transform.IsHolding<GfMatrix4d>()) {
            _params[HdxLightTokens->transform] = transform;
        } else {
            _params[HdxLightTokens->transform] = GfMatrix4d(1);
        }
    }

    // Lighting Params
    if (bits & DirtyParams) {
        _params[HdxLightTokens->params] =
                sceneDelegate->Get(id, HdxLightTokens->params);
    }

    // Shadow Params
    if (bits & DirtyShadowParams) {
        _params[HdxLightTokens->shadowParams] =
                sceneDelegate->Get(id, HdxLightTokens->shadowParams);
    }

    // Shadow Collection
    if (bits & DirtyCollection) {
        VtValue vtShadowCollection =
                sceneDelegate->Get(id, HdxLightTokens->shadowCollection);

        // Optional
        if (vtShadowCollection.IsHolding<HdRprimCollection>()) {
            HdRprimCollection newCollection =
                vtShadowCollection.UncheckedGet<HdRprimCollection>();

            if (_params[HdxLightTokens->shadowCollection] != newCollection) {
                _params[HdxLightTokens->shadowCollection] = newCollection;

                HdChangeTracker& changeTracker =
                             sceneDelegate->GetRenderIndex().GetChangeTracker();

                changeTracker.MarkCollectionDirty(newCollection.GetName());
            }

        } else {
            _params[HdxLightTokens->shadowCollection] = HdRprimCollection();
        }
    }

    *dirtyBits = Clean;
}
Example #25
0
UsdEditContext::~UsdEditContext()
{
    // Stage should never allow an invalid EditTarget to be set...
    if (_stage and TF_VERIFY(_originalEditTarget.IsValid()))
        _stage->SetEditTarget(_originalEditTarget);
}
Example #26
0
void
Hd_SmoothNormalsComputationGPU::Execute(
    HdBufferArrayRangeSharedPtr const &range)
{
    HD_TRACE_FUNCTION();
    HF_MALLOC_TAG_FUNCTION();

    if (!glDispatchCompute)
        return;


    TF_VERIFY(_adjacency);
    HdBufferArrayRangeSharedPtr const &adjacencyRange = _adjacency->GetAdjacencyRange();
    TF_VERIFY(adjacencyRange);

    // select shader by datatype
    TfToken shaderToken;
    if (_srcDataType == GL_FLOAT) {
        if (_dstDataType == GL_FLOAT) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToFloat;
        } else if (_dstDataType == GL_DOUBLE) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToDouble;
        } else if (_dstDataType == GL_INT_2_10_10_10_REV) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToPacked;
        }
    } else if (_srcDataType == GL_DOUBLE) {
        if (_dstDataType == GL_FLOAT) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToFloat;
        } else if (_dstDataType == GL_DOUBLE) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToDouble;
        } else if (_dstDataType == GL_INT_2_10_10_10_REV) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToPacked;
        }
    }
    if (!TF_VERIFY(!shaderToken.IsEmpty())) return;

    HdGLSLProgramSharedPtr computeProgram
        = HdGLSLProgram::GetComputeProgram(shaderToken);
    if (!computeProgram) return;

    GLuint program = computeProgram->GetProgram().GetId();

    // buffer resources for GPU computation
    HdBufferResourceSharedPtr points = range->GetResource(_srcName);
    HdBufferResourceSharedPtr normals = range->GetResource(_dstName);
    HdBufferResourceSharedPtr adjacency = adjacencyRange->GetResource();

    // prepare uniform buffer for GPU computation
    struct Uniform {
        int vertexOffset;
        int adjacencyOffset;
        int pointsOffset;
        int pointsStride;
        int normalsOffset;
        int normalsStride;
    } uniform;

    // coherent vertex offset in aggregated buffer array
    uniform.vertexOffset = range->GetOffset();
    // adjacency offset/stride in aggregated adjacency table
    uniform.adjacencyOffset = adjacencyRange->GetOffset();
    // interleaved offset/stride to points
    // note: this code (and the glsl smooth normal compute shader) assumes
    // components in interleaved vertex array are always same data type.
    // i.e. it can't handle an interleaved array which interleaves
    // float/double, float/int etc.
    uniform.pointsOffset = points->GetOffset() / points->GetComponentSize();
    uniform.pointsStride = points->GetStride() / points->GetComponentSize();
    // interleaved offset/stride to normals
    uniform.normalsOffset = normals->GetOffset() / normals->GetComponentSize();
    uniform.normalsStride = normals->GetStride() / normals->GetComponentSize();

    // The number of points is based off the size of the output,
    // However, the number of points in the adjacency table
    // is computed based off the largest vertex indexed from
    // to topology (aka topology->ComputeNumPoints).
    //
    // Therefore, we need to clamp the number of points
    // to the number of entries in the adjancency table.
    int numDestPoints = range->GetNumElements();
    int numSrcPoints = _adjacency->GetNumPoints();

    int numPoints = std::min(numSrcPoints, numDestPoints);

    // transfer uniform buffer
    GLuint ubo = computeProgram->GetGlobalUniformBuffer().GetId();
    HdRenderContextCaps const &caps = HdRenderContextCaps::GetInstance();
    // XXX: workaround for 319.xx driver bug of glNamedBufferDataEXT on UBO
    // XXX: move this workaround to renderContextCaps
    if (false && caps.directStateAccessEnabled) {
        glNamedBufferDataEXT(ubo, sizeof(uniform), &uniform, GL_STATIC_DRAW);
    } else {
        glBindBuffer(GL_UNIFORM_BUFFER, ubo);
        glBufferData(GL_UNIFORM_BUFFER, sizeof(uniform), &uniform, GL_STATIC_DRAW);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
    }

    glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, points->GetId());
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, normals->GetId());
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, adjacency->GetId());

    // dispatch compute kernel
    glUseProgram(program);

    glDispatchCompute(numPoints, 1, 1);

    glUseProgram(0);
    glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

    glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
}
Example #27
0
/* virtual */
void
HdStLight::Sync(HdSceneDelegate *sceneDelegate,
                HdRenderParam   *renderParam,
                HdDirtyBits     *dirtyBits)
{
    HD_TRACE_FUNCTION();
    HF_MALLOC_TAG_FUNCTION();

    TF_UNUSED(renderParam);

    SdfPath const &id = GetId();

    if (!TF_VERIFY(sceneDelegate != nullptr)) {
        return;
    }

    // HdStLight communicates to the scene graph and caches all interesting
    // values within this class. Later on Get() is called from 
    // TaskState (RenderPass) to perform aggregation/pre-computation, 
    // in order to make the shader execution efficient.

    // Change tracking
    HdDirtyBits bits = *dirtyBits;

    // Transform
    if (bits & DirtyTransform) {
        VtValue transform = sceneDelegate->Get(id, HdLightTokens->transform);
        if (transform.IsHolding<GfMatrix4d>()) {
            _params[HdLightTokens->transform] = transform;
        } else {
            _params[HdLightTokens->transform] = GfMatrix4d(1);
        }
    }

    // Lighting Params
    if (bits & DirtyParams) {
        // If it is an area light we will extract the parameters and convert
        // them to a gl friendly representation.
        if (_lightType == HdPrimTypeTokens->simpleLight) {
            _params[HdLightTokens->params] =
                sceneDelegate->Get(id, HdLightTokens->params);
        } else {
            _params[HdLightTokens->params] =
                _ApproximateAreaLight(id, sceneDelegate);
        }
    }

    // Shadow Params
    if (bits & DirtyShadowParams) {
        _params[HdLightTokens->shadowParams] =
                sceneDelegate->Get(id, HdLightTokens->shadowParams);
    }

    // Shadow Collection
    if (bits & DirtyCollection) {
        VtValue vtShadowCollection =
                sceneDelegate->Get(id, HdLightTokens->shadowCollection);

        // Optional
        if (vtShadowCollection.IsHolding<HdRprimCollection>()) {
            HdRprimCollection newCollection =
                vtShadowCollection.UncheckedGet<HdRprimCollection>();

            if (_params[HdLightTokens->shadowCollection] != newCollection) {
                _params[HdLightTokens->shadowCollection] = newCollection;

                HdChangeTracker& changeTracker =
                             sceneDelegate->GetRenderIndex().GetChangeTracker();

                changeTracker.MarkCollectionDirty(newCollection.GetName());
            }

        } else {
            _params[HdLightTokens->shadowCollection] = HdRprimCollection();
        }
    }

    *dirtyBits = Clean;
}
PXR_NAMESPACE_USING_DIRECTIVE

void
TestTemplates()
{
    // --------------------------------------------------------------------- //
    // This test operates on /RootPrim.foo
    // and /RootPrim.foo:hidden
    // --------------------------------------------------------------------- //
    SdfPath primPath("/RootPrim");
    TfToken prop("foo");
    TfToken metaField("hidden");
    std::string propPath(primPath.GetString() + "." + prop.GetString());

    // --------------------------------------------------------------------- //
    // Author scene and compose the Stage 
    // --------------------------------------------------------------------- //
    SdfLayerRefPtr layer = SdfLayer::CreateAnonymous();
    UsdStageRefPtr stage = UsdStage::Open(layer->GetIdentifier());

    TF_VERIFY(stage->OverridePrim(primPath),
              "Failed to create prim at %s",
              primPath.GetText());

    UsdPrim prim(stage->GetPrimAtPath(primPath));
    TF_VERIFY(prim, "Failed to get Prim from %s", primPath.GetText());

    // Grab the attribute we will be testing with.
    UsdAttribute attr =
        prim.CreateAttribute(prop, SdfValueTypeNames->Double3Array);
    TF_VERIFY(attr, "Failed to create property at %s", propPath.c_str());

    // --------------------------------------------------------------------- //
    // Setup some test data 
    // --------------------------------------------------------------------- //
    VtVec3dArray vtVecOut(1);
    VtVec3dArray vtVecIn;
    std::string tmp;

    VtValue value;

    // ===================================================================== //
    // TEST READING METADATA
    // ===================================================================== //

    // --------------------------------------------------------------------- //
    // GetMetadata & SetMetadata the value as a VtValue
    // --------------------------------------------------------------------- //
    TF_VERIFY(attr.SetMetadata(metaField, VtValue(true)),
              "VtValue: Failed to set hidden metadata at %s",
              propPath.c_str());

    // Print the layer for debugging.
    layer->ExportToString(&tmp);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "Metadata -- VtValue:" << std::endl;
    std::cout << tmp << std::endl;

    // Verify the result.
    TF_VERIFY(attr.GetMetadata(metaField, &value),
              "Metadata -- VtValue: Failed to get property value at %s",
              propPath.c_str());
    TF_VERIFY(value.IsHolding<bool>(),
              "Metadata -- VtValue: not holding bool%s",
              propPath.c_str());
   TF_VERIFY(value.Get<bool>(),
              "Metadata -- VtValue: value was not true %s",
              propPath.c_str());

    // --------------------------------------------------------------------- //
    // GetMetadata & SetMetadata the value as bool 
    // --------------------------------------------------------------------- //
    bool valueIn = false;
    TF_VERIFY(attr.SetMetadata(metaField, true),
              "Metadata -- bool: Failed to set property at %s",
              propPath.c_str());

    // Print the layer for debugging.
    tmp = "";
    layer->ExportToString(&tmp);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "Metadata -- bool:" << std::endl;
    std::cout << tmp << std::endl;

    // Verify Result.
    TF_VERIFY(attr.GetMetadata(metaField, &valueIn),
              "Metadata -- bool: Failed to get property value at %s",
              propPath.c_str());
    TF_VERIFY(valueIn,
              "Metadata -- bool: value was not true %s",
              propPath.c_str());

    
    // ===================================================================== //
    // TEST READING VALUES
    // ===================================================================== //
    
    // --------------------------------------------------------------------- //
    // Get & Set the value as a VtValue
    // --------------------------------------------------------------------- //
    vtVecOut[0] = GfVec3d(9,8,7);
    TF_VERIFY(attr.Set(VtValue(vtVecOut)),
              "VtValue: Failed to set property at %s",
              propPath.c_str());

    // Print the layer for debugging.
    layer->ExportToString(&tmp);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "VtValue:" << std::endl;
    std::cout << tmp << std::endl;

    // Verify the result.
    TF_VERIFY(attr.Get(&value),
              "VtValue: Failed to get property value at %s",
              propPath.c_str());
    TF_VERIFY(value.IsHolding<VtVec3dArray>(),
              "VtValue: not holding VtVec3dArray %s",
              propPath.c_str());
   TF_VERIFY(value.Get<VtVec3dArray>()[0] == vtVecOut[0],
              "VtValue: VtVec3d[0] does not match %s",
              propPath.c_str());

    // --------------------------------------------------------------------- //
    // Get & Set the value as a VtArray 
    // --------------------------------------------------------------------- //
    vtVecOut[0] = GfVec3d(6,5,4);
    TF_VERIFY(attr.Set(vtVecOut),
              "Failed to set property at %s",
              propPath.c_str());

    // Print the layer for debugging.
    tmp = "";
    layer->ExportToString(&tmp);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "VtArray:" << std::endl;
    std::cout << tmp << std::endl;

    // Verify Result.
    TF_VERIFY(attr.Get(&vtVecIn),
              "VtArray: Failed to get property value at %s",
              propPath.c_str());
    TF_VERIFY(vtVecIn[0] == vtVecOut[0],
              "VtArray: VtVec3d[0] does not match %s",
              propPath.c_str());

    // --------------------------------------------------------------------- //
    // Get & Set the value as a VtDictionary (Dictionary composition semantics
    // are exercised in testUsdMetadata).
    // --------------------------------------------------------------------- //
    VtDictionary inDict;
    inDict["$Side"] = "R";
    TF_VERIFY(!prim.HasAuthoredMetadata(SdfFieldKeys->PrefixSubstitutions));
    TF_VERIFY(prim.SetMetadata(SdfFieldKeys->PrefixSubstitutions, inDict));
    VtDictionary outDict;
    TF_VERIFY(prim.HasAuthoredMetadata(SdfFieldKeys->PrefixSubstitutions));
    // Verify bug 97783 - GetMetadata should return true if Usd was able to
    // retrieve/compose a VtDictionary.
    TF_VERIFY(prim.GetMetadata(SdfFieldKeys->PrefixSubstitutions,&outDict));
    TF_VERIFY(inDict == outDict);
    std::cout << "-----------------------------------------" << std::endl;
    std::cout << "VtDictionary:" << std::endl;
    tmp = "";
    layer->ExportToString(&tmp);
    std::cout << tmp << std::endl;
    
}
Example #29
0
void
UsdMayaGLBatchRenderer::TaskDelegate::_SetLightingStateFromLightingContext()
{
    const GlfSimpleLightVector& lights = _lightingContext->GetLights();

    bool hasNumLightsChanged = false;

    // Insert light Ids into the render index for those that do not yet exist.
    while (_lightIds.size() < lights.size()) {
        SdfPath lightId(
            TfStringPrintf("%s/light%d",
                           _rootId.GetText(),
                           (int)_lightIds.size()));
        _lightIds.push_back(lightId);

        // Since we're hardcoded to use HdStRenderDelegate, we expect to have
        // light Sprims.
        TF_VERIFY(GetRenderIndex().IsSprimTypeSupported(HdPrimTypeTokens->light));

        GetRenderIndex().InsertSprim(HdPrimTypeTokens->light, this, lightId);
        hasNumLightsChanged = true;
    }

    // Remove unused light Ids from HdRenderIndex
    while (_lightIds.size() > lights.size()) {
        GetRenderIndex().RemoveSprim(HdPrimTypeTokens->light, _lightIds.back());
        _lightIds.pop_back();
        hasNumLightsChanged = true;
    }

    // invalidate HdLights
    for (size_t i = 0; i < lights.size(); ++i) {
        _ValueCache &cache = _valueCacheMap[_lightIds[i]];
        // store GlfSimpleLight directly.
        cache[HdStLightTokens->params] = VtValue(lights[i]);
        cache[HdStLightTokens->transform] = VtValue();
        cache[HdStLightTokens->shadowParams] = VtValue(HdxShadowParams());
        cache[HdStLightTokens->shadowCollection] = VtValue();

        // Only mark as dirty the parameters to avoid unnecessary invalidation
        // specially marking as dirty lightShadowCollection will trigger
        // a collection dirty on geometry and we don't want that to happen
        // always
        GetRenderIndex().GetChangeTracker().MarkSprimDirty(
            _lightIds[i], HdStLight::AllDirty);
    }

    // sadly the material also comes from lighting context right now...
    HdxSimpleLightTaskParams taskParams
        = _GetValue<HdxSimpleLightTaskParams>(_simpleLightTaskId,
                                              HdTokens->params);
    taskParams.sceneAmbient = _lightingContext->GetSceneAmbient();
    taskParams.material = _lightingContext->GetMaterial();

    // invalidate HdxSimpleLightTask too
    if (hasNumLightsChanged) {
        _SetValue(_simpleLightTaskId, HdTokens->params, taskParams);

        GetRenderIndex().GetChangeTracker().MarkTaskDirty(
            _simpleLightTaskId, HdChangeTracker::DirtyParams);
    }
}
Example #30
0
static void CameraAndLightTest()
{
    HdStRenderDelegate renderDelegate;
    std::unique_ptr<HdRenderIndex> index(HdRenderIndex::New(&renderDelegate));
    TF_VERIFY(index);
    std::unique_ptr<Hdx_UnitTestDelegate> delegate(
                                         new Hdx_UnitTestDelegate(index.get()));

    HdChangeTracker& tracker = index->GetChangeTracker();
    HdPerfLog& perfLog = HdPerfLog::GetInstance();
    perfLog.Enable();
    HdRprimCollection collection(HdTokens->geometry, HdTokens->hull);
    HdRenderPassStateSharedPtr renderPassState(new HdRenderPassState());
    HdRenderPassSharedPtr renderPass(
        new HdSt_RenderPass(index.get(), collection));
    HdEngine engine;

    HdTaskSharedPtr drawTask = boost::make_shared<Hd_TestTask>(renderPass,
                                                               renderPassState);
    HdTaskSharedPtrVector tasks = { drawTask };

    GfMatrix4d tx(1.0f);
    tx.SetRow(3, GfVec4f(5, 0, 5, 1.0));
    SdfPath cube("geometry");
    delegate->AddCube(cube, tx);

    SdfPath camera("camera");
    SdfPath light("light");

    delegate->AddCamera(camera);
    delegate->AddLight(light, GlfSimpleLight());
    delegate->SetLight(light, HdStLightTokens->shadowCollection,
                      VtValue(HdRprimCollection(HdTokens->geometry,
                                                HdTokens->hull)));

    engine.Execute(*index, tasks);

    VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 1);

    // Update camera matrix
    delegate->SetCamera(camera, GfMatrix4d(2), GfMatrix4d(2));
    tracker.MarkSprimDirty(camera, HdStCamera::DirtyViewMatrix);
    tracker.MarkSprimDirty(camera, HdStCamera::DirtyProjMatrix);

    engine.Execute(*index, tasks);

    // batch should not be rebuilt
    VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 1);

    // Update shadow collection
    delegate->SetLight(light, HdStLightTokens->shadowCollection,
                      VtValue(HdRprimCollection(HdTokens->geometry,
                                                HdTokens->refined)));
    tracker.MarkSprimDirty(light, HdStLight::DirtyCollection);

    engine.Execute(*index, tasks);

    // batch rebuilt
    VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 2);

    // Update shadow collection again with the same data
    delegate->SetLight(light, HdStLightTokens->shadowCollection,
                      VtValue(HdRprimCollection(HdTokens->geometry,
                                                HdTokens->refined)));
    tracker.MarkSprimDirty(light, HdStLight::DirtyCollection);

    engine.Execute(*index, tasks);

    // batch should not be rebuilt
    VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 2);
}