Program Listing for File DeviceEnvironment.cuh

Return to documentation for file (include/flamegpu/runtime/environment/DeviceEnvironment.cuh)

#ifndef INCLUDE_FLAMEGPU_RUNTIME_ENVIRONMENT_DEVICEENVIRONMENT_CUH_
#define INCLUDE_FLAMEGPU_RUNTIME_ENVIRONMENT_DEVICEENVIRONMENT_CUH_

// #include <cuda_runtime.h>
#include <string>
#include <cassert>

#include "flamegpu/runtime/environment/DeviceMacroProperty.cuh"
#include "flamegpu/runtime/environment/DeviceEnvironmentDirectedGraph.cuh"
#include "flamegpu/detail/type_decode.h"
#ifndef __CUDACC_RTC__
#include "flamegpu/runtime/detail/curve/DeviceCurve.cuh"
#endif

namespace flamegpu {

class ReadOnlyDeviceEnvironment {
    friend class ReadOnlyDeviceAPI;

 public:
    template<typename T, unsigned int M>
    __device__ __forceinline__ T getProperty(const char(&name)[M]) const;
    template<typename T, unsigned int N = 0, unsigned int M>
    __device__ __forceinline__ T getProperty(const char(&name)[M], unsigned int index) const;
    template<typename T, unsigned int I = 1, unsigned int J = 1, unsigned int K = 1, unsigned int W = 1, unsigned int M>
    __device__ __forceinline__ ReadOnlyDeviceMacroProperty<T, I, J, K, W> getMacroProperty(const char(&name)[M]) const;
    template<unsigned int M>
    __device__ __forceinline__ DeviceEnvironmentDirectedGraph getDirectedGraph(const char(&name)[M]) const;
};
class DeviceEnvironment : public ReadOnlyDeviceEnvironment {
 public:
    template<typename T, unsigned int I = 1, unsigned int J = 1, unsigned int K = 1, unsigned int W = 1, unsigned int M>
    __device__ __forceinline__ DeviceMacroProperty<T, I, J, K, W> getMacroProperty(const char(&name)[M]) const;
};

// Mash compilation of these functions from RTC builds as this requires a dynamic implementation of the function in curve_rtc
#ifndef __CUDACC_RTC__
template<typename T, unsigned int M>
__device__ __forceinline__ T ReadOnlyDeviceEnvironment::getProperty(const char(&name)[M]) const {
    return detail::curve::DeviceCurve::getEnvironmentProperty<T>(name);
}
template<typename T, unsigned int N, unsigned int M>
__device__ __forceinline__ T ReadOnlyDeviceEnvironment::getProperty(const char(&name)[M], const unsigned int index) const {
    return detail::curve::DeviceCurve::getEnvironmentArrayProperty<T, N>(name,  index);
}

template<typename T, unsigned int I, unsigned int J, unsigned int K, unsigned int W, unsigned int N>
__device__ __forceinline__ ReadOnlyDeviceMacroProperty<T, I, J, K, W> ReadOnlyDeviceEnvironment::getMacroProperty(const char(&name)[N]) const {
    char * d_ptr = detail::curve::DeviceCurve::getEnvironmentMacroProperty<T, I, J, K, W>(name);
#if !defined(FLAMEGPU_SEATBELTS) || FLAMEGPU_SEATBELTS
    if (!d_ptr) {
        return ReadOnlyDeviceMacroProperty<T, I, J, K, W>(nullptr, nullptr);
    }
    return ReadOnlyDeviceMacroProperty<T, I, J, K, W>(reinterpret_cast<T*>(d_ptr),
        reinterpret_cast<unsigned int*>(d_ptr + (I * J * K * W * sizeof(T))));  // Read-write flag resides in 8 bits at the end of the buffer
#else

    return ReadOnlyDeviceMacroProperty<T, I, J, K, W>(reinterpret_cast<T*>(d_ptr));
#endif
}
template<typename T, unsigned int I, unsigned int J, unsigned int K, unsigned int W, unsigned int N>
__device__ __forceinline__ DeviceMacroProperty<T, I, J, K, W> DeviceEnvironment::getMacroProperty(const char(&name)[N]) const {
    char* d_ptr = detail::curve::DeviceCurve::getEnvironmentMacroProperty<T, I, J, K, W>(name);
#if !defined(FLAMEGPU_SEATBELTS) || FLAMEGPU_SEATBELTS
    if (!d_ptr) {
        return DeviceMacroProperty<T, I, J, K, W>(nullptr, nullptr);
    }
    return DeviceMacroProperty<T, I, J, K, W>(reinterpret_cast<T*>(d_ptr),
        reinterpret_cast<unsigned int*>(d_ptr + (I * J * K * W * sizeof(T))));  // Read-write flag resides in 8 bits at the end of the buffer
#else
    return DeviceMacroProperty<T, I, J, K, W>(reinterpret_cast<T*>(d_ptr));
#endif
}
template<unsigned int M>
__device__ __forceinline__ DeviceEnvironmentDirectedGraph ReadOnlyDeviceEnvironment::getDirectedGraph(const char(&name)[M]) const {
    const detail::curve::Curve::VariableHash graph_hash = detail::curve::Curve::variableHash(name);
#if !defined(FLAMEGPU_SEATBELTS) || FLAMEGPU_SEATBELTS
    // Seatbelts check that the graph exists, by looking for mandatory vertex _id property
    // Rather than it failing at property lookup time
    if (detail::curve::DeviceCurve::getVariableIndex((graph_hash ^ detail::curve::Curve::variableHash("_environment_directed_graph_vertex")) + detail::curve::Curve::variableHash("_id"))
        == detail::curve::DeviceCurve::UNKNOWN_VARIABLE) {
        DTHROW("Environment directed graph with name '%s' was not found\n", name);
    }
#endif
    return DeviceEnvironmentDirectedGraph(graph_hash);
}
#else

template<unsigned int M>
__device__ __forceinline__ DeviceEnvironmentDirectedGraph ReadOnlyDeviceEnvironment::getDirectedGraph(const char(&name)[M]) const {
    const detail::curve::Curve::VariableHash graph_hash = detail::curve::Curve::variableHash(name);
#if !defined(FLAMEGPU_SEATBELTS) || FLAMEGPU_SEATBELTS
    // Seatbelts check that the graph exists, by requesting it's hash
    if (detail::curve::DeviceCurve::getGraphHash(name) == detail::curve::DeviceCurve::UNKNOWN_GRAPH) {
        DTHROW("Environment directed graph with name '%s' was not found\n", name);
    }
#endif
    return DeviceEnvironmentDirectedGraph(graph_hash);
}
#endif  // __CUDACC_RTC__

}  // namespace flamegpu

#endif  // INCLUDE_FLAMEGPU_RUNTIME_ENVIRONMENT_DEVICEENVIRONMENT_CUH_