搭建 Optix 環境

 

  我參考了 第0個示例 OptixHello 學習Optix的工程配置以及基本框架 的配置過程,該文對於 Optix 的框架介紹的很好,可是按照該文配置遇到了一些問題,我花費了一番功夫本身摸索終於配置好了環境,實現了用Optix計算而後在OpenGL上展現結果的一個簡單的Demo。ios

  個人配置環境爲:Win10,GTX1080,驅動版本431.6,Cuda9.0,Optix6.0,VS2015框架

  Cuda我很早就安裝了,很簡單,這裏就不作介紹了。函數

  一、下載Optix6.0學習

    地址:https://developer.nvidia.com/designworks/optix/downloads/legacyui

    GTX1080應該是隻能支持到6.0版本。我剛開始下載了6.5版本,而後順利使用Cmake打包、VS編譯,將Optix引擎庫引入VS工程後,運行 optix::Context::create(); 都會報錯 「缺失Optix Library」!!!this

    查閱文檔後發現多是驅動的問題:spa

    

    Optix6.5須要435以上的驅動,我更新了個人驅動後只能到431.6,因此只能下載Optix6.0,Optix6.0須要418以上的驅動,好極了!個人驅動合適 ^_^.net

    至此,optix::Context::create()是能夠運行了。命令行

  

  二、設置VS生成ptxcode

    咱們能夠在.cu文件中寫 Optix 的 shader 代碼,這個代碼運行在GPU端,須要使用nvcc編譯(cuda),可是編譯完不會保留中間彙編文件.ptx,而 Optix 須要使用這個 .ptx 文件生成「光線發生器模塊」。

    換句話說,Optix得使用一個.ptx格式的 shader 進行GPU端的計算。那麼咱們必須在VS中進行相關設置,保留.ptx中間文件。    

    兩種方式:

  •  cuda命令行中設置,加入 --keep ,保留全部的中間結果

    

  •  cuda的common屬性配置中設置

    

 

  而後就能夠獲取ptx生成「光線發生器模塊」了

std::string ptxPath(const char* filename) { return std::string("./x64/Release/") + std::string(filename) + ".cu.ptx"; }
optix::Program ray_gen_program = context->createProgramFromPTXFile(ptx, "draw_solid_color");

  這裏除了從ptx文件生成program,還能夠從ptx字符串生成program

context->createProgramFromPTXString("……", "draw_solid_color");

  

  三、設置.cu編譯方式

  我寫了一個簡單的程序,編譯就報錯,.cu文件編譯出錯

  

  我想到多是編譯方式的問題。我最開始設置的混編,由於cuda程序須要混編。

  

  我查了資料,有人說能夠混編,但是我以爲多是混編的問題,因此修改成了只編譯GPU端代碼,可是!!! 我以前寫過cuda混編的代碼,工程中含有cuda混編的代碼,不能直接修改編譯方式,修改了直接報錯。

  若是剔除以前cuda的混編代碼還有點麻煩,想了想既然有人說能夠混編,那我就不改編譯方式了,結果。。。。。。 ,一夜查了各類資料找不到問題所在。。。。。。

  已經晚上11多了,一個師兄還在實驗室,我過去請教了一把,師兄看到我設置的混編,告訴我不能設置爲混編,他從一開始就設置的Generate .ptx file(-ptx),可是言語之間彷彿師兄也沒有設置過混編,不知道行不行。我試着改成編譯GPU端-ptx方式,而後剔除了cuda的混編代碼,而後就行了!

  驚不驚喜,意不意外!

  

  附上文件配置路徑:

  • 包含目錄

  

  • 庫目錄

  

  • 附加依賴項

       

  代碼:

  • draw_color.cu文件
#include <optix.h>
#include <optixu/optixu_math_namespace.h>
using namespace optix;

rtDeclareVariable(uint2, launch_index, rtLaunchIndex, );
rtBuffer<float4, 2> result_buffer;

rtDeclareVariable(float3, draw_color, , );

RT_PROGRAM void draw_solid_color()
{
    //result_buffer[launch_index] = make_float4(draw_color, 1.0f);
    float2 degree = make_float2(launch_index)*3.14 / 180.0f;
    result_buffer[launch_index] = make_float4(sin(degree.x), cos(degree.y), 0.0, 0.f);
}
  • OptixFrame.h
#pragma once
#include <iostream>
#include <sstream>
#include <fstream>
#include <optix.h>
#include <nvrtc.h>
#include <optixu/optixpp_namespace.h>
#include <sutil.h>
#include <GL/glew.h>
#include "../Model/Texture.h"

class OptixFrame
{
public:
    OptixFrame();
    ~OptixFrame();
    GLuint TransBuffer2Texture(GLfloat*);
    GLuint getSrcTexId() {
        return this->srcTexID;
    }

private:
    int width = 800, height = 800;
    optix::Context context;
    optix::Buffer outputBuffer;
    GLuint srcTexID;

private:
    void setup();
    void setColorSpace();
    std::string ptxPath(const char* filename) { return std::string("./x64/Release/") + std::string(filename) + ".cu.ptx"; }
};
  • OptixFrame.cpp
#include "./OptixFrame.h"


OptixFrame::OptixFrame()
{
    try
    {
        this->setup();
    }
    catch (const std::exception& e)
    {
        std::cerr << "Optix Error: " << e.what() << "\n";
    }
}

OptixFrame::~OptixFrame()
{
}

void OptixFrame::setColorSpace() {
    GLboolean use_SRGB = GL_FALSE;
    glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &use_SRGB);
    if (use_SRGB) {
        glEnable(GL_FRAMEBUFFER_SRGB_EXT);
    }
}

GLuint OptixFrame::TransBuffer2Texture(GLfloat* data) {
    glGenTextures(1, &this->srcTexID);
    glBindTexture(GL_TEXTURE_2D, this->srcTexID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->width,this->height, 0, GL_RGBA, GL_FLOAT, data);
    glGenerateMipmap(GL_TEXTURE_2D);
    //Parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);
    return this->srcTexID;
}

void OptixFrame::setup() {
    context = optix::Context::create();
    context->setRayTypeCount(1); //1種光線(有時能夠2種,渲染+陰影)
    context->setEntryPointCount(1);
    //申請Buffer
    this->outputBuffer = context->createBuffer(RT_BUFFER_OUTPUT, RT_FORMAT_FLOAT4, width, height);
    context["result_buffer"]->set(outputBuffer);
    //編譯Shader
    //const char* ptx = sutil::getPtxString("Optix","draw_color.cu");
    std::string ptx = this->ptxPath("draw_color");
    //從ptx字串中標識 "draw_solid_color"入口函數,並建立並返回光線發生器模塊
    optix::Program ray_gen_program = context->createProgramFromPTXFile(ptx, "draw_solid_color");
    context->setRayGenerationProgram(0, ray_gen_program);
    context["draw_color"]->setFloat(0.8f, 0.7f, 0.0f);

    context->setPrintEnabled(true); //能夠配合tfPrintf()進行shader端打印
    context->setPrintBufferSize(4096);

    //內部檢查有效性
    context->validate();
    //開啓第0個入口
    context->launch(0, width, height);

    this->setColorSpace();
    GLfloat* imageData = (GLfloat*)outputBuffer->map(0, RT_BUFFER_MAP_READ);
    this->TransBuffer2Texture(imageData);
}

  這些代碼生成了OpenGL的texture2D紋理,而後就能夠在OpenGL上顯示了,OpenGL上的顯示代碼就不作展現了。

  

  效果圖:

  

相關文章
相關標籤/搜索