gs-effect: Refactor onto std::shared_ptr

This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2019-12-15 11:13:47 +01:00
parent 1f25b56579
commit 11a2329519
2 changed files with 100 additions and 942 deletions

View file

@ -19,7 +19,6 @@
#include "gs-effect.hpp" #include "gs-effect.hpp"
#include <fstream> #include <fstream>
#include <iostream>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "obs/gs/gs-helper.hpp" #include "obs/gs/gs-helper.hpp"
@ -29,120 +28,118 @@
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4201) #pragma warning(disable : 4201)
#endif #endif
#include <graphics/effect.h>
#include <obs.h> #include <obs.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
//#define OBS_LOAD_EFFECT_FILE //#define OBS_LOAD_EFFECT_FILE
#define MAX_EFFECT_SIZE 32 * 1024 * 1024;
gs::effect::effect(std::string file) static std::string load_file_as_code(std::filesystem::path file)
{ {
#ifdef OBS_LOAD_EFFECT_FILE uintmax_t size = std::filesystem::file_size(file);
char* errorMessage = nullptr; if (size > MAX_EFFECT_SIZE) {
auto gctx = gs::context(); throw std::runtime_error("File is too large to be loaded.");
m_effect = gs_effect_create_from_file(file.c_str(), &errorMessage);
if (!m_effect || errorMessage) {
std::string error = "Generic Error";
if (errorMessage) {
error = std::string(errorMessage);
bfree((void*)errorMessage);
}
throw std::runtime_error(error);
}
#else
std::ifstream filestream = std::ifstream(file, std::ios::binary);
if (!filestream.is_open()) {
throw std::runtime_error("Failed to open file.");
} }
filestream.ignore(std::numeric_limits<std::streamsize>::max()); std::ifstream ifs(file, std::ios::binary);
std::streamsize length = filestream.gcount(); if (!ifs.is_open() || ifs.bad()) {
filestream.clear(); // Since ignore will have set eof. throw std::runtime_error("An unknown error occured trying to open the file.");
filestream.seekg(0, std::ios_base::beg);
if (length > 256 * 1024 * 1024) {
throw std::runtime_error("Shader too large (>256mb)");
} }
std::vector<char> shader_buf(size_t(length + 1), 0); std::vector<char> buf(size_t(size + 1), 0);
filestream.read(shader_buf.data(), length); ifs.read(buf.data(), size);
char* errorMessage = nullptr; return std::string(buf.data(), buf.data() + size);
auto gctx = gs::context();
_effect = gs_effect_create(shader_buf.data(), file.c_str(), &errorMessage);
if (!_effect || errorMessage) {
std::string error = "Generic Error";
if (errorMessage) {
error = std::string(errorMessage);
bfree((void*)errorMessage);
}
throw std::runtime_error(error);
}
#endif
} }
gs::effect::effect(std::string code, std::string name) gs::effect::effect(std::string code, std::string name)
{ {
char* errorMessage = nullptr;
auto gctx = gs::context(); auto gctx = gs::context();
_effect = gs_effect_create(code.c_str(), name.c_str(), &errorMessage);
if (!_effect || errorMessage) { char* error_buffer = nullptr;
std::string error = "Generic Error"; gs_effect_t* effect = gs_effect_create(code.c_str(), name.c_str(), &error_buffer);
if (errorMessage) {
error = std::string(errorMessage); if (!effect) {
bfree((void*)errorMessage); throw error_buffer ? std::runtime_error(error_buffer)
} : std::runtime_error("Unknown error during effect compile.");
throw std::runtime_error(error);
} }
reset(effect);
} }
gs::effect::effect(std::filesystem::path file) : effect(load_file_as_code(file), file.string()) {}
gs::effect::~effect() gs::effect::~effect()
{ {
auto gctx = gs::context(); auto gctx = gs::context();
gs_effect_destroy(_effect); gs_effect_destroy(get());
} }
gs_effect_t* gs::effect::get_object() size_t gs::effect::count_techniques()
{ {
return _effect; return static_cast<size_t>(get()->techniques.num);
}
gs::effect_technique gs::effect::get_technique(size_t idx)
{
if (idx >= count_techniques()) {
return nullptr;
}
return gs::effect_technique(get()->techniques.array + idx, this);
}
gs::effect_technique gs::effect::get_technique(std::string name)
{
for (size_t idx = 0; idx < count_techniques(); idx++) {
auto ptr = get()->techniques.array + idx;
if (strcmp(ptr->name, name.c_str()) == 0) {
return gs::effect_technique(ptr, this);
}
}
return nullptr;
}
bool gs::effect::has_technique(std::string name)
{
if (get_technique(name))
return true;
return false;
} }
size_t gs::effect::count_parameters() size_t gs::effect::count_parameters()
{ {
return (size_t)gs_effect_get_num_params(_effect); return get()->params.num;
} }
std::list<std::shared_ptr<gs::effect_parameter>> gs::effect::get_parameters() gs::effect_parameter gs::effect::get_parameter(size_t idx)
{ {
size_t num = gs_effect_get_num_params(_effect); if (idx >= count_parameters()) {
std::list<std::shared_ptr<gs::effect_parameter>> ps; throw std::out_of_range("Index is out of range.");
for (size_t idx = 0; idx < num; idx++) {
ps.emplace_back(get_parameter(idx));
} }
return ps;
return gs::effect_parameter(get()->params.array + idx, this);
} }
std::shared_ptr<gs::effect_parameter> gs::effect::get_parameter(size_t idx) gs::effect_parameter gs::effect::get_parameter(std::string name)
{ {
gs_eparam_t* param = gs_effect_get_param_by_idx(_effect, idx); for (size_t idx = 0; idx < count_techniques(); idx++) {
if (!param) auto ptr = get()->params.array + idx;
return nullptr; if (strcmp(ptr->name, name.c_str()) == 0) {
return std::make_shared<effect_parameter>(this->shared_from_this(), param); return gs::effect_parameter(ptr, this);
} }
}
std::shared_ptr<gs::effect_parameter> gs::effect::get_parameter(std::string name)
{
gs_eparam_t* param = gs_effect_get_param_by_name(_effect, name.c_str());
if (!param)
return nullptr; return nullptr;
return std::make_shared<effect_parameter>(this->shared_from_this(), param);
} }
bool gs::effect::has_parameter(std::string name) bool gs::effect::has_parameter(std::string name)
{ {
auto eprm = get_parameter(name); if (get_parameter(name))
if (eprm)
return true; return true;
return false; return false;
} }
@ -151,635 +148,6 @@ bool gs::effect::has_parameter(std::string name, effect_parameter::type type)
{ {
auto eprm = get_parameter(name); auto eprm = get_parameter(name);
if (eprm) if (eprm)
return eprm->get_type() == type; return eprm.get_type() == type;
return false;
}
std::shared_ptr<gs::effect> gs::effect::create(std::string file)
{
return std::shared_ptr<gs::effect>(new gs::effect(file));
}
std::shared_ptr<gs::effect> gs::effect::create(std::string code, std::string name)
{
return std::shared_ptr<gs::effect>(new gs::effect(code, name));
}
gs::effect_parameter::effect_parameter(std::shared_ptr<gs::effect> effect, gs_eparam_t* param)
: _effect(effect), _param(param)
{
if (!effect)
throw std::invalid_argument("effect");
if (!param)
throw std::invalid_argument("param");
gs_effect_get_param_info(_param, &_param_info);
}
std::string gs::effect_parameter::get_name()
{
return _param_info.name;
}
gs::effect_parameter::type gs::effect_parameter::get_type()
{
switch (_param_info.type) {
case GS_SHADER_PARAM_BOOL:
return type::Boolean;
case GS_SHADER_PARAM_FLOAT:
return type::Float;
case GS_SHADER_PARAM_VEC2:
return type::Float2;
case GS_SHADER_PARAM_VEC3:
return type::Float3;
case GS_SHADER_PARAM_VEC4:
return type::Float4;
case GS_SHADER_PARAM_INT:
return type::Integer;
case GS_SHADER_PARAM_INT2:
return type::Integer2;
case GS_SHADER_PARAM_INT3:
return type::Integer3;
case GS_SHADER_PARAM_INT4:
return type::Integer4;
case GS_SHADER_PARAM_MATRIX4X4:
return type::Matrix;
case GS_SHADER_PARAM_TEXTURE:
return type::Texture;
case GS_SHADER_PARAM_STRING:
return type::String;
default:
case GS_SHADER_PARAM_UNKNOWN:
return type::Unknown;
}
}
void gs::effect_parameter::set_bool(bool v)
{
if (get_type() != type::Boolean)
throw std::bad_cast();
gs_effect_set_bool(_param, v);
}
void gs::effect_parameter::get_bool(bool& v)
{
if (get_type() != type::Boolean)
throw std::bad_cast();
void* ptr = gs_effect_get_val(_param);
if (ptr) {
v = *reinterpret_cast<bool*>(ptr);
bfree(ptr);
} else {
v = false;
}
}
void gs::effect_parameter::get_default_bool(bool& v)
{
if (get_type() != type::Boolean)
throw std::bad_cast();
void* ptr = gs_effect_get_default_val(_param);
if (ptr) {
v = *reinterpret_cast<bool*>(ptr);
bfree(ptr);
} else {
v = false;
}
}
void gs::effect_parameter::set_bool_array(bool v[], size_t sz)
{
if (get_type() != type::Boolean)
throw std::bad_cast();
gs_effect_set_val(_param, v, sz);
}
void gs::effect_parameter::set_float(float_t x)
{
if (get_type() != type::Float)
throw std::bad_cast();
gs_effect_set_float(_param, x);
}
void gs::effect_parameter::get_float(float_t& x)
{
if (get_type() != type::Float)
throw std::bad_cast();
void* ptr = gs_effect_get_val(_param);
if (ptr) {
x = *reinterpret_cast<float_t*>(ptr);
bfree(ptr);
} else {
x = 0;
}
}
void gs::effect_parameter::get_default_float(float_t& x)
{
if (get_type() != type::Float)
throw std::bad_cast();
void* ptr = gs_effect_get_default_val(_param);
if (ptr) {
x = *reinterpret_cast<float_t*>(ptr);
bfree(ptr);
} else {
x = 0;
}
}
void gs::effect_parameter::set_float2(vec2 const& v)
{
if (get_type() != type::Float2)
throw std::bad_cast();
gs_effect_set_vec2(_param, &v);
}
void gs::effect_parameter::get_float2(vec2& v)
{
get_float2(v.x, v.y);
}
void gs::effect_parameter::get_default_float2(vec2& v)
{
get_default_float2(v.x, v.y);
}
void gs::effect_parameter::set_float2(float_t x, float_t y)
{
vec2 data;
data.x = x;
data.y = y;
set_float2(data);
}
void gs::effect_parameter::get_float2(float_t& x, float_t& y)
{
if (get_type() != type::Float2)
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
x = *reinterpret_cast<float_t*>(ptr);
y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t));
bfree(ptr);
} else {
x = y = 0;
}
}
void gs::effect_parameter::get_default_float2(float_t& x, float_t& y)
{
if (get_type() != type::Float2)
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
x = *reinterpret_cast<float_t*>(ptr);
y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t));
bfree(ptr);
} else {
x = y = 0;
}
}
void gs::effect_parameter::set_float3(vec3 const& v)
{
if (get_type() != type::Float3)
throw std::bad_cast();
gs_effect_set_vec3(_param, &v);
}
void gs::effect_parameter::get_float3(vec3& v)
{
get_float3(v.x, v.y, v.z);
}
void gs::effect_parameter::get_default_float3(vec3& v)
{
get_default_float3(v.x, v.y, v.z);
}
void gs::effect_parameter::set_float3(float_t x, float_t y, float_t z)
{
if (get_type() != type::Float3)
throw std::bad_cast();
vec3 v = {{x, y, z, 0}};
gs_effect_set_vec3(_param, &v);
}
void gs::effect_parameter::get_float3(float_t& x, float_t& y, float_t& z)
{
if (get_type() != type::Float3)
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
x = *reinterpret_cast<float_t*>(ptr);
y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t));
z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 2);
bfree(ptr);
} else {
x = y = z = 0;
}
}
void gs::effect_parameter::get_default_float3(float_t& x, float_t& y, float_t& z)
{
if (get_type() != type::Float3)
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
x = *reinterpret_cast<float_t*>(ptr);
y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t));
z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 2);
bfree(ptr);
} else {
x = y = z = 0;
}
}
void gs::effect_parameter::set_float4(vec4 const& v)
{
if (get_type() != type::Float4)
throw std::bad_cast();
gs_effect_set_vec4(_param, &v);
}
void gs::effect_parameter::get_float4(vec4& v)
{
get_float4(v.x, v.y, v.z, v.w);
}
void gs::effect_parameter::get_default_float4(vec4& v)
{
get_default_float4(v.x, v.y, v.z, v.w);
}
void gs::effect_parameter::set_float4(float_t x, float_t y, float_t z, float_t w)
{
if (get_type() != type::Float4)
throw std::bad_cast();
vec4 v = {{x, y, z, w}};
gs_effect_set_vec4(_param, &v);
}
void gs::effect_parameter::get_float4(float_t& x, float_t& y, float_t& z, float_t& w)
{
if (get_type() != type::Float4)
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
x = *reinterpret_cast<float_t*>(ptr);
y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t));
z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 2);
w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 3);
bfree(ptr);
} else {
x = y = z = w = 0;
}
}
void gs::effect_parameter::get_default_float4(float_t& x, float_t& y, float_t& z, float_t& w)
{
if (get_type() != type::Float4)
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
x = *reinterpret_cast<float_t*>(ptr);
y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t));
z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 2);
w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 3);
bfree(ptr);
} else {
x = y = z = w = 0;
}
}
void gs::effect_parameter::set_float_array(float_t v[], size_t sz)
{
if ((get_type() != type::Float) && (get_type() != type::Float2) && (get_type() != type::Float3)
&& (get_type() != type::Float4))
throw std::bad_cast();
gs_effect_set_val(_param, v, sizeof(float_t) * sz);
}
void gs::effect_parameter::set_int(int32_t x)
{
if ((get_type() != type::Integer) && (get_type() != type::Unknown))
throw std::bad_cast();
gs_effect_set_int(_param, x);
}
void gs::effect_parameter::get_int(int32_t& x)
{
if ((get_type() != type::Integer) && (get_type() != type::Unknown))
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
x = *reinterpret_cast<int32_t*>(ptr);
bfree(ptr);
} else {
x = 0;
}
}
void gs::effect_parameter::get_default_int(int32_t& x)
{
if ((get_type() != type::Integer) && (get_type() != type::Unknown))
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
x = *reinterpret_cast<int32_t*>(ptr);
bfree(ptr);
} else {
x = 0;
}
}
void gs::effect_parameter::set_int2(int32_t x, int32_t y)
{
if ((get_type() != type::Integer2) && (get_type() != type::Unknown))
throw std::bad_cast();
int32_t v[2] = {x, y};
gs_effect_set_val(_param, v, sizeof(int) * 2);
}
void gs::effect_parameter::get_int2(int32_t& x, int32_t& y)
{
if ((get_type() != type::Integer2) && (get_type() != type::Unknown))
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
x = *reinterpret_cast<int32_t*>(ptr);
y = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t));
bfree(ptr);
} else {
x = y = 0;
}
}
void gs::effect_parameter::get_default_int2(int32_t& x, int32_t& y)
{
if ((get_type() != type::Integer2) && (get_type() != type::Unknown))
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
x = *reinterpret_cast<int32_t*>(ptr);
y = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t));
bfree(ptr);
} else {
x = y = 0;
}
}
void gs::effect_parameter::set_int3(int32_t x, int32_t y, int32_t z)
{
if ((get_type() != type::Integer3) && (get_type() != type::Unknown))
throw std::bad_cast();
int32_t v[3] = {x, y, z};
gs_effect_set_val(_param, v, sizeof(int) * 3);
}
void gs::effect_parameter::get_int3(int32_t& x, int32_t& y, int32_t& z)
{
if ((get_type() != type::Integer3) && (get_type() != type::Unknown))
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
x = *reinterpret_cast<int32_t*>(ptr);
y = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t));
z = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t) * 2);
bfree(ptr);
} else {
x = y = z = 0;
}
}
void gs::effect_parameter::get_default_int3(int32_t& x, int32_t& y, int32_t& z)
{
if ((get_type() != type::Integer3) && (get_type() != type::Unknown))
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
x = *reinterpret_cast<int32_t*>(ptr);
y = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t));
z = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t) * 2);
bfree(ptr);
} else {
x = y = z = 0;
}
}
void gs::effect_parameter::set_int4(int32_t x, int32_t y, int32_t z, int32_t w)
{
if ((get_type() != type::Integer4) && (get_type() != type::Unknown))
throw std::bad_cast();
int32_t v[4] = {x, y, z, w};
gs_effect_set_val(_param, v, sizeof(int) * 4);
}
void gs::effect_parameter::get_int4(int32_t& x, int32_t& y, int32_t& z, int32_t& w)
{
if ((get_type() != type::Integer4) && (get_type() != type::Unknown))
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
x = *reinterpret_cast<int32_t*>(ptr);
y = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t));
z = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t) * 2);
w = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t) * 3);
bfree(ptr);
} else {
x = y = z = w = 0;
}
}
void gs::effect_parameter::get_default_int4(int32_t& x, int32_t& y, int32_t& z, int32_t& w)
{
if ((get_type() != type::Integer4) && (get_type() != type::Unknown))
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
x = *reinterpret_cast<int32_t*>(ptr);
y = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t));
z = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t) * 2);
w = *reinterpret_cast<int32_t*>(ptr + sizeof(int32_t) * 3);
bfree(ptr);
} else {
x = y = z = w = 0;
}
}
void gs::effect_parameter::set_int_array(int32_t v[], size_t sz)
{
if ((get_type() != type::Integer) && (get_type() != type::Integer2) && (get_type() != type::Integer3)
&& (get_type() != type::Integer4) && (get_type() != type::Unknown))
throw std::bad_cast();
gs_effect_set_val(_param, v, sizeof(int) * sz);
}
void gs::effect_parameter::set_matrix(matrix4 const& v)
{
if (get_type() != type::Matrix)
throw std::bad_cast();
gs_effect_set_matrix4(_param, &v);
}
void gs::effect_parameter::get_matrix(matrix4& v)
{
if (get_type() != type::Matrix)
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
v.x.x = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 0);
v.x.y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 1);
v.x.z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 2);
v.x.w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 3);
v.y.x = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 4);
v.y.y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 5);
v.y.z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 6);
v.y.w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 7);
v.z.x = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 8);
v.z.y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 9);
v.z.z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 10);
v.z.w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 11);
v.t.x = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 12);
v.t.y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 13);
v.t.z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 14);
v.t.w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 15);
bfree(ptr);
} else {
v.x = vec4{};
v.y = vec4{};
v.z = vec4{};
v.t = vec4{};
}
}
void gs::effect_parameter::get_default_matrix(matrix4& v)
{
if (get_type() != type::Matrix)
throw std::bad_cast();
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
v.x.x = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 0);
v.x.y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 1);
v.x.z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 2);
v.x.w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 3);
v.y.x = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 4);
v.y.y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 5);
v.y.z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 6);
v.y.w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 7);
v.z.x = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 8);
v.z.y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 9);
v.z.z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 10);
v.z.w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 11);
v.t.x = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 12);
v.t.y = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 13);
v.t.z = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 14);
v.t.w = *reinterpret_cast<float_t*>(ptr + sizeof(float_t) * 15);
bfree(ptr);
} else {
v.x = vec4{};
v.y = vec4{};
v.z = vec4{};
v.t = vec4{};
}
}
void gs::effect_parameter::set_texture(std::shared_ptr<gs::texture> v)
{
if (get_type() != type::Texture)
throw std::bad_cast();
gs_effect_set_texture(_param, v->get_object());
}
void gs::effect_parameter::set_texture(gs_texture_t* v)
{
if (get_type() != type::Texture)
throw std::bad_cast();
gs_effect_set_texture(_param, v);
}
void gs::effect_parameter::set_sampler(std::shared_ptr<gs::sampler> v)
{
if (get_type() != type::Texture)
throw std::bad_cast();
gs_effect_set_next_sampler(_param, v->get_object());
}
void gs::effect_parameter::set_sampler(gs_sampler_state* v)
{
if (get_type() != type::Texture)
throw std::bad_cast();
gs_effect_set_next_sampler(_param, v);
}
void gs::effect_parameter::set_string(std::string const& v)
{
if (get_type() != type::String)
throw std::bad_cast();
gs_effect_set_val(_param, v.c_str(), v.length());
}
void gs::effect_parameter::get_string(std::string& v)
{
if (get_type() != type::String)
throw std::bad_cast();
size_t ptr_len = gs_effect_get_val_size(_param);
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_val(_param));
if (ptr) {
v = std::string(ptr, ptr + ptr_len - 1);
bfree(ptr);
} else {
v = "";
}
}
void gs::effect_parameter::get_default_string(std::string& v)
{
if (get_type() != type::String)
throw std::bad_cast();
size_t ptr_len = gs_effect_get_default_val_size(_param);
uint8_t* ptr = static_cast<uint8_t*>(gs_effect_get_default_val(_param));
if (ptr) {
v = std::string(ptr, ptr + ptr_len - 1);
bfree(ptr);
} else {
v = "";
}
}
size_t gs::effect_parameter::count_annotations()
{
return gs_param_get_num_annotations(_param);
}
std::shared_ptr<gs::effect_parameter> gs::effect_parameter::get_annotation(size_t idx)
{
gs_eparam_t* param = gs_param_get_annotation_by_idx(_param, idx);
if (!param)
return nullptr;
return std::make_shared<effect_parameter>(_effect, param);
}
std::shared_ptr<gs::effect_parameter> gs::effect_parameter::get_annotation(std::string name)
{
gs_eparam_t* param = gs_param_get_annotation_by_name(_param, name.c_str());
if (!param)
return nullptr;
return std::make_shared<effect_parameter>(_effect, param);
}
bool gs::effect_parameter::has_annotation(std::string name)
{
auto eprm = get_annotation(name);
if (eprm)
return true;
return false;
}
bool gs::effect_parameter::has_annotation(std::string name, effect_parameter::type type)
{
auto eprm = get_annotation(name);
if (eprm)
return eprm->get_type() == type;
return false; return false;
} }

View file

@ -19,254 +19,44 @@
#pragma once #pragma once
#include <cinttypes> #include <cinttypes>
#include <filesystem>
#include <list> #include <list>
#include <memory> #include <memory>
#include <string> #include <string>
#include "gs-sampler.hpp" #include "gs-effect-parameter.hpp"
#include "gs-texture.hpp" #include "gs-effect-technique.hpp"
// OBS
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4201)
#endif
#include <graphics/graphics.h>
#include <graphics/matrix4.h>
#include <graphics/vec2.h>
#include <graphics/vec3.h>
#include <graphics/vec4.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace gs { namespace gs {
class effect; class effect : private std::shared_ptr<gs_effect_t> {
class effect_parameter {
std::shared_ptr<::gs::effect> _effect;
gs_eparam_t* _param;
gs_effect_param_info _param_info;
public: public:
enum class type : uint8_t {
Unknown,
Boolean,
Float,
Float2,
Float3,
Float4,
Integer,
Integer2,
Integer3,
Integer4,
Matrix,
String,
Texture,
};
public:
effect_parameter(std::shared_ptr<gs::effect> effect, gs_eparam_t* param);
std::string get_name();
type get_type();
void set_bool(bool v);
void get_bool(bool& v);
void get_default_bool(bool& v);
void set_bool_array(bool v[], size_t sz);
void set_float(float_t x);
void get_float(float_t& x);
void get_default_float(float_t& x);
void set_float2(vec2 const& v);
void get_float2(vec2& v);
void get_default_float2(vec2& v);
void set_float2(float_t x, float_t y);
void get_float2(float_t& x, float_t& y);
void get_default_float2(float_t& x, float_t& y);
void set_float3(vec3 const& v);
void get_float3(vec3& v);
void get_default_float3(vec3& v);
void set_float3(float_t x, float_t y, float_t z);
void get_float3(float_t& x, float_t& y, float_t& z);
void get_default_float3(float_t& x, float_t& y, float_t& z);
void set_float4(vec4 const& v);
void get_float4(vec4& v);
void get_default_float4(vec4& v);
void set_float4(float_t x, float_t y, float_t z, float_t w);
void get_float4(float_t& x, float_t& y, float_t& z, float_t& w);
void get_default_float4(float_t& x, float_t& y, float_t& z, float_t& w);
void set_float_array(float_t v[], size_t sz);
void set_int(int32_t x);
void get_int(int32_t& x);
void get_default_int(int32_t& x);
void set_int2(int32_t x, int32_t y);
void get_int2(int32_t& x, int32_t& y);
void get_default_int2(int32_t& x, int32_t& y);
void set_int3(int32_t x, int32_t y, int32_t z);
void get_int3(int32_t& x, int32_t& y, int32_t& z);
void get_default_int3(int32_t& x, int32_t& y, int32_t& z);
void set_int4(int32_t x, int32_t y, int32_t z, int32_t w);
void get_int4(int32_t& x, int32_t& y, int32_t& z, int32_t& w);
void get_default_int4(int32_t& x, int32_t& y, int32_t& z, int32_t& w);
void set_int_array(int32_t v[], size_t sz);
void set_matrix(matrix4 const& v);
void get_matrix(matrix4& v);
void get_default_matrix(matrix4& v);
void set_texture(std::shared_ptr<gs::texture> v);
void set_texture(gs_texture_t* v);
void set_sampler(std::shared_ptr<gs::sampler> v);
void set_sampler(gs_sampler_state* v);
void set_string(std::string const& v);
void get_string(std::string& v);
void get_default_string(std::string& v);
size_t count_annotations();
std::shared_ptr<effect_parameter> get_annotation(size_t idx);
std::shared_ptr<effect_parameter> get_annotation(std::string name);
bool has_annotation(std::string name);
bool has_annotation(std::string name, effect_parameter::type type);
public /* Helpers */:
inline float_t get_bool()
{
bool v;
get_bool(v);
return v;
};
inline bool get_default_bool()
{
bool v;
get_default_bool(v);
return v;
};
inline float_t get_float()
{
float_t v;
get_float(v);
return v;
};
inline float_t get_default_float()
{
float_t v;
get_default_float(v);
return v;
};
inline vec2 get_float2()
{
vec2 v;
get_float2(v);
return v;
};
inline vec2 get_default_float2()
{
vec2 v;
get_default_float2(v);
return v;
};
inline vec3 get_float3()
{
vec3 v;
get_float3(v);
return v;
};
inline vec3 get_default_float3()
{
vec3 v;
get_default_float3(v);
return v;
};
inline vec4 get_float4()
{
vec4 v;
get_float4(v);
return v;
};
inline vec4 get_default_float4()
{
vec4 v;
get_default_float4(v);
return v;
};
inline int32_t get_int()
{
int32_t v;
get_int(v);
return v;
};
inline int32_t get_default_int()
{
int32_t v;
get_default_int(v);
return v;
};
inline matrix4 get_matrix()
{
matrix4 v;
get_matrix(v);
return v;
};
inline matrix4 get_default_matrix()
{
matrix4 v;
get_default_matrix(v);
return v;
};
inline std::string get_string()
{
std::string v;
get_string(v);
return v;
};
inline std::string get_default_string()
{
std::string v;
get_default_string(v);
return v;
};
};
class effect : public std::enable_shared_from_this<::gs::effect> {
protected:
gs_effect_t* _effect;
public:
effect(std::string file);
effect(std::string code, std::string name); effect(std::string code, std::string name);
virtual ~effect(); effect(std::filesystem::path file);
~effect();
gs_effect_t* get_object(); size_t count_techniques();
gs::effect_technique get_technique(size_t idx);
gs::effect_technique get_technique(std::string name);
bool has_technique(std::string name);
size_t count_parameters(); size_t count_parameters();
std::list<std::shared_ptr<effect_parameter>> get_parameters(); gs::effect_parameter get_parameter(size_t idx);
std::shared_ptr<effect_parameter> get_parameter(size_t idx); gs::effect_parameter get_parameter(std::string name);
std::shared_ptr<effect_parameter> get_parameter(std::string name);
bool has_parameter(std::string name); bool has_parameter(std::string name);
bool has_parameter(std::string name, effect_parameter::type type); bool has_parameter(std::string name, effect_parameter::type type);
public: public /* Legacy Support */:
static std::shared_ptr<gs::effect> create(std::string file); inline gs_effect_t* get_object()
static std::shared_ptr<gs::effect> create(std::string code, std::string name); {
return get();
}
static gs::effect create(std::string file)
{
return gs::effect(file);
};
static gs::effect create(std::string code, std::string name)
{
return gs::effect(code, name);
};
}; };
} // namespace gs } // namespace gs