diff --git a/Runtime/ConsoleVariables/FileStoreManager.cpp b/Runtime/ConsoleVariables/FileStoreManager.cpp index bbc0f0852..722f0d0a5 100644 --- a/Runtime/ConsoleVariables/FileStoreManager.cpp +++ b/Runtime/ConsoleVariables/FileStoreManager.cpp @@ -71,6 +71,7 @@ FileStoreManager::FileStoreManager(std::string_view org, std::string_view domain #endif } else { m_storeRoot = std::string(prefPath); + SDL_free(prefPath); } g_instance = this; } diff --git a/Runtime/Graphics/CCubeMaterial.cpp b/Runtime/Graphics/CCubeMaterial.cpp index 549846b50..f7d25faa7 100644 --- a/Runtime/Graphics/CCubeMaterial.cpp +++ b/Runtime/Graphics/CCubeMaterial.cpp @@ -220,7 +220,7 @@ void CCubeMaterial::SetCurrent(const CModelFlags& flags, const CCubeSurface& sur } // SetNumIndStages(numIndStages); - // SetNumTevStages(finalTevCount); + aurora::gfx::disable_tev_stage(static_cast(finalTevCount)); // SetNumTexGens(tcgCount); // SetNumColorChans(finalNumColorChans); } diff --git a/Runtime/Graphics/CCubeModel.cpp b/Runtime/Graphics/CCubeModel.cpp index e67d742de..991a59860 100644 --- a/Runtime/Graphics/CCubeModel.cpp +++ b/Runtime/Graphics/CCubeModel.cpp @@ -25,8 +25,8 @@ static zeus::CVector3f sPlayerPosition; CCubeModel::CCubeModel(std::vector* surfaces, std::vector>* textures, u8* materialData, std::vector* positions, std::vector* colors, - std::vector* normals, std::vector* texCoords, - std::vector* packedTexCoords, const zeus::CAABox& aabb, u8 flags, bool b1, + std::vector* normals, std::vector>* texCoords, + std::vector>* packedTexCoords, const zeus::CAABox& aabb, u8 flags, bool b1, u32 idx) : x0_modelInstance(surfaces, materialData, positions, colors, normals, texCoords, packedTexCoords) , x1c_textures(textures) @@ -256,12 +256,8 @@ void CCubeModel::EnableShadowMaps(const CTexture& shadowTex, const zeus::CTransf void CCubeModel::DisableShadowMaps() { sRenderModelShadow = false; } void CCubeModel::SetArraysCurrent() { - if (x0_modelInstance.GetVertexPointer() != nullptr) { - aurora::gfx::model::set_vertex_buffer(*x0_modelInstance.GetVertexPointer()); - } - if (x0_modelInstance.GetNormalPointer() != nullptr) { - aurora::gfx::model::set_normal_buffer(*x0_modelInstance.GetNormalPointer()); - } + aurora::gfx::model::set_vertex_buffer(x0_modelInstance.GetVertexPointer()); + aurora::gfx::model::set_normal_buffer(x0_modelInstance.GetNormalPointer()); SetStaticArraysCurrent(); } @@ -281,8 +277,8 @@ void CCubeModel::SetRenderModelBlack(bool v) { } void CCubeModel::SetSkinningArraysCurrent(TVectorRef positions, TVectorRef normals) { - aurora::gfx::model::set_vertex_buffer(*positions); - aurora::gfx::model::set_normal_buffer(*normals); + aurora::gfx::model::set_vertex_buffer(positions); + aurora::gfx::model::set_normal_buffer(normals); // colors unused SetStaticArraysCurrent(); } @@ -295,22 +291,20 @@ void CCubeModel::SetStaticArraysCurrent() { sUsingPackedLightmaps = false; } if (sUsingPackedLightmaps) { - aurora::gfx::model::set_tex0_tc_buffer(*packedTexCoords); - } else if (texCoords != nullptr) { - aurora::gfx::model::set_tex0_tc_buffer(*packedTexCoords); - } - if (texCoords != nullptr) { - aurora::gfx::model::set_tc_buffer(*texCoords); + aurora::gfx::model::set_tex0_tc_buffer(packedTexCoords); + } else { + aurora::gfx::model::set_tex0_tc_buffer(texCoords); } + aurora::gfx::model::set_tc_buffer(texCoords); CCubeMaterial::KillCachedViewDepState(); } void CCubeModel::SetUsingPackedLightmaps(bool v) { sUsingPackedLightmaps = v; if (v) { - aurora::gfx::model::set_tex0_tc_buffer(*x0_modelInstance.GetPackedTCPointer()); + aurora::gfx::model::set_tex0_tc_buffer(x0_modelInstance.GetPackedTCPointer()); } else { - aurora::gfx::model::set_tex0_tc_buffer(*x0_modelInstance.GetTCPointer()); + aurora::gfx::model::set_tex0_tc_buffer(x0_modelInstance.GetTCPointer()); } } diff --git a/Runtime/Graphics/CCubeModel.hpp b/Runtime/Graphics/CCubeModel.hpp index f4b437e42..4b7a5148b 100644 --- a/Runtime/Graphics/CCubeModel.hpp +++ b/Runtime/Graphics/CCubeModel.hpp @@ -33,13 +33,13 @@ private: std::vector* x8_positions; // was void* std::vector* xc_normals; // was void* std::vector* x10_colors; // was void* - std::vector* x14_texCoords; // was void* - std::vector* x18_packedTexCoords; // was void* + std::vector>* x14_texCoords; // was void* + std::vector>* x18_packedTexCoords; // was void* public: ModelInstance(std::vector* surfaces, u8* material, std::vector* positions, std::vector* colors, std::vector* normals, - std::vector* texCoords, std::vector* packedTexCoords) + std::vector>* texCoords, std::vector>* packedTexCoords) : x0_surfacePtrs(surfaces) , x4_materialData(material) , x8_positions(positions) @@ -58,8 +58,8 @@ private: [[nodiscard]] TVectorRef GetVertexPointer() const { return x8_positions; } [[nodiscard]] TVectorRef GetNormalPointer() const { return xc_normals; } [[nodiscard]] std::vector* GetColorPointer() const { return x10_colors; } - [[nodiscard]] std::vector* GetTCPointer() const { return x14_texCoords; } - [[nodiscard]] std::vector* GetPackedTCPointer() const { return x18_packedTexCoords; } + [[nodiscard]] std::vector>* GetTCPointer() const { return x14_texCoords; } + [[nodiscard]] std::vector>* GetPackedTCPointer() const { return x18_packedTexCoords; } }; ModelInstance x0_modelInstance; @@ -75,8 +75,8 @@ private: public: CCubeModel(std::vector* surfaces, std::vector>* textures, u8* materialData, std::vector* positions, std::vector* colors, - std::vector* normals, std::vector* texCoords, - std::vector* packedTexCoords, const zeus::CAABox& aabb, u8 flags, bool b1, u32 idx); + std::vector* normals, std::vector>* texCoords, + std::vector>* packedTexCoords, const zeus::CAABox& aabb, u8 flags, bool b1, u32 idx); CCubeMaterial GetMaterialByIndex(u32 idx); bool TryLockTextures(); diff --git a/Runtime/Graphics/CCubeRenderer.cpp b/Runtime/Graphics/CCubeRenderer.cpp index 638d6c1f7..622a123fe 100644 --- a/Runtime/Graphics/CCubeRenderer.cpp +++ b/Runtime/Graphics/CCubeRenderer.cpp @@ -233,8 +233,8 @@ void CCubeRenderer::AddStaticGeometry(const std::vector* const_cast*>(inst.GetVertexPointer()), const_cast*>(inst.GetColorPointer()), const_cast*>(inst.GetNormalPointer()), - const_cast*>(inst.GetTCPointer()), - const_cast*>(inst.GetPackedTCPointer()), + const_cast>*>(inst.GetTCPointer()), + const_cast>*>(inst.GetPackedTCPointer()), inst.GetBoundingBox(), inst.GetFlags(), false, instIdx)); ++instIdx; } diff --git a/Runtime/Graphics/CMetroidModelInstance.hpp b/Runtime/Graphics/CMetroidModelInstance.hpp index c8eb6a024..087c1aff9 100644 --- a/Runtime/Graphics/CMetroidModelInstance.hpp +++ b/Runtime/Graphics/CMetroidModelInstance.hpp @@ -22,8 +22,8 @@ class CMetroidModelInstance { std::vector x60_positions; // was void* std::vector x64_normals; // was void* std::vector x68_colors; // was void* - std::vector x6c_texCoords; // was void* - std::vector x70_packedTexCoords; // was void* + std::vector> x6c_texCoords; // was void* + std::vector> x70_packedTexCoords; // was void* public: CMetroidModelInstance() = default; @@ -40,8 +40,8 @@ public: [[nodiscard]] TVectorRef GetVertexPointer() const { return &x60_positions; } [[nodiscard]] TVectorRef GetNormalPointer() const { return &x64_normals; } [[nodiscard]] const std::vector* GetColorPointer() const { return &x68_colors; } - [[nodiscard]] const std::vector* GetTCPointer() const { return &x6c_texCoords; } - [[nodiscard]] const std::vector* GetPackedTCPointer() const { return &x70_packedTexCoords; } + [[nodiscard]] const std::vector>* GetTCPointer() const { return &x6c_texCoords; } + [[nodiscard]] const std::vector>* GetPackedTCPointer() const { return &x70_packedTexCoords; } }; } // namespace metaforce diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index ea3cc0b74..97bb6d04a 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -87,8 +87,8 @@ private: std::vector m_positions; std::vector m_normals; std::vector m_colors; - std::vector m_floatUVs; - std::vector m_shortUVs; + std::vector> m_floatUVs; + std::vector> m_shortUVs; public: CModel(std::unique_ptr in, u32 dataLen, IObjectStore* store); diff --git a/aurora/include/aurora/common.hpp b/aurora/include/aurora/common.hpp index 90306b0be..7a0305b48 100644 --- a/aurora/include/aurora/common.hpp +++ b/aurora/include/aurora/common.hpp @@ -7,7 +7,55 @@ #include "Runtime/RetroTypes.hpp" +#include + namespace aurora { +template +struct Vec2 { + T x{}; + T y{}; + + constexpr Vec2(T x, T y) : x(x), y(y) {} + constexpr Vec2(const zeus::CVector2f& vec) : x(vec.x()), y(vec.y()) {} +}; +template +struct Vec3 { + T x{}; + T y{}; + T z{}; + + constexpr Vec3(T x, T y, T z) : x(x), y(y), z(z) {} + constexpr Vec3(const zeus::CVector3f& vec) : x(vec.x()), y(vec.y()), z(vec.z()) {} +}; +template +struct Vec4 { + T x{}; + T y{}; + T z{}; + T w{}; + + constexpr Vec4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} + constexpr Vec4(const zeus::CVector4f& vec) : x(vec.x()), y(vec.y()), z(vec.z()), w(vec.w()) {} + constexpr Vec4(const zeus::CColor& color) : x(color.r()), y(color.g()), z(color.b()), w(color.a()) {} +}; +template +struct Mat4x4 { + Vec4 m0{}; + Vec4 m1{}; + Vec4 m2{}; + Vec4 m3{}; + + constexpr Mat4x4(const Vec4& m0, const Vec4& m1, const Vec4& m2, const Vec4& m3) + : m0(m0), m1(m1), m2(m2), m3(m3) {} + constexpr Mat4x4(const zeus::CMatrix4f& m) : m0(m[0]), m1(m[1]), m2(m[2]), m3(m[3]) {} +}; +constexpr Mat4x4 Mat4x4_Identity{ + Vec4{1.f, 0.f, 0.f, 0.f}, + Vec4{0.f, 1.f, 0.f, 0.f}, + Vec4{0.f, 0.f, 1.f, 0.f}, + Vec4{0.f, 0.f, 0.f, 1.f}, +}; + template class ArrayRef { public: diff --git a/aurora/include/aurora/model.hpp b/aurora/include/aurora/model.hpp index 9d0c02f20..e3533b9c1 100644 --- a/aurora/include/aurora/model.hpp +++ b/aurora/include/aurora/model.hpp @@ -3,10 +3,10 @@ #include "common.hpp" namespace aurora::gfx::model { -void set_vertex_buffer(const std::vector& data) noexcept; -void set_normal_buffer(const std::vector& norm) noexcept; -void set_tex0_tc_buffer(const std::vector& tcs) noexcept; // Tex coords for TEX0 -void set_tc_buffer(const std::vector& tcs) noexcept; // Tex coords for the TEX1-7 +void set_vertex_buffer(const std::vector* data) noexcept; +void set_normal_buffer(const std::vector* norm) noexcept; +void set_tex0_tc_buffer(const std::vector>* tcs) noexcept; // Tex coords for TEX0 +void set_tc_buffer(const std::vector>* tcs) noexcept; // Tex coords for the TEX1-7 void set_vtx_desc_compressed(u32 vtxDesc) noexcept; void queue_surface(const u8* dlStart, u32 dlSize) noexcept; diff --git a/aurora/lib/gfx/common.hpp b/aurora/lib/gfx/common.hpp index 9879b87e9..0e2b99175 100644 --- a/aurora/lib/gfx/common.hpp +++ b/aurora/lib/gfx/common.hpp @@ -95,52 +95,6 @@ private: m_capacity = size; } }; - -template -struct Vec2 { - T x{}; - T y{}; - - constexpr Vec2(T x, T y) : x(x), y(y) {} - constexpr Vec2(const zeus::CVector2f& vec) : x(vec.x()), y(vec.y()) {} -}; -template -struct Vec3 { - T x{}; - T y{}; - T z{}; - - constexpr Vec3(T x, T y, T z) : x(x), y(y), z(z) {} - constexpr Vec3(const zeus::CVector3f& vec) : x(vec.x()), y(vec.y()), z(vec.z()) {} -}; -template -struct Vec4 { - T x{}; - T y{}; - T z{}; - T w{}; - - constexpr Vec4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} - constexpr Vec4(const zeus::CVector4f& vec) : x(vec.x()), y(vec.y()), z(vec.z()), w(vec.w()) {} - constexpr Vec4(const zeus::CColor& color) : x(color.r()), y(color.g()), z(color.b()), w(color.a()) {} -}; -template -struct Mat4x4 { - Vec4 m0{}; - Vec4 m1{}; - Vec4 m2{}; - Vec4 m3{}; - - constexpr Mat4x4(const Vec4& m0, const Vec4& m1, const Vec4& m2, const Vec4& m3) - : m0(m0), m1(m1), m2(m2), m3(m3) {} - constexpr Mat4x4(const zeus::CMatrix4f& m) : m0(m[0]), m1(m[1]), m2(m[2]), m3(m[3]) {} -}; -constexpr Mat4x4 Mat4x4_Identity{ - Vec4{1.f, 0.f, 0.f, 0.f}, - Vec4{0.f, 1.f, 0.f, 0.f}, - Vec4{0.f, 0.f, 1.f, 0.f}, - Vec4{0.f, 0.f, 0.f, 1.f}, -}; } // namespace aurora namespace aurora::gfx { diff --git a/aurora/lib/gfx/gx.cpp b/aurora/lib/gfx/gx.cpp index aeb2c42a5..64dbd09f4 100644 --- a/aurora/lib/gfx/gx.cpp +++ b/aurora/lib/gfx/gx.cpp @@ -68,7 +68,7 @@ constexpr zeus::CMatrix4f DepthCorrect{ 0.f, 0.f, 0.f, 1.f, // clang-format on }; -void update_projection(const zeus::CMatrix4f& proj) noexcept { gx::g_proj = DepthCorrect * proj; } +void update_projection(const zeus::CMatrix4f& proj) noexcept { gx::g_proj = /*DepthCorrect **/ proj; } void update_fog_state(const metaforce::CFogState& state) noexcept { gx::g_fogState = state; } void disable_tev_stage(metaforce::ERglTevStage stage) noexcept { gx::g_tevStages[static_cast(stage)].reset(); } @@ -295,11 +295,11 @@ wgpu::RenderPipeline build_pipeline(const PipelineConfig& config, const ShaderIn .targetCount = colorTargets.size(), .targets = colorTargets.data(), }; - const auto layouts = build_bind_group_layouts(info, config.shaderConfig); + auto layouts = build_bind_group_layouts(info, config.shaderConfig); const std::array bindGroupLayouts{ - layouts.uniformLayout, - layouts.samplerLayout, - layouts.textureLayout, + std::move(layouts.uniformLayout), + std::move(layouts.samplerLayout), + std::move(layouts.textureLayout), }; const auto pipelineLayoutDescriptor = wgpu::PipelineLayoutDescriptor{ .label = "GX Pipeline Layout", @@ -368,6 +368,12 @@ Range build_uniform(const ShaderInfo& info) noexcept { const auto xf = get_combined_matrix(); uniBuf.append(&xf, 64); } + for (int i = 0; i < info.usesTevReg.size(); ++i) { + if (!info.usesTevReg.test(i)) { + continue; + } + uniBuf.append(&g_colorRegs[i], 16); + } for (int i = 0; i < info.sampledColorChannels.size(); ++i) { if (!info.sampledColorChannels.test(i)) { continue; diff --git a/aurora/lib/gfx/gx.hpp b/aurora/lib/gfx/gx.hpp index 8aad4caf5..ccc75d06e 100644 --- a/aurora/lib/gfx/gx.hpp +++ b/aurora/lib/gfx/gx.hpp @@ -108,6 +108,7 @@ struct ShaderInfo { std::bitset sampledTextures; std::bitset<4> sampledKcolors; std::bitset<2> sampledColorChannels; + std::bitset<3> usesTevReg; u32 uniformSize = 0; bool usesVtxColor : 1 = false; bool usesNormal : 1 = false; @@ -143,21 +144,29 @@ struct DlVert { namespace aurora { template <> +inline void xxh3_update(XXH3_state_t& state, const metaforce::CTevCombiners::CTevOp& input) { + XXH3_64bits_update(&state, &input.x0_clamp, sizeof(bool)); + XXH3_64bits_update(&state, &input.x4_op, sizeof(metaforce::CTevCombiners::CTevOp::x4_op)); + XXH3_64bits_update(&state, &input.x8_bias, sizeof(metaforce::CTevCombiners::CTevOp::x8_bias)); + XXH3_64bits_update(&state, &input.xc_scale, sizeof(metaforce::CTevCombiners::CTevOp::xc_scale)); + XXH3_64bits_update(&state, &input.x10_regId, sizeof(metaforce::CTevCombiners::CTevOp::x10_regId)); +} +template <> inline void xxh3_update(XXH3_state_t& state, const gfx::gx::STevStage& input) { - XXH3_64bits_update(&state, &input.colorPass, sizeof(metaforce::CTevCombiners::ColorPass)); - XXH3_64bits_update(&state, &input.alphaPass, sizeof(metaforce::CTevCombiners::AlphaPass)); - XXH3_64bits_update(&state, &input.colorOp, sizeof(metaforce::CTevCombiners::CTevOp)); - XXH3_64bits_update(&state, &input.alphaOp, sizeof(metaforce::CTevCombiners::CTevOp)); - XXH3_64bits_update(&state, &input.kcSel, sizeof(GX::TevKColorSel)); - XXH3_64bits_update(&state, &input.kaSel, sizeof(GX::TevKAlphaSel)); - XXH3_64bits_update(&state, &input.texCoordId, sizeof(GX::TexCoordID)); - XXH3_64bits_update(&state, &input.texMapId, sizeof(GX::TexMapID)); - XXH3_64bits_update(&state, &input.channelId, sizeof(GX::ChannelID)); + XXH3_64bits_update(&state, &input.colorPass, sizeof(gfx::gx::STevStage::colorPass)); + XXH3_64bits_update(&state, &input.alphaPass, sizeof(gfx::gx::STevStage::alphaPass)); + xxh3_update(state, input.colorOp); + xxh3_update(state, input.alphaOp); + XXH3_64bits_update(&state, &input.kcSel, sizeof(gfx::gx::STevStage::kcSel)); + XXH3_64bits_update(&state, &input.kaSel, sizeof(gfx::gx::STevStage::kaSel)); + XXH3_64bits_update(&state, &input.texCoordId, sizeof(gfx::gx::STevStage::texCoordId)); + XXH3_64bits_update(&state, &input.texMapId, sizeof(gfx::gx::STevStage::texMapId)); + XXH3_64bits_update(&state, &input.channelId, sizeof(gfx::gx::STevStage::channelId)); } template <> inline XXH64_hash_t xxh3_hash(const gfx::gx::ShaderConfig& input, XXH64_hash_t seed) { XXH3_state_t state; - XXH3_INITSTATE(&state); + memset(&state, 0, sizeof(XXH3_state_t)); XXH3_64bits_reset_withSeed(&state, seed); for (const auto& item : input.tevStages) { if (!item) { @@ -165,7 +174,9 @@ inline XXH64_hash_t xxh3_hash(const gfx::gx::ShaderConfig& input, XXH64_hash_t s } xxh3_update(state, *item); } - XXH3_64bits_update(&state, input.channelMatSrcs.data(), input.channelMatSrcs.size() * sizeof(GX::ColorSrc)); + for (const auto& item : input.channelMatSrcs) { + XXH3_64bits_update(&state, &item, sizeof(GX::ColorSrc)); + } XXH3_64bits_update(&state, &input.alphaDiscard, sizeof(bool)); XXH3_64bits_update(&state, &input.denormalizedVertexAttributes, sizeof(bool)); XXH3_64bits_update(&state, &input.denormalizedHasNrm, sizeof(bool)); diff --git a/aurora/lib/gfx/gx_shader.cpp b/aurora/lib/gfx/gx_shader.cpp index bb7789383..d447af852 100644 --- a/aurora/lib/gfx/gx_shader.cpp +++ b/aurora/lib/gfx/gx_shader.cpp @@ -19,13 +19,23 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const STe case GX::CC_APREV: return "prev.a"; case GX::CC_C0: + info.usesTevReg.set(0); + return "tevreg0.rgb"; case GX::CC_A0: + info.usesTevReg.set(0); + return "tevreg0.a"; case GX::CC_C1: + info.usesTevReg.set(1); + return "tevreg1.rgb"; case GX::CC_A1: + info.usesTevReg.set(1); + return "tevreg1.a"; case GX::CC_C2: + info.usesTevReg.set(2); + return "tevreg2.rgb"; case GX::CC_A2: - Log.report(logvisor::Fatal, FMT_STRING("TODO {}"), arg); - unreachable(); + info.usesTevReg.set(2); + return "tevreg2.a"; case GX::CC_TEXC: { if (stage.texMapId == GX::TEXMAP_NULL) { Log.report(logvisor::Fatal, FMT_STRING("unmapped texture for stage {}"), stageIdx); @@ -161,6 +171,9 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const STe } case GX::CC_ZERO: return "0.0"; + default: + Log.report(logvisor::Fatal, FMT_STRING("invalid color arg {}"), arg); + unreachable(); } } @@ -169,10 +182,14 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const STe case GX::CA_APREV: return "prev.a"; case GX::CA_A0: + info.usesTevReg.set(0); + return "tevreg0.a"; case GX::CA_A1: + info.usesTevReg.set(1); + return "tevreg1.a"; case GX::CA_A2: - Log.report(logvisor::Fatal, FMT_STRING("TODO {}"), arg); - unreachable(); + info.usesTevReg.set(2); + return "tevreg2.a"; case GX::CA_TEXA: { if (stage.texMapId == GX::TEXMAP_NULL) { Log.report(logvisor::Fatal, FMT_STRING("unmapped texture for stage {}"), stageIdx); @@ -269,6 +286,9 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const STe } case GX::CA_ZERO: return "0.0"; + default: + Log.report(logvisor::Fatal, FMT_STRING("invalid alpha arg {}"), arg); + unreachable(); } } @@ -292,6 +312,9 @@ static std::string_view tev_bias(GX::TevBias bias) { return " + 0.5"; case GX::TB_SUBHALF: return " - 0.5"; + default: + Log.report(logvisor::Fatal, FMT_STRING("invalid bias {}"), bias); + unreachable(); } } @@ -305,6 +328,9 @@ static std::string_view tev_scale(GX::TevScale scale) { return " * 4.0"; case GX::CS_DIVIDE_2: return " / 2.0"; + default: + Log.report(logvisor::Fatal, FMT_STRING("invalid scale {}"), scale); + unreachable(); } } @@ -379,7 +405,7 @@ std::pair build_shader(const ShaderConfig& confi } else { uniformBindings += R"""( struct Vec3Block { - data: array>; + data: array>; }; struct Vec2Block { data: array>; @@ -398,7 +424,7 @@ var v_packed_uvs: Vec2Block; "\n , @location(1) in_uv_0_4_idx: vec4" "\n , @location(2) in_uv_5_7_idx: vec4"; vtxOutAttrs += "\n @builtin(position) pos: vec4;"; - vtxXfrAttrsPre += "\n out.pos = ubuf.xf * vec4(v_verts.data[in_pos_nrm_idx[0]], 1.0);"; + vtxXfrAttrsPre += "\n out.pos = ubuf.xf * vec4(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"; } std::string fragmentFnPre; @@ -413,6 +439,18 @@ var v_packed_uvs: Vec2Block; case GX::TevRegID::TEVPREV: outReg = "prev"; break; + case GX::TEVREG0: + outReg = "tevreg0"; + info.usesTevReg.set(0); + break; + case GX::TEVREG1: + outReg = "tevreg1"; + info.usesTevReg.set(1); + break; + case GX::TEVREG2: + outReg = "tevreg2"; + info.usesTevReg.set(2); + break; default: Log.report(logvisor::Fatal, FMT_STRING("TODO: colorOp outReg {}"), stage->colorOp.x10_regId); } @@ -423,6 +461,9 @@ var v_packed_uvs: Vec2Block; color_arg_reg(stage->colorPass.x8_c, idx, *stage, info), color_arg_reg(stage->colorPass.xc_d, idx, *stage, info), tev_op(stage->colorOp.x4_op), tev_bias(stage->colorOp.x8_bias), tev_scale(stage->colorOp.xc_scale)); + if (stage->colorOp.x0_clamp) { + op = fmt::format(FMT_STRING("clamp({}, vec3(0.0), vec3(1.0))"), op); + } fragmentFn += fmt::format(FMT_STRING("\n {0} = vec4({1}, {0}.a);"), outReg, op); } { @@ -431,6 +472,18 @@ var v_packed_uvs: Vec2Block; case GX::TevRegID::TEVPREV: outReg = "prev.a"; break; + case GX::TEVREG0: + outReg = "tevreg0.a"; + info.usesTevReg.set(0); + break; + case GX::TEVREG1: + outReg = "tevreg1.a"; + info.usesTevReg.set(1); + break; + case GX::TEVREG2: + outReg = "tevreg2.a"; + info.usesTevReg.set(2); + break; default: Log.report(logvisor::Fatal, FMT_STRING("TODO: alphaOp outReg {}"), stage->alphaOp.x10_regId); } @@ -441,10 +494,20 @@ var v_packed_uvs: Vec2Block; alpha_arg_reg(stage->alphaPass.x8_c, idx, *stage, info), alpha_arg_reg(stage->alphaPass.xc_d, idx, *stage, info), tev_op(stage->alphaOp.x4_op), tev_bias(stage->alphaOp.x8_bias), tev_scale(stage->alphaOp.xc_scale)); + if (stage->alphaOp.x0_clamp) { + op = fmt::format(FMT_STRING("clamp({}, 0.0, 1.0)"), op); + } fragmentFn += fmt::format(FMT_STRING("\n {0} = {1};"), outReg, op); } idx++; } + for (int i = 0; i < info.usesTevReg.size(); ++i) { + if (!info.usesTevReg.test(i)) { + continue; + } + uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4;"), i); + fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i); + } for (int i = 0; i < info.sampledColorChannels.size(); ++i) { if (!info.sampledColorChannels.test(i)) { continue; @@ -499,12 +562,12 @@ var v_packed_uvs: Vec2Block; vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2;"), locIdx, i); if (i < 4) { if (i == 0) { - vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_packed_uvs.data[in_uv_0_4[{}]];"), i, i); + vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_packed_uvs.data[in_uv_0_4_idx[{}]];"), i, i); } else { - vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_uvs.data[in_uv_0_4[{}]];"), i, i); + vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_uvs.data[in_uv_0_4_idx[{}]];"), i, i); } } else { - vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_uvs.data[in_uv_5_7[{}]];"), i, i - 4); + vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{}_uv = v_uvs.data[in_uv_5_7_idx[{}]];"), i, i - 4); } } fragmentFnPre += fmt::format( @@ -544,9 +607,10 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 {{ wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{}; wgslDescriptor.source = shaderSource.c_str(); + const auto label = fmt::format(FMT_STRING("GX Shader {:x}"), hash); const auto shaderDescriptor = wgpu::ShaderModuleDescriptor{ .nextInChain = &wgslDescriptor, - .label = "GX Shader", + .label = label.c_str(), }; auto shader = gpu::g_device.CreateShaderModule(&shaderDescriptor); diff --git a/aurora/lib/gfx/model/shader.cpp b/aurora/lib/gfx/model/shader.cpp index 26a3f3973..398e034ab 100644 --- a/aurora/lib/gfx/model/shader.cpp +++ b/aurora/lib/gfx/model/shader.cpp @@ -10,14 +10,14 @@ enum class VtxDescAttr : u8 { Position = 0, Normal = 2, Color0 = 4, - Color1 = 8, - Tex0 = 10, - Tex1 = 12, - Tex2 = 14, - Tex3 = 16, - Tex4 = 18, - Tex5 = 20, - Tex6 = 22, + Color1 = 6, + Tex0 = 8, + Tex1 = 10, + Tex2 = 12, + Tex3 = 14, + Tex4 = 16, + Tex5 = 18, + Tex6 = 20, PnMatIdx = 24, Tex0MatIdx = 25, Tex1MatIdx = 26, @@ -51,13 +51,13 @@ static logvisor::Module Log("aurora::gfx::model"); static const std::vector* vtxData; static const std::vector* nrmData; -static const std::vector* tex0TcData; -static const std::vector* tcData; +static const std::vector>* tex0TcData; +static const std::vector>* tcData; -void set_vertex_buffer(const std::vector& data) noexcept { vtxData = &data; } -void set_normal_buffer(const std::vector& norm) noexcept { nrmData = &norm; } -void set_tex0_tc_buffer(const std::vector& tcs) noexcept { tex0TcData = &tcs; } -void set_tc_buffer(const std::vector& tcs) noexcept { tcData = &tcs; } +void set_vertex_buffer(const std::vector* data) noexcept { vtxData = data; } +void set_normal_buffer(const std::vector* norm) noexcept { nrmData = norm; } +void set_tex0_tc_buffer(const std::vector>* tcs) noexcept { tex0TcData = tcs; } +void set_tc_buffer(const std::vector>* tcs) noexcept { tcData = tcs; } enum class VertexFormat : u8 { F32F32, @@ -170,12 +170,12 @@ void queue_surface(const u8* dlStart, u32 dlSize) noexcept { const auto idxRange = push_indices(ArrayRef{indices}); const auto sVtxRange = push_storage(reinterpret_cast(vtxData->data()), vtxData->size() * 16); const auto sNrmRange = push_storage(reinterpret_cast(nrmData->data()), nrmData->size() * 16); - const auto sTcRange = push_storage(reinterpret_cast(tcData->data()), tcData->size() * 16); + const auto sTcRange = push_storage(reinterpret_cast(tcData->data()), tcData->size() * 8); Range sPackedTcRange; if (tcData == tex0TcData) { sPackedTcRange = sTcRange; } else { - sPackedTcRange = push_storage(reinterpret_cast(tex0TcData->data()), tex0TcData->size() * 16); + sPackedTcRange = push_storage(reinterpret_cast(tex0TcData->data()), tex0TcData->size() * 8); } model::PipelineConfig config{}; diff --git a/aurora/lib/gfx/texture.cpp b/aurora/lib/gfx/texture.cpp index 05b14c393..bc583448b 100644 --- a/aurora/lib/gfx/texture.cpp +++ b/aurora/lib/gfx/texture.cpp @@ -130,27 +130,38 @@ void write_texture(const TextureHandle& handle, ArrayRef data) noexcept } } - const auto dstView = wgpu::ImageCopyTexture{ - .texture = ref.texture, - }; - if (ref.size.depthOrArrayLayers != 1) { - Log.report(logvisor::Fatal, FMT_STRING("write_texture: unsupported depth {}"), ref.size.depthOrArrayLayers); - unreachable(); + uint32_t offset = 0; + for (uint32_t mip = 0; mip < ref.mipCount; ++mip) { + const auto mipSize = wgpu::Extent3D{ + .width = std::max(ref.size.width >> mip, 1u), + .height = std::max(ref.size.height >> mip, 1u), + .depthOrArrayLayers = ref.size.depthOrArrayLayers, + }; + const auto info = format_info(ref.format); + const auto physicalSize = physical_size(mipSize, info); + const uint32_t widthBlocks = physicalSize.width / info.blockWidth; + const uint32_t heightBlocks = physicalSize.height / info.blockHeight; + const uint32_t bytesPerRow = widthBlocks * info.blockSize; + const uint32_t dataSize = bytesPerRow * heightBlocks * mipSize.depthOrArrayLayers; + if (offset + dataSize > data.size()) { + Log.report(logvisor::Fatal, FMT_STRING("write_texture: expected at least {} bytes, got {}"), offset + dataSize, + data.size()); + unreachable(); + } + const auto dstView = wgpu::ImageCopyTexture{ + .texture = ref.texture, + .mipLevel = mip, + }; + const auto dataLayout = wgpu::TextureDataLayout{ + .bytesPerRow = bytesPerRow, + .rowsPerImage = heightBlocks, + }; + g_queue.WriteTexture(&dstView, data.data() + offset, dataSize, &dataLayout, &physicalSize); + offset += dataSize; } - const auto info = format_info(ref.format); - const auto physicalSize = physical_size(ref.size, info); - const uint32_t widthBlocks = physicalSize.width / info.blockWidth; - const uint32_t heightBlocks = physicalSize.height / info.blockHeight; - const uint32_t bytesPerRow = widthBlocks * info.blockSize; - const uint32_t dataSize = bytesPerRow * heightBlocks * ref.size.depthOrArrayLayers; - if (dataSize > data.size()) { - Log.report(logvisor::Fatal, FMT_STRING("write_texture: expected at least {} bytes, got {}"), dataSize, data.size()); - unreachable(); + if (offset < data.size()) { + Log.report(logvisor::Warning, FMT_STRING("write_texture: texture used {} bytes, but given {} bytes"), offset, + data.size()); } - const auto dataLayout = wgpu::TextureDataLayout{ - .bytesPerRow = bytesPerRow, - .rowsPerImage = heightBlocks, - }; - g_queue.WriteTexture(&dstView, data.data(), dataSize, &dataLayout, &ref.size); } } // namespace aurora::gfx diff --git a/aurora/lib/gpu.cpp b/aurora/lib/gpu.cpp index fb903395c..b5453ccaa 100644 --- a/aurora/lib/gpu.cpp +++ b/aurora/lib/gpu.cpp @@ -102,7 +102,7 @@ static TextureWithSampler create_depth_texture() { } static void error_callback(WGPUErrorType type, char const* message, void* userdata) { - Log.report(logvisor::Error, FMT_STRING("Dawn error {}: {}"), + Log.report(logvisor::Fatal, FMT_STRING("Dawn error {}: {}"), magic_enum::enum_name(static_cast(type)), message); }