summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authoriwubcode <iwubcode@users.noreply.github.com>2023-12-09 16:24:05 -0600
committeriwubcode <iwubcode@users.noreply.github.com>2023-12-12 00:01:22 -0600
commitb69d336838c7b6faa2c2a75ca5e6a0da0eccdf6f (patch)
treec34b7c28bae0504c22bf7c4d8dd1eeeeb65b23f4 /Source/Core/VideoCommon
parent2c6bf2d224f5f3732d53244de53be266bbec2ac3 (diff)
VideoCommon: update shader asset to provide a variant default value
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/Assets/ShaderAsset.cpp215
-rw-r--r--Source/Core/VideoCommon/Assets/ShaderAsset.h68
2 files changed, 204 insertions, 79 deletions
diff --git a/Source/Core/VideoCommon/Assets/ShaderAsset.cpp b/Source/Core/VideoCommon/Assets/ShaderAsset.cpp
index 9a31421334..02f2d45a38 100644
--- a/Source/Core/VideoCommon/Assets/ShaderAsset.cpp
+++ b/Source/Core/VideoCommon/Assets/ShaderAsset.cpp
@@ -4,19 +4,176 @@
#include "VideoCommon/Assets/ShaderAsset.h"
#include <algorithm>
-#include <array>
-#include <string_view>
#include <utility>
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
+#include "Common/VariantUtil.h"
#include "VideoCommon/Assets/CustomAssetLibrary.h"
namespace VideoCommon
{
-static bool ParseShaderProperties(const CustomAssetLibrary::AssetID& asset_id,
- const picojson::array& properties_data,
- std::map<std::string, ShaderProperty>* shader_properties)
+template <typename ElementType, std::size_t ElementCount, typename PropertyType>
+bool ParseNumeric(const CustomAssetLibrary::AssetID& asset_id, const picojson::value& json_value,
+ 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]]
return false;
@@ -50,41 +207,6 @@ static bool ParseShaderProperties(const CustomAssetLibrary::AssetID& asset_id,
std::string type = type_iter->second.to_str();
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");
if (description_iter == property_data_obj.end())
{
@@ -118,7 +240,18 @@ static bool ParseShaderProperties(const CustomAssetLibrary::AssetID& asset_id,
asset_id);
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;
diff --git a/Source/Core/VideoCommon/Assets/ShaderAsset.h b/Source/Core/VideoCommon/Assets/ShaderAsset.h
index 4030cd96ce..0cc4255596 100644
--- a/Source/Core/VideoCommon/Assets/ShaderAsset.h
+++ b/Source/Core/VideoCommon/Assets/ShaderAsset.h
@@ -3,45 +3,49 @@
#pragma once
+#include <array>
#include <map>
#include <string>
+#include <variant>
#include <picojson.h>
-#include "Common/EnumFormatter.h"
#include "VideoCommon/Assets/CustomAsset.h"
namespace VideoCommon
{
struct ShaderProperty
{
- // "SamplerShared" denotes that the sampler
- // 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
+ struct RGB
{
- Type_Undefined,
- 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
+ std::array<float, 3> value;
};
- 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;
};
struct PixelShaderData
@@ -66,15 +70,3 @@ private:
CustomAssetLibrary::LoadInfo LoadImpl(const CustomAssetLibrary::AssetID& asset_id) override;
};
} // 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"})
- {
- }
-};