Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSL fails assert when updating shader group after executing shader when using BatchedRendererServices #1800

Open
johnfea opened this issue Apr 19, 2024 · 1 comment
Labels
batch shading Specific to the SIMD batch shading back end bug Crash or wrong behavior of an existing feature.

Comments

@johnfea
Copy link

johnfea commented Apr 19, 2024

In this minimal sample the following assert triggers at the end of main() but in my production code it triggered at the second call to ShaderGroupBegin(). When compiling OSL in Release mode instead of Debug mode, there's seemingly no issues.

Problem

/src/liboslexec/instance.cpp:75: ~ShaderInstance: Assertion 'm_instops.size() == 0 && m_instargs.size() == 0' failed.

Steps to Reproduce

g++ -g test.cpp -loslcomp -loslexec -loslnoise -loslquery -lOpenImageIO -lOpenImageIO_Util
./a.out

oslmaterial.hpp:

#pragma once
#if OSL_USE_BATCHED
#include <OSL/batched_shaderglobals.h>
#include <OSL/batched_rendererservices.h>
#endif
#include <OSL/dual_vec.h>

class OSLMaterial;

class OSLMaterialN : public OSL::BatchedRendererServices<8> {
public:

explicit OSLMaterialN(OSLMaterial& m);

//OIIO::ErrorHandler& errhandler() const { return *m_errhandler; }
/// Turn information at hitpoint into ShaderGlobals for OSL
void globals_from_hit(::OSL::BatchedShaderGlobals<8>& bsg)
{
    
// Uniform
auto& usg = bsg.uniform;
std::memset(&usg, 0, sizeof(::OSL::UniformShaderGlobals));
usg.raytype = 1; // 1 stands for camera ray?

// Varying
auto& vsg = bsg.varying;

using ::OSL::assign_all;
using ::OSL::Vec3;
}

bool is_overridden_get_inverse_matrix_WmWxWf() const override { return false; };
bool is_overridden_get_matrix_WmWsWf() const override { return false; };
bool is_overridden_get_inverse_matrix_WmsWf() const override { return false; };
bool is_overridden_get_inverse_matrix_WmWsWf() const override { return false; };
bool is_overridden_texture() const override { return false; };
bool is_overridden_texture3d() const override { return false; };
bool is_overridden_environment() const override { return false; };
bool is_overridden_pointcloud_search() const override { return false; };
bool is_overridden_pointcloud_get() const override { return false; };
bool is_overridden_pointcloud_write() const override { return false; };

OSLMaterial& m_sr;

private:

};

/// Custom RendererServices
class OSLMaterial : public OSL::RendererServices {
public:

OSLMaterial();

OIIO::ErrorHandler& errhandler() const { return *m_errhandler; }
/// Turn information at hitpoint into ShaderGlobals for OSL
void globals_from_hit(OSL::ShaderGlobals& sg)
{
sg.P = {0.0f,0.0f,0.0f}; // surface pos
sg.dPdx = {0.0f,0.0f,0.0f};
sg.dPdy = {0.0f,0.0f,0.0f};
sg.dPdz = {0.0f,0.0f,0.0f}; // for volume shading only

sg.I = {0.0f,0.0f,-1.0f}; // incident ray
sg.dIdx = {0.0f,0.0f,0.0f};
sg.dIdy = {0.0f,0.0f,0.0f};

sg.N = {0.0f,0.0f,1.0f}; // shading normal
sg.Ng = {0.0f,0.0f,1.0f}; // true geometric normal

sg.u = 0.5f; // 2D surface parameter u, and its differentials.
sg.dudx = 0.0f;
sg.dudy = 0.0f;
sg.v = 0.5f; // 2D surface parameter v, and its differentials.
sg.dvdx = 0.0f;
sg.dvdy = 0.0f;

// Surface tangents: derivative of P with respect to surface u and v.
sg.dPdu = {1.0f,0.0f,0.0f};
sg.dPdv = {0.0f,1.0f,0.0f};

sg.time = 0.0f;
sg.dtime = 0.001f;

// Velocity vector: derivative of position P with respect to time.
sg.dPdtime = {0.0f,0.0f,0.0f};

// For lights or light attenuation shaders: the point being illuminated (???)
sg.Ps = {0.0f,0.0f,0.0f};
sg.dPsdx = {0.0f,0.0f,0.0f};
sg.dPsdy = {0.0f,0.0f,0.0f};

// Renderer user pointers
sg.renderstate= NULL;
sg.tracedata=NULL;
sg.objdata=NULL;

sg.renderer = this;

sg.raytype = 1; // 1 stands for camera ray?
sg.flipHandedness = 0;
sg.backfacing = 0;

// output closure, needs to be null initialized
sg.Ci=NULL;
}

// ShaderGroupRef storage
std::vector<OSL::ShaderGroupRef>& shaders() { return m_shaders; }
std::vector<OSL::ShaderGroupRef> m_shaders;

OSL::BatchedRendererServices<8>* batched(OSL::WidthOf<8>) override
{
return &m_batch;
}

private:
OSLMaterialN m_batch;
std::unique_ptr<OIIO::ErrorHandler> m_errhandler;
};
test.cpp:

#include <iostream>
#include <OSL/oslexec.h>
#include <OSL/oslcomp.h>
#include <OSL/oslclosure.h>
#include <OSL/oslconfig.h>
#include <OSL/rendererservices.h>
#include <OSL/genclosure.h>
#include <OSL/dual_vec.h>
#include "oslmaterial.hpp"

using namespace OSL;

OSLMaterialN::OSLMaterialN(OSLMaterial& m) : OSL::BatchedRendererServices<8>(m.texturesys()), m_sr(m)
{
}

OSLMaterial::OSLMaterial() : m_batch(*this)
{
}

// Supported closures and parameters
struct EmptyParams {};

enum ClosureIDs {
EMISSION_ID,
BACKGROUND_ID,
DIFFUSE_ID,
};

struct DiffuseParams {
    OSL::Vec3 N;
};

void register_closures(OSL::ShadingSystem* ss)
{
// "Describe the memory layout of each closure type to the OSL runtime"
constexpr int MaxParams = 32;
struct BuiltinClosures {
const char* name;
int id;
OSL::ClosureParam params[MaxParams];  // "upper bound"
};
// Closures with support built into OSL, connected by the 1st string
BuiltinClosures supported[] = {
  { "emission", EMISSION_ID, { CLOSURE_FINISH_PARAM(EmptyParams) } },
  { "background", BACKGROUND_ID, { CLOSURE_FINISH_PARAM(EmptyParams) } },
  { "diffuse", DIFFUSE_ID,
	{ CLOSURE_VECTOR_PARAM(DiffuseParams, N),
	CLOSURE_FINISH_PARAM(DiffuseParams) } },
  };
// Closure registration here enables that type of closure, when executing or compiling a shader
for (const BuiltinClosures& c : supported)
  ss->register_closure(c.name, c.id, c.params, nullptr, nullptr);
}

int main(void)
{
// Renderer for OSL
OSLMaterial* oslmat = new OSLMaterial();

OSL::TextureSystem* texturesys = TextureSystem::create();
OSL::ShadingSystem* ss = new OSL::ShadingSystem(oslmat, texturesys, &oslmat->errhandler());
register_closures(ss);

OSL::PerThreadInfo* thread_info;
OSL::ShadingContext* context;
OSL::ShaderGlobals globals;
thread_info = ss->create_thread_info();
context = ss->get_context(thread_info);

// Renderer hit a surface to be shaded, construct ShaderGlobals from information at hitpoint
oslmat->globals_from_hit(globals);

// Create one shader
OSLCompiler compiler;
std::vector<std::string> options;

// Create a new shader group
oslmat->m_shaders.emplace_back();
oslmat->m_shaders[0] = ss->ShaderGroupBegin (std::to_string(0));
ShaderGroupRef group = oslmat->m_shaders[0];

{
OSL::OSLCompiler compiler;
compiler.compile("matte.osl", options);
}
ss->Shader(*group, "surface", "matte", "My Matte");
ss->ShaderGroupEnd(*group);

// Run the shader that was just created
ss->execute(context, *group, globals);

ShaderGroupRef group2;
{
// Replace shader group
oslmat->m_shaders[0] = ss->ShaderGroupBegin (std::to_string(0));
group2 = oslmat->m_shaders[0];
ss->Shader(*group2, "surface", "matte", "My Matte");
ss->ShaderGroupEnd(*group2);
}

// Run the shader again
oslmat->globals_from_hit(globals);
ss->execute(context, *group2, globals);

ss->release_context(context);
ss->destroy_thread_info(thread_info);

//delete ss;
delete oslmat;

std::cout << "next we fail assert" << std::endl;
return 0;
}

Versions

  • OSL branch/version: 1.13.18.0
  • OS: Linux
  • C++ compiler: g++ 10.2.1
  • LLVM version: clang 11.0.1-2
  • OIIO version: 2.5.4
@johnfea
Copy link
Author

johnfea commented Apr 24, 2024

I tried this again with improved ending for test.cpp that passed asan:

delete oslmat;
delete ss;

And for what ever reason now the sample failed the assert in the same place as my main code:

// Replace shader group
oslmat->m_shaders[0] = ss->ShaderGroupBegin (std::to_string(0));

@lgritz lgritz added bug Crash or wrong behavior of an existing feature. batch shading Specific to the SIMD batch shading back end labels May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
batch shading Specific to the SIMD batch shading back end bug Crash or wrong behavior of an existing feature.
Projects
None yet
Development

No branches or pull requests

2 participants