载入中...
搜索中...
未找到
EvpackShader.cpp
浏览该文件的文档.
2#include <algorithm>
3#include <cmath>
4#include <cstdio>
5#include <glm/gtc/type_ptr.hpp>
7#include "asset/ShaderAsset.h"
9#include "graphics/Graphics.h"
10#include "graphics/Shader.h"
11
12namespace eve::asset_graphics {
13namespace {
14template <std::size_t N>
15bool finite(const std::array<float, N>& values) {
16 return std::all_of(values.begin(), values.end(), [](float value) { return std::isfinite(value); });
17}
18} // namespace
24EvpackShader::EvpackShader(std::unique_ptr<Impl> impl) : impl_(std::move(impl)) {}
26 auto result = release();
27 if (!result) std::fprintf(stderr, "EvpackShader release failed: %s\n", result.error()->message().c_str());
28}
29const asset::ShaderAsset& EvpackShader::definition() const noexcept { return impl_->definition; }
31 const AssetRef& asset,
32 const asset::EvpackCapabilities& capabilities,
33 graphics::Graphics& graphics) {
34 if (graphics.getBackendName() != "vulkan" || capabilities.graphics != graphics.getBackendName())
36 Diagnostic::error(DiagnosticCode::Unsupported, "Shader backend mismatch", {}, {}, "asset.shader.runtime"));
37 auto decoded = asset::loadShaderAsset(reader, asset, capabilities);
38 if (!decoded) return Result<std::unique_ptr<EvpackShader>>::failure(decoded.status());
39 auto validated = validateShaderAssetGpu(decoded.value());
40 if (!validated) return Result<std::unique_ptr<EvpackShader>>::failure(validated.status());
41 auto result = std::unique_ptr<EvpackShader>(
42 new EvpackShader(std::make_unique<Impl>(Impl{graphics, std::move(decoded).takeValue()})));
43 try {
44 auto& impl = *result->impl_;
45 impl.shader = impl.definition.interface == asset::ShaderAssetInterface::Mesh3D
46 ? graphics.newMeshShaderFromSpv(impl.definition.vertex, impl.definition.fragment)
47 : graphics.newShaderFromSpv(impl.definition.vertex, impl.definition.fragment);
48 if (!impl.shader)
50 DiagnosticCode::Failed, "Shader upload returned no allocation", {}, {}, "asset.shader.runtime"));
51 for (const auto& parameter : impl.definition.parameters) {
52 switch (parameter.defaults.size()) {
53 case 1: impl.shader->declareFloat(parameter.name); break;
54 case 2: impl.shader->declareVec2(parameter.name); break;
55 case 3: impl.shader->declareVec3(parameter.name); break;
56 case 4: impl.shader->declareVec4(parameter.name); break;
57 default:
59 DiagnosticCode::InvalidArgument, "Invalid parameter width", {}, {}, "asset.shader.runtime"));
60 }
61 impl.shader->sendToVar(parameter.name, parameter.defaults.data(),
62 parameter.defaults.size() * sizeof(float));
63 }
64 // Initialize/upload the entire ABI block, including unused trailing slots.
65 unsigned padding = 0;
66 while (impl.shader->usedFloats() < graphics::Shader::kMaxFloats) {
67 const auto name = "__eve_padding_" + std::to_string(padding++);
68 if (!impl.shader->hasUniform(name)) impl.shader->declareFloat(name);
69 }
70 return Result<std::unique_ptr<EvpackShader>>::success(std::move(result));
71 } catch (const std::exception& error) {
73 Diagnostic::error(DiagnosticCode::Failed, error.what(), {}, {}, "asset.shader.runtime"));
74 }
75}
76Result<void> EvpackShader::setParameter(std::string_view name, std::span<const float> values) try {
77 if (!impl_->shader)
79 Diagnostic::error(DiagnosticCode::StaleHandle, "Shader lease is released", {}, {}, "asset.shader.runtime"));
80 const auto it = std::find_if(impl_->definition.parameters.begin(), impl_->definition.parameters.end(),
81 [&](const auto& parameter) { return parameter.name == name; });
82 if (it == impl_->definition.parameters.end() || it->defaults.size() != values.size() ||
83 !std::all_of(values.begin(), values.end(), [](float value) { return std::isfinite(value); }))
85 "Unknown parameter, wrong width or non-finite value", {}, {},
86 "asset.shader.runtime"));
87 impl_->shader->sendToVar(it->name, values.data(), values.size_bytes());
88 return Result<void>::success();
89} catch (const std::exception& error) {
91 Diagnostic::error(DiagnosticCode::Failed, error.what(), {}, {}, "asset.shader.runtime"));
92}
93Result<void> EvpackShader::drawMesh(graphics::Mesh& mesh, const std::array<float, 16>& transform,
94 OptionalRef<graphics::Texture> texture, const std::array<float, 4>& tint) try {
95 if (!impl_->shader)
97 Diagnostic::error(DiagnosticCode::StaleHandle, "Shader lease is released", {}, {}, "asset.shader.runtime"));
98 if (impl_->definition.interface != asset::ShaderAssetInterface::Mesh3D || !finite(transform) || !finite(tint))
100 DiagnosticCode::InvalidArgument, "Invalid mesh draw or shader kind", {}, {}, "asset.shader.runtime"));
101 impl_->graphics.drawMeshShader(&mesh, glm::make_mat4(transform.data()), texture ? &texture->get() : nullptr,
102 graphics::Color(tint[0], tint[1], tint[2], tint[3]), impl_->shader);
103 return Result<void>::success();
104} catch (const std::exception& error) {
106 Diagnostic::error(DiagnosticCode::Failed, error.what(), {}, {}, "asset.shader.runtime"));
107}
109 const std::array<float, 4>& tint) try {
110 if (!impl_->shader)
112 Diagnostic::error(DiagnosticCode::StaleHandle, "Shader lease is released", {}, {}, "asset.shader.runtime"));
113 if (impl_->definition.interface != asset::ShaderAssetInterface::Sprite2D || !finite(rect) || !finite(tint))
115 DiagnosticCode::InvalidArgument, "Invalid sprite draw or shader kind", {}, {}, "asset.shader.runtime"));
116 impl_->graphics.drawTexturedRectShader(texture ? &texture->get() : nullptr, impl_->shader, rect[0], rect[1],
117 rect[2], rect[3], graphics::Color(tint[0], tint[1], tint[2], tint[3]));
118 return Result<void>::success();
119} catch (const std::exception& error) {
121 Diagnostic::error(DiagnosticCode::Failed, error.what(), {}, {}, "asset.shader.runtime"));
122}
124 if (!impl_->shader) return Result<void>::success();
125 if (!impl_->graphics.releaseShader(impl_->shader))
126 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Failed, "Graphics rejected shader release", {},
127 {}, "asset.shader.runtime"));
128 delete impl_->shader; // releaseShader transfers the CPU facade back to the lease.
129 impl_->shader = nullptr;
130 return Result<void>::success();
131} catch (const std::exception& error) {
133 Diagnostic::error(DiagnosticCode::Failed, error.what(), {}, {}, "asset.shader.runtime"));
134}
135} // namespace eve::asset_graphics
double value
void * impl
std::map< std::string, Var > values
Typed capability-aware runtime access to admitted packs.
glm::vec4 tint
std::string name
bool finite
std::string error
Definition Package.cpp:60
Mesh * mesh
Stable asset identity backed by PersistentId.
Definition ResourceRef.h:53
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Immutable reader retaining an admitted pack by shared ownership.
Unique lease on a validated package shader and its independent parameter instance....
Result< void > drawMesh(graphics::Mesh &mesh, const std::array< float, 16 > &transform, OptionalRef< graphics::Texture > texture, const std::array< float, 4 > &tint)
Draw through the owning Graphics in an open 3D frame; all arguments are immediate borrowed inputs.
Result< void > setParameter(std::string_view name, std::span< const float > values)
Set one declared scalar/vector with exact finite component count; failure leaves it unchanged.
EvpackShader(const EvpackShader &)=delete
Result< void > release()
Release explicitly; failure retains the lease for retry. Destruction retries and reports errors.
const asset::ShaderAsset & definition() const noexcept
Immutable CPU metadata borrowed until this lease is destroyed.
Result< void > drawSprite(OptionalRef< graphics::Texture > texture, const std::array< float, 4 > &rect, const std::array< float, 4 > &tint)
Draw a sprite in the active canvas; rect is x/y/width/height in pixels.
static Result< std::unique_ptr< EvpackShader > > load(const asset::EvpackResourceReader &reader, const AssetRef &asset, const asset::EvpackCapabilities &capabilities, graphics::Graphics &graphics)
Validate then upload; failures preserve all existing instances. Reader is not retained.
virtual std::string getBackendName() const =0
Renderer backend id used by sibling modules (e.g. Gpgpu).
virtual Shader * newMeshShaderFromSpv(const std::vector< uint32_t > &vertSpv, const std::vector< uint32_t > &fragSpv)=0
Create a Mesh3D custom shader (MeshVertex + Frame UBO + albedo). Empty vert → default mesh3d....
virtual Shader * newShaderFromSpv(const std::vector< uint32_t > &vertSpv, const std::vector< uint32_t > &fragSpv)=0
Create a custom 2D shader from SPIR-V words (vert + frag). Owned by Graphics. Vertex stage may be emp...
GPU mesh handle (+ optional CPU morph targets).
Definition Mesh.h:25
Custom GPU program.
Definition Shader.h:39
static constexpr int kMaxFloats
Definition Shader.h:41
Result< void > validateShaderAssetGpu(const asset::ShaderAsset &shader)
Validate complete SPIR-V semantics and the supported engine pipeline interface before upload.
EVENGINE_API_FOUNDATION Result< ShaderAsset > loadShaderAsset(const EvpackResourceReader &reader, const AssetRef &asset, const EvpackCapabilities &capabilities)
Read and decode one capability-selected eve.shader/1 from an admitted runtime package.
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13
std::optional< std::reference_wrapper< T > > OptionalRef
Optional borrowed reference; it does not extend T's lifetime.
Definition BorrowedRef.h:24
Actual runtime device capabilities used for variant selection.
Definition Evpack.h:92
Owning CPU program snapshot; decoding does not prove GPU/descriptor compatibility.
Definition ShaderAsset.h:26