OSL has OSL::ShaderGlobals, which contains all the state for OSL shader execution. The renderer fills it out and hands a pointer to OSL, and any callbacks (e.g. for querying attributes) get the pointer back. In order to store renderer-specific data in it, there's a few opaque pointers in the struct, but using those has led to a mess of reinterpret_cast<> and pointer indirection in order to carry all the data around. However, there is a way to do this nicer: Good old C-style struct inheritance. In short: Unless you're doing pointer arithmetic, you can just add additional data at the end of a base struct, and the rest of the code won't care. In this case, this means that we can have our own ShaderGlobals struct and add more Cycles-specific data at the end. Additionally, we can replace the generic opaque void pointers with ones of the correct type, which saves us from needing to cast them back. Since we have a copy of ShaderGlobals for GPU OSL anyways, it's just a matter of refactoring the code a bit to make use of that. The advantages of this are: - Avoids casts all over the place, just needs one cast to turn our ShaderGlobals into the "base" type that OSL expects and one to turn the pointer that OSL gives us on callbacks back into our "derived" type. - Removes indirection, all the relevant stuff (sd, kg, state) is now directly in the ShaderGlobals - Removes some OSL-specific state from ShaderData, which helps to keep memory usage down Pull Request: https://projects.blender.org/blender/blender/pulls/133689
104 lines
2.2 KiB
C++
104 lines
2.2 KiB
C++
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#pragma once
|
|
|
|
#ifdef WITH_OSL
|
|
|
|
# include <OSL/oslexec.h>
|
|
|
|
# include "util/map.h"
|
|
# include "util/param.h"
|
|
# include "util/vector.h"
|
|
|
|
# include "kernel/types.h"
|
|
|
|
# include "kernel/osl/compat.h"
|
|
# include "kernel/osl/types.h"
|
|
|
|
# ifndef WIN32
|
|
using std::isfinite;
|
|
# endif
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
class OSLRenderServices;
|
|
class ColorSpaceProcessor;
|
|
struct ThreadKernelGlobalsCPU;
|
|
|
|
/* OSL Globals
|
|
*
|
|
* Data needed by OSL render services, that is global to a rendering session.
|
|
* This includes all OSL shaders, name to attribute mapping and texture handles.
|
|
*/
|
|
|
|
struct OSLGlobals {
|
|
OSLGlobals()
|
|
{
|
|
ss = nullptr;
|
|
ts = nullptr;
|
|
services = nullptr;
|
|
use = false;
|
|
}
|
|
|
|
bool use;
|
|
|
|
/* shading system */
|
|
OSL::ShadingSystem *ss;
|
|
OSL::TextureSystem *ts;
|
|
OSLRenderServices *services;
|
|
|
|
/* shader states */
|
|
vector<OSL::ShaderGroupRef> surface_state;
|
|
vector<OSL::ShaderGroupRef> volume_state;
|
|
vector<OSL::ShaderGroupRef> displacement_state;
|
|
vector<OSL::ShaderGroupRef> bump_state;
|
|
OSL::ShaderGroupRef background_state;
|
|
|
|
/* attributes */
|
|
using ObjectNameMap = unordered_map<OSLUStringHash, int>;
|
|
|
|
ObjectNameMap object_name_map;
|
|
vector<ustring> object_names;
|
|
};
|
|
|
|
/* trace() call result */
|
|
struct OSLTraceData {
|
|
Ray ray;
|
|
Intersection isect;
|
|
ShaderData sd;
|
|
bool setup;
|
|
bool init;
|
|
bool hit;
|
|
};
|
|
|
|
/* thread key for thread specific data lookup */
|
|
struct OSLThreadData {
|
|
/* Global Data */
|
|
OSLGlobals *globals = nullptr;
|
|
OSL::ShadingSystem *ss = nullptr;
|
|
|
|
/* Per-thread data. */
|
|
int thread_index = -1;
|
|
|
|
mutable ShaderGlobals shader_globals;
|
|
mutable OSLTraceData tracedata;
|
|
|
|
OSL::PerThreadInfo *osl_thread_info = nullptr;
|
|
OSL::ShadingContext *context = nullptr;
|
|
OIIO::TextureSystem::Perthread *oiio_thread_info = nullptr;
|
|
|
|
OSLThreadData(OSLGlobals *globals, const int thread_index);
|
|
~OSLThreadData();
|
|
|
|
OSLThreadData(OSLThreadData &other) = delete;
|
|
OSLThreadData(OSLThreadData &&other) noexcept;
|
|
OSLThreadData &operator=(const OSLThreadData &other) = delete;
|
|
OSLThreadData &operator=(OSLThreadData &&other) = delete;
|
|
};
|
|
|
|
CCL_NAMESPACE_END
|
|
|
|
#endif
|