mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
VideoCommon: update shader asset to provide a variant default value
This commit is contained in:
@ -4,19 +4,176 @@
|
|||||||
#include "VideoCommon/Assets/ShaderAsset.h"
|
#include "VideoCommon/Assets/ShaderAsset.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
|
||||||
#include <string_view>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
#include "Common/VariantUtil.h"
|
||||||
#include "VideoCommon/Assets/CustomAssetLibrary.h"
|
#include "VideoCommon/Assets/CustomAssetLibrary.h"
|
||||||
|
|
||||||
namespace VideoCommon
|
namespace VideoCommon
|
||||||
{
|
{
|
||||||
static bool ParseShaderProperties(const CustomAssetLibrary::AssetID& asset_id,
|
template <typename ElementType, std::size_t ElementCount, typename PropertyType>
|
||||||
const picojson::array& properties_data,
|
bool ParseNumeric(const CustomAssetLibrary::AssetID& asset_id, const picojson::value& json_value,
|
||||||
std::map<std::string, ShaderProperty>* shader_properties)
|
std::string_view code_name, PropertyType* value)
|
||||||
|
{
|
||||||
|
static_assert(ElementCount <= 4, "Numeric data expected to be four elements or less");
|
||||||
|
if constexpr (ElementCount == 1)
|
||||||
|
{
|
||||||
|
if (!json_value.is<double>())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO,
|
||||||
|
"Asset id '{}' shader has attribute '{}' where "
|
||||||
|
"a double was expected but not provided.",
|
||||||
|
asset_id, code_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = static_cast<ElementType>(json_value.get<double>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!json_value.is<picojson::array>())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO,
|
||||||
|
"Asset id '{}' shader has attribute '{}' where "
|
||||||
|
"an array was expected but not provided.",
|
||||||
|
asset_id, code_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto json_data = json_value.get<picojson::array>();
|
||||||
|
|
||||||
|
if (json_data.size() != ElementCount)
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO,
|
||||||
|
"Asset id '{}' shader has attribute '{}' with incorrect number "
|
||||||
|
"of elements, expected {}",
|
||||||
|
asset_id, code_name, ElementCount);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::all_of(json_data.begin(), json_data.end(),
|
||||||
|
[](const picojson::value& v) { return v.is<double>(); }))
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO,
|
||||||
|
"Asset id '{}' shader has attribute '{}' where "
|
||||||
|
"all elements are not of type double.",
|
||||||
|
asset_id, code_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<ElementType, ElementCount> data;
|
||||||
|
for (std::size_t i = 0; i < ElementCount; i++)
|
||||||
|
{
|
||||||
|
data[i] = static_cast<ElementType>(json_data[i].get<double>());
|
||||||
|
}
|
||||||
|
*value = std::move(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ParseShaderValue(const CustomAssetLibrary::AssetID& asset_id,
|
||||||
|
const picojson::value& json_value, std::string_view code_name,
|
||||||
|
std::string_view type, ShaderProperty::Value* value)
|
||||||
|
{
|
||||||
|
if (type == "int")
|
||||||
|
{
|
||||||
|
return ParseNumeric<s32, 1>(asset_id, json_value, code_name, value);
|
||||||
|
}
|
||||||
|
else if (type == "int2")
|
||||||
|
{
|
||||||
|
return ParseNumeric<s32, 2>(asset_id, json_value, code_name, value);
|
||||||
|
}
|
||||||
|
else if (type == "int3")
|
||||||
|
{
|
||||||
|
return ParseNumeric<s32, 3>(asset_id, json_value, code_name, value);
|
||||||
|
}
|
||||||
|
else if (type == "int4")
|
||||||
|
{
|
||||||
|
return ParseNumeric<s32, 4>(asset_id, json_value, code_name, value);
|
||||||
|
}
|
||||||
|
else if (type == "float")
|
||||||
|
{
|
||||||
|
return ParseNumeric<float, 1>(asset_id, json_value, code_name, value);
|
||||||
|
}
|
||||||
|
else if (type == "float2")
|
||||||
|
{
|
||||||
|
return ParseNumeric<float, 2>(asset_id, json_value, code_name, value);
|
||||||
|
}
|
||||||
|
else if (type == "float3")
|
||||||
|
{
|
||||||
|
return ParseNumeric<float, 3>(asset_id, json_value, code_name, value);
|
||||||
|
}
|
||||||
|
else if (type == "float4")
|
||||||
|
{
|
||||||
|
return ParseNumeric<float, 4>(asset_id, json_value, code_name, value);
|
||||||
|
}
|
||||||
|
else if (type == "rgb")
|
||||||
|
{
|
||||||
|
ShaderProperty::RGB rgb;
|
||||||
|
if (!ParseNumeric<float, 3>(asset_id, json_value, code_name, &rgb.value))
|
||||||
|
return false;
|
||||||
|
*value = std::move(rgb);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (type == "rgba")
|
||||||
|
{
|
||||||
|
ShaderProperty::RGBA rgba;
|
||||||
|
if (!ParseNumeric<float, 4>(asset_id, json_value, code_name, &rgba.value))
|
||||||
|
return false;
|
||||||
|
*value = std::move(rgba);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (type == "bool")
|
||||||
|
{
|
||||||
|
if (json_value.is<bool>())
|
||||||
|
{
|
||||||
|
*value = json_value.get<bool>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == "sampler2d")
|
||||||
|
{
|
||||||
|
if (json_value.is<std::string>())
|
||||||
|
{
|
||||||
|
ShaderProperty::Sampler2D sampler2d;
|
||||||
|
sampler2d.value = json_value.get<std::string>();
|
||||||
|
*value = std::move(sampler2d);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == "sampler2darray")
|
||||||
|
{
|
||||||
|
if (json_value.is<std::string>())
|
||||||
|
{
|
||||||
|
ShaderProperty::Sampler2DArray sampler2darray;
|
||||||
|
sampler2darray.value = json_value.get<std::string>();
|
||||||
|
*value = std::move(sampler2darray);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == "samplercube")
|
||||||
|
{
|
||||||
|
if (json_value.is<std::string>())
|
||||||
|
{
|
||||||
|
ShaderProperty::SamplerCube samplercube;
|
||||||
|
samplercube.value = json_value.get<std::string>();
|
||||||
|
*value = std::move(samplercube);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse the json, value is not valid for type '{}'",
|
||||||
|
asset_id, type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ParseShaderProperties(const VideoCommon::CustomAssetLibrary::AssetID& asset_id,
|
||||||
|
const picojson::array& properties_data,
|
||||||
|
std::map<std::string, VideoCommon::ShaderProperty>* shader_properties)
|
||||||
{
|
{
|
||||||
if (!shader_properties) [[unlikely]]
|
if (!shader_properties) [[unlikely]]
|
||||||
return false;
|
return false;
|
||||||
@ -50,41 +207,6 @@ static bool ParseShaderProperties(const CustomAssetLibrary::AssetID& asset_id,
|
|||||||
std::string type = type_iter->second.to_str();
|
std::string type = type_iter->second.to_str();
|
||||||
Common::ToLower(&type);
|
Common::ToLower(&type);
|
||||||
|
|
||||||
static constexpr std::array<std::pair<std::string_view, ShaderProperty::Type>,
|
|
||||||
static_cast<int>(ShaderProperty::Type::Type_Max)>
|
|
||||||
pairs = {{
|
|
||||||
{"sampler2d", ShaderProperty::Type::Type_Sampler2D},
|
|
||||||
{"samplercube", ShaderProperty::Type::Type_SamplerCube},
|
|
||||||
{"samplerarrayshared_main", ShaderProperty::Type::Type_SamplerArrayShared_Main},
|
|
||||||
{"samplerarrayshared_additional",
|
|
||||||
ShaderProperty::Type::Type_SamplerArrayShared_Additional},
|
|
||||||
{"int", ShaderProperty::Type::Type_Int},
|
|
||||||
{"int2", ShaderProperty::Type::Type_Int2},
|
|
||||||
{"int3", ShaderProperty::Type::Type_Int3},
|
|
||||||
{"int4", ShaderProperty::Type::Type_Int4},
|
|
||||||
{"float", ShaderProperty::Type::Type_Float},
|
|
||||||
{"float2", ShaderProperty::Type::Type_Float2},
|
|
||||||
{"float3", ShaderProperty::Type::Type_Float3},
|
|
||||||
{"float4", ShaderProperty::Type::Type_Float4},
|
|
||||||
{"rgb", ShaderProperty::Type::Type_RGB},
|
|
||||||
{"rgba", ShaderProperty::Type::Type_RGBA},
|
|
||||||
{"bool", ShaderProperty::Type::Type_Bool},
|
|
||||||
}};
|
|
||||||
if (const auto it = std::find_if(pairs.begin(), pairs.end(),
|
|
||||||
[&](const auto& pair) { return pair.first == type; });
|
|
||||||
it != pairs.end())
|
|
||||||
{
|
|
||||||
property.m_type = it->second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(VIDEO,
|
|
||||||
"Asset '{}' failed to parse json, property entry type '{}' is "
|
|
||||||
"an invalid option",
|
|
||||||
asset_id, type_iter->second.to_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto description_iter = property_data_obj.find("description");
|
const auto description_iter = property_data_obj.find("description");
|
||||||
if (description_iter == property_data_obj.end())
|
if (description_iter == property_data_obj.end())
|
||||||
{
|
{
|
||||||
@ -118,7 +240,18 @@ static bool ParseShaderProperties(const CustomAssetLibrary::AssetID& asset_id,
|
|||||||
asset_id);
|
asset_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
shader_properties->try_emplace(code_name_iter->second.to_str(), std::move(property));
|
std::string code_name = code_name_iter->second.to_str();
|
||||||
|
|
||||||
|
const auto default_iter = property_data_obj.find("default");
|
||||||
|
if (default_iter != property_data_obj.end())
|
||||||
|
{
|
||||||
|
if (!ParseShaderValue(asset_id, default_iter->second, code_name, type, &property.m_default))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shader_properties->try_emplace(std::move(code_name), std::move(property));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -3,45 +3,49 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
#include <picojson.h>
|
#include <picojson.h>
|
||||||
|
|
||||||
#include "Common/EnumFormatter.h"
|
|
||||||
#include "VideoCommon/Assets/CustomAsset.h"
|
#include "VideoCommon/Assets/CustomAsset.h"
|
||||||
|
|
||||||
namespace VideoCommon
|
namespace VideoCommon
|
||||||
{
|
{
|
||||||
struct ShaderProperty
|
struct ShaderProperty
|
||||||
{
|
{
|
||||||
// "SamplerShared" denotes that the sampler
|
struct RGB
|
||||||
// already exists outside of the shader source
|
|
||||||
// (ex: in the Dolphin defined pixel shader)
|
|
||||||
// "Main" is the first entry in a shared sampler array
|
|
||||||
// and "Additional" denotes a subsequent entry
|
|
||||||
// in the array
|
|
||||||
enum class Type
|
|
||||||
{
|
{
|
||||||
Type_Undefined,
|
std::array<float, 3> value;
|
||||||
Type_SamplerArrayShared_Main,
|
|
||||||
Type_SamplerArrayShared_Additional,
|
|
||||||
Type_Sampler2D,
|
|
||||||
Type_SamplerCube,
|
|
||||||
Type_Int,
|
|
||||||
Type_Int2,
|
|
||||||
Type_Int3,
|
|
||||||
Type_Int4,
|
|
||||||
Type_Float,
|
|
||||||
Type_Float2,
|
|
||||||
Type_Float3,
|
|
||||||
Type_Float4,
|
|
||||||
Type_RGB,
|
|
||||||
Type_RGBA,
|
|
||||||
Type_Bool,
|
|
||||||
Type_Max = Type_Bool
|
|
||||||
};
|
};
|
||||||
Type m_type;
|
|
||||||
|
struct RGBA
|
||||||
|
{
|
||||||
|
std::array<float, 4> value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sampler2D
|
||||||
|
{
|
||||||
|
CustomAssetLibrary::AssetID value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sampler2DArray
|
||||||
|
{
|
||||||
|
CustomAssetLibrary::AssetID value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SamplerCube
|
||||||
|
{
|
||||||
|
CustomAssetLibrary::AssetID value;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Value = std::variant<s32, std::array<s32, 2>, std::array<s32, 3>, std::array<s32, 4>, float,
|
||||||
|
std::array<float, 2>, std::array<float, 3>, std::array<float, 4>, bool,
|
||||||
|
RGB, RGBA, Sampler2D, Sampler2DArray, SamplerCube>;
|
||||||
|
|
||||||
|
Value m_default;
|
||||||
std::string m_description;
|
std::string m_description;
|
||||||
};
|
};
|
||||||
struct PixelShaderData
|
struct PixelShaderData
|
||||||
@ -66,15 +70,3 @@ private:
|
|||||||
CustomAssetLibrary::LoadInfo LoadImpl(const CustomAssetLibrary::AssetID& asset_id) override;
|
CustomAssetLibrary::LoadInfo LoadImpl(const CustomAssetLibrary::AssetID& asset_id) override;
|
||||||
};
|
};
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
|
||||||
template <>
|
|
||||||
struct fmt::formatter<VideoCommon::ShaderProperty::Type>
|
|
||||||
: EnumFormatter<VideoCommon::ShaderProperty::Type::Type_Max>
|
|
||||||
{
|
|
||||||
constexpr formatter()
|
|
||||||
: EnumFormatter({"Undefined", "DolphinSamplerArray_Main", "DolphinSamplerArray_Additional",
|
|
||||||
"2DSampler", "CubeSampler", "Int", "Int2", "Int3", "Int4", "Float", "Float2",
|
|
||||||
"Float3", "Float4", "RGB", "RGBA", "Bool"})
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
Reference in New Issue
Block a user