mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-18 12:05:24 +00:00
More CCubeMaterial, more CGraphics, more aurora::gx
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "shader.hpp"
|
||||
|
||||
#include "../../gpu.hpp"
|
||||
#include "../gx.hpp"
|
||||
|
||||
#include <logvisor/logvisor.hpp>
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
@@ -65,24 +65,6 @@ struct Command {
|
||||
} data;
|
||||
};
|
||||
|
||||
zeus::CMatrix4f g_mv;
|
||||
zeus::CMatrix4f g_mvInv;
|
||||
zeus::CMatrix4f g_proj;
|
||||
metaforce::CFogState g_fogState;
|
||||
// GX state
|
||||
metaforce::ERglCullMode g_cullMode;
|
||||
metaforce::ERglBlendMode g_blendMode;
|
||||
metaforce::ERglBlendFactor g_blendFacSrc;
|
||||
metaforce::ERglBlendFactor g_blendFacDst;
|
||||
metaforce::ERglLogicOp g_blendOp;
|
||||
bool g_depthCompare;
|
||||
bool g_depthUpdate;
|
||||
metaforce::ERglEnum g_depthFunc;
|
||||
std::array<zeus::CColor, 4> g_colorRegs;
|
||||
bool g_alphaUpdate;
|
||||
std::optional<float> g_dstAlpha;
|
||||
zeus::CColor g_clearColor;
|
||||
|
||||
using NewPipelineCallback = std::function<wgpu::RenderPipeline()>;
|
||||
static std::mutex g_pipelineMutex;
|
||||
static std::thread g_pipelineThread;
|
||||
@@ -135,48 +117,6 @@ static void push_draw_command(ShaderDrawCommand data) { g_commands.push_back({Co
|
||||
|
||||
bool get_dxt_compression_supported() noexcept { return g_device.HasFeature(wgpu::FeatureName::TextureCompressionBC); }
|
||||
|
||||
// GX state
|
||||
void set_cull_mode(metaforce::ERglCullMode mode) noexcept { g_cullMode = mode; }
|
||||
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst,
|
||||
metaforce::ERglLogicOp op) noexcept {
|
||||
g_blendMode = mode;
|
||||
g_blendFacSrc = src;
|
||||
g_blendFacDst = dst;
|
||||
g_blendOp = op;
|
||||
}
|
||||
void set_depth_mode(bool compare_enable, metaforce::ERglEnum func, bool update_enable) noexcept {
|
||||
g_depthCompare = compare_enable;
|
||||
g_depthFunc = func;
|
||||
g_depthUpdate = update_enable;
|
||||
}
|
||||
void set_gx_reg1_color(const zeus::CColor& color) noexcept { g_colorRegs[1] = color; }
|
||||
void set_alpha_update(bool enabled) noexcept { g_alphaUpdate = enabled; }
|
||||
void set_dst_alpha(bool enabled, float value) noexcept {
|
||||
if (enabled) {
|
||||
g_dstAlpha = value;
|
||||
} else {
|
||||
g_dstAlpha.reset();
|
||||
}
|
||||
}
|
||||
void set_clear_color(const zeus::CColor& color) noexcept { g_clearColor = color; }
|
||||
|
||||
// Model state
|
||||
void set_alpha_discard(bool v) {}
|
||||
|
||||
void update_model_view(const zeus::CMatrix4f& mv, const zeus::CMatrix4f& mv_inv) noexcept {
|
||||
g_mv = mv;
|
||||
g_mvInv = mv_inv;
|
||||
}
|
||||
constexpr zeus::CMatrix4f DepthCorrect{
|
||||
// clang-format off
|
||||
1.f, 0.f, 0.f, 0.f,
|
||||
0.f, 1.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.5f, 0.5f,
|
||||
0.f, 0.f, 0.f, 1.f,
|
||||
// clang-format on
|
||||
};
|
||||
void update_projection(const zeus::CMatrix4f& proj) noexcept { g_proj = DepthCorrect * proj; }
|
||||
void update_fog_state(const metaforce::CFogState& state) noexcept { g_fogState = state; }
|
||||
void set_viewport(const zeus::CRectangle& rect, float znear, float zfar) noexcept {
|
||||
g_commands.push_back({CommandType::SetViewport, {.setViewport = {rect, znear, zfar}}});
|
||||
}
|
||||
@@ -243,9 +183,8 @@ PipelineRef pipeline_ref(colored_quad::PipelineConfig config) {
|
||||
}
|
||||
|
||||
void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v,
|
||||
const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3,
|
||||
const zeus::CVector3f& v4) noexcept {
|
||||
auto data = movie_player::make_draw_data(g_state.moviePlayer, tex_y, tex_u, tex_v, v1, v2, v3, v4);
|
||||
float h_pad, float v_pad) noexcept {
|
||||
auto data = movie_player::make_draw_data(g_state.moviePlayer, tex_y, tex_u, tex_v, h_pad, v_pad);
|
||||
push_draw_command({.type = ShaderType::MoviePlayer, .moviePlayer = data});
|
||||
}
|
||||
template <>
|
||||
|
||||
@@ -142,24 +142,6 @@ constexpr Mat4x4<float> Mat4x4_Identity{
|
||||
} // namespace aurora
|
||||
|
||||
namespace aurora::gfx {
|
||||
extern zeus::CMatrix4f g_mv;
|
||||
extern zeus::CMatrix4f g_mvInv;
|
||||
extern zeus::CMatrix4f g_proj;
|
||||
extern metaforce::CFogState g_fogState;
|
||||
// GX state
|
||||
extern metaforce::ERglCullMode g_cullMode;
|
||||
extern metaforce::ERglBlendMode g_blendMode;
|
||||
extern metaforce::ERglBlendFactor g_blendFacSrc;
|
||||
extern metaforce::ERglBlendFactor g_blendFacDst;
|
||||
extern metaforce::ERglLogicOp g_blendOp;
|
||||
extern bool g_depthCompare;
|
||||
extern bool g_depthUpdate;
|
||||
extern metaforce::ERglEnum g_depthFunc;
|
||||
extern std::array<zeus::CColor, 4> g_colorRegs;
|
||||
extern bool g_alphaUpdate;
|
||||
extern std::optional<float> g_dstAlpha;
|
||||
extern zeus::CColor g_clearColor;
|
||||
|
||||
extern wgpu::Buffer g_vertexBuffer;
|
||||
extern wgpu::Buffer g_uniformBuffer;
|
||||
extern wgpu::Buffer g_indexBuffer;
|
||||
@@ -232,6 +214,4 @@ const wgpu::BindGroup& find_bind_group(BindGroupRef id);
|
||||
const wgpu::Sampler& sampler_ref(const wgpu::SamplerDescriptor& descriptor);
|
||||
|
||||
uint32_t align_uniform(uint32_t value);
|
||||
|
||||
static inline Mat4x4<float> get_combined_matrix() { return g_proj * g_mv; }
|
||||
} // namespace aurora::gfx
|
||||
|
||||
150
aurora/lib/gfx/gx.cpp
Normal file
150
aurora/lib/gfx/gx.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "gx.hpp"
|
||||
|
||||
#include "common.hpp"
|
||||
#include "../gpu.hpp"
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
namespace aurora::gfx {
|
||||
static logvisor::Module Log("aurora::gfx::gx");
|
||||
|
||||
zeus::CMatrix4f g_mv;
|
||||
zeus::CMatrix4f g_mvInv;
|
||||
zeus::CMatrix4f g_proj;
|
||||
metaforce::CFogState g_fogState;
|
||||
metaforce::ERglCullMode g_cullMode;
|
||||
metaforce::ERglBlendMode g_blendMode;
|
||||
metaforce::ERglBlendFactor g_blendFacSrc;
|
||||
metaforce::ERglBlendFactor g_blendFacDst;
|
||||
metaforce::ERglLogicOp g_blendOp;
|
||||
bool g_depthCompare;
|
||||
bool g_depthUpdate;
|
||||
metaforce::ERglEnum g_depthFunc;
|
||||
std::array<zeus::CColor, 3> g_colorRegs;
|
||||
std::array<zeus::CColor, GX::MAX_KCOLOR> g_kcolors;
|
||||
bool g_alphaUpdate;
|
||||
std::optional<float> g_dstAlpha;
|
||||
zeus::CColor g_clearColor = zeus::skClear;
|
||||
|
||||
std::array<SChannelState, 2> g_colorChannels;
|
||||
std::array<LightVariant, MaxLights> g_lights;
|
||||
std::bitset<MaxLights> g_lightState;
|
||||
|
||||
std::array<std::optional<STevStage>, maxTevStages> g_tevStages;
|
||||
|
||||
// GX state
|
||||
void set_cull_mode(metaforce::ERglCullMode mode) noexcept { g_cullMode = mode; }
|
||||
void set_blend_mode(metaforce::ERglBlendMode mode, metaforce::ERglBlendFactor src, metaforce::ERglBlendFactor dst,
|
||||
metaforce::ERglLogicOp op) noexcept {
|
||||
g_blendMode = mode;
|
||||
g_blendFacSrc = src;
|
||||
g_blendFacDst = dst;
|
||||
g_blendOp = op;
|
||||
}
|
||||
void set_depth_mode(bool compare_enable, metaforce::ERglEnum func, bool update_enable) noexcept {
|
||||
g_depthCompare = compare_enable;
|
||||
g_depthFunc = func;
|
||||
g_depthUpdate = update_enable;
|
||||
}
|
||||
void set_tev_reg_color(GX::TevRegID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::TEVREG0 || id > GX::TEVREG2) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_reg_color: bad reg {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_colorRegs[id - 1] = color;
|
||||
}
|
||||
void set_tev_k_color(GX::TevKColorID id, const zeus::CColor& color) noexcept {
|
||||
if (id >= GX::MAX_KCOLOR) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_color: bad reg {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_kcolors[id] = color;
|
||||
}
|
||||
void set_alpha_update(bool enabled) noexcept { g_alphaUpdate = enabled; }
|
||||
void set_dst_alpha(bool enabled, float value) noexcept {
|
||||
if (enabled) {
|
||||
g_dstAlpha = value;
|
||||
} else {
|
||||
g_dstAlpha.reset();
|
||||
}
|
||||
}
|
||||
void set_clear_color(const zeus::CColor& color) noexcept { g_clearColor = color; }
|
||||
void set_alpha_discard(bool v) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void update_model_view(const zeus::CMatrix4f& mv, const zeus::CMatrix4f& mv_inv) noexcept {
|
||||
g_mv = mv;
|
||||
g_mvInv = mv_inv;
|
||||
}
|
||||
constexpr zeus::CMatrix4f DepthCorrect{
|
||||
// clang-format off
|
||||
1.f, 0.f, 0.f, 0.f,
|
||||
0.f, 1.f, 0.f, 0.f,
|
||||
0.f, 0.f, 0.5f, 0.5f,
|
||||
0.f, 0.f, 0.f, 1.f,
|
||||
// clang-format on
|
||||
};
|
||||
void update_projection(const zeus::CMatrix4f& proj) noexcept { g_proj = DepthCorrect * proj; }
|
||||
void update_fog_state(const metaforce::CFogState& state) noexcept { g_fogState = state; }
|
||||
|
||||
void disable_tev_stage(metaforce::ERglTevStage stage) noexcept { g_tevStages[static_cast<size_t>(stage)].reset(); }
|
||||
void update_tev_stage(metaforce::ERglTevStage stage, const metaforce::CTevCombiners::ColorPass& colPass,
|
||||
const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp,
|
||||
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept {
|
||||
g_tevStages[static_cast<size_t>(stage)] = {colPass, alphaPass, colorOp, alphaOp};
|
||||
}
|
||||
|
||||
void set_tev_order(GX::TevStageID id, GX::TexCoordID tcid, GX::TexMapID tmid, GX::ChannelID cid) noexcept {
|
||||
auto& stage = g_tevStages[id];
|
||||
if (!stage) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_order: disabled stage {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
stage->texCoordId = tcid;
|
||||
stage->texMapId = tmid;
|
||||
stage->channelId = cid;
|
||||
}
|
||||
void set_tev_k_color_sel(GX::TevStageID id, GX::TevKColorSel sel) noexcept {
|
||||
auto& stage = g_tevStages[id];
|
||||
if (!stage) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_color_sel: disabled stage {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
stage->kcSel = sel;
|
||||
}
|
||||
void set_tev_k_alpha_sel(GX::TevStageID id, GX::TevKAlphaSel sel) noexcept {
|
||||
auto& stage = g_tevStages[id];
|
||||
if (!stage) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_tev_k_alpha_sel: disabled stage {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
stage->kaSel = sel;
|
||||
}
|
||||
|
||||
void set_chan_amb_color(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_chan_amb_color: invalid channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_colorChannels[id - GX::COLOR0A0].ambColor = color;
|
||||
}
|
||||
void set_chan_mat_color(GX::ChannelID id, const zeus::CColor& color) noexcept {
|
||||
if (id < GX::COLOR0A0 || id > GX::COLOR1A1) {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("set_chan_mat_color: invalid channel {}"), id);
|
||||
unreachable();
|
||||
}
|
||||
g_colorChannels[id - GX::COLOR0A0].matColor = color;
|
||||
}
|
||||
|
||||
void load_light(GX::LightID id, const Light& light) noexcept {
|
||||
g_lights[id] = light;
|
||||
}
|
||||
void load_light_ambient(GX::LightID id, const zeus::CColor& ambient) noexcept {
|
||||
g_lights[id] = ambient;
|
||||
}
|
||||
void set_light_state(std::bitset<MaxLights> bits) noexcept {
|
||||
g_lightState = bits;
|
||||
}
|
||||
} // namespace aurora::gfx
|
||||
60
aurora/lib/gfx/gx.hpp
Normal file
60
aurora/lib/gfx/gx.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace aurora::gfx {
|
||||
extern zeus::CMatrix4f g_mv;
|
||||
extern zeus::CMatrix4f g_mvInv;
|
||||
extern zeus::CMatrix4f g_proj;
|
||||
extern metaforce::CFogState g_fogState;
|
||||
extern metaforce::ERglCullMode g_cullMode;
|
||||
extern metaforce::ERglBlendMode g_blendMode;
|
||||
extern metaforce::ERglBlendFactor g_blendFacSrc;
|
||||
extern metaforce::ERglBlendFactor g_blendFacDst;
|
||||
extern metaforce::ERglLogicOp g_blendOp;
|
||||
extern bool g_depthCompare;
|
||||
extern bool g_depthUpdate;
|
||||
extern metaforce::ERglEnum g_depthFunc;
|
||||
extern std::array<zeus::CColor, 3> g_colorRegs;
|
||||
extern std::array<zeus::CColor, GX::MAX_KCOLOR> g_kcolors;
|
||||
extern bool g_alphaUpdate;
|
||||
extern std::optional<float> g_dstAlpha;
|
||||
extern zeus::CColor g_clearColor;
|
||||
|
||||
struct SChannelState {
|
||||
zeus::CColor matColor;
|
||||
zeus::CColor ambColor;
|
||||
};
|
||||
extern std::array<SChannelState, 2> g_colorChannels;
|
||||
using LightVariant = std::variant<std::monostate, Light, zeus::CColor>;
|
||||
extern std::array<LightVariant, MaxLights> g_lights;
|
||||
extern std::bitset<MaxLights> g_lightState;
|
||||
|
||||
struct STevStage {
|
||||
metaforce::CTevCombiners::ColorPass colorPass;
|
||||
metaforce::CTevCombiners::AlphaPass alphaPass;
|
||||
metaforce::CTevCombiners::CTevOp colorOp;
|
||||
metaforce::CTevCombiners::CTevOp alphaOp;
|
||||
GX::TevKColorSel kcSel = GX::TEV_KCSEL_1;
|
||||
GX::TevKAlphaSel kaSel = GX::TEV_KASEL_1;
|
||||
GX::TexCoordID texCoordId = GX::TEXCOORD_NULL;
|
||||
GX::TexMapID texMapId = GX::TEXMAP_NULL;
|
||||
GX::ChannelID channelId = GX::COLOR_NULL;
|
||||
|
||||
STevStage(const metaforce::CTevCombiners::ColorPass& colPass, const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp, const metaforce::CTevCombiners::CTevOp& alphaOp)
|
||||
: colorPass(colPass), alphaPass(alphaPass), colorOp(colorOp), alphaOp(alphaOp) {}
|
||||
};
|
||||
|
||||
constexpr u32 maxTevStages = GX::MAX_TEVSTAGE;
|
||||
extern std::array<std::optional<STevStage>, maxTevStages> g_tevStages;
|
||||
|
||||
static inline XXH64_hash_t hash_tev_stages(XXH64_hash_t seed = 0) {
|
||||
const auto end = std::find_if(g_tevStages.cbegin(), g_tevStages.cend(), [](const auto& a) { return !a; });
|
||||
return xxh3_hash(g_tevStages.data(), (end - g_tevStages.begin()) * sizeof(STevStage), seed);
|
||||
}
|
||||
|
||||
static inline Mat4x4<float> get_combined_matrix() { return g_proj * g_mv; }
|
||||
} // namespace aurora::gfx
|
||||
@@ -12,13 +12,7 @@ using gpu::utils::make_vertex_state;
|
||||
State construct_state() {
|
||||
wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{};
|
||||
wgslDescriptor.source = R"""(
|
||||
struct Uniform {
|
||||
xf: mat4x4<f32>;
|
||||
color: vec4<f32>;
|
||||
};
|
||||
@group(0) @binding(0)
|
||||
var<uniform> ubuf: Uniform;
|
||||
@group(0) @binding(1)
|
||||
var tex_sampler: sampler;
|
||||
@group(1) @binding(0)
|
||||
var tex_y: texture_2d<f32>;
|
||||
@@ -35,7 +29,7 @@ struct VertexOutput {
|
||||
@stage(vertex)
|
||||
fn vs_main(@location(0) in_pos: vec3<f32>, @location(1) in_uv: vec2<f32>) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
out.pos = ubuf.xf * vec4<f32>(in_pos, 1.0);
|
||||
out.pos = vec4<f32>(in_pos, 1.0);
|
||||
out.uv = in_uv;
|
||||
return out;
|
||||
}
|
||||
@@ -47,7 +41,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
textureSample(tex_u, tex_sampler, in.uv).x - 0.5,
|
||||
textureSample(tex_v, tex_sampler, in.uv).x - 0.5
|
||||
);
|
||||
return ubuf.color * vec4<f32>(
|
||||
return vec4<f32>(
|
||||
yuv.x + 1.5958 * yuv.z,
|
||||
yuv.x - 0.39173 * yuv.y - 0.8129 * yuv.z,
|
||||
yuv.x + 2.017 * yuv.y,
|
||||
@@ -61,24 +55,9 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
};
|
||||
auto shader = g_device.CreateShaderModule(&shaderDescriptor);
|
||||
|
||||
wgpu::SupportedLimits limits;
|
||||
g_device.GetLimits(&limits);
|
||||
const auto uniform_alignment = limits.limits.minUniformBufferOffsetAlignment;
|
||||
const auto uniform_size = ALIGN(sizeof(Uniform), uniform_alignment);
|
||||
|
||||
const std::array uniformLayoutEntries{
|
||||
wgpu::BindGroupLayoutEntry{
|
||||
.binding = 0,
|
||||
.visibility = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment,
|
||||
.buffer =
|
||||
wgpu::BufferBindingLayout{
|
||||
.type = wgpu::BufferBindingType::Uniform,
|
||||
.hasDynamicOffset = true,
|
||||
.minBindingSize = uniform_size,
|
||||
},
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry{
|
||||
.binding = 1,
|
||||
.visibility = wgpu::ShaderStage::Fragment,
|
||||
.sampler =
|
||||
wgpu::SamplerBindingLayout{
|
||||
@@ -107,11 +86,6 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
const std::array uniformBindGroupEntries{
|
||||
wgpu::BindGroupEntry{
|
||||
.binding = 0,
|
||||
.buffer = g_uniformBuffer,
|
||||
.size = uniform_size,
|
||||
},
|
||||
wgpu::BindGroupEntry{
|
||||
.binding = 1,
|
||||
.sampler = sampler,
|
||||
},
|
||||
};
|
||||
@@ -219,24 +193,17 @@ wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] Pipeli
|
||||
}
|
||||
|
||||
DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const TextureHandle& tex_u,
|
||||
const TextureHandle& tex_v, const zeus::CVector3f& v1, const zeus::CVector3f& v2,
|
||||
const zeus::CVector3f& v3, const zeus::CVector3f& v4) {
|
||||
const TextureHandle& tex_v, float h_pad, float v_pad) {
|
||||
auto pipeline = pipeline_ref(PipelineConfig{});
|
||||
|
||||
const std::array verts{
|
||||
Vert{{v1.x(), v1.z(), v1.y()}, {0.0, 0.0}},
|
||||
Vert{{v2.x(), v2.z(), v2.y()}, {0.0, 1.0}},
|
||||
Vert{{v3.x(), v3.z(), v3.y()}, {1.0, 0.0}},
|
||||
Vert{{v4.x(), v4.z(), v4.y()}, {1.0, 1.0}},
|
||||
Vert{{-h_pad, v_pad, 0.f}, {0.0, 0.0}},
|
||||
Vert{{-h_pad, -v_pad, 0.f}, {0.0, 1.0}},
|
||||
Vert{{h_pad, v_pad, 0.f}, {1.0, 0.0}},
|
||||
Vert{{h_pad, -v_pad, 0.f}, {1.0, 1.0}},
|
||||
};
|
||||
const auto vertRange = push_verts(ArrayRef{verts});
|
||||
|
||||
const auto uniform = Uniform{
|
||||
.xf = Mat4x4_Identity,
|
||||
.color = zeus::skWhite,
|
||||
};
|
||||
const auto uniformRange = push_uniform(uniform);
|
||||
|
||||
const std::array entries{
|
||||
wgpu::BindGroupEntry{
|
||||
.binding = 0,
|
||||
@@ -261,7 +228,6 @@ DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const Te
|
||||
return {
|
||||
.pipeline = pipeline,
|
||||
.vertRange = vertRange,
|
||||
.uniformRange = uniformRange,
|
||||
.textureBindGroup = textureBindGroup,
|
||||
};
|
||||
}
|
||||
@@ -271,8 +237,7 @@ void render(const State& state, const DrawData& data, const wgpu::RenderPassEnco
|
||||
return;
|
||||
}
|
||||
|
||||
const std::array offsets{data.uniformRange.first};
|
||||
pass.SetBindGroup(0, state.uniformBindGroup, offsets.size(), offsets.data());
|
||||
pass.SetBindGroup(0, state.uniformBindGroup);
|
||||
pass.SetBindGroup(1, find_bind_group(data.textureBindGroup));
|
||||
pass.SetVertexBuffer(0, g_vertexBuffer, data.vertRange.first, data.vertRange.second);
|
||||
pass.Draw(4);
|
||||
|
||||
@@ -30,15 +30,10 @@ struct alignas(4) Vert {
|
||||
Vec3<float> pos;
|
||||
Vec2<float> uv;
|
||||
};
|
||||
struct alignas(4) Uniform {
|
||||
Mat4x4<float> xf;
|
||||
Vec4<float> color;
|
||||
};
|
||||
|
||||
State construct_state();
|
||||
wgpu::RenderPipeline create_pipeline(const State& state, [[maybe_unused]] PipelineConfig config);
|
||||
DrawData make_draw_data(const State& state, const TextureHandle& tex_y, const TextureHandle& tex_u,
|
||||
const TextureHandle& tex_v, const zeus::CVector3f& v1, const zeus::CVector3f& v2,
|
||||
const zeus::CVector3f& v3, const zeus::CVector3f& v4);
|
||||
const TextureHandle& tex_v, float h_pad, float v_pad);
|
||||
void render(const State& state, const DrawData& data, const wgpu::RenderPassEncoder& pass);
|
||||
} // namespace aurora::gfx::movie_player
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "../gpu.hpp"
|
||||
#include "common.hpp"
|
||||
#include "gx.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
@@ -12,28 +13,6 @@ using namespace fmt::literals;
|
||||
|
||||
static logvisor::Module Log("aurora::gfx::stream");
|
||||
|
||||
struct STevStage {
|
||||
metaforce::CTevCombiners::ColorPass colorPass;
|
||||
metaforce::CTevCombiners::AlphaPass alphaPass;
|
||||
metaforce::CTevCombiners::CTevOp colorOp;
|
||||
metaforce::CTevCombiners::CTevOp alphaOp;
|
||||
|
||||
STevStage(const metaforce::CTevCombiners::ColorPass& colPass, const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp, const metaforce::CTevCombiners::CTevOp& alphaOp)
|
||||
: colorPass(colPass), alphaPass(alphaPass), colorOp(colorOp), alphaOp(alphaOp) {}
|
||||
};
|
||||
constexpr u32 maxTevStages = 2;
|
||||
static std::array<std::optional<STevStage>, maxTevStages> sTevStages;
|
||||
|
||||
void disable_tev_stage(metaforce::ERglTevStage stage) noexcept { sTevStages[static_cast<size_t>(stage)].reset(); }
|
||||
|
||||
void update_tev_stage(metaforce::ERglTevStage stage, const metaforce::CTevCombiners::ColorPass& colPass,
|
||||
const metaforce::CTevCombiners::AlphaPass& alphaPass,
|
||||
const metaforce::CTevCombiners::CTevOp& colorOp,
|
||||
const metaforce::CTevCombiners::CTevOp& alphaOp) noexcept {
|
||||
sTevStages[static_cast<size_t>(stage)] = {colPass, alphaPass, colorOp, alphaOp};
|
||||
}
|
||||
|
||||
struct SStreamState {
|
||||
GX::Primitive primitive;
|
||||
metaforce::EStreamFlags flags;
|
||||
@@ -218,7 +197,7 @@ std::unordered_map<ShaderRef, wgpu::ShaderModule> g_streamCachedShaders;
|
||||
|
||||
static ShaderRef generate_shader() {
|
||||
auto flags = sStreamState->flags;
|
||||
const auto hash = xxh3_hash(sTevStages, static_cast<metaforce::EStreamFlags::MaskType>(flags));
|
||||
const auto hash = hash_tev_stages(static_cast<metaforce::EStreamFlags::MaskType>(flags));
|
||||
if (g_streamCachedShaders.contains(hash)) {
|
||||
return hash;
|
||||
}
|
||||
@@ -264,7 +243,7 @@ static ShaderRef generate_shader() {
|
||||
}
|
||||
std::string fragmentFn;
|
||||
bool hasRast = false;
|
||||
for (size_t idx = 0; const auto& stage : sTevStages) {
|
||||
for (size_t idx = 0; const auto& stage : g_tevStages) {
|
||||
if (!stage) {
|
||||
idx++;
|
||||
continue;
|
||||
@@ -288,7 +267,7 @@ static ShaderRef generate_shader() {
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
for (size_t idx = 0; const auto& stage : sTevStages) {
|
||||
for (size_t idx = 0; const auto& stage : g_tevStages) {
|
||||
if (!stage) {
|
||||
idx++;
|
||||
continue;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "shader.hpp"
|
||||
|
||||
#include "../gx.hpp"
|
||||
#include "../../gpu.hpp"
|
||||
|
||||
#include <logvisor/logvisor.hpp>
|
||||
|
||||
Reference in New Issue
Block a user