Esempio n. 1
0
bgfx_entry_uniform* entry_uniform_reader::read_from_value(const Value& value, std::string prefix, bgfx_effect* effect, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params)
{
	if (!validate_parameters(value, prefix))
	{
		return nullptr;
	}

	std::string name = value["uniform"].GetString();
	bgfx_uniform* uniform = effect->uniform(name);

	if (!READER_CHECK(uniform != nullptr, (prefix + "Uniform '" + name + " does not appear to exist\n").c_str()))
	{
		return nullptr;
	}

	if (value.HasMember("slider"))
	{
		return slider_uniform_reader::read_from_value(value, prefix, uniform, sliders);
	}
	else if (value.HasMember("value"))
	{
		return value_uniform_reader::read_from_value(value, prefix, uniform);
	}
	else if (value.HasMember("parameter"))
	{
		return param_uniform_reader::read_from_value(value, prefix, uniform, params);
	}
	else
	{
		READER_CHECK(false, (prefix + "Unrecognized uniform type for uniform binding " + name).c_str());
	}


	return nullptr;
}
Esempio n. 2
0
static int __init cpcihp_generic_init(void)
{
	int status;
	struct resource *r;
	struct pci_dev *dev;

	info(DRIVER_DESC " version: " DRIVER_VERSION);
	status = validate_parameters();
	if (status)
		return status;

	r = request_region(port, 1, "#ENUM hotswap signal register");
	if (!r)
		return -EBUSY;

	dev = pci_get_domain_bus_and_slot(0, bridge_busnr,
					  PCI_DEVFN(bridge_slot, 0));
	if (!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
		err("Invalid bridge device %s", bridge);
		pci_dev_put(dev);
		return -EINVAL;
	}
	bus = dev->subordinate;
	pci_dev_put(dev);

	memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
	generic_hpc.ops = &generic_hpc_ops;

	status = cpci_hp_register_controller(&generic_hpc);
	if (status != 0) {
		err("Could not register cPCI hotplug controller");
		return -ENODEV;
	}
	dbg("registered controller");

	status = cpci_hp_register_bus(bus, first_slot, last_slot);
	if (status != 0) {
		err("Could not register cPCI hotplug bus");
		goto init_bus_register_error;
	}
	dbg("registered bus");

	status = cpci_hp_start();
	if (status != 0) {
		err("Could not started cPCI hotplug system");
		goto init_start_error;
	}
	dbg("started cpci hp system");
	return 0;
init_start_error:
	cpci_hp_unregister_bus(bus);
init_bus_register_error:
	cpci_hp_unregister_controller(&generic_hpc);
	err("status = %d", status);
	return status;

}
Esempio n. 3
0
bgfx_suppressor* suppressor_reader::read_from_value(const Value& value, std::string prefix, std::map<std::string, bgfx_slider*>& sliders)
{
	if (!validate_parameters(value, prefix))
	{
		return nullptr;
	}

	std::string name = value["name"].GetString();
	uint32_t condition = uint32_t(get_enum_from_value(value, "condition", bgfx_suppressor::condition_type::CONDITION_EQUAL, CONDITION_NAMES, CONDITION_COUNT));
	bgfx_suppressor::combine_mode mode = bgfx_suppressor::combine_mode(get_enum_from_value(value, "combine", bgfx_suppressor::combine_mode::COMBINE_OR, COMBINE_NAMES, COMBINE_COUNT));

	std::vector<bgfx_slider*> check_sliders;
	check_sliders.push_back(sliders[name + "0"]);

	int slider_count;
	switch (check_sliders[0]->type())
	{
		case bgfx_slider::slider_type::SLIDER_FLOAT:
		case bgfx_slider::slider_type::SLIDER_INT:
		case bgfx_slider::slider_type::SLIDER_INT_ENUM:
			slider_count = 1;
			break;
		case bgfx_slider::slider_type::SLIDER_VEC2:
			slider_count = 2;
			break;
		case bgfx_slider::slider_type::SLIDER_COLOR:
			slider_count = 3;
			break;
		default:
			slider_count = 0;
			break;
	}

	int values[4];
	if (slider_count > 1)
	{
		get_values(value, prefix, "value", values, slider_count);
		if (!READER_CHECK(slider_count == value["value"].GetArray().Size(), (prefix + "Expected " + std::to_string(slider_count) + " values, got " + std::to_string(value["value"].GetArray().Size()) + "\n").c_str())) return nullptr;
		for (int index = 1; index < slider_count; index++)
		{
			check_sliders.push_back(sliders[name + std::to_string(index)]);
		}
	}
	else
	{
		values[0] = get_int(value, "value", 0);
	}

	return new bgfx_suppressor(check_sliders, condition, mode, values);
}
Esempio n. 4
0
void 
mu_test_validate_parameters__saltlen () 
{
  size_t outlen;
  size_t inlen;
  size_t saltlen;

  outlen = 32;
  inlen = 1024;
  saltlen = 32;
  mu_check ( validate_parameters (outlen, inlen, saltlen) == 0 );

  saltlen = 0;
  mu_check ( validate_parameters (outlen, inlen, saltlen) == ERROR_SALTLEN_TOO_SMALL );

  saltlen = SALTLEN_MIN - 1;
  mu_check ( validate_parameters (outlen, inlen, saltlen) == ERROR_SALTLEN_TOO_SMALL );

  saltlen = 1 << 24;
  mu_check ( validate_parameters (outlen, inlen, saltlen) == ERROR_SALTLEN_TOO_BIG);

  saltlen = SALTLEN_MAX;
  mu_check ( validate_parameters (outlen, inlen, saltlen) == ERROR_SALTLEN_TOO_BIG);
}
Esempio n. 5
0
Distribution new_Distribution_from_fp(FILE * fp){
	if(NULL==fp){ return NULL; }
	Distribution dist = calloc(1,sizeof(*dist));
	fscanf(fp,"%c",&dist->key);
	switch(dist->key){
		case 'M': fscanf(fp,"%d",&dist->np);
			  if(dist->np<1){ goto cleanup; }
			  NormMixParam normmix = new_NormMixParam(dist->np);
			  dist->info = (void *)normmix;
			  for(int i=0 ; i<dist->np ; i++){
				  int ret = fscanf(fp,real_format_str,&normmix->prob[i]);
				  ret += fscanf(fp,real_format_str,&normmix->mean[i]);
				  ret += fscanf(fp,real_format_str,&normmix->sd[i]);
				  if(3!=ret){ goto cleanup;}
			  }
			  dist->np = 3*dist->np-1;
			  break;
		case 'W': dist->np = 2;
			  break;
		case 'L': dist->np = 2;
			  break;
		case 'N': dist->np = 2;
			  break;
	}
	if(NULL==dist->info){
		dist->param = calloc(dist->np,sizeof(real_t));
		if(NULL==dist->param){ goto cleanup; }
		for ( int i=0 ; i<dist->np ; i++){
			int ret = fscanf(fp, real_format_str , &dist->param[i]);
			if(1!=ret){ goto cleanup; }
		}
	}
	if(!validate_parameters(dist)){ goto cleanup; }

	return dist;

cleanup:
	free_Distribution(dist);
	return NULL;
}
Esempio n. 6
0
bgfx_chain* chain_reader::read_from_value(const Value& value, std::string prefix, osd_options& options, running_machine& machine, uint32_t window_index, uint32_t screen_index, texture_manager& textures, target_manager& targets, effect_manager& effects)
{
	if (!validate_parameters(value, prefix))
	{
		return nullptr;
	}

	std::string name = value["name"].GetString();
	std::string author = value["author"].GetString();

	// Parse sliders
	std::vector<bgfx_slider*> sliders;
	if (value.HasMember("sliders"))
	{
		const Value& slider_array = value["sliders"];
		for (UINT32 i = 0; i < slider_array.Size(); i++)
		{
			std::vector<bgfx_slider*> expanded_sliders = slider_reader::read_from_value(slider_array[i], prefix + "sliders[" + std::to_string(i) + "]: ", machine, window_index, screen_index);
			if (expanded_sliders.size() == 0)
			{
				return nullptr;
			}
			for (bgfx_slider* slider : expanded_sliders)
			{
				sliders.push_back(slider);
			}
		}
	}

	// Parse whether the screen container is transformed by the chain's shaders
	bool transform = false;
	if (value.HasMember("transform"))
	{
		transform = value["transform"].GetBool();
	}

	// Map sliders
	std::map<std::string, bgfx_slider*> slider_map;
	for (bgfx_slider* slider : sliders)
	{
		slider_map[slider->name()] = slider;
	}

	// Parse parameters
	std::vector<bgfx_parameter*> parameters;
	if (value.HasMember("parameters"))
	{
		const Value& param_array = value["parameters"];
		for (UINT32 i = 0; i < param_array.Size(); i++)
		{
			bgfx_parameter* parameter = parameter_reader::read_from_value(param_array[i], prefix + "parameters[" + std::to_string(i) + "]; ", window_index);
			if (parameter == nullptr)
			{
				return nullptr;
			}
			parameters.push_back(parameter);
		}
	}

	// Map parameters
	std::map<std::string, bgfx_parameter*> param_map;
	for (bgfx_parameter* param : parameters)
	{
		param_map[param->name()] = param;
	}

	// Create targets
	std::vector<bgfx_target*> target_list;
	if (value.HasMember("targets"))
	{
		const Value& target_array = value["targets"];
		// TODO: Move into its own reader
		for (UINT32 i = 0; i < target_array.Size(); i++)
		{
			bgfx_target* target = target_reader::read_from_value(target_array[i], prefix + "targets[" + std::to_string(i) + "]: ", targets, options, screen_index);
			if (target == nullptr)
			{
				return nullptr;
			}
			target_list.push_back(target);
		}
	}

	// Parse chain entries
	std::vector<bgfx_chain_entry*> entries;
	if (value.HasMember("passes"))
	{
		const Value& entry_array = value["passes"];
		for (UINT32 i = 0; i < entry_array.Size(); i++)
		{
			bgfx_chain_entry* entry = chain_entry_reader::read_from_value(entry_array[i], prefix + "passes[" + std::to_string(i) + "]: ", options, textures, targets, effects, slider_map, param_map, screen_index);
			if (entry == nullptr)
			{
				return nullptr;
			}
			entries.push_back(entry);
		}
	}

	return new bgfx_chain(name, author, transform, targets, sliders, parameters, entries, target_list, screen_index);
}
Esempio n. 7
0
bgfx_chain* chain_reader::read_from_value(const Value& value, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t screen_width, uint32_t screen_height)
{
	validate_parameters(value);

	std::string name = value["name"].GetString();
	std::string author = value["author"].GetString();

	// Parse sliders
	std::vector<bgfx_slider*> sliders;
	if (value.HasMember("sliders"))
	{
		const Value& slider_array = value["sliders"];
		for (UINT32 i = 0; i < slider_array.Size(); i++)
		{
			sliders.push_back(slider_reader::read_from_value(slider_array[i]));
		}
	}

	// Parse parameters
	std::vector<bgfx_parameter*> parameters;
	if (value.HasMember("parameters"))
	{
		const Value& param_array = value["parameters"];
		for (UINT32 i = 0; i < param_array.Size(); i++)
		{
			parameters.push_back(parameter_reader::read_from_value(param_array[i]));
		}
	}

	// Parse chain entries
	std::vector<bgfx_chain_entry*> entries;
	if (value.HasMember("passes"))
	{
		const Value& entry_array = value["passes"];
		for (UINT32 i = 0; i < entry_array.Size(); i++)
		{
			entries.push_back(chain_entry_reader::read_from_value(entry_array[i], textures, targets, effects));
		}
	}

	// Create targets
	if (value.HasMember("targets"))
	{
		const Value& target_array = value["targets"];
		for (UINT32 i = 0; i < target_array.Size(); i++)
		{
			assert(target_array[i].HasMember("name"));
			assert(target_array[i]["name"].IsString());
			uint32_t width = 0;
			uint32_t height = 0;
			if (target_array[i].HasMember("screen") && target_array[i]["screen"].IsBool())
			{
				width = screen_width;
				height = screen_height;
			}
			else
			{
				assert(target_array[i].HasMember("width"));
				assert(target_array[i]["width"].IsDouble());
				assert(target_array[i].HasMember("height"));
				assert(target_array[i]["height"].IsDouble());
				width = uint32_t(target_array[i]["width"].GetDouble());
				height = uint32_t(target_array[i]["height"].GetDouble());
			}
			targets.create_target(target_array[i]["name"].GetString(), bgfx::TextureFormat::RGBA8, width, height);
		}
	}

	return new bgfx_chain(name, author, sliders, parameters, entries);
}
Esempio n. 8
0
bgfx_effect* effect_reader::read_from_value(const Value& value, std::string prefix, shader_manager& shaders)
{
	if (!validate_parameters(value, prefix))
	{
		return nullptr;
	}

	uint64_t blend = 0;
	if (value.HasMember("blend"))
	{
		blend = blend_reader::read_from_value(value["blend"]);
	}
	uint64_t depth = depth_reader::read_from_value(value["depth"], prefix + "depth: ");
	uint64_t cull = cull_reader::read_from_value(value["cull"]);
	uint64_t write = write_reader::read_from_value(value["write"]);

	std::vector<bgfx_uniform*> uniforms;
	const Value& uniform_array = value["uniforms"];
	for (uint32_t i = 0; i < uniform_array.Size(); i++)
	{
		bgfx_uniform* uniform = uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: ");
		if (uniform == nullptr)
		{
			return nullptr;
		}
		uniforms.push_back(uniform);
	}

	std::string vertex_name(value["vertex"].GetString());
	bgfx::ShaderHandle vertex_shader = shaders.shader(vertex_name);
	if (vertex_shader.idx == 0xffff)
	{
		for (bgfx_uniform* uniform : uniforms)
		{
			if (uniform != nullptr)
			{
				delete uniform;
			}
		}
		return nullptr;
	}

	std::string fragment_name("");
	if (value.HasMember("fragment"))
	{
		fragment_name = value["fragment"].GetString();
	}
	else if (value.HasMember("pixel"))
	{
		fragment_name = value["pixel"].GetString();
	}
	bgfx::ShaderHandle fragment_shader = shaders.shader(fragment_name);
	if (fragment_shader.idx == 0xffff)
	{
		for (bgfx_uniform* uniform : uniforms)
		{
			if (uniform != nullptr)
			{
				delete uniform;
			}
		}
		return nullptr;
	}

	return new bgfx_effect(blend | depth | cull | write, vertex_shader, fragment_shader, uniforms);
}
int main(int argc, char **argv)
{
  ROS_INFO("Starting pid with node name %s", node_name.c_str());

  // Initialize ROS stuff
  ros::init(argc, argv, node_name);     // Note node_name can be overidden by launch file
  ros::NodeHandle node;
  ros::NodeHandle node_priv("~");

  while (ros::Time(0) == ros::Time::now())
  {
    ROS_INFO("controller spinning waiting for time to become non-zero");
    sleep(1);
  }

  // Get params if specified in launch file or as params on command-line, set defaults
  node_priv.param<double>("Kp", Kp, 1.0);
  node_priv.param<double>("Ki", Ki, 0.0);
  node_priv.param<double>("Kd", Kd, 0.0);
  node_priv.param<double>("upper_limit", upper_limit, 1000.0);
  node_priv.param<double>("lower_limit", lower_limit, -1000.0);
  node_priv.param<double>("windup_limit", windup_limit, 1000.0);
  node_priv.param<double>("cutoff_frequency", cutoff_frequency, -1.0);
  node_priv.param<std::string>("topic_from_controller", topic_from_controller, "control_effort");
  node_priv.param<std::string>("topic_from_plant", topic_from_plant, "rpms");
  node_priv.param<std::string>("setpoint_topic", setpoint_topic, "setpoint");
  node_priv.param<double>("max_loop_frequency", max_loop_frequency, 1.0);
  node_priv.param<double>("min_loop_frequency", min_loop_frequency, 1000.0);

  // Update params if specified as command-line options, & print settings
  print_parameters();
  if (not validate_parameters())
  {
    std::cout << "Error: invalid parameter\n";
  }

  // instantiate publishers & subscribers
  control_effort_pub = node.advertise<std_msgs::Float64>(topic_from_controller, 1);

  ros::Subscriber sub = node.subscribe(topic_from_plant, 1, plant_state_callback );
  // COmment for now not to have changes. We want constant rpms
  //ros::Subscriber setpoint_sub = node.subscribe(setpoint_topic, 1, setpoint_callback );
  ros::Subscriber pid_enabled_sub = node.subscribe("pid_enable", 1, pid_enable_callback );


/*  // configure dynamic reconfiguration
  dynamic_reconfigure::Server<pid::PidConfig> config_server;
  dynamic_reconfigure::Server<pid::PidConfig>::CallbackType f;
  f = boost::bind(&reconfigure_callback, _1, _2);
  config_server.setCallback(f);
*/

/*
  // initialize diagnostics
  diags = new PidControllerDiags;

  diag_status.level = diagnostic_msgs::DiagnosticStatus::OK;
  diag_status.message = "PID status nominal";

  diags->diag_updater.setHardwareID(node_name);
  diags->diag_updater.add(diags->freq_status);
  diags->diag_updater.add("PID status", get_pid_diag_status);
*/

  // Respond to inputs until shut down
  ros::spin();

  return 0;
}
Esempio n. 10
0
bgfx_chain_entry* chain_entry_reader::read_from_value(const Value& value, std::string prefix, chain_manager& chains, std::map<std::string, bgfx_slider*>& sliders, std::map<std::string, bgfx_parameter*>& params, uint32_t screen_index)
{
	if (!validate_parameters(value, prefix))
	{
		printf("Failed validation\n");
		return nullptr;
	}

	bgfx_effect* effect = chains.effects().effect(value["effect"].GetString());
	if (effect == nullptr)
	{
		return nullptr;
	}

	std::string name = value["name"].GetString();

	std::vector<bgfx_input_pair*> inputs;
	if (value.HasMember("input"))
	{
		const Value& input_array = value["input"];
		for (uint32_t i = 0; i < input_array.Size(); i++)
		{
			const Value& input = input_array[i];
			if (!READER_CHECK(input.HasMember("sampler"), (prefix + "input[" + std::to_string(i) + ": Must have string value 'sampler' (what sampler are we binding to?)\n").c_str())) return nullptr;
			if (!READER_CHECK(input["sampler"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'sampler' must be a string\n").c_str())) return nullptr;
			bool has_texture = input.HasMember("texture");
			bool has_target = input.HasMember("target");
			bool has_option = input.HasMember("option");
			if (!READER_CHECK(has_texture || has_target || has_option, (prefix + "input[" + std::to_string(i) + ": Must have string value 'target', 'texture' or 'option' (what source are we using?)\n").c_str())) return nullptr;
			if (!READER_CHECK(!has_texture || input["texture"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'texture' must be a string\n").c_str())) return nullptr;
			if (!READER_CHECK(!has_target || input["target"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'target' must be a string\n").c_str())) return nullptr;
			if (!READER_CHECK(!has_option || input["option"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'option' must be a string\n").c_str())) return nullptr;
			if (!READER_CHECK(has_target || !input.HasMember("bilinear") || input["bilinear"].IsBool(), (prefix + "input[" + std::to_string(i) + ": Value 'bilinear' must be a boolean\n").c_str())) return nullptr;
			if (!READER_CHECK(has_target || !input.HasMember("clamp") || input["clamp"].IsBool(), (prefix + "input[" + std::to_string(i) + ": Value 'clamp' must be a boolean\n").c_str())) return nullptr;
			if (!READER_CHECK(has_texture || has_option || !input.HasMember("selection") || input["selection"].IsString(), (prefix + "input[" + std::to_string(i) + ": Value 'selection' must be a string\n").c_str())) return nullptr;
			bool bilinear = get_bool(input, "bilinear", true);
			bool clamp = get_bool(input, "clamp", false);
			std::string selection = get_string(input, "selection", "");

			std::vector<std::string> texture_names;
			std::string texture_name = "";
			if (has_texture || has_option)
			{
				if (has_texture)
				{
					texture_name = input["texture"].GetString();
				}
				if (has_option)
				{
					std::string option = input["option"].GetString();

					texture_name = chains.options().value(option.c_str());
				}

				if (texture_name != "" && texture_name != "screen")
				{
					if (selection == "")
					{
						// create texture for specified file name
						uint32_t flags = bilinear ? 0u : (BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT);
						flags |= clamp ? (BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP) : 0u;
						bgfx_texture* texture = chains.textures().create_png_texture(chains.options().art_path(), texture_name, texture_name, flags, screen_index);
						if (texture == nullptr)
						{
							return nullptr;
						}
					}
					else
					{
						// create texture for specified file name
						uint32_t flags = bilinear ? 0u : (BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT);
						flags |= clamp ? (BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP) : 0u;
						bgfx_texture* texture = chains.textures().create_png_texture(chains.options().art_path(), texture_name, texture_name, flags, screen_index);
						if (texture == nullptr)
						{
							return nullptr;
						}

						// get directory of file
						std::string directory_path = std::string(chains.options().art_path());
						std::string file_directory = "";
						const size_t last_slash = texture_name.rfind('/');
						if (last_slash != std::string::npos)
						{
							file_directory = texture_name.substr(0, last_slash);

							directory_path += "/" + file_directory;
						}

						osd::directory::ptr directory = osd::directory::open(directory_path);
						if (directory)
						{
							for (const osd::directory::entry *entry = directory->read(); entry != nullptr; entry = directory->read())
							{
								if (entry->type == osd::directory::entry::entry_type::FILE)
								{
									std::string file(entry->name);
									std::string extension(".png");

									// split into file name and extension
									std::string file_name;
									std::string file_extension;
									const size_t last_dot = file.rfind('.');
									if (last_dot != std::string::npos)
									{
										file_name = file.substr(0, last_dot);
										file_extension = file.substr(last_dot, file.length() - last_dot);
									}

									std::string file_path;
									if (file_directory == "")
									{
										file_path = file;
									}
									else
									{
										file_path = file_directory + "/" + file;
									}

									// check for .png extension
									if (file_extension == extension)
									{
										// create textures for all files containd in the path of the specified file name
										uint32_t flags = bilinear ? 0u : (BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT);
										flags |= clamp ? (BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP) : 0u;
										bgfx_texture* texture = chains.textures().create_png_texture(chains.options().art_path(), file_path, file_path, flags, screen_index);
										if (texture == nullptr)
										{
											return nullptr;
										}
										texture_names.push_back(file_path);
									}
								}
							}
						}
					}
				}
			}
			else if (has_target)
			{
				texture_name = input["target"].GetString();
			}
			else
			{
				return nullptr;
			}

			std::string sampler = input["sampler"].GetString();
			bgfx_input_pair* input_pair = new bgfx_input_pair(i, sampler, texture_name, texture_names, selection, chains, screen_index);
			inputs.push_back(input_pair);
		}
	}

	std::vector<bgfx_entry_uniform*> uniforms;
	if (value.HasMember("uniforms"))
	{
		const Value& uniform_array = value["uniforms"];
		for (uint32_t i = 0; i < uniform_array.Size(); i++)
		{
			bgfx_entry_uniform* uniform = entry_uniform_reader::read_from_value(uniform_array[i], prefix + "uniforms[" + std::to_string(i) + "]: ", effect, sliders, params);
			if (uniform == nullptr)
			{
				for (bgfx_entry_uniform* existing_uniform : uniforms) delete existing_uniform;
				return nullptr;
			}
			uniforms.push_back(uniform);
		}
	}

	std::vector<bgfx_suppressor*> suppressors;
	if (value.HasMember("disablewhen"))
	{
		const Value& suppressor_array = value["disablewhen"];
		for (uint32_t i = 0; i < suppressor_array.Size(); i++)
		{
			bgfx_suppressor* suppressor = suppressor_reader::read_from_value(suppressor_array[i], prefix, sliders);
			if (suppressor == nullptr)
			{
				for (bgfx_entry_uniform* uniform : uniforms) delete uniform;
				for (bgfx_suppressor* existing_suppressor : suppressors) delete existing_suppressor;
				return nullptr;
			}
			suppressors.push_back(suppressor);
		}
	}

	// Parse clear state
	clear_state* clear = nullptr;
	if (value.HasMember("clear"))
	{
		clear = clear_reader::read_from_value(value["clear"], prefix + "clear state: ");
	}
	else
	{
		clear = new clear_state(BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x00000000, 1.0f, 0);
	}

	std::string output = value["output"].GetString();
	return new bgfx_chain_entry(name, effect, clear, suppressors, inputs, uniforms, chains.targets(), output);
}