mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-10-24 17:09:06 +00:00
Merge pull request #13895 from iwubcode/update_shader_asset
VideoCommon: update shader asset to support additional features in custom pipelines
This commit is contained in:
commit
a8a6cfebc7
6 changed files with 252 additions and 166 deletions
|
|
@ -3,9 +3,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace VideoCommon
|
namespace VideoCommon
|
||||||
|
|
@ -13,7 +10,7 @@ namespace VideoCommon
|
||||||
class CustomTextureData;
|
class CustomTextureData;
|
||||||
struct MaterialData;
|
struct MaterialData;
|
||||||
struct MeshData;
|
struct MeshData;
|
||||||
struct PixelShaderData;
|
struct RasterSurfaceShaderData;
|
||||||
struct TextureAndSamplerData;
|
struct TextureAndSamplerData;
|
||||||
|
|
||||||
// This class provides functionality to load
|
// This class provides functionality to load
|
||||||
|
|
@ -38,8 +35,9 @@ public:
|
||||||
// Loads a texture, if there are no levels, bytes loaded will be empty
|
// Loads a texture, if there are no levels, bytes loaded will be empty
|
||||||
virtual LoadInfo LoadTexture(const AssetID& asset_id, CustomTextureData* data) = 0;
|
virtual LoadInfo LoadTexture(const AssetID& asset_id, CustomTextureData* data) = 0;
|
||||||
|
|
||||||
// Loads a pixel shader
|
// Loads a raster surface shader
|
||||||
virtual LoadInfo LoadPixelShader(const AssetID& asset_id, PixelShaderData* data) = 0;
|
virtual LoadInfo LoadRasterSurfaceShader(const AssetID& asset_id,
|
||||||
|
RasterSurfaceShaderData* data) = 0;
|
||||||
|
|
||||||
// Loads a material
|
// Loads a material
|
||||||
virtual LoadInfo LoadMaterial(const AssetID& asset_id, MaterialData* data) = 0;
|
virtual LoadInfo LoadMaterial(const AssetID& asset_id, MaterialData* data) = 0;
|
||||||
|
|
|
||||||
|
|
@ -40,29 +40,37 @@ std::size_t GetAssetSize(const CustomTextureData& data)
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadPixelShader(const AssetID& asset_id,
|
CustomAssetLibrary::LoadInfo
|
||||||
PixelShaderData* data)
|
DirectFilesystemAssetLibrary::LoadRasterSurfaceShader(const AssetID& asset_id,
|
||||||
|
RasterSurfaceShaderData* data)
|
||||||
{
|
{
|
||||||
const auto asset_map = GetAssetMapForID(asset_id);
|
const auto asset_map = GetAssetMapForID(asset_id);
|
||||||
|
|
||||||
// Asset map for a pixel shader is the shader and some metadata
|
// Asset map for a pixel shader is the shader and some metadata
|
||||||
if (asset_map.size() != 2)
|
if (asset_map.size() != 3)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have two files mapped!", asset_id);
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have three files mapped!", asset_id);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto metadata = asset_map.find("metadata");
|
const auto metadata = asset_map.find("metadata");
|
||||||
const auto shader = asset_map.find("shader");
|
|
||||||
if (metadata == asset_map.end())
|
if (metadata == asset_map.end())
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have a metadata entry mapped!", asset_id);
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have a metadata entry mapped!", asset_id);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader == asset_map.end())
|
const auto vertex_shader = asset_map.find("vertex_shader");
|
||||||
|
if (vertex_shader == asset_map.end())
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have a shader entry mapped!", asset_id);
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have a vertex shader entry mapped!", asset_id);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto pixel_shader = asset_map.find("pixel_shader");
|
||||||
|
if (pixel_shader == asset_map.end())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' expected to have a pixel shader entry mapped!", asset_id);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,24 +86,43 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadPixelShader(const
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::size_t shader_size;
|
std::size_t vertex_shader_size;
|
||||||
{
|
{
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
shader_size = std::filesystem::file_size(shader->second, ec);
|
vertex_shader_size = std::filesystem::file_size(vertex_shader->second, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(VIDEO,
|
ERROR_LOG_FMT(
|
||||||
"Asset '{}' error - failed to get shader source file size with error '{}'!",
|
VIDEO, "Asset '{}' error - failed to get vertex shader source file size with error '{}'!",
|
||||||
asset_id, ec);
|
asset_id, ec);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto approx_mem_size = metadata_size + shader_size;
|
std::size_t pixel_shader_size;
|
||||||
|
|
||||||
if (!File::ReadFileToString(PathToString(shader->second), data->m_shader_source))
|
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the shader file '{}',", asset_id,
|
std::error_code ec;
|
||||||
PathToString(shader->second));
|
pixel_shader_size = std::filesystem::file_size(pixel_shader->second, ec);
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(
|
||||||
|
VIDEO, "Asset '{}' error - failed to get pixel shader source file size with error '{}'!",
|
||||||
|
asset_id, ec);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto approx_mem_size = metadata_size + vertex_shader_size + pixel_shader_size;
|
||||||
|
|
||||||
|
if (!File::ReadFileToString(PathToString(vertex_shader->second), data->vertex_source))
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the vertex shader file '{}',",
|
||||||
|
asset_id, PathToString(vertex_shader->second));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File::ReadFileToString(PathToString(pixel_shader->second), data->pixel_source))
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' error - failed to load the pixel shader file '{}',", asset_id,
|
||||||
|
PathToString(pixel_shader->second));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,7 +147,7 @@ CustomAssetLibrary::LoadInfo DirectFilesystemAssetLibrary::LoadPixelShader(const
|
||||||
|
|
||||||
const auto& root_obj = root.get<picojson::object>();
|
const auto& root_obj = root.get<picojson::object>();
|
||||||
|
|
||||||
if (!PixelShaderData::FromJson(asset_id, root_obj, data))
|
if (!RasterSurfaceShaderData::FromJson(asset_id, root_obj, data))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return LoadInfo{approx_mem_size};
|
return LoadInfo{approx_mem_size};
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class DirectFilesystemAssetLibrary final : public WatchableFilesystemAssetLibrar
|
||||||
public:
|
public:
|
||||||
LoadInfo LoadTexture(const AssetID& asset_id, TextureAndSamplerData* data) override;
|
LoadInfo LoadTexture(const AssetID& asset_id, TextureAndSamplerData* data) override;
|
||||||
LoadInfo LoadTexture(const AssetID& asset_id, CustomTextureData* data) override;
|
LoadInfo LoadTexture(const AssetID& asset_id, CustomTextureData* data) override;
|
||||||
LoadInfo LoadPixelShader(const AssetID& asset_id, PixelShaderData* data) override;
|
LoadInfo LoadRasterSurfaceShader(const AssetID& asset_id, RasterSurfaceShaderData* data) override;
|
||||||
LoadInfo LoadMaterial(const AssetID& asset_id, MaterialData* data) override;
|
LoadInfo LoadMaterial(const AssetID& asset_id, MaterialData* data) override;
|
||||||
LoadInfo LoadMesh(const AssetID& asset_id, MeshData* data) override;
|
LoadInfo LoadMesh(const AssetID& asset_id, MeshData* data) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/VariantUtil.h"
|
#include "Common/VariantUtil.h"
|
||||||
#include "VideoCommon/Assets/CustomAssetLibrary.h"
|
#include "VideoCommon/Assets/CustomAssetLibrary.h"
|
||||||
|
#include "VideoCommon/ShaderGenCommon.h"
|
||||||
|
|
||||||
namespace VideoCommon
|
namespace VideoCommon
|
||||||
{
|
{
|
||||||
|
|
@ -134,36 +135,6 @@ static bool ParseShaderValue(const CustomAssetLibrary::AssetID& asset_id,
|
||||||
return true;
|
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 '{}'",
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse the json, value is not valid for type '{}'",
|
||||||
asset_id, type);
|
asset_id, type);
|
||||||
|
|
@ -223,7 +194,7 @@ ParseShaderProperties(const VideoCommon::CustomAssetLibrary::AssetID& asset_id,
|
||||||
asset_id);
|
asset_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
property.m_description = description_iter->second.to_str();
|
property.description = description_iter->second.to_str();
|
||||||
|
|
||||||
const auto code_name_iter = property_data_obj.find("code_name");
|
const auto code_name_iter = property_data_obj.find("code_name");
|
||||||
if (code_name_iter == property_data_obj.end())
|
if (code_name_iter == property_data_obj.end())
|
||||||
|
|
@ -245,11 +216,16 @@ ParseShaderProperties(const VideoCommon::CustomAssetLibrary::AssetID& asset_id,
|
||||||
const auto default_iter = property_data_obj.find("default");
|
const auto default_iter = property_data_obj.find("default");
|
||||||
if (default_iter != property_data_obj.end())
|
if (default_iter != property_data_obj.end())
|
||||||
{
|
{
|
||||||
if (!ParseShaderValue(asset_id, default_iter->second, code_name, type, &property.m_default))
|
if (!ParseShaderValue(asset_id, default_iter->second, code_name, type,
|
||||||
|
&property.default_value))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
property.default_value = ShaderProperty::GetDefaultValueFromTypeName(type);
|
||||||
|
}
|
||||||
|
|
||||||
shader_properties->try_emplace(std::move(code_name), std::move(property));
|
shader_properties->try_emplace(std::move(code_name), std::move(property));
|
||||||
}
|
}
|
||||||
|
|
@ -257,63 +233,124 @@ ParseShaderProperties(const VideoCommon::CustomAssetLibrary::AssetID& asset_id,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PixelShaderData::FromJson(const VideoCommon::CustomAssetLibrary::AssetID& asset_id,
|
bool RasterSurfaceShaderData::FromJson(const VideoCommon::CustomAssetLibrary::AssetID& asset_id,
|
||||||
const picojson::object& json, PixelShaderData* data)
|
const picojson::object& json, RasterSurfaceShaderData* data)
|
||||||
{
|
{
|
||||||
const auto properties_iter = json.find("properties");
|
const auto parse_properties = [&](const char* name, std::string_view source,
|
||||||
if (properties_iter == json.end())
|
std::map<std::string, ShaderProperty>* properties) -> bool {
|
||||||
{
|
const auto properties_iter = json.find(name);
|
||||||
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, 'properties' not found", asset_id);
|
if (properties_iter == json.end())
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!properties_iter->second.is<picojson::array>())
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, 'properties' is not the right json type",
|
|
||||||
asset_id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const auto& properties_array = properties_iter->second.get<picojson::array>();
|
|
||||||
if (!ParseShaderProperties(asset_id, properties_array, &data->m_properties))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (const auto& [name, property] : data->m_properties)
|
|
||||||
{
|
|
||||||
if (data->m_shader_source.find(name) == std::string::npos)
|
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, '{}' not found", asset_id, name);
|
||||||
VIDEO,
|
|
||||||
"Asset '{}' failed to parse json, the code name '{}' defined in the metadata was not "
|
|
||||||
"found in the shader source",
|
|
||||||
asset_id, name);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
if (!properties_iter->second.is<picojson::array>())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, '{}' is not the right json type",
|
||||||
|
asset_id, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto& properties_array = properties_iter->second.get<picojson::array>();
|
||||||
|
|
||||||
|
if (!ParseShaderProperties(asset_id, properties_array, properties))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const auto& [code_name, property] : *properties)
|
||||||
|
{
|
||||||
|
if (source.find(code_name) == std::string::npos)
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(
|
||||||
|
VIDEO,
|
||||||
|
"Asset '{}' failed to parse json, the code name '{}' defined in the metadata was not "
|
||||||
|
"found in the source for '{}'",
|
||||||
|
asset_id, code_name, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto parse_samplers =
|
||||||
|
[&](const char* name,
|
||||||
|
std::vector<VideoCommon::RasterSurfaceShaderData::SamplerData>* samplers) -> bool {
|
||||||
|
const auto samplers_iter = json.find(name);
|
||||||
|
if (samplers_iter == json.end())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, '{}' not found", asset_id, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!samplers_iter->second.is<picojson::array>())
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, '{}' is not the right json type",
|
||||||
|
asset_id, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto& samplers_array = samplers_iter->second.get<picojson::array>();
|
||||||
|
if (!std::ranges::all_of(samplers_array, [](const picojson::value& json_data) {
|
||||||
|
return json_data.is<picojson::object>();
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO, "Asset '{}' failed to parse json, '{}' must contain objects", asset_id,
|
||||||
|
name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& sampler_json : samplers_array)
|
||||||
|
{
|
||||||
|
auto& sampler_json_obj = sampler_json.get<picojson::object>();
|
||||||
|
|
||||||
|
SamplerData sampler;
|
||||||
|
|
||||||
|
if (const auto sampler_name = ReadStringFromJson(sampler_json_obj, "name"))
|
||||||
|
{
|
||||||
|
sampler.name = *sampler_name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO,
|
||||||
|
"Asset '{}' failed to parse sampler json, 'name' not found or wrong type",
|
||||||
|
asset_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto sampler_type =
|
||||||
|
ReadNumericFromJson<AbstractTextureType>(sampler_json_obj, "type"))
|
||||||
|
{
|
||||||
|
sampler.type = *sampler_type;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERROR_LOG_FMT(VIDEO,
|
||||||
|
"Asset '{}' failed to parse sampler json, 'type' not found or wrong type",
|
||||||
|
asset_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
samplers->push_back(std::move(sampler));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!parse_properties("properties", data->pixel_source, &data->uniform_properties))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!parse_samplers("samplers", &data->samplers))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelShaderData::ToJson(picojson::object& obj, const PixelShaderData& data)
|
void RasterSurfaceShaderData::ToJson(picojson::object& obj, const RasterSurfaceShaderData& data)
|
||||||
{
|
{
|
||||||
picojson::array json_properties;
|
const auto add_property = [](picojson::array* json_properties, const std::string& name,
|
||||||
for (const auto& [name, property] : data.m_properties)
|
const ShaderProperty& property) {
|
||||||
{
|
|
||||||
picojson::object json_property;
|
picojson::object json_property;
|
||||||
json_property.emplace("code_name", name);
|
|
||||||
json_property.emplace("description", property.m_description);
|
|
||||||
|
|
||||||
std::visit(overloaded{[&](const ShaderProperty::Sampler2D& default_value) {
|
json_property.emplace("code_name", name);
|
||||||
json_property.emplace("type", "sampler2d");
|
json_property.emplace("description", property.description);
|
||||||
json_property.emplace("default", default_value.value);
|
|
||||||
},
|
std::visit(overloaded{[&](s32 default_value) {
|
||||||
[&](const ShaderProperty::Sampler2DArray& default_value) {
|
|
||||||
json_property.emplace("type", "sampler2darray");
|
|
||||||
json_property.emplace("default", default_value.value);
|
|
||||||
},
|
|
||||||
[&](const ShaderProperty::SamplerCube& default_value) {
|
|
||||||
json_property.emplace("type", "samplercube");
|
|
||||||
json_property.emplace("default", default_value.value);
|
|
||||||
},
|
|
||||||
[&](s32 default_value) {
|
|
||||||
json_property.emplace("type", "int");
|
json_property.emplace("type", "int");
|
||||||
json_property.emplace("default", static_cast<double>(default_value));
|
json_property.emplace("default", static_cast<double>(default_value));
|
||||||
},
|
},
|
||||||
|
|
@ -357,37 +394,43 @@ void PixelShaderData::ToJson(picojson::object& obj, const PixelShaderData& data)
|
||||||
json_property.emplace("type", "bool");
|
json_property.emplace("type", "bool");
|
||||||
json_property.emplace("default", default_value);
|
json_property.emplace("default", default_value);
|
||||||
}},
|
}},
|
||||||
property.m_default);
|
property.default_value);
|
||||||
|
|
||||||
json_properties.emplace_back(std::move(json_property));
|
json_properties->emplace_back(std::move(json_property));
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto add_sampler = [](picojson::array* json_samplers, const SamplerData& sampler) {
|
||||||
|
picojson::object json_sampler;
|
||||||
|
json_sampler.emplace("name", sampler.name);
|
||||||
|
json_sampler.emplace("type", static_cast<double>(sampler.type));
|
||||||
|
json_samplers->emplace_back(std::move(json_sampler));
|
||||||
|
};
|
||||||
|
|
||||||
|
picojson::array json_properties;
|
||||||
|
for (const auto& [name, property] : data.uniform_properties)
|
||||||
|
{
|
||||||
|
add_property(&json_properties, name, property);
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.emplace("properties", std::move(json_properties));
|
obj.emplace("properties", std::move(json_properties));
|
||||||
|
|
||||||
|
picojson::array json_samplers;
|
||||||
|
for (const auto& sampler : data.samplers)
|
||||||
|
{
|
||||||
|
add_sampler(&json_samplers, sampler);
|
||||||
|
}
|
||||||
|
obj.emplace("samplers", json_samplers);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::span<const std::string_view> ShaderProperty::GetValueTypeNames()
|
std::span<const std::string_view> ShaderProperty::GetValueTypeNames()
|
||||||
{
|
{
|
||||||
static constexpr std::array<std::string_view, 14> values = {
|
static constexpr std::array<std::string_view, 11> values = {
|
||||||
"sampler2d", "sampler2darray", "samplercube", "int", "int2", "int3", "int4",
|
"int", "int2", "int3", "int4", "float", "float2", "float3", "float4", "rgb", "rgba", "bool"};
|
||||||
"float", "float2", "float3", "float4", "rgb", "rgba", "bool"};
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderProperty::Value ShaderProperty::GetDefaultValueFromTypeName(std::string_view name)
|
ShaderProperty::Value ShaderProperty::GetDefaultValueFromTypeName(std::string_view name)
|
||||||
{
|
{
|
||||||
if (name == "sampler2d")
|
if (name == "int")
|
||||||
{
|
|
||||||
return Sampler2D{};
|
|
||||||
}
|
|
||||||
else if (name == "sampler2darray")
|
|
||||||
{
|
|
||||||
return Sampler2DArray{};
|
|
||||||
}
|
|
||||||
else if (name == "samplercube")
|
|
||||||
{
|
|
||||||
return SamplerCube{};
|
|
||||||
}
|
|
||||||
else if (name == "int")
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -435,10 +478,44 @@ ShaderProperty::Value ShaderProperty::GetDefaultValueFromTypeName(std::string_vi
|
||||||
return Value{};
|
return Value{};
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomAssetLibrary::LoadInfo PixelShaderAsset::LoadImpl(const CustomAssetLibrary::AssetID& asset_id)
|
void ShaderProperty::WriteAsShaderCode(ShaderCode& shader_source, std::string_view name,
|
||||||
|
const ShaderProperty& property)
|
||||||
{
|
{
|
||||||
auto potential_data = std::make_shared<PixelShaderData>();
|
const auto write_shader = [&](std::string_view type, u32 element_count) {
|
||||||
const auto loaded_info = m_owning_library->LoadPixelShader(asset_id, potential_data.get());
|
if (element_count == 1)
|
||||||
|
{
|
||||||
|
shader_source.Write("{} {};\n", type, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shader_source.Write("{}{} {};\n", type, element_count, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = element_count; i < 4; i++)
|
||||||
|
{
|
||||||
|
shader_source.Write("{} {}_padding_{};\n", type, name, i + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::visit(overloaded{[&](s32) { write_shader("int", 1); },
|
||||||
|
[&](const std::array<s32, 2>&) { write_shader("int", 2); },
|
||||||
|
[&](const std::array<s32, 3>&) { write_shader("int", 3); },
|
||||||
|
[&](const std::array<s32, 4>&) { write_shader("int", 4); },
|
||||||
|
[&](float) { write_shader("float", 1); },
|
||||||
|
[&](const std::array<float, 2>&) { write_shader("float", 2); },
|
||||||
|
[&](const std::array<float, 3>&) { write_shader("float", 3); },
|
||||||
|
[&](const std::array<float, 4>&) { write_shader("float", 4); },
|
||||||
|
[&](const ShaderProperty::RGB&) { write_shader("float", 3); },
|
||||||
|
[&](const ShaderProperty::RGBA&) { write_shader("float", 4); },
|
||||||
|
[&](bool) { write_shader("bool", 1); }},
|
||||||
|
property.default_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomAssetLibrary::LoadInfo
|
||||||
|
RasterSurfaceShaderAsset::LoadImpl(const CustomAssetLibrary::AssetID& asset_id)
|
||||||
|
{
|
||||||
|
auto potential_data = std::make_shared<RasterSurfaceShaderData>();
|
||||||
|
const auto loaded_info =
|
||||||
|
m_owning_library->LoadRasterSurfaceShader(asset_id, potential_data.get());
|
||||||
if (loaded_info.bytes_loaded == 0)
|
if (loaded_info.bytes_loaded == 0)
|
||||||
return {};
|
return {};
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@
|
||||||
#include <picojson.h>
|
#include <picojson.h>
|
||||||
|
|
||||||
#include "VideoCommon/Assets/CustomAsset.h"
|
#include "VideoCommon/Assets/CustomAsset.h"
|
||||||
|
#include "VideoCommon/TextureConfig.h"
|
||||||
|
|
||||||
|
class ShaderCode;
|
||||||
|
|
||||||
namespace VideoCommon
|
namespace VideoCommon
|
||||||
{
|
{
|
||||||
|
|
@ -28,45 +31,43 @@ struct ShaderProperty
|
||||||
std::array<float, 4> value;
|
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,
|
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,
|
std::array<float, 2>, std::array<float, 3>, std::array<float, 4>, bool,
|
||||||
RGB, RGBA, Sampler2D, Sampler2DArray, SamplerCube>;
|
RGB, RGBA>;
|
||||||
static std::span<const std::string_view> GetValueTypeNames();
|
static std::span<const std::string_view> GetValueTypeNames();
|
||||||
static Value GetDefaultValueFromTypeName(std::string_view name);
|
static Value GetDefaultValueFromTypeName(std::string_view name);
|
||||||
|
static void WriteAsShaderCode(ShaderCode& shader_source, std::string_view name,
|
||||||
|
const ShaderProperty& property);
|
||||||
|
|
||||||
Value m_default;
|
Value default_value;
|
||||||
std::string m_description;
|
std::string description;
|
||||||
};
|
};
|
||||||
struct PixelShaderData
|
|
||||||
|
struct RasterSurfaceShaderData
|
||||||
{
|
{
|
||||||
static bool FromJson(const CustomAssetLibrary::AssetID& asset_id, const picojson::object& json,
|
static bool FromJson(const CustomAssetLibrary::AssetID& asset_id, const picojson::object& json,
|
||||||
PixelShaderData* data);
|
RasterSurfaceShaderData* data);
|
||||||
static void ToJson(picojson::object& obj, const PixelShaderData& data);
|
static void ToJson(picojson::object& obj, const RasterSurfaceShaderData& data);
|
||||||
|
|
||||||
// These shader properties describe the input that the
|
// These shader properties describe the input that the
|
||||||
// shader expects to expose. The key is text
|
// shader expects to expose. The key is text
|
||||||
// expected to be in the shader code and the propery
|
// expected to be in the shader code and the propery
|
||||||
// describes various details about the input
|
// describes various details about the input
|
||||||
std::map<std::string, ShaderProperty> m_properties;
|
std::map<std::string, ShaderProperty> uniform_properties;
|
||||||
std::string m_shader_source;
|
std::string vertex_source;
|
||||||
|
std::string pixel_source;
|
||||||
|
|
||||||
|
struct SamplerData
|
||||||
|
{
|
||||||
|
AbstractTextureType type;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
bool operator==(const SamplerData&) const = default;
|
||||||
|
};
|
||||||
|
std::vector<SamplerData> samplers;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PixelShaderAsset final : public CustomLoadableAsset<PixelShaderData>
|
class RasterSurfaceShaderAsset final : public CustomLoadableAsset<RasterSurfaceShaderData>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using CustomLoadableAsset::CustomLoadableAsset;
|
using CustomLoadableAsset::CustomLoadableAsset;
|
||||||
|
|
|
||||||
|
|
@ -22,21 +22,4 @@ struct CustomPipeline
|
||||||
void UpdatePixelData(std::shared_ptr<VideoCommon::CustomAssetLibrary> library,
|
void UpdatePixelData(std::shared_ptr<VideoCommon::CustomAssetLibrary> library,
|
||||||
std::span<const u32> texture_units,
|
std::span<const u32> texture_units,
|
||||||
const VideoCommon::CustomAssetLibrary::AssetID& material_to_load);
|
const VideoCommon::CustomAssetLibrary::AssetID& material_to_load);
|
||||||
|
|
||||||
VideoCommon::CachedAsset<VideoCommon::MaterialAsset> m_pixel_material;
|
|
||||||
VideoCommon::CachedAsset<VideoCommon::PixelShaderAsset> m_pixel_shader;
|
|
||||||
|
|
||||||
struct CachedTextureAsset
|
|
||||||
{
|
|
||||||
VideoCommon::CachedAsset<VideoCommon::TextureAsset> m_cached_asset;
|
|
||||||
std::unique_ptr<AbstractTexture> m_texture;
|
|
||||||
std::string m_sampler_code;
|
|
||||||
std::string m_define_code;
|
|
||||||
};
|
|
||||||
std::vector<std::optional<CachedTextureAsset>> m_game_textures;
|
|
||||||
|
|
||||||
ShaderCode m_last_generated_shader_code;
|
|
||||||
ShaderCode m_last_generated_material_code;
|
|
||||||
|
|
||||||
std::vector<u8> m_material_data;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue