<commit_before>/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_EXR_YES)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Image/File_Exr.h"
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//***************************************************************************
// Infos
//***************************************************************************

//***************************************************************************
// Const
//***************************************************************************

enum Elements
{
    Pos_FileInformation,
    Pos_GenericSection,
    Pos_IndustrySpecific,
    Pos_UserDefined,
    Pos_Padding,
    Pos_ImageData,
};

//***************************************************************************
// Constructor/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
File_Exr::File_Exr()
:File__Analyze()
{
    //Configuration
    ParserName="EXR";
    StreamSource=IsStream;
}

//***************************************************************************
// Streams management
//***************************************************************************

//---------------------------------------------------------------------------
void File_Exr::Streams_Accept()
{
    Fill(Stream_General, 0, General_Format, "EXR");

    if (!IsSub)
    {
        TestContinuousFileNames();

        Stream_Prepare((Config->File_Names.size()>1 || Config->File_IsReferenced_Get())?Stream_Video:Stream_Image);
        if (File_Size!=(int64u)-1)
            Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_StreamSize), File_Size);
        if (StreamKind_Last==Stream_Video)
            Fill(Stream_Video, StreamPos_Last, Video_FrameCount, Config->File_Names.size());
    }
    else
        Stream_Prepare(Stream_Image);

    //Configuration
    Buffer_MaximumSize=64*1024*1024; //Some big frames are possible (e.g YUV 4:2:2 10 bits 1080p)
}

//***************************************************************************
// Buffer
//***************************************************************************

//---------------------------------------------------------------------------
bool File_Exr::FileHeader_Begin()
{
    //Element_Size
    if (Buffer_Size<4)
        return false; //Must wait for more data

    if (CC4(Buffer)!=0x762F3101) //"v/1"+1
    {
        Reject();
        return false;
    }

    //All should be OK...
    Accept();

    return true;
}

//---------------------------------------------------------------------------
void File_Exr::FileHeader_Parse()
{
    //Parsing
    int32u Flags;
    int8u Version;
    bool Deep, Multipart;
    Skip_L4(                                                    "Magic number");
    Get_L1 (Version,                                            "Version field");
    Get_L3 (Flags,                                              "Flags");
        Skip_Flags(Flags, 0,                                    "Single tile");
        Get_Flags (Flags, 1, LongName,                          "Long name");
        Get_Flags (Flags, 2, Deep,                              "Non-image");
        Get_Flags (Flags, 3, Multipart,                         "Multipart");

    //Filling
    if (Frame_Count==0)
    {
        Fill(Stream_General, 0, General_Format_Version, __T("Version ")+Ztring::ToZtring(Version));
        Fill(StreamKind_Last, 0, "Format", "EXR");
        Fill(StreamKind_Last, 0, "Format_Version", __T("Version ")+Ztring::ToZtring(Version));
        Fill(StreamKind_Last, 0, "Format_Profile", (Flags&0x02)?"Tile":"Line");
        if (Deep)
            Fill(Stream_General, 0, "Deep", "Yes");
        if (Multipart)
            Fill(Stream_General, 0, "Multipart", "Yes");
    }
    Frame_Count++;
    if (Frame_Count_NotParsedIncluded!=(int64u)-1)
        Frame_Count_NotParsedIncluded++;
    ImageData_End=Config->File_Current_Size;
}

//***************************************************************************
// Buffer - Per element
//***************************************************************************

//---------------------------------------------------------------------------
bool File_Exr::Header_Begin()
{
    //Name
    name_End=0;
    while (Buffer_Offset+name_End<Buffer_Size)
    {
        if (Buffer[Buffer_Offset+name_End]=='\0')
            break;
        if (name_End>(LongName?255:31))
            break;
        name_End++;
    }
    if (Buffer_Offset+name_End>=Buffer_Size)
        return false;
    if (name_End>(LongName?255:31))
    {
        Reject();
        return false;
    }
    if (name_End==0)
        return true;

    //Type
    type_End=0;
    while (Buffer_Offset+name_End+1+type_End<Buffer_Size)
    {
        if (Buffer[Buffer_Offset+name_End+1+type_End]=='\0')
            break;
        if (type_End>(LongName?255:31))
            break;
        type_End++;
    }

    if (Buffer_Offset+name_End+1+type_End>=Buffer_Size)
        return false;
    if (type_End>(LongName?255:31))
    {
        Reject();
        return false;
    }

    if (Buffer_Offset+name_End+1+type_End+1+4>=Buffer_Size)
        return false;

    return true;
}

//---------------------------------------------------------------------------
void File_Exr::Header_Parse()
{
    //Image data
    if (name_End==0)
    {
        //Filling
        Header_Fill_Code(0, "Image data");
        Header_Fill_Size(ImageData_End-(File_Offset+Buffer_Offset));
        return;
    }

    int32u size;
    Get_String(name_End, name,                                  "name");
    Element_Offset++; //Null byte
    Get_String(type_End, type,                                  "type");
    Element_Offset++; //Null byte
    Get_L4 (size,                                               "size");

    //Filling
    Header_Fill_Code(0, Ztring().From_ISO_8859_1(name.c_str()));
    Header_Fill_Size(name_End+1+type_End+1+4+size);
}

//---------------------------------------------------------------------------
void File_Exr::Data_Parse()
{
         if (name_End==0)
        ImageData();
    else if (name=="channels" && type=="chlist")
        channels();
    else if (name=="comments" && type=="string")
        comments();
    else if (name=="compression" && type=="compression" && Element_Size==1)
        compression();
    else if (name=="dataWindow" && type=="box2i" && Element_Size==16)
        dataWindow();
    else if (name=="displayWindow" && type=="box2i" && Element_Size==16)
        displayWindow();
    else if (name=="pixelAspectRatio" && type=="float" && Element_Size==4)
        pixelAspectRatio();
    else
        Skip_XX(Element_Size,                                   "value");
}

//---------------------------------------------------------------------------
void File_Exr::ImageData()
{
    Skip_XX(Element_Size,                                       "data");

    if (!Status[IsFilled])
        Fill();
    if (Config->ParseSpeed<1.0)
        Finish();
}

//---------------------------------------------------------------------------
struct Exr_channel
{
    string name;
    int32u xSampling;
    int32u ySampling;
};
void File_Exr::channels()
{
    //Parsing
    std::vector<Exr_channel> ChannelList;
    while (Element_Offset+1<Element_Size)
    {
        Element_Begin1("channel");

        //Name
        size_t name_Size=0;
        while (Element_Offset+name_Size<Element_Size)
        {
            if (!Buffer[Buffer_Offset+(size_t)Element_Offset+name_Size])
                break;
            name_Size++;
        }
        name_End++;

        Exr_channel Channel;
        Get_String(name_Size, Channel.name,                 "name"); Element_Info1(Channel.name);
        Element_Offset++; //Null byte
        Skip_L4(                                            "pixel type");
        Skip_L1(                                            "pLinear");
        Skip_B3(                                            "reserved");
        Get_L4 (Channel.xSampling,                          "xSampling");
        Get_L4 (Channel.ySampling,                          "ySampling");
        ChannelList.push_back(Channel);

        Element_End0();
    }

    //Color space
    /* TODO: not finished
    bool HasAlpha=false;
    string ColorSpace, ChromaSubsampling;
    if (!ChannelList.empty() && ChannelList[0].name=="A")
    {
        HasAlpha=true;
        ChannelList.erase(ChannelList.begin());
    }
    if (ChannelList.size()==1 && ChannelList[0].name=="Y")
    {
        ColorSpace="Y";
    }
    else if (ChannelList.size()==3 && ChannelList[0].name=="V" && ChannelList[1].name=="U" && ChannelList[2].name=="Y")
    {
        ColorSpace="YUV";

        //Chroma subsampling
        if (ChannelList[2].xSampling==1 && ChannelList[2].xSampling==1 && ChannelList[0].xSampling==ChannelList[1].xSampling && ChannelList[0].ySampling==ChannelList[1].ySampling)
        {
            switch (ChannelList[0].xSampling)
            {
                case 1 :
                        switch (ChannelList[0].ySampling)
                        {
                            case 1 : ChromaSubsampling="4:4:4"; break;
                            default: ;
                        }
                        break;
                case 2 :
                        switch (ChannelList[0].ySampling)
                        {
                            case 1 : ChromaSubsampling="4:2:2"; break;
                            case 2 : ChromaSubsampling="4:2:0"; break;
                            default: ;
                        }
                        break;
                case 4 :
                        switch (ChannelList[0].ySampling)
                        {
                            case 1 : ChromaSubsampling="4:1:1"; break;
                            case 2 : ChromaSubsampling="4:1:0"; break;
                            default: ;
                        }
                        break;
                default: ;
            }
        }
    }
    else if (ChannelList.size()==3 && ChannelList[0].name=="B" && ChannelList[1].name=="G" && ChannelList[2].name=="R")
    {
        ColorSpace="RGB";
    }
    else
    {
        //TODO
    }
    if (!ColorSpace.empty())
    {
        if (HasAlpha)
            ColorSpace+='A';
        Fill(StreamKind_Last, 0, "ColorSpace", ColorSpace);
    }
    if (!ChromaSubsampling.empty())
        Fill(StreamKind_Last, 0, "ChromaSubsampling", ChromaSubsampling);
    */
}

//---------------------------------------------------------------------------
void File_Exr::comments ()
{
    //Parsing
    Ztring value;
    Get_UTF8(Element_Size, value,                               "value");

    //Filling
    if (Frame_Count==1)
        Fill(StreamKind_Last, 0, General_Comment, value);
}

//---------------------------------------------------------------------------
void File_Exr::compression ()
{
    //Parsing
    int8u value;
    Get_L1 (value,                                              "value");

    //Filling
    std::string Compression;
    switch (value)
    {
        case 0x00 : Compression="raw"; break;
        case 0x01 : Compression="RLZ"; break;
        case 0x02 : Compression="ZIPS"; break;
        case 0x03 : Compression="ZIP"; break;
        case 0x04 : Compression="PIZ"; break;
        case 0x05 : Compression="PXR24"; break;
        case 0x06 : Compression="B44"; break;
        case 0x07 : Compression="B44A"; break;
        default   : ;
    }

    if (Frame_Count==1)
        Fill(StreamKind_Last, 0, "Format_Compression", Compression.c_str());
}

//---------------------------------------------------------------------------
void File_Exr::dataWindow ()
{
    //Parsing
    int32u xMin, yMin, xMax, yMax;
    Get_L4 (xMin,                                               "xMin");
    Get_L4 (yMin,                                               "yMin");
    Get_L4 (xMax,                                               "xMax");
    Get_L4 (yMax,                                               "yMax");
}

//---------------------------------------------------------------------------
void File_Exr::displayWindow ()
{
    //Parsing
    int32u xMin, yMin, xMax, yMax;
    Get_L4 (xMin,                                               "xMin");
    Get_L4 (yMin,                                               "yMin");
    Get_L4 (xMax,                                               "xMax");
    Get_L4 (yMax,                                               "yMax");

    //Filling
    if (Frame_Count==1)
    {
        Fill(StreamKind_Last, 0, "Width", xMax-xMin+1);
        Fill(StreamKind_Last, 0, "Height", yMax-yMin+1);
    }
}

//---------------------------------------------------------------------------
void File_Exr::pixelAspectRatio ()
{
    //Parsing
    float value;
    Get_LF4(value,                                              "value");

    //Filling
    if (Frame_Count==1)
        Fill(StreamKind_Last, 0, "PixelAspectRatio", value?value:1, 3);
}

} //NameSpace

#endif //MEDIAINFO_EXR_YES
<commit_msg>Fix off-by-one issue when parsing EXR header flags<commit_after>/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_EXR_YES)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Image/File_Exr.h"
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//***************************************************************************
// Infos
//***************************************************************************

//***************************************************************************
// Const
//***************************************************************************

enum Elements
{
    Pos_FileInformation,
    Pos_GenericSection,
    Pos_IndustrySpecific,
    Pos_UserDefined,
    Pos_Padding,
    Pos_ImageData,
};

//***************************************************************************
// Constructor/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
File_Exr::File_Exr()
:File__Analyze()
{
    //Configuration
    ParserName="EXR";
    StreamSource=IsStream;
}

//***************************************************************************
// Streams management
//***************************************************************************

//---------------------------------------------------------------------------
void File_Exr::Streams_Accept()
{
    Fill(Stream_General, 0, General_Format, "EXR");

    if (!IsSub)
    {
        TestContinuousFileNames();

        Stream_Prepare((Config->File_Names.size()>1 || Config->File_IsReferenced_Get())?Stream_Video:Stream_Image);
        if (File_Size!=(int64u)-1)
            Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_StreamSize), File_Size);
        if (StreamKind_Last==Stream_Video)
            Fill(Stream_Video, StreamPos_Last, Video_FrameCount, Config->File_Names.size());
    }
    else
        Stream_Prepare(Stream_Image);

    //Configuration
    Buffer_MaximumSize=64*1024*1024; //Some big frames are possible (e.g YUV 4:2:2 10 bits 1080p)
}

//***************************************************************************
// Buffer
//***************************************************************************

//---------------------------------------------------------------------------
bool File_Exr::FileHeader_Begin()
{
    //Element_Size
    if (Buffer_Size<4)
        return false; //Must wait for more data

    if (CC4(Buffer)!=0x762F3101) //"v/1"+1
    {
        Reject();
        return false;
    }

    //All should be OK...
    Accept();

    return true;
}

//---------------------------------------------------------------------------
void File_Exr::FileHeader_Parse()
{
    //Parsing
    int32u Flags;
    int8u Version;
    bool Deep, Multipart;
    Skip_L4(                                                    "Magic number");
    Get_L1 (Version,                                            "Version field");
    //Note that bit 0 is unused
    Get_L3 (Flags,                                              "Flags");
        Skip_Flags(Flags, 1,                                    "Single tile");
        Get_Flags (Flags, 2, LongName,                          "Long name");
        Get_Flags (Flags, 3, Deep,                              "Non-image");
        Get_Flags (Flags, 4, Multipart,                         "Multipart");

    //Filling
    if (Frame_Count==0)
    {
        Fill(Stream_General, 0, General_Format_Version, __T("Version ")+Ztring::ToZtring(Version));
        Fill(StreamKind_Last, 0, "Format", "EXR");
        Fill(StreamKind_Last, 0, "Format_Version", __T("Version ")+Ztring::ToZtring(Version));
        Fill(StreamKind_Last, 0, "Format_Profile", (Flags&0x02)?"Tile":"Line");
        if (Deep)
            Fill(Stream_General, 0, "Deep", "Yes");
        if (Multipart)
            Fill(Stream_General, 0, "Multipart", "Yes");
    }
    Frame_Count++;
    if (Frame_Count_NotParsedIncluded!=(int64u)-1)
        Frame_Count_NotParsedIncluded++;
    ImageData_End=Config->File_Current_Size;
}

//***************************************************************************
// Buffer - Per element
//***************************************************************************

//---------------------------------------------------------------------------
bool File_Exr::Header_Begin()
{
    //Name
    name_End=0;
    while (Buffer_Offset+name_End<Buffer_Size)
    {
        if (Buffer[Buffer_Offset+name_End]=='\0')
            break;
        if (name_End>(LongName?255:31))
            break;
        name_End++;
    }
    if (Buffer_Offset+name_End>=Buffer_Size)
        return false;
    if (name_End>(LongName?255:31))
    {
        Reject();
        return false;
    }
    if (name_End==0)
        return true;

    //Type
    type_End=0;
    while (Buffer_Offset+name_End+1+type_End<Buffer_Size)
    {
        if (Buffer[Buffer_Offset+name_End+1+type_End]=='\0')
            break;
        if (type_End>(LongName?255:31))
            break;
        type_End++;
    }

    if (Buffer_Offset+name_End+1+type_End>=Buffer_Size)
        return false;
    if (type_End>(LongName?255:31))
    {
        Reject();
        return false;
    }

    if (Buffer_Offset+name_End+1+type_End+1+4>=Buffer_Size)
        return false;

    return true;
}

//---------------------------------------------------------------------------
void File_Exr::Header_Parse()
{
    //Image data
    if (name_End==0)
    {
        //Filling
        Header_Fill_Code(0, "Image data");
        Header_Fill_Size(ImageData_End-(File_Offset+Buffer_Offset));
        return;
    }

    int32u size;
    Get_String(name_End, name,                                  "name");
    Element_Offset++; //Null byte
    Get_String(type_End, type,                                  "type");
    Element_Offset++; //Null byte
    Get_L4 (size,                                               "size");

    //Filling
    Header_Fill_Code(0, Ztring().From_ISO_8859_1(name.c_str()));
    Header_Fill_Size(name_End+1+type_End+1+4+size);
}

//---------------------------------------------------------------------------
void File_Exr::Data_Parse()
{
         if (name_End==0)
        ImageData();
    else if (name=="channels" && type=="chlist")
        channels();
    else if (name=="comments" && type=="string")
        comments();
    else if (name=="compression" && type=="compression" && Element_Size==1)
        compression();
    else if (name=="dataWindow" && type=="box2i" && Element_Size==16)
        dataWindow();
    else if (name=="displayWindow" && type=="box2i" && Element_Size==16)
        displayWindow();
    else if (name=="pixelAspectRatio" && type=="float" && Element_Size==4)
        pixelAspectRatio();
    else
        Skip_XX(Element_Size,                                   "value");
}

//---------------------------------------------------------------------------
void File_Exr::ImageData()
{
    Skip_XX(Element_Size,                                       "data");

    if (!Status[IsFilled])
        Fill();
    if (Config->ParseSpeed<1.0)
        Finish();
}

//---------------------------------------------------------------------------
struct Exr_channel
{
    string name;
    int32u xSampling;
    int32u ySampling;
};
void File_Exr::channels()
{
    //Parsing
    std::vector<Exr_channel> ChannelList;
    while (Element_Offset+1<Element_Size)
    {
        Element_Begin1("channel");

        //Name
        size_t name_Size=0;
        while (Element_Offset+name_Size<Element_Size)
        {
            if (!Buffer[Buffer_Offset+(size_t)Element_Offset+name_Size])
                break;
            name_Size++;
        }
        name_End++;

        Exr_channel Channel;
        Get_String(name_Size, Channel.name,                 "name"); Element_Info1(Channel.name);
        Element_Offset++; //Null byte
        Skip_L4(                                            "pixel type");
        Skip_L1(                                            "pLinear");
        Skip_B3(                                            "reserved");
        Get_L4 (Channel.xSampling,                          "xSampling");
        Get_L4 (Channel.ySampling,                          "ySampling");
        ChannelList.push_back(Channel);

        Element_End0();
    }

    //Color space
    /* TODO: not finished
    bool HasAlpha=false;
    string ColorSpace, ChromaSubsampling;
    if (!ChannelList.empty() && ChannelList[0].name=="A")
    {
        HasAlpha=true;
        ChannelList.erase(ChannelList.begin());
    }
    if (ChannelList.size()==1 && ChannelList[0].name=="Y")
    {
        ColorSpace="Y";
    }
    else if (ChannelList.size()==3 && ChannelList[0].name=="V" && ChannelList[1].name=="U" && ChannelList[2].name=="Y")
    {
        ColorSpace="YUV";

        //Chroma subsampling
        if (ChannelList[2].xSampling==1 && ChannelList[2].xSampling==1 && ChannelList[0].xSampling==ChannelList[1].xSampling && ChannelList[0].ySampling==ChannelList[1].ySampling)
        {
            switch (ChannelList[0].xSampling)
            {
                case 1 :
                        switch (ChannelList[0].ySampling)
                        {
                            case 1 : ChromaSubsampling="4:4:4"; break;
                            default: ;
                        }
                        break;
                case 2 :
                        switch (ChannelList[0].ySampling)
                        {
                            case 1 : ChromaSubsampling="4:2:2"; break;
                            case 2 : ChromaSubsampling="4:2:0"; break;
                            default: ;
                        }
                        break;
                case 4 :
                        switch (ChannelList[0].ySampling)
                        {
                            case 1 : ChromaSubsampling="4:1:1"; break;
                            case 2 : ChromaSubsampling="4:1:0"; break;
                            default: ;
                        }
                        break;
                default: ;
            }
        }
    }
    else if (ChannelList.size()==3 && ChannelList[0].name=="B" && ChannelList[1].name=="G" && ChannelList[2].name=="R")
    {
        ColorSpace="RGB";
    }
    else
    {
        //TODO
    }
    if (!ColorSpace.empty())
    {
        if (HasAlpha)
            ColorSpace+='A';
        Fill(StreamKind_Last, 0, "ColorSpace", ColorSpace);
    }
    if (!ChromaSubsampling.empty())
        Fill(StreamKind_Last, 0, "ChromaSubsampling", ChromaSubsampling);
    */
}

//---------------------------------------------------------------------------
void File_Exr::comments ()
{
    //Parsing
    Ztring value;
    Get_UTF8(Element_Size, value,                               "value");

    //Filling
    if (Frame_Count==1)
        Fill(StreamKind_Last, 0, General_Comment, value);
}

//---------------------------------------------------------------------------
void File_Exr::compression ()
{
    //Parsing
    int8u value;
    Get_L1 (value,                                              "value");

    //Filling
    std::string Compression;
    switch (value)
    {
        case 0x00 : Compression="raw"; break;
        case 0x01 : Compression="RLZ"; break;
        case 0x02 : Compression="ZIPS"; break;
        case 0x03 : Compression="ZIP"; break;
        case 0x04 : Compression="PIZ"; break;
        case 0x05 : Compression="PXR24"; break;
        case 0x06 : Compression="B44"; break;
        case 0x07 : Compression="B44A"; break;
        default   : ;
    }

    if (Frame_Count==1)
        Fill(StreamKind_Last, 0, "Format_Compression", Compression.c_str());
}

//---------------------------------------------------------------------------
void File_Exr::dataWindow ()
{
    //Parsing
    int32u xMin, yMin, xMax, yMax;
    Get_L4 (xMin,                                               "xMin");
    Get_L4 (yMin,                                               "yMin");
    Get_L4 (xMax,                                               "xMax");
    Get_L4 (yMax,                                               "yMax");
}

//---------------------------------------------------------------------------
void File_Exr::displayWindow ()
{
    //Parsing
    int32u xMin, yMin, xMax, yMax;
    Get_L4 (xMin,                                               "xMin");
    Get_L4 (yMin,                                               "yMin");
    Get_L4 (xMax,                                               "xMax");
    Get_L4 (yMax,                                               "yMax");

    //Filling
    if (Frame_Count==1)
    {
        Fill(StreamKind_Last, 0, "Width", xMax-xMin+1);
        Fill(StreamKind_Last, 0, "Height", yMax-yMin+1);
    }
}

//---------------------------------------------------------------------------
void File_Exr::pixelAspectRatio ()
{
    //Parsing
    float value;
    Get_LF4(value,                                              "value");

    //Filling
    if (Frame_Count==1)
        Fill(StreamKind_Last, 0, "PixelAspectRatio", value?value:1, 3);
}

} //NameSpace

#endif //MEDIAINFO_EXR_YES
<|endoftext|>


<commit_before>// Copyright (c) 2014, Facebook, Inc.  All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
// This file implements the "bridge" between Java and C++ for
// rocksdb::Slice.

#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <string>

#include "include/org_rocksdb_AbstractSlice.h"
#include "include/org_rocksdb_Slice.h"
#include "include/org_rocksdb_DirectSlice.h"
#include "rocksdb/slice.h"
#include "rocksjni/portal.h"

// <editor-fold desc="org.rocksdb.AbstractSlice>

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    createNewSliceFromString
 * Signature: (Ljava/lang/String;)V
 */
void Java_org_rocksdb_AbstractSlice_createNewSliceFromString(
    JNIEnv* env, jobject jobj, jstring jstr) {

  const auto* str = env->GetStringUTFChars(jstr, 0);
  const size_t len = strlen(str);
  char* buf = new char[len];
  memcpy(buf, str, len);
  env->ReleaseStringUTFChars(jstr, str);

  const auto* slice = new rocksdb::Slice(buf);
  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    size0
 * Signature: (J)I
 */
jint Java_org_rocksdb_AbstractSlice_size0(
    JNIEnv* env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  return static_cast<jint>(slice->size());
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    empty0
 * Signature: (J)Z
 */
jboolean Java_org_rocksdb_AbstractSlice_empty0(
    JNIEnv* env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  return slice->empty();
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    toString0
 * Signature: (JZ)Ljava/lang/String;
 */
jstring Java_org_rocksdb_AbstractSlice_toString0(
    JNIEnv* env, jobject jobj, jlong handle, jboolean hex) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  const std::string s = slice->ToString(hex);
  return env->NewStringUTF(s.c_str());
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    compare0
 * Signature: (JJ)I;
 */
jint Java_org_rocksdb_AbstractSlice_compare0(
    JNIEnv* env, jobject jobj, jlong handle, jlong otherHandle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  const auto* otherSlice =
    reinterpret_cast<rocksdb::Slice*>(otherHandle);
  return slice->compare(*otherSlice);
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    startsWith0
 * Signature: (JJ)Z;
 */
jboolean Java_org_rocksdb_AbstractSlice_startsWith0(
    JNIEnv* env, jobject jobj, jlong handle, jlong otherHandle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  const auto* otherSlice =
    reinterpret_cast<rocksdb::Slice*>(otherHandle);
  return slice->starts_with(*otherSlice);
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    disposeInternal
 * Signature: (J)V
 */
void Java_org_rocksdb_AbstractSlice_disposeInternal(
    JNIEnv* env, jobject jobj, jlong handle) {
  delete reinterpret_cast<rocksdb::Slice*>(handle);
}

// </editor-fold>

// <editor-fold desc="org.rocksdb.Slice>

/*
 * Class:     org_rocksdb_Slice
 * Method:    createNewSlice0
 * Signature: ([BI)V
 */
void Java_org_rocksdb_Slice_createNewSlice0(
    JNIEnv * env, jobject jobj, jbyteArray data, jint offset) {

  const jsize dataSize = env->GetArrayLength(data);
  const int len = dataSize - offset;
  jbyte* ptrData = new jbyte[len];
  env->GetByteArrayRegion(data, offset, len, ptrData);

  const auto* slice = new rocksdb::Slice((const char*)ptrData, len);
  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
}

/*
 * Class:     org_rocksdb_Slice
 * Method:    createNewSlice1
 * Signature: ([B)V
 */
void Java_org_rocksdb_Slice_createNewSlice1(
    JNIEnv * env, jobject jobj, jbyteArray data) {

  const int len = env->GetArrayLength(data) + 1;

  jboolean isCopy;
  jbyte* ptrData = env->GetByteArrayElements(data, &isCopy);
  char* buf = new char[len];

  memcpy(buf, ptrData, len - 1);
  buf[len-1]='\0';

  const auto* slice =
      new rocksdb::Slice(buf, len - 1);

  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
  env->ReleaseByteArrayElements(data, ptrData, JNI_ABORT);
  // NOTE: buf will be deleted in the org.rocksdb.Slice#dispose method
}

/*
 * Class:     org_rocksdb_Slice
 * Method:    data0
 * Signature: (J)[B
 */
jbyteArray Java_org_rocksdb_Slice_data0(
    JNIEnv* env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  const int len = static_cast<int>(slice->size());
  const jbyteArray data = env->NewByteArray(len);
  env->SetByteArrayRegion(data, 0, len,
    reinterpret_cast<const jbyte*>(slice->data()));
  return data;
}

/*
 * Class:     org_rocksdb_Slice
 * Method:    disposeInternalBuf
 * Signature: (J)V
 */
void Java_org_rocksdb_Slice_disposeInternalBuf(
    JNIEnv * env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  delete [] slice->data_;
}

// </editor-fold>

// <editor-fold desc="org.rocksdb.DirectSlice>

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    createNewDirectSlice0
 * Signature: (Ljava/nio/ByteBuffer;I)V
 */
void Java_org_rocksdb_DirectSlice_createNewDirectSlice0(
    JNIEnv* env, jobject jobj, jobject data, jint length) {
  const auto* ptrData =
     reinterpret_cast<char*>(env->GetDirectBufferAddress(data));
  const auto* slice = new rocksdb::Slice(ptrData, length);
  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    createNewDirectSlice1
 * Signature: (Ljava/nio/ByteBuffer;)V
 */
void Java_org_rocksdb_DirectSlice_createNewDirectSlice1(
    JNIEnv* env, jobject jobj, jobject data) {
  const auto* ptrData =
    reinterpret_cast<char*>(env->GetDirectBufferAddress(data));
  const auto* slice = new rocksdb::Slice(ptrData);
  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    data0
 * Signature: (J)Ljava/lang/Object;
 */
jobject Java_org_rocksdb_DirectSlice_data0(
    JNIEnv* env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  return env->NewDirectByteBuffer(const_cast<char*>(slice->data()),
    slice->size());
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    get0
 * Signature: (JI)B
 */
jbyte Java_org_rocksdb_DirectSlice_get0(
    JNIEnv* env, jobject jobj, jlong handle, jint offset) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  return (*slice)[offset];
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    clear0
 * Signature: (J)V
 */
void Java_org_rocksdb_DirectSlice_clear0(
    JNIEnv* env, jobject jobj, jlong handle) {
  auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  delete [] slice->data_;
  slice->clear();
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    removePrefix0
 * Signature: (JI)V
 */
void Java_org_rocksdb_DirectSlice_removePrefix0(
    JNIEnv* env, jobject jobj, jlong handle, jint length) {
  auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  slice->remove_prefix(length);
}

// </editor-fold>
<commit_msg>[RocksJava] DirectSlice String termination fix<commit_after>// Copyright (c) 2014, Facebook, Inc.  All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
// This file implements the "bridge" between Java and C++ for
// rocksdb::Slice.

#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <string>

#include "include/org_rocksdb_AbstractSlice.h"
#include "include/org_rocksdb_Slice.h"
#include "include/org_rocksdb_DirectSlice.h"
#include "rocksdb/slice.h"
#include "rocksjni/portal.h"

// <editor-fold desc="org.rocksdb.AbstractSlice>

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    createNewSliceFromString
 * Signature: (Ljava/lang/String;)V
 */
void Java_org_rocksdb_AbstractSlice_createNewSliceFromString(
    JNIEnv* env, jobject jobj, jstring jstr) {

  const auto* str = env->GetStringUTFChars(jstr, 0);
  const size_t len = strlen(str) + 1;
  char* buf = new char[len];
  memcpy(buf, str, len - 1);
  buf[len-1]='\0';

  env->ReleaseStringUTFChars(jstr, str);

  const auto* slice = new rocksdb::Slice(buf);
  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    size0
 * Signature: (J)I
 */
jint Java_org_rocksdb_AbstractSlice_size0(
    JNIEnv* env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  return static_cast<jint>(slice->size());
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    empty0
 * Signature: (J)Z
 */
jboolean Java_org_rocksdb_AbstractSlice_empty0(
    JNIEnv* env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  return slice->empty();
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    toString0
 * Signature: (JZ)Ljava/lang/String;
 */
jstring Java_org_rocksdb_AbstractSlice_toString0(
    JNIEnv* env, jobject jobj, jlong handle, jboolean hex) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  const std::string s = slice->ToString(hex);
  return env->NewStringUTF(s.c_str());
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    compare0
 * Signature: (JJ)I;
 */
jint Java_org_rocksdb_AbstractSlice_compare0(
    JNIEnv* env, jobject jobj, jlong handle, jlong otherHandle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  const auto* otherSlice =
    reinterpret_cast<rocksdb::Slice*>(otherHandle);
  return slice->compare(*otherSlice);
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    startsWith0
 * Signature: (JJ)Z;
 */
jboolean Java_org_rocksdb_AbstractSlice_startsWith0(
    JNIEnv* env, jobject jobj, jlong handle, jlong otherHandle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  const auto* otherSlice =
    reinterpret_cast<rocksdb::Slice*>(otherHandle);
  return slice->starts_with(*otherSlice);
}

/*
 * Class:     org_rocksdb_AbstractSlice
 * Method:    disposeInternal
 * Signature: (J)V
 */
void Java_org_rocksdb_AbstractSlice_disposeInternal(
    JNIEnv* env, jobject jobj, jlong handle) {
  delete reinterpret_cast<rocksdb::Slice*>(handle);
}

// </editor-fold>

// <editor-fold desc="org.rocksdb.Slice>

/*
 * Class:     org_rocksdb_Slice
 * Method:    createNewSlice0
 * Signature: ([BI)V
 */
void Java_org_rocksdb_Slice_createNewSlice0(
    JNIEnv * env, jobject jobj, jbyteArray data, jint offset) {

  const jsize dataSize = env->GetArrayLength(data);
  const int len = dataSize - offset;
  jbyte* ptrData = new jbyte[len];
  env->GetByteArrayRegion(data, offset, len, ptrData);

  const auto* slice = new rocksdb::Slice((const char*)ptrData, len);
  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
}

/*
 * Class:     org_rocksdb_Slice
 * Method:    createNewSlice1
 * Signature: ([B)V
 */
void Java_org_rocksdb_Slice_createNewSlice1(
    JNIEnv * env, jobject jobj, jbyteArray data) {

  const int len = env->GetArrayLength(data) + 1;

  jboolean isCopy;
  jbyte* ptrData = env->GetByteArrayElements(data, &isCopy);
  char* buf = new char[len];

  memcpy(buf, ptrData, len - 1);
  buf[len-1]='\0';

  const auto* slice =
      new rocksdb::Slice(buf, len - 1);

  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
  env->ReleaseByteArrayElements(data, ptrData, JNI_ABORT);
  // NOTE: buf will be deleted in the org.rocksdb.Slice#dispose method
}

/*
 * Class:     org_rocksdb_Slice
 * Method:    data0
 * Signature: (J)[B
 */
jbyteArray Java_org_rocksdb_Slice_data0(
    JNIEnv* env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  const int len = static_cast<int>(slice->size());
  const jbyteArray data = env->NewByteArray(len);
  env->SetByteArrayRegion(data, 0, len,
    reinterpret_cast<const jbyte*>(slice->data()));
  return data;
}

/*
 * Class:     org_rocksdb_Slice
 * Method:    disposeInternalBuf
 * Signature: (J)V
 */
void Java_org_rocksdb_Slice_disposeInternalBuf(
    JNIEnv * env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  delete [] slice->data_;
}

// </editor-fold>

// <editor-fold desc="org.rocksdb.DirectSlice>

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    createNewDirectSlice0
 * Signature: (Ljava/nio/ByteBuffer;I)V
 */
void Java_org_rocksdb_DirectSlice_createNewDirectSlice0(
    JNIEnv* env, jobject jobj, jobject data, jint length) {
  const auto* ptrData =
     reinterpret_cast<char*>(env->GetDirectBufferAddress(data));
  const auto* slice = new rocksdb::Slice(ptrData, length);
  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    createNewDirectSlice1
 * Signature: (Ljava/nio/ByteBuffer;)V
 */
void Java_org_rocksdb_DirectSlice_createNewDirectSlice1(
    JNIEnv* env, jobject jobj, jobject data) {
  const auto* ptrData =
    reinterpret_cast<char*>(env->GetDirectBufferAddress(data));
  const auto* slice = new rocksdb::Slice(ptrData);
  rocksdb::AbstractSliceJni::setHandle(env, jobj, slice);
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    data0
 * Signature: (J)Ljava/lang/Object;
 */
jobject Java_org_rocksdb_DirectSlice_data0(
    JNIEnv* env, jobject jobj, jlong handle) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  return env->NewDirectByteBuffer(const_cast<char*>(slice->data()),
    slice->size());
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    get0
 * Signature: (JI)B
 */
jbyte Java_org_rocksdb_DirectSlice_get0(
    JNIEnv* env, jobject jobj, jlong handle, jint offset) {
  const auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  return (*slice)[offset];
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    clear0
 * Signature: (J)V
 */
void Java_org_rocksdb_DirectSlice_clear0(
    JNIEnv* env, jobject jobj, jlong handle) {
  auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  delete [] slice->data_;
  slice->clear();
}

/*
 * Class:     org_rocksdb_DirectSlice
 * Method:    removePrefix0
 * Signature: (JI)V
 */
void Java_org_rocksdb_DirectSlice_removePrefix0(
    JNIEnv* env, jobject jobj, jlong handle, jint length) {
  auto* slice = reinterpret_cast<rocksdb::Slice*>(handle);
  slice->remove_prefix(length);
}

// </editor-fold>
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <chrono>
#include <random>

#define ETL_COUNTERS
//#define ETL_COUNTERS_VERBOSE

#define IF_DEBUG if(false)

#include "etl/etl.hpp"

typedef std::chrono::high_resolution_clock timer_clock;
typedef std::chrono::milliseconds milliseconds;

float fake = 0;

/*
 *
 * Current values are (alloc/release/gpu_to_cpu/cpu_to_gpu):
 * Simple: 13 /  13 /   0 /   2 (Optimal!)
 * Basic:  25 /  25 /   0 /   3 (Optimal!)
 * Sub:   163 / 163 / 160 / 480
 * ML:    179 / 179 /  10 /  19
 */

void simple() {
    std::cout << "Simple" << std::endl;
    etl::reset_counters();

    {
        etl::dyn_matrix<float, 2> A(4096, 4096);
        etl::dyn_matrix<float, 2> B(4096, 4096);
        etl::dyn_matrix<float, 2> C(4096, 4096);

        A = 1e-4 >> etl::sequence_generator<float>(1.0);
        B = 1e-4 >> etl::sequence_generator<float>(1.0);
        C = 1e-4 >> etl::sequence_generator<float>(1.0);

        for (size_t i = 0; i < 10; ++i) {
            C = A * B;
            fake += etl::mean(C);
        }

        std::cout << "   Result: " << fake << std::endl;
        std::cout << "Should be: 2.8826e+10" << std::endl;
    }

    etl::dump_counters();
}

void basic() {
    std::cout << "Basic" << std::endl;

    etl::reset_counters();

    {
        etl::dyn_matrix<float, 2> A(4096, 4096);
        etl::dyn_matrix<float, 2> B(4096, 4096);
        etl::dyn_matrix<float, 2> C(4096, 4096);
        etl::dyn_matrix<float, 2> D(4096, 4096);
        etl::dyn_matrix<float, 2> E(4096, 4096);

        A = 1e-4 >> etl::sequence_generator<float>(1.0);
        B = 1e-4 >> etl::sequence_generator<float>(1.0);
        C = 1e-4 >> etl::sequence_generator<float>(1.0);
        D = 1e-4 >> etl::sequence_generator<float>(1.0);
        E = 1e-4 >> etl::sequence_generator<float>(1.0);

        for (size_t i = 0; i < 10; ++i) {
            IF_DEBUG std::cout << i << ":0 C = A * B * E" << std::endl;
            C = A * B * E;
            IF_DEBUG std::cout << i << ":1 D = A * trans(A)" << std::endl;
            D = A * trans(A);
            IF_DEBUG std::cout << i << ":2 D *= 1.1" << std::endl;
            D *= 1.1;
            IF_DEBUG std::cout << i << ":3 E = D" << std::endl;
            E = D;
            IF_DEBUG std::cout << i << ":4 D += C" << std::endl;
            D += C;
            IF_DEBUG std::cout << i << ":5 fake += etl::mean(D)" << std::endl;
            fake += etl::mean(D);
            IF_DEBUG std::cout << i << ":6 end" << std::endl;
        }

        std::cout << "   Result: " << fake << std::endl;
        std::cout << "Should be: 3.36933e+23" << std::endl;
    }

    etl::dump_counters();
}

void sub() {
    std::cout << "Sub" << std::endl;

    etl::reset_counters();
    {
        etl::dyn_matrix<float, 3> A(16, 2048, 2048);
        etl::dyn_matrix<float, 3> B(16, 2048, 2048);
        etl::dyn_matrix<float, 3> C(16, 2048, 2048);
        etl::dyn_matrix<float, 3> D(16, 2048, 2048);

        A = etl::normal_generator<float>(1.0, 0.0);
        B = etl::normal_generator<float>(1.0, 0.0);
        C = etl::normal_generator<float>(1.0, 0.0);
        D = etl::normal_generator<float>(1.0, 0.0);

        for (size_t i = 0; i < 10; ++i) {
            for (size_t k = 0; k < 16; ++k) {
                C(k) = A(k) * B(k) * B(k);
                D(k) += C(k);
                D(k) *= 1.1;
                fake += etl::mean(D(k));
            }
        }
    }

    etl::dump_counters();
}

// Simulate forward propagation in a neural network (with some ops as DLL)
void ml() {
    std::cout << "ML" << std::endl;
    etl::reset_counters();

    {
        etl::dyn_matrix<float, 4> I(32, 3, 28, 28);
        etl::dyn_matrix<float, 2> L(32, 10);

        etl::dyn_matrix<float, 4> C1_W(16, 3, 3, 3);
        etl::dyn_matrix<float, 1> C1_B(16);
        etl::dyn_matrix<float, 4> C1_W_G(16, 3, 3, 3);
        etl::dyn_matrix<float, 1> C1_B_G(16);
        etl::dyn_matrix<float, 4> C1_O(32, 16, 28, 28);
        etl::dyn_matrix<float, 4> C1_E(32, 16, 28, 28);

        etl::dyn_matrix<float, 4> P1_O(32, 16, 14, 14);
        etl::dyn_matrix<float, 4> P1_E(32, 16, 14, 14);

        etl::dyn_matrix<float, 4> C2_W(16, 16, 3, 3);
        etl::dyn_matrix<float, 1> C2_B(16);
        etl::dyn_matrix<float, 4> C2_W_G(16, 16, 3, 3);
        etl::dyn_matrix<float, 1> C2_B_G(16);
        etl::dyn_matrix<float, 4> C2_O(32, 16, 14, 14);
        etl::dyn_matrix<float, 4> C2_E(32, 16, 14, 14);

        etl::dyn_matrix<float, 4> P2_O(32, 16, 7, 7);
        etl::dyn_matrix<float, 4> P2_E(32, 16, 7, 7);

        etl::dyn_matrix<float, 2> FC1_W(16 * 7 * 7, 500);
        etl::dyn_matrix<float, 1> FC1_B(500);
        etl::dyn_matrix<float, 2> FC1_W_G(16 * 7 * 7, 500);
        etl::dyn_matrix<float, 1> FC1_B_G(500);
        etl::dyn_matrix<float, 2> FC1_O(32, 500);
        etl::dyn_matrix<float, 2> FC1_E(32, 500);

        etl::dyn_matrix<float, 2> FC2_W(500, 10);
        etl::dyn_matrix<float, 1> FC2_B(10);
        etl::dyn_matrix<float, 2> FC2_W_G(500, 10);
        etl::dyn_matrix<float, 1> FC2_B_G(10);
        etl::dyn_matrix<float, 2> FC2_O(32, 10);
        etl::dyn_matrix<float, 2> FC2_E(32, 10);

        for (size_t i = 0; i < 10; ++i) {
            // Forward Propagation
            C1_O = relu(bias_add_4d(etl::ml::convolution_forward<1, 1, 1, 1>(I, C1_W), C1_B));
            P1_O = etl::max_pool_2d<2, 2>(C1_O);

            C2_O = relu(bias_add_4d(etl::ml::convolution_forward<1, 1, 1, 1>(P1_O, C2_W), C2_B));
            P2_O = etl::max_pool_2d<2, 2>(C2_O);

            FC1_O = sigmoid(bias_add_2d(etl::reshape<32, 16 * 7 * 7>(P2_O) * FC1_W, FC1_B));
            FC2_O = sigmoid(bias_add_2d(FC1_O * FC2_W, FC2_B));

            // Backward propagation of the errors

            FC2_E = L - FC2_O;                                            // Errors of last layer  (!GPU)
            FC1_E = FC2_E * trans(FC2_W);                                 // Backpropagate FC2 -> FC1
            FC1_E = etl::ml::sigmoid_backward(FC1_O, FC1_E);              // Adapt errors of FC1
            etl::reshape<32, 16 * 7 * 7>(P2_E) = FC1_E * trans(FC1_W);    // FC1 -> MP2
            C2_E = etl::max_pool_upsample_2d<2, 2>(C2_O, P2_O, P2_E);     // MP2 -> C2
            C2_E = etl::ml::relu_backward(C2_O, C2_E);                    // Adapt errors of C2
            P1_E = etl::ml::convolution_backward<1, 1, 1, 1>(C2_E, C2_W); // C2 -> MP1
            C1_E = etl::max_pool_upsample_2d<2, 2>(C1_O, P1_O, P1_E);     // MP1 -> C1
            C1_E = etl::ml::relu_backward(C1_O, C1_E);                    // Adapt errors of C1

            // Compute the gradients

            C1_W_G = etl::ml::convolution_backward_filter<1, 1, 1, 1>(I, C1_E);
            C1_B_G = bias_batch_sum_4d(C1_E);

            C2_W_G = etl::ml::convolution_backward_filter<1, 1, 1, 1>(P1_O, C2_E);
            C2_B_G = bias_batch_sum_4d(C2_E);

            FC1_W_G = batch_outer(etl::reshape<32, 16 * 7 * 7>(P2_O), FC1_E);
            FC1_B_G = bias_batch_sum_2d(FC1_E);

            FC2_W_G = batch_outer(FC1_O, FC2_E);
            FC2_B_G = bias_batch_sum_2d(FC2_E);

            //TODO Apply the gradients
        }
    }

    etl::dump_counters();
}

int main() {
    auto start_time = timer_clock::now();

    simple();
    basic();
    sub();
    ml();

    auto end_time = timer_clock::now();
    auto duration = std::chrono::duration_cast<milliseconds>(end_time - start_time);

    std::cout << "duration: " << duration.count() << "ms" << std::endl;

    return (int)fake;
}
<commit_msg>Use the GPU pool for counters<commit_after>//=======================================================================
// Copyright (c) 2014-2017 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <chrono>
#include <random>

#define ETL_COUNTERS
//#define ETL_COUNTERS_VERBOSE

// Use GPU pool to limit allocations
#define ETL_GPU_POOL

#define IF_DEBUG if(false)

#include "etl/etl.hpp"

typedef std::chrono::high_resolution_clock timer_clock;
typedef std::chrono::milliseconds milliseconds;

float fake = 0;

/*
 *
 * Current values are (alloc/release/gpu_to_cpu/cpu_to_gpu):
 *
 * No pool
 * Simple: 13 /  13 /   0 /   2 (Optimal!)
 * Basic:  25 /  25 /   0 /   3 (Optimal!)
 * Sub:   163 / 163 / 160 / 480
 * ML:    179 / 179 /  10 /  19
 *
 * GPU pool
 * Simple:  4 / 0 /   0 /   2 (Optimal!)
 * Basic:   2 / 0 /   0 /   3 (Optimal!)
 * Sub:     4 / 0 / 160 / 480
 * ML:     40 / 0 /  10 /  19
 */

void simple() {
    std::cout << "Simple" << std::endl;
    etl::reset_counters();

    {
        etl::dyn_matrix<float, 2> A(4096, 4096);
        etl::dyn_matrix<float, 2> B(4096, 4096);
        etl::dyn_matrix<float, 2> C(4096, 4096);

        A = 1e-4 >> etl::sequence_generator<float>(1.0);
        B = 1e-4 >> etl::sequence_generator<float>(1.0);
        C = 1e-4 >> etl::sequence_generator<float>(1.0);

        for (size_t i = 0; i < 10; ++i) {
            C = A * B;
            fake += etl::mean(C);
        }

        std::cout << "   Result: " << fake << std::endl;
        std::cout << "Should be: 2.8826e+10" << std::endl;
    }

    etl::dump_counters();
}

void basic() {
    std::cout << "Basic" << std::endl;

    etl::reset_counters();

    {
        etl::dyn_matrix<float, 2> A(4096, 4096);
        etl::dyn_matrix<float, 2> B(4096, 4096);
        etl::dyn_matrix<float, 2> C(4096, 4096);
        etl::dyn_matrix<float, 2> D(4096, 4096);
        etl::dyn_matrix<float, 2> E(4096, 4096);

        A = 1e-4 >> etl::sequence_generator<float>(1.0);
        B = 1e-4 >> etl::sequence_generator<float>(1.0);
        C = 1e-4 >> etl::sequence_generator<float>(1.0);
        D = 1e-4 >> etl::sequence_generator<float>(1.0);
        E = 1e-4 >> etl::sequence_generator<float>(1.0);

        for (size_t i = 0; i < 10; ++i) {
            IF_DEBUG std::cout << i << ":0 C = A * B * E" << std::endl;
            C = A * B * E;
            IF_DEBUG std::cout << i << ":1 D = A * trans(A)" << std::endl;
            D = A * trans(A);
            IF_DEBUG std::cout << i << ":2 D *= 1.1" << std::endl;
            D *= 1.1;
            IF_DEBUG std::cout << i << ":3 E = D" << std::endl;
            E = D;
            IF_DEBUG std::cout << i << ":4 D += C" << std::endl;
            D += C;
            IF_DEBUG std::cout << i << ":5 fake += etl::mean(D)" << std::endl;
            fake += etl::mean(D);
            IF_DEBUG std::cout << i << ":6 end" << std::endl;
        }

        std::cout << "   Result: " << fake << std::endl;
        std::cout << "Should be: 3.36933e+23" << std::endl;
    }

    etl::dump_counters();
}

void sub() {
    std::cout << "Sub" << std::endl;

    etl::reset_counters();
    {
        etl::dyn_matrix<float, 3> A(16, 2048, 2048);
        etl::dyn_matrix<float, 3> B(16, 2048, 2048);
        etl::dyn_matrix<float, 3> C(16, 2048, 2048);
        etl::dyn_matrix<float, 3> D(16, 2048, 2048);

        A = etl::normal_generator<float>(1.0, 0.0);
        B = etl::normal_generator<float>(1.0, 0.0);
        C = etl::normal_generator<float>(1.0, 0.0);
        D = etl::normal_generator<float>(1.0, 0.0);

        for (size_t i = 0; i < 10; ++i) {
            for (size_t k = 0; k < 16; ++k) {
                C(k) = A(k) * B(k) * B(k);
                D(k) += C(k);
                D(k) *= 1.1;
                fake += etl::mean(D(k));
            }
        }
    }

    etl::dump_counters();
}

// Simulate forward propagation in a neural network (with some ops as DLL)
void ml() {
    std::cout << "ML" << std::endl;
    etl::reset_counters();

    {
        etl::dyn_matrix<float, 4> I(32, 3, 28, 28);
        etl::dyn_matrix<float, 2> L(32, 10);

        etl::dyn_matrix<float, 4> C1_W(16, 3, 3, 3);
        etl::dyn_matrix<float, 1> C1_B(16);
        etl::dyn_matrix<float, 4> C1_W_G(16, 3, 3, 3);
        etl::dyn_matrix<float, 1> C1_B_G(16);
        etl::dyn_matrix<float, 4> C1_O(32, 16, 28, 28);
        etl::dyn_matrix<float, 4> C1_E(32, 16, 28, 28);

        etl::dyn_matrix<float, 4> P1_O(32, 16, 14, 14);
        etl::dyn_matrix<float, 4> P1_E(32, 16, 14, 14);

        etl::dyn_matrix<float, 4> C2_W(16, 16, 3, 3);
        etl::dyn_matrix<float, 1> C2_B(16);
        etl::dyn_matrix<float, 4> C2_W_G(16, 16, 3, 3);
        etl::dyn_matrix<float, 1> C2_B_G(16);
        etl::dyn_matrix<float, 4> C2_O(32, 16, 14, 14);
        etl::dyn_matrix<float, 4> C2_E(32, 16, 14, 14);

        etl::dyn_matrix<float, 4> P2_O(32, 16, 7, 7);
        etl::dyn_matrix<float, 4> P2_E(32, 16, 7, 7);

        etl::dyn_matrix<float, 2> FC1_W(16 * 7 * 7, 500);
        etl::dyn_matrix<float, 1> FC1_B(500);
        etl::dyn_matrix<float, 2> FC1_W_G(16 * 7 * 7, 500);
        etl::dyn_matrix<float, 1> FC1_B_G(500);
        etl::dyn_matrix<float, 2> FC1_O(32, 500);
        etl::dyn_matrix<float, 2> FC1_E(32, 500);

        etl::dyn_matrix<float, 2> FC2_W(500, 10);
        etl::dyn_matrix<float, 1> FC2_B(10);
        etl::dyn_matrix<float, 2> FC2_W_G(500, 10);
        etl::dyn_matrix<float, 1> FC2_B_G(10);
        etl::dyn_matrix<float, 2> FC2_O(32, 10);
        etl::dyn_matrix<float, 2> FC2_E(32, 10);

        for (size_t i = 0; i < 10; ++i) {
            // Forward Propagation
            C1_O = relu(bias_add_4d(etl::ml::convolution_forward<1, 1, 1, 1>(I, C1_W), C1_B));
            P1_O = etl::max_pool_2d<2, 2>(C1_O);

            C2_O = relu(bias_add_4d(etl::ml::convolution_forward<1, 1, 1, 1>(P1_O, C2_W), C2_B));
            P2_O = etl::max_pool_2d<2, 2>(C2_O);

            FC1_O = sigmoid(bias_add_2d(etl::reshape<32, 16 * 7 * 7>(P2_O) * FC1_W, FC1_B));
            FC2_O = sigmoid(bias_add_2d(FC1_O * FC2_W, FC2_B));

            // Backward propagation of the errors

            FC2_E = L - FC2_O;                                            // Errors of last layer  (!GPU)
            FC1_E = FC2_E * trans(FC2_W);                                 // Backpropagate FC2 -> FC1
            FC1_E = etl::ml::sigmoid_backward(FC1_O, FC1_E);              // Adapt errors of FC1
            etl::reshape<32, 16 * 7 * 7>(P2_E) = FC1_E * trans(FC1_W);    // FC1 -> MP2
            C2_E = etl::max_pool_upsample_2d<2, 2>(C2_O, P2_O, P2_E);     // MP2 -> C2
            C2_E = etl::ml::relu_backward(C2_O, C2_E);                    // Adapt errors of C2
            P1_E = etl::ml::convolution_backward<1, 1, 1, 1>(C2_E, C2_W); // C2 -> MP1
            C1_E = etl::max_pool_upsample_2d<2, 2>(C1_O, P1_O, P1_E);     // MP1 -> C1
            C1_E = etl::ml::relu_backward(C1_O, C1_E);                    // Adapt errors of C1

            // Compute the gradients

            C1_W_G = etl::ml::convolution_backward_filter<1, 1, 1, 1>(I, C1_E);
            C1_B_G = bias_batch_sum_4d(C1_E);

            C2_W_G = etl::ml::convolution_backward_filter<1, 1, 1, 1>(P1_O, C2_E);
            C2_B_G = bias_batch_sum_4d(C2_E);

            FC1_W_G = batch_outer(etl::reshape<32, 16 * 7 * 7>(P2_O), FC1_E);
            FC1_B_G = bias_batch_sum_2d(FC1_E);

            FC2_W_G = batch_outer(FC1_O, FC2_E);
            FC2_B_G = bias_batch_sum_2d(FC2_E);

            //TODO Apply the gradients
        }
    }

    etl::dump_counters();
}

int main() {
    auto start_time = timer_clock::now();

    simple();
    basic();
    sub();
    ml();

    auto end_time = timer_clock::now();
    auto duration = std::chrono::duration_cast<milliseconds>(end_time - start_time);

    std::cout << "duration: " << duration.count() << "ms" << std::endl;

    return (int)fake;
}
<|endoftext|>


<commit_before>/*
 * FluidSimulator.cpp
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 FilipeCN
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include "FluidSimulator.h"
using namespace aergia::algorithms;

#include <iostream>
using namespace std;

FluidSimulator::FluidSimulator(){
    curStep = 0;
    SRC = 0;
    DST = 1;
}

FluidSimulator::~FluidSimulator(){

}

void FluidSimulator::generateGrid(int G, vec2 size, GLint internalFormat, GLenum format,
        GLenum type){

    for (int i = 0; i < 2; ++i) {
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);

        glGenTextures(1, &grids[G].t[i]);
        glBindTexture(GL_TEXTURE_2D, grids[G].t[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

/*
    switch ((int)size.z) {
        case 1:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RED, GL_FLOAT, 0);
            break;
        case 2:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RG, GL_HALF_FLOAT, 0);
            break;
        case 3:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RGB, GL_HALF_FLOAT, 0);
            break;
        case 4:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RGBA, GL_HALF_FLOAT, 0);
            break;
    }
*/
        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, (GLsizei) size.x, (GLsizei) size.y, 0,
                format, type, 0);

        CHECK_GL_ERRORS;

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, grids[G].t[i], 0);

        CHECK_GL_ERRORS;
        CHECK_FRAMEBUFFER;

        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    grids[G].size = size;
    grids[G].internalFormat = internalFormat;
    grids[G].format = format;
    grids[G].type = type;
}

void FluidSimulator::swap(){
    int tmp = SRC;
    SRC = DST;
    DST = tmp;
}

void FluidSimulator::printGrid(GLuint grid, vec2 size){
    float * data = new float[(int)(size.x*size.y)];
    for(int i(0); i < (int)size.y; ++i) {
        for(int j(0); j < (int)size.x; ++j) {
            data[i * (int)size.x + j] = 0.0f;
        }
    }

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, grid);
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, data);

    CHECK_GL_ERRORS;

    cout << "printing grid:\n";
    for(int i(0); i < (int)size.y; ++i) {
        for(int j(0); j < (int)size.x; ++j) {
            cout << data[i * (int)size.x + j] << ",";
        }
        cout << endl;
    }
}

bool FluidSimulator::init(vec2 gridSize, float dx, float dt) {

    glGenVertexArrays(1, &junkVAO);

    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    this->gridSize = gridSize;
    this->cellSize = dx;
    this->timeStep = dt;

    generateGrid(U, vec2(gridSize.x+1,gridSize.y), GL_R16F, GL_RED, GL_FLOAT);
    grids[U].offset = vec2(-cellSize/2.0,0.0);
    grids[U].m = 0;

    generateGrid(V, vec2(gridSize.x,gridSize.y+1), GL_R16F, GL_RED, GL_FLOAT);
    grids[V].offset = vec2(-cellSize/2.0,0.0);
    grids[V].m = 1;

    generateGrid(Q, vec2(gridSize.x,gridSize.y), GL_R16F, GL_RED, GL_FLOAT);
    grids[Q].offset = vec2(-cellSize/2.0,0.0);
    grids[Q].m = 2;

    advectShader.loadFiles("advect", "shaders");

    advectShader.setUniform("u.m", 0);
    advectShader.setUniform("u.offset", grids[U].offset);

    advectShader.setUniform("v.m", 1);
    advectShader.setUniform("v.offset", grids[V].offset);

    advectShader.setUniform("q.m", 2);
    advectShader.setUniform("q.offset", grids[Q].offset);

    advectShader.setUniform("dt", timeStep);
    advectShader.setUniform("dx", cellSize);

    texShader.loadFiles("screenTexture", "shaders");
    texShader.setUniform("tex", 0);

    simpleShader.loadFiles("simple", "shaders");

    return true;
}

void FluidSimulator::step() {
    //return;
    glViewport(0, 0, (GLsizei) gridSize.x, (GLsizei) gridSize.y);

    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            grids[Q].t[DST], 0);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, grids[U].t[SRC]);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, grids[V].t[SRC]);
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, grids[Q].t[SRC]);

    advectShader.begin();
        glDrawArrays( GL_TRIANGLES, 0, 3 );
    advectShader.end();

    swap();

    curStep++;
}

void FluidSimulator::render(){
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, grids[Q].t[SRC]);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    texShader.begin();
        glDrawArrays( GL_TRIANGLES, 0, 3 );
    texShader.end();
}

void FluidSimulator::setGrid(int i, const GLvoid *data) {
    int width = (int) grids[i].size.x;
    int height = (int) grids[i].size.y;

    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, grids[i].internalFormat, width, height, 0,
            grids[i].format, grids[i].type, data);

    CHECK_GL_ERRORS;

    glViewport(0, 0, width, height);

    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            grids[i].t[SRC], 0);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);

    texShader.begin();
    glDrawArrays( GL_TRIANGLES, 0, 3 );
    texShader.end();

    CHECK_GL_ERRORS;
}
<commit_msg>grid data<commit_after>/*
 * FluidSimulator.cpp
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 FilipeCN
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include "FluidSimulator.h"
using namespace aergia::algorithms;

#include <iostream>
using namespace std;

FluidSimulator::FluidSimulator(){
    curStep = 0;
    SRC = 0;
    DST = 1;
}

FluidSimulator::~FluidSimulator(){

}

void FluidSimulator::generateGrid(int G, vec2 size, GLint internalFormat, GLenum format,
        GLenum type){

    for (int i = 0; i < 2; ++i) {
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);

        glGenTextures(1, &grids[G].t[i]);
        glBindTexture(GL_TEXTURE_2D, grids[G].t[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

/*
    switch ((int)size.z) {
        case 1:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RED, GL_FLOAT, 0);
            break;
        case 2:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RG, GL_HALF_FLOAT, 0);
            break;
        case 3:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RGB, GL_HALF_FLOAT, 0);
            break;
        case 4:
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (GLsizei) size.x, (GLsizei) size.y, 0, GL_RGBA, GL_HALF_FLOAT, 0);
            break;
    }
*/
        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, (GLsizei) size.x, (GLsizei) size.y, 0,
                format, type, 0);

        CHECK_GL_ERRORS;

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, grids[G].t[i], 0);

        CHECK_GL_ERRORS;
        CHECK_FRAMEBUFFER;

        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    grids[G].size = size;
    grids[G].internalFormat = internalFormat;
    grids[G].format = format;
    grids[G].type = type;
}

void FluidSimulator::swap(){
    int tmp = SRC;
    SRC = DST;
    DST = tmp;
}

void FluidSimulator::printGrid(GLuint grid, vec2 size){
    float * data = new float[(int)(size.x*size.y)];
    for(int i(0); i < (int)size.y; ++i) {
        for(int j(0); j < (int)size.x; ++j) {
            data[i * (int)size.x + j] = 0.0f;
        }
    }

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, grid);
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, data);

    CHECK_GL_ERRORS;

    cout << "printing grid:\n";
    for(int i(0); i < (int)size.y; ++i) {
        for(int j(0); j < (int)size.x; ++j) {
            cout << data[i * (int)size.x + j] << ",";
        }
        cout << endl;
    }
}

bool FluidSimulator::init(vec2 gridSize, float dx, float dt) {

    glGenVertexArrays(1, &junkVAO);

    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    this->gridSize = gridSize;
    this->cellSize = dx;
    this->timeStep = dt;

    generateGrid(U, vec2(gridSize.x+1,gridSize.y), GL_R16F, GL_RED, GL_FLOAT);
    grids[U].offset = vec2(-cellSize/2.0,0.0);
    grids[U].m = 0;

    generateGrid(V, vec2(gridSize.x,gridSize.y+1), GL_R16F, GL_RED, GL_FLOAT);
    grids[V].offset = vec2(-cellSize/2.0,0.0);
    grids[V].m = 1;

    generateGrid(Q, vec2(gridSize.x,gridSize.y), GL_R16F, GL_RED, GL_FLOAT);
    grids[Q].offset = vec2(-cellSize/2.0,0.0);
    grids[Q].m = 2;

    advectShader.loadFiles("advect", "shaders");

    advectShader.setUniform("u.m", 0);
    advectShader.setUniform("u.offset", grids[U].offset);

    advectShader.setUniform("v.m", 1);
    advectShader.setUniform("v.offset", grids[V].offset);

    advectShader.setUniform("q.m", 2);
    advectShader.setUniform("q.offset", grids[Q].offset);

    advectShader.setUniform("dt", timeStep);
    advectShader.setUniform("dx", cellSize);

    texShader.loadFiles("screenTexture", "shaders");
    texShader.setUniform("tex", 0);

    simpleShader.loadFiles("simple", "shaders");

    return true;
}

void FluidSimulator::step() {
    //return;
    glViewport(0, 0, (GLsizei) gridSize.x, (GLsizei) gridSize.y);

    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            grids[Q].t[DST], 0);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, grids[U].t[SRC]);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, grids[V].t[SRC]);
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, grids[Q].t[SRC]);

    advectShader.begin();
        glDrawArrays( GL_TRIANGLES, 0, 3 );
    advectShader.end();

    swap();

    curStep++;
}

void FluidSimulator::render(){
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, grids[Q].t[SRC]);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    texShader.begin();
        glDrawArrays( GL_TRIANGLES, 0, 3 );
    texShader.end();
}

void FluidSimulator::setGrid(int i, const GLvoid *data) {
    int width = (int) grids[i].size.x;
    int height = (int) grids[i].size.y;

    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, grids[i].internalFormat, width, height, 0,
            grids[i].format, grids[i].type, data);

    CHECK_GL_ERRORS;

    glViewport(0, 0, width, height);

    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            grids[i].t[SRC], 0);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);

    texShader.begin();
    glDrawArrays( GL_TRIANGLES, 0, 3 );
    texShader.end();

    CHECK_GL_ERRORS;
}
<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <string.h>
#include "ir.h"
#include "glsl_types.h"
#include "hash_table.h"

/**
 * Duplicate an IR variable
 *
 * \note
 * This will probably be made \c virtual and moved to the base class
 * eventually.
 */
ir_instruction *
ir_variable::clone(struct hash_table *ht) const
{
   ir_variable *var = new ir_variable(type, name);

   var->max_array_access = this->max_array_access;
   var->read_only = this->read_only;
   var->centroid = this->centroid;
   var->invariant = this->invariant;
   var->mode = this->mode;
   var->interpolation = this->interpolation;

   if (ht) {
      hash_table_insert(ht, var, (void *)const_cast<ir_variable *>(this));
   }

   return var;
}

ir_instruction *
ir_swizzle::clone(struct hash_table *ht) const
{
   return new ir_swizzle((ir_rvalue *)this->val->clone(ht), this->mask);
}

ir_instruction *
ir_return::clone(struct hash_table *ht) const
{
   ir_rvalue *new_value = NULL;

   if (this->value)
      new_value = (ir_rvalue *)this->value->clone(ht);

   return new ir_return(new_value);
}

ir_instruction *
ir_loop_jump::clone(struct hash_table *ht) const
{
   (void)ht;

   return new ir_loop_jump(this->mode);
}

ir_instruction *
ir_if::clone(struct hash_table *ht) const
{
   ir_if *new_if = new ir_if((ir_rvalue *)this->condition->clone(ht));

   foreach_iter(exec_list_iterator, iter, this->then_instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      new_if->then_instructions.push_tail(ir->clone(ht));
   }

   foreach_iter(exec_list_iterator, iter, this->else_instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      new_if->else_instructions.push_tail(ir->clone(ht));
   }

   return new_if;
}

ir_instruction *
ir_loop::clone(struct hash_table *ht) const
{
   ir_loop *new_loop = new ir_loop();

   if (this->from)
      new_loop->from = (ir_rvalue *)this->from->clone(ht);
   if (this->to)
      new_loop->to = (ir_rvalue *)this->to->clone(ht);
   if (this->increment)
      new_loop->increment = (ir_rvalue *)this->increment->clone(ht);
   new_loop->counter = counter;

   foreach_iter(exec_list_iterator, iter, this->body_instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      new_loop->body_instructions.push_tail(ir->clone(ht));
   }

   return new_loop;
}

ir_instruction *
ir_call::clone(struct hash_table *ht) const
{
   exec_list new_parameters;

   foreach_iter(exec_list_iterator, iter, this->actual_parameters) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      new_parameters.push_tail(ir->clone(ht));
   }

   return new ir_call(this->callee, &new_parameters);
}

ir_instruction *
ir_expression::clone(struct hash_table *ht) const
{
   ir_rvalue *op[2] = {NULL, NULL};
   unsigned int i;

   for (i = 0; i < get_num_operands(); i++) {
      op[i] = (ir_rvalue *)this->operands[i]->clone(ht);
   }

   return new ir_expression(this->operation, this->type, op[0], op[1]);
}

ir_instruction *
ir_dereference_variable::clone(struct hash_table *ht) const
{
   ir_variable *new_var;

   if (ht) {
      new_var = (ir_variable *)hash_table_find(ht, this->var);
      if (!new_var)
	 new_var = this->var;
   } else {
      new_var = this->var;
   }

   return new ir_dereference_variable(new_var);
}

ir_instruction *
ir_dereference_array::clone(struct hash_table *ht) const
{
   return new ir_dereference_array((ir_rvalue *)this->array->clone(ht),
				   (ir_rvalue *)this->array_index->clone(ht));
}

ir_instruction *
ir_dereference_record::clone(struct hash_table *ht) const
{
   return new ir_dereference_record((ir_rvalue *)this->record->clone(ht),
				    this->field);
}

ir_instruction *
ir_texture::clone(struct hash_table *ht) const
{
   ir_texture *new_tex = new ir_texture(this->op);

   new_tex->sampler = (ir_dereference *)this->sampler->clone(ht);
   new_tex->coordinate = (ir_rvalue *)this->coordinate->clone(ht);
   if (this->projector)
      new_tex->projector = (ir_rvalue *)this->projector->clone(ht);
   if (this->shadow_comparitor) {
      new_tex->shadow_comparitor =
	 (ir_rvalue *)this->shadow_comparitor->clone(ht);
   }

   for (int i = 0; i < 3; i++)
      new_tex->offsets[i] = this->offsets[i];

   switch (this->op) {
   case ir_tex:
      break;
   case ir_txb:
      new_tex->lod_info.bias = (ir_rvalue *)this->lod_info.bias->clone(ht);
      break;
   case ir_txl:
   case ir_txf:
      new_tex->lod_info.lod = (ir_rvalue *)this->lod_info.lod->clone(ht);
      break;
   case ir_txd:
      new_tex->lod_info.grad.dPdx =
	 (ir_rvalue *)this->lod_info.grad.dPdx->clone(ht);
      new_tex->lod_info.grad.dPdy =
	 (ir_rvalue *)this->lod_info.grad.dPdy->clone(ht);
      break;
   }

   return new_tex;
}

ir_instruction *
ir_assignment::clone(struct hash_table *ht) const
{
   ir_rvalue *new_condition = NULL;

   if (this->condition)
      new_condition = (ir_rvalue *)this->condition->clone(ht);

   return new ir_assignment((ir_rvalue *)this->lhs->clone(ht),
			    (ir_rvalue *)this->rhs->clone(ht),
			    new_condition);
}

ir_instruction *
ir_function::clone(struct hash_table *ht) const
{
   (void)ht;
   /* FINISHME */
   abort();
}

ir_instruction *
ir_function_signature::clone(struct hash_table *ht) const
{
   (void)ht;
   /* FINISHME */
   abort();
}

ir_instruction *
ir_constant::clone(struct hash_table *ht) const
{
   switch (this->type->base_type) {
   case GLSL_TYPE_UINT:
   case GLSL_TYPE_INT:
   case GLSL_TYPE_FLOAT:
   case GLSL_TYPE_BOOL:
      return new ir_constant(this->type, &this->value);

   case GLSL_TYPE_STRUCT: {
      ir_constant *c = new ir_constant;

      c->type = this->type;
      for (exec_node *node = this->components.head
	      ; !node->is_tail_sentinal()
	      ; node = node->next) {
	 ir_constant *const orig = (ir_constant *) node;

	 c->components.push_tail(orig->clone(NULL));
      }

      return c;
   }

   default:
      assert(!"Should not get here."); break;
      return NULL;
   }
}
<commit_msg>Quiet unused arg warning for ir_constant cloning.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <string.h>
#include "ir.h"
#include "glsl_types.h"
#include "hash_table.h"

/**
 * Duplicate an IR variable
 *
 * \note
 * This will probably be made \c virtual and moved to the base class
 * eventually.
 */
ir_instruction *
ir_variable::clone(struct hash_table *ht) const
{
   ir_variable *var = new ir_variable(type, name);

   var->max_array_access = this->max_array_access;
   var->read_only = this->read_only;
   var->centroid = this->centroid;
   var->invariant = this->invariant;
   var->mode = this->mode;
   var->interpolation = this->interpolation;

   if (ht) {
      hash_table_insert(ht, var, (void *)const_cast<ir_variable *>(this));
   }

   return var;
}

ir_instruction *
ir_swizzle::clone(struct hash_table *ht) const
{
   return new ir_swizzle((ir_rvalue *)this->val->clone(ht), this->mask);
}

ir_instruction *
ir_return::clone(struct hash_table *ht) const
{
   ir_rvalue *new_value = NULL;

   if (this->value)
      new_value = (ir_rvalue *)this->value->clone(ht);

   return new ir_return(new_value);
}

ir_instruction *
ir_loop_jump::clone(struct hash_table *ht) const
{
   (void)ht;

   return new ir_loop_jump(this->mode);
}

ir_instruction *
ir_if::clone(struct hash_table *ht) const
{
   ir_if *new_if = new ir_if((ir_rvalue *)this->condition->clone(ht));

   foreach_iter(exec_list_iterator, iter, this->then_instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      new_if->then_instructions.push_tail(ir->clone(ht));
   }

   foreach_iter(exec_list_iterator, iter, this->else_instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      new_if->else_instructions.push_tail(ir->clone(ht));
   }

   return new_if;
}

ir_instruction *
ir_loop::clone(struct hash_table *ht) const
{
   ir_loop *new_loop = new ir_loop();

   if (this->from)
      new_loop->from = (ir_rvalue *)this->from->clone(ht);
   if (this->to)
      new_loop->to = (ir_rvalue *)this->to->clone(ht);
   if (this->increment)
      new_loop->increment = (ir_rvalue *)this->increment->clone(ht);
   new_loop->counter = counter;

   foreach_iter(exec_list_iterator, iter, this->body_instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      new_loop->body_instructions.push_tail(ir->clone(ht));
   }

   return new_loop;
}

ir_instruction *
ir_call::clone(struct hash_table *ht) const
{
   exec_list new_parameters;

   foreach_iter(exec_list_iterator, iter, this->actual_parameters) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      new_parameters.push_tail(ir->clone(ht));
   }

   return new ir_call(this->callee, &new_parameters);
}

ir_instruction *
ir_expression::clone(struct hash_table *ht) const
{
   ir_rvalue *op[2] = {NULL, NULL};
   unsigned int i;

   for (i = 0; i < get_num_operands(); i++) {
      op[i] = (ir_rvalue *)this->operands[i]->clone(ht);
   }

   return new ir_expression(this->operation, this->type, op[0], op[1]);
}

ir_instruction *
ir_dereference_variable::clone(struct hash_table *ht) const
{
   ir_variable *new_var;

   if (ht) {
      new_var = (ir_variable *)hash_table_find(ht, this->var);
      if (!new_var)
	 new_var = this->var;
   } else {
      new_var = this->var;
   }

   return new ir_dereference_variable(new_var);
}

ir_instruction *
ir_dereference_array::clone(struct hash_table *ht) const
{
   return new ir_dereference_array((ir_rvalue *)this->array->clone(ht),
				   (ir_rvalue *)this->array_index->clone(ht));
}

ir_instruction *
ir_dereference_record::clone(struct hash_table *ht) const
{
   return new ir_dereference_record((ir_rvalue *)this->record->clone(ht),
				    this->field);
}

ir_instruction *
ir_texture::clone(struct hash_table *ht) const
{
   ir_texture *new_tex = new ir_texture(this->op);

   new_tex->sampler = (ir_dereference *)this->sampler->clone(ht);
   new_tex->coordinate = (ir_rvalue *)this->coordinate->clone(ht);
   if (this->projector)
      new_tex->projector = (ir_rvalue *)this->projector->clone(ht);
   if (this->shadow_comparitor) {
      new_tex->shadow_comparitor =
	 (ir_rvalue *)this->shadow_comparitor->clone(ht);
   }

   for (int i = 0; i < 3; i++)
      new_tex->offsets[i] = this->offsets[i];

   switch (this->op) {
   case ir_tex:
      break;
   case ir_txb:
      new_tex->lod_info.bias = (ir_rvalue *)this->lod_info.bias->clone(ht);
      break;
   case ir_txl:
   case ir_txf:
      new_tex->lod_info.lod = (ir_rvalue *)this->lod_info.lod->clone(ht);
      break;
   case ir_txd:
      new_tex->lod_info.grad.dPdx =
	 (ir_rvalue *)this->lod_info.grad.dPdx->clone(ht);
      new_tex->lod_info.grad.dPdy =
	 (ir_rvalue *)this->lod_info.grad.dPdy->clone(ht);
      break;
   }

   return new_tex;
}

ir_instruction *
ir_assignment::clone(struct hash_table *ht) const
{
   ir_rvalue *new_condition = NULL;

   if (this->condition)
      new_condition = (ir_rvalue *)this->condition->clone(ht);

   return new ir_assignment((ir_rvalue *)this->lhs->clone(ht),
			    (ir_rvalue *)this->rhs->clone(ht),
			    new_condition);
}

ir_instruction *
ir_function::clone(struct hash_table *ht) const
{
   (void)ht;
   /* FINISHME */
   abort();
}

ir_instruction *
ir_function_signature::clone(struct hash_table *ht) const
{
   (void)ht;
   /* FINISHME */
   abort();
}

ir_instruction *
ir_constant::clone(struct hash_table *ht) const
{
   (void)ht;

   switch (this->type->base_type) {
   case GLSL_TYPE_UINT:
   case GLSL_TYPE_INT:
   case GLSL_TYPE_FLOAT:
   case GLSL_TYPE_BOOL:
      return new ir_constant(this->type, &this->value);

   case GLSL_TYPE_STRUCT: {
      ir_constant *c = new ir_constant;

      c->type = this->type;
      for (exec_node *node = this->components.head
	      ; !node->is_tail_sentinal()
	      ; node = node->next) {
	 ir_constant *const orig = (ir_constant *) node;

	 c->components.push_tail(orig->clone(NULL));
      }

      return c;
   }

   default:
      assert(!"Should not get here."); break;
      return NULL;
   }
}
<|endoftext|>