void RendererServices::clear_derivatives(
    const OIIO::TypeDesc&       type,
    void*                       val)
{
    if (type != OIIO::TypeDesc::TypeString)
        memset(reinterpret_cast<char*>(val) + type.size(), 0, 2 * type.size());
}
void RendererServices::clear_attr_derivatives(
    bool                    derivs,
    const OIIO::TypeDesc&   type,
    void*                   val)
{
    if (derivs)
    {
        if (type == OIIO::TypeDesc::TypeString)
        {
            reinterpret_cast<OIIO::ustring*>(val)[1] = g_empty_ustr;
            reinterpret_cast<OIIO::ustring*>(val)[2] = g_empty_ustr;
        }
        else
            memset(reinterpret_cast<char*>(val) + type.size(), 0, 2 * type.size());
    }
}
bool RendererServices::getmessage(
    OSL::ShaderGlobals*     sg,
    OIIO::ustring           source,
    OIIO::ustring           name,
    OIIO::TypeDesc          type,
    void*                   val,
    bool                    derivatives)
{
    const ShadingPoint::OSLTraceData* trace_data =
        reinterpret_cast<ShadingPoint::OSLTraceData*>(sg->tracedata);

    if (trace_data->m_traced)
    {
        if (source == g_trace_ustr)
        {
            if (name == g_hit_ustr && type == OIIO::TypeDesc::TypeInt)
                reinterpret_cast<int*>(val)[0] = trace_data->m_hit ? 1 : 0;
            else if (name == g_hitdist_ustr && type == OIIO::TypeDesc::TypeFloat)
                reinterpret_cast<float*>(val)[0] = trace_data->m_hit_distance;
            else if (name == g_N_ustr && type == OIIO::TypeDesc::TypeNormal)
                *reinterpret_cast<OSL::Vec3*>(val) = trace_data->m_N;
            else if (name == g_Ng_ustr && type == OIIO::TypeDesc::TypeNormal)
                *reinterpret_cast<OSL::Vec3*>(val) = trace_data->m_Ng;
            else if (name == g_P_ustr && type == OIIO::TypeDesc::TypePoint)
                *reinterpret_cast<OSL::Vec3*>(val) = trace_data->m_P;
            else if (name == g_u_ustr && type == OIIO::TypeDesc::TypeFloat)
                reinterpret_cast<float*>(val)[0] = trace_data->m_u;
            else if (name == g_v_ustr && type == OIIO::TypeDesc::TypeFloat)
                reinterpret_cast<float*>(val)[0] = trace_data->m_v;
            else
                return false;

            // For now, set derivatives to zero.
            if (derivatives)
                memset(reinterpret_cast<char*>(val) + type.size(), 0, 2 * type.size());

            return true;
        }
    }

    return false;
}