mirror of https://github.com/AxioDL/metaforce.git
Hacky scan visor rendering
This commit is contained in:
parent
1115b451a5
commit
9d634e6a05
|
@ -640,9 +640,9 @@ void CCubeRenderer::SetPerspective(float fovy, float width, float height, float
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<zeus::CVector2f, zeus::CVector2f> CCubeRenderer::SetViewportOrtho(bool centered, float znear, float zfar) {
|
std::pair<zeus::CVector2f, zeus::CVector2f> CCubeRenderer::SetViewportOrtho(bool centered, float znear, float zfar) {
|
||||||
auto left = static_cast<float>(centered ? CGraphics::GetViewportLeft() - CGraphics::GetViewportWidth() / 2
|
auto left = static_cast<float>(centered ? CGraphics::GetViewportLeft() - CGraphics::GetViewportHalfWidth()
|
||||||
: CGraphics::GetViewportLeft());
|
: CGraphics::GetViewportLeft());
|
||||||
auto top = static_cast<float>(centered ? CGraphics::GetViewportTop() - CGraphics::GetViewportHeight() / 2
|
auto top = static_cast<float>(centered ? CGraphics::GetViewportTop() - CGraphics::GetViewportHalfHeight()
|
||||||
: CGraphics::GetViewportHeight());
|
: CGraphics::GetViewportHeight());
|
||||||
auto right = static_cast<float>(CGraphics::GetViewportLeft() +
|
auto right = static_cast<float>(CGraphics::GetViewportLeft() +
|
||||||
(centered ? CGraphics::GetViewportWidth() / 2 : CGraphics::GetViewportWidth()));
|
(centered ? CGraphics::GetViewportWidth() / 2 : CGraphics::GetViewportWidth()));
|
||||||
|
|
|
@ -305,78 +305,17 @@ public:
|
||||||
static float GetCroppedViewportUVYMin() { return g_CroppedViewport.x20_uvYMin; }
|
static float GetCroppedViewportUVYMin() { return g_CroppedViewport.x20_uvYMin; }
|
||||||
static float GetCroppedViewportUVYMax() { return g_CroppedViewport.x24_uvYMax; }
|
static float GetCroppedViewportUVYMax() { return g_CroppedViewport.x24_uvYMax; }
|
||||||
|
|
||||||
// static boo::IGraphicsDataFactory::Platform g_BooPlatform;
|
|
||||||
// static const char* g_BooPlatformName;
|
|
||||||
// static boo::IGraphicsDataFactory* g_BooFactory;
|
|
||||||
// static boo::IGraphicsCommandQueue* g_BooMainCommandQueue;
|
|
||||||
// static boo::ObjToken<boo::ITextureR> g_SpareTexture;
|
|
||||||
|
|
||||||
static const std::array<zeus::CMatrix3f, 6> skCubeBasisMats;
|
static const std::array<zeus::CMatrix3f, 6> skCubeBasisMats;
|
||||||
|
|
||||||
// static void InitializeBoo(boo::IGraphicsDataFactory* factory, boo::IGraphicsCommandQueue* cc,
|
|
||||||
// const boo::ObjToken<boo::ITextureR>& spareTex) {
|
|
||||||
// g_BooPlatform = factory->platform();
|
|
||||||
// g_BooPlatformName = factory->platformName();
|
|
||||||
// g_BooFactory = factory;
|
|
||||||
// g_BooMainCommandQueue = cc;
|
|
||||||
// g_SpareTexture = spareTex;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void ShutdownBoo() {
|
|
||||||
// g_BooFactory = nullptr;
|
|
||||||
// g_BooMainCommandQueue = nullptr;
|
|
||||||
// g_SpareTexture.reset();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static const char* PlatformName() { return g_BooPlatformName; }
|
|
||||||
|
|
||||||
// static void CommitResources(const boo::FactoryCommitFunc& commitFunc __BooTraceArgs) {
|
|
||||||
// g_BooFactory->commitTransaction(commitFunc __BooTraceArgsUse);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static bool g_commitAsLazy;
|
|
||||||
// static void SetCommitResourcesAsLazy(bool newStatus) {
|
|
||||||
// if (newStatus != g_commitAsLazy) {
|
|
||||||
// g_commitAsLazy = newStatus;
|
|
||||||
// if (!newStatus && g_BooFactory) {
|
|
||||||
// g_BooFactory->commitPendingTransaction();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void CommitResources(const boo::FactoryCommitFunc& commitFunc __BooTraceArgs) {
|
|
||||||
// CommitResources(commitFunc __BooTraceArgsUse, g_commitAsLazy);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void CommitResources(const boo::FactoryCommitFunc& commitFunc __BooTraceArgs, bool lazy) {
|
|
||||||
// if (!g_BooFactory) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (lazy) {
|
|
||||||
// g_BooFactory->lazyCommitTransaction(commitFunc __BooTraceArgsUse);
|
|
||||||
// } else {
|
|
||||||
// g_BooFactory->commitTransaction(commitFunc __BooTraceArgsUse);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void SetShaderDataBinding(const boo::ObjToken<boo::IShaderDataBinding>& binding) {
|
|
||||||
// g_BooMainCommandQueue->setShaderDataBinding(binding);
|
|
||||||
// }
|
|
||||||
static void ResolveSpareTexture(const SClipScreenRect& rect, int bindIdx = 0, bool clearDepth = false) {
|
static void ResolveSpareTexture(const SClipScreenRect& rect, int bindIdx = 0, bool clearDepth = false) {
|
||||||
aurora::gfx::resolve_color({rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}, bindIdx, clearDepth);
|
aurora::gfx::resolve_color({rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}, bindIdx, clearDepth);
|
||||||
// boo::SWindowRect wrect = {rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height};
|
}
|
||||||
// g_BooMainCommandQueue->resolveBindTexture(g_SpareTexture, wrect, true, bindIdx, true, false, clearDepth);
|
static void LoadDolphinSpareTexture(int bindIdx, GX::TexMapID id) {
|
||||||
|
aurora::gfx::bind_color(bindIdx, id);
|
||||||
}
|
}
|
||||||
static void ResolveSpareDepth(const SClipScreenRect& rect, int bindIdx = 0) {
|
static void ResolveSpareDepth(const SClipScreenRect& rect, int bindIdx = 0) {
|
||||||
aurora::gfx::resolve_depth({rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}, bindIdx);
|
aurora::gfx::resolve_depth({rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}, bindIdx);
|
||||||
// boo::SWindowRect wrect = {rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height};
|
|
||||||
// g_BooMainCommandQueue->resolveBindTexture(g_SpareTexture, wrect, true, bindIdx, false, true);
|
|
||||||
}
|
}
|
||||||
// static void DrawInstances(size_t start, size_t count, size_t instCount, size_t startInst = 0) {
|
|
||||||
// g_BooMainCommandQueue->drawInstances(start, count, instCount, startInst);
|
|
||||||
// }
|
|
||||||
// static void DrawArray(size_t start, size_t count) { g_BooMainCommandQueue->draw(start, count); }
|
|
||||||
// static void DrawArrayIndexed(size_t start, size_t count) { g_BooMainCommandQueue->drawIndexed(start, count); }
|
|
||||||
|
|
||||||
static void SetTevStates(EStreamFlags flags) noexcept;
|
static void SetTevStates(EStreamFlags flags) noexcept;
|
||||||
static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass);
|
static void SetTevOp(ERglTevStage stage, const CTevCombiners::CTevPass& pass);
|
||||||
|
|
|
@ -473,21 +473,15 @@ void CInGameGuiManager::Draw(CStateManager& stateMgr) {
|
||||||
// if (!GetIsGameDraw())
|
// if (!GetIsGameDraw())
|
||||||
// g_Renderer->x318_26_requestRGBA6 = true;
|
// g_Renderer->x318_26_requestRGBA6 = true;
|
||||||
if (x1d8_onScreenTexAlpha > 0.f && x1dc_onScreenTexTok.IsLoaded()) {
|
if (x1d8_onScreenTexAlpha > 0.f && x1dc_onScreenTexTok.IsLoaded()) {
|
||||||
if (!m_onScreenQuad || m_onScreenQuad->GetTex().GetObj() != x1dc_onScreenTexTok.GetObj())
|
g_Renderer->SetDepthReadWrite(false, false);
|
||||||
m_onScreenQuad.emplace(EFilterType::Blend, x1dc_onScreenTexTok);
|
g_Renderer->SetBlendMode_AlphaBlended();
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
|
||||||
// No depth read/write
|
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||||
// Alpha blend
|
int w = x1c4_onScreenTex.x4_origin.x;
|
||||||
int w = (CGraphics::GetViewportLeft() + (x1c4_onScreenTex.x4_origin.x - CGraphics::GetViewportWidth()) / 2 +
|
int h = x1c4_onScreenTex.x4_origin.y;
|
||||||
x1c4_onScreenTex.xc_extent.x) -
|
int x = CGraphics::GetViewportLeft() + (CGraphics::GetViewportWidth() - w) / 2 + x1c4_onScreenTex.xc_extent.x;
|
||||||
x1c4_onScreenTex.x4_origin.x;
|
int y = CGraphics::GetViewportTop() + (CGraphics::GetViewportHeight() - h) / 2 - x1c4_onScreenTex.xc_extent.y;
|
||||||
int h = (CGraphics::GetViewportTop() + (x1c4_onScreenTex.x4_origin.y - CGraphics::GetViewportHeight()) / 2 -
|
CGraphics::Render2D(*x1dc_onScreenTexTok, x, y, w, h, zeus::CColor{1.f, x1d8_onScreenTexAlpha});
|
||||||
x1c4_onScreenTex.xc_extent.y) -
|
|
||||||
x1c4_onScreenTex.x4_origin.y;
|
|
||||||
zeus::CRectangle rect(x1c4_onScreenTex.x4_origin.x / float(CGraphics::GetViewportWidth()),
|
|
||||||
x1c4_onScreenTex.x4_origin.y / float(CGraphics::GetViewportHeight()),
|
|
||||||
w / float(CGraphics::GetViewportWidth()), h / float(CGraphics::GetViewportHeight()));
|
|
||||||
m_onScreenQuad->draw(zeus::CColor(1.f, x1d8_onScreenTexAlpha), 1.f, rect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float staticAlpha = 0.f;
|
float staticAlpha = 0.f;
|
||||||
|
@ -517,8 +511,10 @@ void CInGameGuiManager::Draw(CStateManager& stateMgr) {
|
||||||
x40_samusReflection->Draw(stateMgr);
|
x40_samusReflection->Draw(stateMgr);
|
||||||
if (drawVisor) {
|
if (drawVisor) {
|
||||||
CGraphics::SetDepthRange(DEPTH_HUD, DEPTH_SCREEN_ACTORS);
|
CGraphics::SetDepthRange(DEPTH_HUD, DEPTH_SCREEN_ACTORS);
|
||||||
if (staticAlpha > 0.f)
|
if (staticAlpha > 0.f) {
|
||||||
m_randomStatic.draw(zeus::CColor(1.f, staticAlpha), 1.f);
|
CCameraFilterPass::DrawFilter(EFilterType::Blend, EFilterShape::RandomStatic, zeus::CColor{1.f, staticAlpha},
|
||||||
|
nullptr, 1.f);
|
||||||
|
}
|
||||||
x34_samusHud->Draw(stateMgr, x1f4_visorStaticAlpha * (1.f - staticAlpha), x1e0_helmetVisMode,
|
x34_samusHud->Draw(stateMgr, x1f4_visorStaticAlpha * (1.f - staticAlpha), x1e0_helmetVisMode,
|
||||||
x1ec_hudVisMode != EHudVisMode::Zero, x1e4_enableTargetingManager && !scanVisor);
|
x1ec_hudVisMode != EHudVisMode::Zero, x1e4_enableTargetingManager && !scanVisor);
|
||||||
}
|
}
|
||||||
|
@ -552,10 +548,10 @@ void CInGameGuiManager::Draw(CStateManager& stateMgr) {
|
||||||
CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_HUD);
|
CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_HUD);
|
||||||
x148_model_automapper->SetIsVisible(true);
|
x148_model_automapper->SetIsVisible(true);
|
||||||
x148_model_automapper->Draw(CGuiWidgetDrawParms(1.f, zeus::skZero3f));
|
x148_model_automapper->Draw(CGuiWidgetDrawParms(1.f, zeus::skZero3f));
|
||||||
// ZTest no write
|
CGraphics::SetDepthWriteMode(true, ERglEnum::GEqual, false);
|
||||||
x38_autoMapper->Draw(stateMgr, zeus::CTransform::Translate(0.f, 0.02f, 0.f) * x18c_mapCamXf,
|
x38_autoMapper->Draw(stateMgr, zeus::CTransform::Translate(0.f, 0.02f, 0.f) * x18c_mapCamXf,
|
||||||
mapAlpha * x1f4_visorStaticAlpha * t);
|
mapAlpha * x1f4_visorStaticAlpha * t);
|
||||||
// Zest and write
|
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
|
||||||
x148_model_automapper->SetIsVisible(false);
|
x148_model_automapper->SetIsVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +586,7 @@ void CInGameGuiManager::Draw(CStateManager& stateMgr) {
|
||||||
dieDur = 6.f;
|
dieDur = 6.f;
|
||||||
|
|
||||||
float alpha = zeus::clamp(0.f, stateMgr.GetPlayer().GetDeathTime() / dieDur, 1.f);
|
float alpha = zeus::clamp(0.f, stateMgr.GetPlayer().GetDeathTime() / dieDur, 1.f);
|
||||||
m_deathWhiteout.draw(zeus::CColor(1.f, alpha));
|
CCameraFilterPass::DrawFilter(EFilterType::Blend, EFilterShape::Fullscreen, zeus::CColor{1.f, alpha}, nullptr, 1.f);
|
||||||
|
|
||||||
float zStart = dieDur - 0.5f - 0.5f - 1.f;
|
float zStart = dieDur - 0.5f - 0.5f - 1.f;
|
||||||
float xStart = 0.5f - zStart;
|
float xStart = 0.5f - zStart;
|
||||||
|
@ -601,24 +597,24 @@ void CInGameGuiManager::Draw(CStateManager& stateMgr) {
|
||||||
float colT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - colStart) / 0.5f, 1.f);
|
float colT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - colStart) / 0.5f, 1.f);
|
||||||
SClipScreenRect rect(CGraphics::g_Viewport);
|
SClipScreenRect rect(CGraphics::g_Viewport);
|
||||||
CGraphics::ResolveSpareTexture(rect);
|
CGraphics::ResolveSpareTexture(rect);
|
||||||
m_deathBlackout.draw(zeus::skBlack);
|
CCameraFilterPass::DrawFilter(EFilterType::Blend, EFilterShape::Fullscreen, zeus::skBlack, nullptr, 1.f);
|
||||||
float z = 0.5f * (zT * zT * zT * zT * zT * (CGraphics::GetViewportHeight() - 12.f) + 12.f);
|
float z = 0.5f * (zT * zT * zT * zT * zT * (CGraphics::GetViewportHeight() - 12.f) + 12.f);
|
||||||
float x = 0.5f * (xT * (CGraphics::GetViewportWidth() - 12.f) + 12.f);
|
float x = 0.5f * (xT * (CGraphics::GetViewportWidth() - 12.f) + 12.f);
|
||||||
|
|
||||||
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
|
// const std::array<CTexturedQuadFilter::Vert, 4> verts{{
|
||||||
{{-x, 0.f, z}, {0.f, 0.f}},
|
// {{-x, 0.f, z}, {0.f, 0.f}},
|
||||||
{{-x, 0.f, -z}, {0.f, 1.f}},
|
// {{-x, 0.f, -z}, {0.f, 1.f}},
|
||||||
{{x, 0.f, z}, {1.f, 0.f}},
|
// {{x, 0.f, z}, {1.f, 0.f}},
|
||||||
{{x, 0.f, -z}, {1.f, 1.f}},
|
// {{x, 0.f, -z}, {1.f, 1.f}},
|
||||||
}};
|
// }};
|
||||||
|
|
||||||
// if (!m_deathRenderTexQuad)
|
// if (!m_deathRenderTexQuad)
|
||||||
// m_deathRenderTexQuad.emplace(EFilterType::Blend, CGraphics::g_SpareTexture.get());
|
// m_deathRenderTexQuad.emplace(EFilterType::Blend, CGraphics::g_SpareTexture.get());
|
||||||
// m_deathRenderTexQuad->drawVerts(zeus::CColor(1.f, colT), verts);
|
// m_deathRenderTexQuad->drawVerts(zeus::CColor(1.f, colT), verts);
|
||||||
|
|
||||||
if (!m_deathDotQuad)
|
// if (!m_deathDotQuad)
|
||||||
m_deathDotQuad.emplace(EFilterType::Multiply, x50_deathDot);
|
// m_deathDotQuad.emplace(EFilterType::Multiply, x50_deathDot);
|
||||||
m_deathDotQuad->drawVerts(zeus::CColor(1.f, colT), verts);
|
// m_deathDotQuad->drawVerts(zeus::CColor(1.f, colT), verts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,6 @@ private:
|
||||||
SOnScreenTex x1c4_onScreenTex;
|
SOnScreenTex x1c4_onScreenTex;
|
||||||
float x1d8_onScreenTexAlpha = 0.f;
|
float x1d8_onScreenTexAlpha = 0.f;
|
||||||
TLockedToken<CTexture> x1dc_onScreenTexTok; // Used to be heap-allocated
|
TLockedToken<CTexture> x1dc_onScreenTexTok; // Used to be heap-allocated
|
||||||
std::optional<CTexturedQuadFilterAlpha> m_onScreenQuad;
|
|
||||||
EHelmetVisMode x1e0_helmetVisMode;
|
EHelmetVisMode x1e0_helmetVisMode;
|
||||||
bool x1e4_enableTargetingManager;
|
bool x1e4_enableTargetingManager;
|
||||||
bool x1e8_enableAutoMapper;
|
bool x1e8_enableAutoMapper;
|
||||||
|
@ -100,12 +99,6 @@ private:
|
||||||
bool x1f8_26_deferTransition : 1 = false;
|
bool x1f8_26_deferTransition : 1 = false;
|
||||||
bool x1f8_27_exitSaveUI : 1 = true;
|
bool x1f8_27_exitSaveUI : 1 = true;
|
||||||
|
|
||||||
std::optional<CTexturedQuadFilter> m_deathRenderTexQuad;
|
|
||||||
std::optional<CTexturedQuadFilter> m_deathDotQuad;
|
|
||||||
CRandomStaticFilter m_randomStatic{EFilterType::Blend};
|
|
||||||
CColoredQuadFilter m_deathWhiteout{EFilterType::Blend};
|
|
||||||
CColoredQuadFilter m_deathBlackout{EFilterType::Blend};
|
|
||||||
|
|
||||||
static std::vector<TLockedToken<CDependencyGroup>> LockPauseScreenDependencies();
|
static std::vector<TLockedToken<CDependencyGroup>> LockPauseScreenDependencies();
|
||||||
bool CheckDGRPLoadComplete() const;
|
bool CheckDGRPLoadComplete() const;
|
||||||
void BeginStateTransition(EInGameGuiState state, CStateManager& stateMgr);
|
void BeginStateTransition(EInGameGuiState state, CStateManager& stateMgr);
|
||||||
|
|
|
@ -355,33 +355,28 @@ void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* t
|
||||||
rect.x10_height = int(vpH);
|
rect.x10_height = int(vpH);
|
||||||
CGraphics::ResolveSpareTexture(rect);
|
CGraphics::ResolveSpareTexture(rect);
|
||||||
|
|
||||||
|
// TODO hack; figure out why needed
|
||||||
|
CGraphics::SetCullMode(ERglCullMode::None);
|
||||||
|
|
||||||
|
{
|
||||||
|
SCOPED_GRAPHICS_DEBUG_GROUP("x64_scanDim Draw", zeus::skMagenta);
|
||||||
x64_scanDim.Draw();
|
x64_scanDim.Draw();
|
||||||
|
}
|
||||||
|
|
||||||
g_Renderer->SetViewportOrtho(true, -1.f, 1.f);
|
g_Renderer->SetViewportOrtho(true, -1.f, 1.f);
|
||||||
|
|
||||||
const zeus::CTransform windowScale = zeus::CTransform::Scale(x48_interpWindowDims.x(), 1.f, x48_interpWindowDims.y());
|
const zeus::CTransform windowScale = zeus::CTransform::Scale(x48_interpWindowDims.x(), 1.f, x48_interpWindowDims.y());
|
||||||
const zeus::CTransform seventeenScale = zeus::CTransform::Scale(17.f * vpScale, 1.f, 17.f * vpScale);
|
const zeus::CTransform seventeenScale = zeus::CTransform::Scale(17.f * vpScale, 1.f, 17.f * vpScale);
|
||||||
CGraphics::SetModelMatrix(seventeenScale * windowScale);
|
const zeus::CTransform mm = seventeenScale * windowScale;
|
||||||
|
g_Renderer->SetModelMatrix(mm);
|
||||||
|
CGraphics::LoadDolphinSpareTexture(0, GX::TEXMAP0);
|
||||||
|
|
||||||
const float uvX0 = float(rect.x4_left) / float(CGraphics::GetViewportWidth());
|
if (x108_newScanPane) {
|
||||||
const float uvX1 = float(rect.x4_left + rect.xc_width) / float(CGraphics::GetViewportWidth());
|
SCOPED_GRAPHICS_DEBUG_GROUP("x108_newScanPane Draw", zeus::skMagenta);
|
||||||
const float uvY0 = float(rect.x8_top) / float(CGraphics::GetViewportHeight());
|
x108_newScanPane->Draw(CModelFlags{5, 0, 7, zeus::CColor{1.f, transFactor}});
|
||||||
const float uvY1 = float(rect.x8_top + rect.x10_height) / float(CGraphics::GetViewportHeight());
|
}
|
||||||
std::array<CTexturedQuadFilter::Vert, 4> rttVerts{{
|
|
||||||
{{-5.f, 0.f, 4.45f}, {uvX0, uvY0}},
|
|
||||||
{{5.f, 0.f, 4.45f}, {uvX1, uvY0}},
|
|
||||||
{{-5.f, 0.f, -4.45f}, {uvX0, uvY1}},
|
|
||||||
{{5.f, 0.f, -4.45f}, {uvX1, uvY1}},
|
|
||||||
}};
|
|
||||||
// if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) {
|
|
||||||
// rttVerts[0].m_uv.y() = uvY1;
|
|
||||||
// rttVerts[1].m_uv.y() = uvY1;
|
|
||||||
// rttVerts[2].m_uv.y() = uvY0;
|
|
||||||
// rttVerts[3].m_uv.y() = uvY0;
|
|
||||||
// }
|
|
||||||
// x108_newScanPane.drawVerts(zeus::CColor(1.f, transFactor), rttVerts);
|
|
||||||
|
|
||||||
// No cull faces
|
CGraphics::SetCullMode(ERglCullMode::None);
|
||||||
|
|
||||||
zeus::CColor frameColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanFrameInactiveColor(),
|
zeus::CColor frameColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanFrameInactiveColor(),
|
||||||
g_tweakGuiColors->GetScanFrameActiveColor(), x54c_scanFrameColorInterp);
|
g_tweakGuiColors->GetScanFrameActiveColor(), x54c_scanFrameColorInterp);
|
||||||
|
@ -390,7 +385,6 @@ void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* t
|
||||||
CModelFlags flags(5, 0, 0,
|
CModelFlags flags(5, 0, 0,
|
||||||
frameColor + g_tweakGuiColors->GetScanFrameImpulseColor() *
|
frameColor + g_tweakGuiColors->GetScanFrameImpulseColor() *
|
||||||
zeus::CColor(x550_scanFrameColorImpulseInterp, x550_scanFrameColorImpulseInterp));
|
zeus::CColor(x550_scanFrameColorImpulseInterp, x550_scanFrameColorImpulseInterp));
|
||||||
// TODO flags.m_noCull = true;
|
|
||||||
|
|
||||||
const zeus::CTransform verticalFlip = zeus::CTransform::Scale(1.f, 1.f, -1.f);
|
const zeus::CTransform verticalFlip = zeus::CTransform::Scale(1.f, 1.f, -1.f);
|
||||||
const zeus::CTransform horizontalFlip = zeus::CTransform::Scale(-1.f, 1.f, 1.f);
|
const zeus::CTransform horizontalFlip = zeus::CTransform::Scale(-1.f, 1.f, 1.f);
|
||||||
|
@ -454,7 +448,7 @@ void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* t
|
||||||
xf0_scanFrameStretchSide->Draw(flags);
|
xf0_scanFrameStretchSide->Draw(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cull faces
|
CGraphics::SetCullMode(ERglCullMode::Front);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerVisor::DrawXRayEffect(const CStateManager&) {
|
void CPlayerVisor::DrawXRayEffect(const CStateManager&) {
|
||||||
|
|
|
@ -98,6 +98,7 @@ void set_scissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) noexcept;
|
||||||
|
|
||||||
void resolve_color(const ClipRect& rect, uint32_t bind, bool clear_depth) noexcept;
|
void resolve_color(const ClipRect& rect, uint32_t bind, bool clear_depth) noexcept;
|
||||||
void resolve_depth(const ClipRect& rect, uint32_t bind) noexcept;
|
void resolve_depth(const ClipRect& rect, uint32_t bind) noexcept;
|
||||||
|
void bind_color(u32 bindIdx, GX::TexMapID id) noexcept;
|
||||||
|
|
||||||
void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v, float h_pad,
|
void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v, float h_pad,
|
||||||
float v_pad) noexcept;
|
float v_pad) noexcept;
|
||||||
|
@ -106,7 +107,6 @@ TextureHandle new_static_texture_2d(uint32_t width, uint32_t height, uint32_t mi
|
||||||
ArrayRef<uint8_t> data, zstring_view label) noexcept;
|
ArrayRef<uint8_t> data, zstring_view label) noexcept;
|
||||||
TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, metaforce::ETexelFormat format,
|
TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t mips, metaforce::ETexelFormat format,
|
||||||
zstring_view label) noexcept;
|
zstring_view label) noexcept;
|
||||||
TextureHandle new_render_texture(uint32_t width, uint32_t height, uint32_t color_bind_count, uint32_t depth_bind_count,
|
TextureHandle new_render_texture(uint32_t width, uint32_t height, zstring_view label) noexcept;
|
||||||
zstring_view label) noexcept;
|
|
||||||
void write_texture(const TextureHandle& handle, ArrayRef<uint8_t> data) noexcept;
|
void write_texture(const TextureHandle& handle, ArrayRef<uint8_t> data) noexcept;
|
||||||
} // namespace aurora::gfx
|
} // namespace aurora::gfx
|
||||||
|
|
|
@ -300,52 +300,26 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
|
||||||
};
|
};
|
||||||
auto encoder = g_device.CreateCommandEncoder(&encoderDescriptor);
|
auto encoder = g_device.CreateCommandEncoder(&encoderDescriptor);
|
||||||
gfx::end_frame(encoder);
|
gfx::end_frame(encoder);
|
||||||
|
gfx::render(encoder);
|
||||||
{
|
{
|
||||||
const std::array attachments{
|
const std::array attachments{
|
||||||
wgpu::RenderPassColorAttachment{
|
wgpu::RenderPassColorAttachment{
|
||||||
.view = view,
|
.view = view,
|
||||||
// .resolveTarget = g_frameBufferResolved.view,
|
|
||||||
.loadOp = wgpu::LoadOp::Clear,
|
.loadOp = wgpu::LoadOp::Clear,
|
||||||
.storeOp = wgpu::StoreOp::Store,
|
.storeOp = wgpu::StoreOp::Store,
|
||||||
.clearValue =
|
|
||||||
{
|
|
||||||
.r = gfx::gx::g_gxState.clearColor.r(),
|
|
||||||
.g = gfx::gx::g_gxState.clearColor.g(),
|
|
||||||
.b = gfx::gx::g_gxState.clearColor.b(),
|
|
||||||
.a = gfx::gx::g_gxState.clearColor.a(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const auto depthStencilAttachment = wgpu::RenderPassDepthStencilAttachment{
|
|
||||||
.view = g_depthBuffer.view,
|
|
||||||
.depthLoadOp = wgpu::LoadOp::Clear,
|
|
||||||
.depthStoreOp = wgpu::StoreOp::Discard,
|
|
||||||
.clearDepth = 1.f,
|
|
||||||
};
|
|
||||||
auto renderPassDescriptor = wgpu::RenderPassDescriptor{
|
|
||||||
.label = "Main render pass",
|
|
||||||
.colorAttachmentCount = attachments.size(),
|
|
||||||
.colorAttachments = attachments.data(),
|
|
||||||
.depthStencilAttachment = &depthStencilAttachment,
|
|
||||||
};
|
|
||||||
auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
|
|
||||||
gfx::render(pass);
|
|
||||||
pass.End();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const std::array attachments{
|
|
||||||
wgpu::RenderPassColorAttachment{
|
|
||||||
.view = view,
|
|
||||||
.loadOp = wgpu::LoadOp::Load,
|
|
||||||
.storeOp = wgpu::StoreOp::Store,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
auto renderPassDescriptor = wgpu::RenderPassDescriptor{
|
auto renderPassDescriptor = wgpu::RenderPassDescriptor{
|
||||||
.label = "ImGui render pass",
|
.label = "Post render pass",
|
||||||
.colorAttachmentCount = attachments.size(),
|
.colorAttachmentCount = attachments.size(),
|
||||||
.colorAttachments = attachments.data(),
|
.colorAttachments = attachments.data(),
|
||||||
};
|
};
|
||||||
auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
|
auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
|
||||||
|
// Copy EFB -> XFB (swapchain)
|
||||||
|
pass.SetPipeline(gpu::g_CopyPipeline);
|
||||||
|
pass.SetBindGroup(0, gpu::g_CopyBindGroup);
|
||||||
|
pass.Draw(3);
|
||||||
|
// Render ImGui
|
||||||
imgui::render(pass);
|
imgui::render(pass);
|
||||||
pass.End();
|
pass.End();
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,17 @@ static wgpu::SupportedLimits g_cachedLimits;
|
||||||
static ShaderState g_state;
|
static ShaderState g_state;
|
||||||
static PipelineRef g_currentPipeline;
|
static PipelineRef g_currentPipeline;
|
||||||
|
|
||||||
static std::vector<Command> g_commands;
|
using CommandList = std::vector<Command>;
|
||||||
|
struct RenderPass {
|
||||||
|
u32 resolveTarget = UINT32_MAX;
|
||||||
|
ClipRect resolveRect;
|
||||||
|
zeus::CColor clearColor{0.f, 0.f};
|
||||||
|
CommandList commands;
|
||||||
|
bool clear = true;
|
||||||
|
};
|
||||||
|
static std::vector<RenderPass> g_renderPasses;
|
||||||
|
static u32 g_currentRenderPass;
|
||||||
|
std::vector<TextureHandle> g_resolvedTextures;
|
||||||
|
|
||||||
static ByteBuffer g_serializedPipelines{};
|
static ByteBuffer g_serializedPipelines{};
|
||||||
static u32 g_serializedPipelineCount = 0;
|
static u32 g_serializedPipelineCount = 0;
|
||||||
|
@ -175,27 +185,23 @@ static PipelineRef find_pipeline(ShaderType type, const PipelineConfig& config,
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void push_draw_command(ShaderDrawCommand data) {
|
static inline void push_command(CommandType type, const Command::Data& data) {
|
||||||
g_commands.push_back({
|
g_renderPasses[g_currentRenderPass].commands.push_back({
|
||||||
.type = CommandType::Draw,
|
.type = type,
|
||||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||||
.debugGroupStack = g_debugGroupStack,
|
.debugGroupStack = g_debugGroupStack,
|
||||||
#endif
|
#endif
|
||||||
.data = {.draw = data},
|
.data = data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void push_draw_command(ShaderDrawCommand data) { push_command(CommandType::Draw, Command::Data{.draw = data}); }
|
||||||
|
|
||||||
static Command::Data::SetViewportCommand g_cachedViewport;
|
static Command::Data::SetViewportCommand g_cachedViewport;
|
||||||
void set_viewport(float left, float top, float width, float height, float znear, float zfar) noexcept {
|
void set_viewport(float left, float top, float width, float height, float znear, float zfar) noexcept {
|
||||||
Command::Data::SetViewportCommand cmd{left, top, width, height, znear, zfar};
|
Command::Data::SetViewportCommand cmd{left, top, width, height, znear, zfar};
|
||||||
if (cmd != g_cachedViewport) {
|
if (cmd != g_cachedViewport) {
|
||||||
g_commands.push_back({
|
push_command(CommandType::SetViewport, Command::Data{.setViewport = cmd});
|
||||||
.type = CommandType::SetViewport,
|
|
||||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
|
||||||
.debugGroupStack = g_debugGroupStack,
|
|
||||||
#endif
|
|
||||||
.data = {.setViewport = cmd},
|
|
||||||
});
|
|
||||||
g_cachedViewport = cmd;
|
g_cachedViewport = cmd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,24 +209,40 @@ static Command::Data::SetScissorCommand g_cachedScissor;
|
||||||
void set_scissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) noexcept {
|
void set_scissor(uint32_t x, uint32_t y, uint32_t w, uint32_t h) noexcept {
|
||||||
Command::Data::SetScissorCommand cmd{x, y, w, h};
|
Command::Data::SetScissorCommand cmd{x, y, w, h};
|
||||||
if (cmd != g_cachedScissor) {
|
if (cmd != g_cachedScissor) {
|
||||||
g_commands.push_back({
|
push_command(CommandType::SetScissor, Command::Data{.setScissor = cmd});
|
||||||
.type = CommandType::SetScissor,
|
|
||||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
|
||||||
.debugGroupStack = g_debugGroupStack,
|
|
||||||
#endif
|
|
||||||
.data = {.setScissor = cmd},
|
|
||||||
});
|
|
||||||
g_cachedScissor = cmd;
|
g_cachedScissor = cmd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator==(const wgpu::Extent3D& lhs, const wgpu::Extent3D& rhs) {
|
||||||
|
return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depthOrArrayLayers == rhs.depthOrArrayLayers;
|
||||||
|
}
|
||||||
|
|
||||||
void resolve_color(const ClipRect& rect, uint32_t bind, bool clear_depth) noexcept {
|
void resolve_color(const ClipRect& rect, uint32_t bind, bool clear_depth) noexcept {
|
||||||
// TODO
|
if (g_resolvedTextures.size() < bind + 1) {
|
||||||
|
g_resolvedTextures.resize(bind + 1);
|
||||||
|
}
|
||||||
|
const wgpu::Extent3D size{
|
||||||
|
.width = static_cast<uint32_t>(rect.width),
|
||||||
|
.height = static_cast<uint32_t>(rect.height),
|
||||||
|
};
|
||||||
|
if (!g_resolvedTextures[bind] || g_resolvedTextures[bind].ref->size != size) {
|
||||||
|
g_resolvedTextures[bind] = new_render_texture(rect.width, rect.height, "Resolved Texture");
|
||||||
|
}
|
||||||
|
auto& currentPass = g_renderPasses[g_currentRenderPass];
|
||||||
|
currentPass.resolveTarget = bind;
|
||||||
|
currentPass.resolveRect = rect;
|
||||||
|
auto& newPass = g_renderPasses.emplace_back();
|
||||||
|
newPass.clearColor = gx::g_gxState.clearColor;
|
||||||
|
newPass.clear = false; // TODO
|
||||||
|
++g_currentRenderPass;
|
||||||
}
|
}
|
||||||
void resolve_depth(const ClipRect& rect, uint32_t bind) noexcept {
|
void resolve_depth(const ClipRect& rect, uint32_t bind) noexcept {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bind_color(u32 bindIdx, GX::TexMapID id) noexcept { gx::g_gxState.textures[static_cast<size_t>(id)] = {bindIdx}; }
|
||||||
|
|
||||||
void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v, float h_pad,
|
void queue_movie_player(const TextureHandle& tex_y, const TextureHandle& tex_u, const TextureHandle& tex_v, float h_pad,
|
||||||
float v_pad) noexcept {
|
float v_pad) noexcept {
|
||||||
auto data = movie_player::make_draw_data(g_state.moviePlayer, tex_y, tex_u, tex_v, h_pad, v_pad);
|
auto data = movie_player::make_draw_data(g_state.moviePlayer, tex_y, tex_u, tex_v, h_pad, v_pad);
|
||||||
|
@ -323,6 +345,7 @@ void initialize() {
|
||||||
{
|
{
|
||||||
// Load serialized pipeline cache
|
// Load serialized pipeline cache
|
||||||
std::ifstream file("pipeline_cache.bin", std::ios::in | std::ios::binary | std::ios::ate);
|
std::ifstream file("pipeline_cache.bin", std::ios::in | std::ios::binary | std::ios::ate);
|
||||||
|
if (file) {
|
||||||
const size_t size = file.tellg();
|
const size_t size = file.tellg();
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
constexpr size_t headerSize = sizeof(g_serializedPipelineCount);
|
constexpr size_t headerSize = sizeof(g_serializedPipelineCount);
|
||||||
|
@ -332,6 +355,7 @@ void initialize() {
|
||||||
file.read(reinterpret_cast<char*>(g_serializedPipelines.data()), size - headerSize);
|
file.read(reinterpret_cast<char*>(g_serializedPipelines.data()), size - headerSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (g_serializedPipelineCount > 0) {
|
if (g_serializedPipelineCount > 0) {
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
while (offset < g_serializedPipelines.size()) {
|
while (offset < g_serializedPipelines.size()) {
|
||||||
|
@ -390,9 +414,11 @@ void shutdown() {
|
||||||
{
|
{
|
||||||
// Write serialized pipelines to file
|
// Write serialized pipelines to file
|
||||||
std::ofstream file("pipeline_cache.bin", std::ios::out | std::ios::trunc | std::ios::binary);
|
std::ofstream file("pipeline_cache.bin", std::ios::out | std::ios::trunc | std::ios::binary);
|
||||||
|
if (file) {
|
||||||
file.write(reinterpret_cast<const char*>(&g_serializedPipelineCount), sizeof(g_serializedPipelineCount));
|
file.write(reinterpret_cast<const char*>(&g_serializedPipelineCount), sizeof(g_serializedPipelineCount));
|
||||||
file.write(reinterpret_cast<const char*>(g_serializedPipelines.data()), g_serializedPipelines.size());
|
file.write(reinterpret_cast<const char*>(g_serializedPipelines.data()), g_serializedPipelines.size());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gx::shutdown();
|
gx::shutdown();
|
||||||
|
|
||||||
|
@ -440,6 +466,9 @@ void begin_frame() {
|
||||||
mapBuffer(g_uniforms, UniformBufferSize);
|
mapBuffer(g_uniforms, UniformBufferSize);
|
||||||
mapBuffer(g_indices, IndexBufferSize);
|
mapBuffer(g_indices, IndexBufferSize);
|
||||||
mapBuffer(g_storage, StorageBufferSize);
|
mapBuffer(g_storage, StorageBufferSize);
|
||||||
|
|
||||||
|
g_renderPasses.emplace_back();
|
||||||
|
g_currentRenderPass = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for imgui debug
|
// for imgui debug
|
||||||
|
@ -468,13 +497,80 @@ void end_frame(const wgpu::CommandEncoder& cmd) {
|
||||||
map_staging_buffer();
|
map_staging_buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void render(const wgpu::RenderPassEncoder& pass) {
|
void render(wgpu::CommandEncoder& cmd) {
|
||||||
|
for (u32 i = 0; i < g_renderPasses.size(); ++i) {
|
||||||
|
const auto& passInfo = g_renderPasses[i];
|
||||||
|
bool finalPass = i == g_renderPasses.size() - 1;
|
||||||
|
if (finalPass && passInfo.resolveTarget != UINT32_MAX) {
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("Final render pass must not have resolve target"));
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
const std::array attachments{
|
||||||
|
wgpu::RenderPassColorAttachment{
|
||||||
|
.view = gpu::g_frameBuffer.view,
|
||||||
|
.resolveTarget = gpu::g_graphicsConfig.msaaSamples > 1 ? gpu::g_frameBufferResolved.view : nullptr,
|
||||||
|
.loadOp = passInfo.clear ? wgpu::LoadOp::Clear : wgpu::LoadOp::Load,
|
||||||
|
.storeOp = wgpu::StoreOp::Store,
|
||||||
|
.clearValue =
|
||||||
|
{
|
||||||
|
.r = passInfo.clearColor.r(),
|
||||||
|
.g = passInfo.clearColor.g(),
|
||||||
|
.b = passInfo.clearColor.b(),
|
||||||
|
.a = passInfo.clearColor.a(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const wgpu::RenderPassDepthStencilAttachment depthStencilAttachment{
|
||||||
|
.view = gpu::g_depthBuffer.view,
|
||||||
|
.depthLoadOp = wgpu::LoadOp::Clear,
|
||||||
|
.depthStoreOp = wgpu::StoreOp::Discard,
|
||||||
|
.depthClearValue = 1.f,
|
||||||
|
};
|
||||||
|
const auto label = fmt::format(FMT_STRING("Render pass {}"), i);
|
||||||
|
const wgpu::RenderPassDescriptor renderPassDescriptor{
|
||||||
|
.label = label.c_str(),
|
||||||
|
.colorAttachmentCount = attachments.size(),
|
||||||
|
.colorAttachments = attachments.data(),
|
||||||
|
.depthStencilAttachment = &depthStencilAttachment,
|
||||||
|
};
|
||||||
|
auto pass = cmd.BeginRenderPass(&renderPassDescriptor);
|
||||||
|
render_pass(pass, i);
|
||||||
|
pass.End();
|
||||||
|
|
||||||
|
if (passInfo.resolveTarget != UINT32_MAX) {
|
||||||
|
wgpu::ImageCopyTexture src{
|
||||||
|
.origin =
|
||||||
|
wgpu::Origin3D{
|
||||||
|
.x = static_cast<uint32_t>(passInfo.resolveRect.x),
|
||||||
|
.y = static_cast<uint32_t>(passInfo.resolveRect.y),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (gpu::g_graphicsConfig.msaaSamples > 1) {
|
||||||
|
src.texture = gpu::g_frameBufferResolved.texture;
|
||||||
|
} else {
|
||||||
|
src.texture = gpu::g_frameBuffer.texture;
|
||||||
|
}
|
||||||
|
auto& target = g_resolvedTextures[passInfo.resolveTarget];
|
||||||
|
const wgpu::ImageCopyTexture dst{
|
||||||
|
.texture = target.ref->texture,
|
||||||
|
};
|
||||||
|
const wgpu::Extent3D size{
|
||||||
|
.width = static_cast<uint32_t>(passInfo.resolveRect.width),
|
||||||
|
.height = static_cast<uint32_t>(passInfo.resolveRect.height),
|
||||||
|
};
|
||||||
|
cmd.CopyTextureToTexture(&src, &dst, &size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_renderPasses.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_pass(const wgpu::RenderPassEncoder& pass, u32 idx) {
|
||||||
g_currentPipeline = UINT64_MAX;
|
g_currentPipeline = UINT64_MAX;
|
||||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||||
std::vector<std::string> lastDebugGroupStack;
|
std::vector<std::string> lastDebugGroupStack;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (const auto& cmd : g_commands) {
|
for (const auto& cmd : g_renderPasses[idx].commands) {
|
||||||
#ifdef AURORA_GFX_DEBUG_GROUPS
|
#ifdef AURORA_GFX_DEBUG_GROUPS
|
||||||
{
|
{
|
||||||
size_t firstDiff = lastDebugGroupStack.size();
|
size_t firstDiff = lastDebugGroupStack.size();
|
||||||
|
@ -524,8 +620,6 @@ void render(const wgpu::RenderPassEncoder& pass) {
|
||||||
pass.PopDebugGroup();
|
pass.PopDebugGroup();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_commands.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bind_pipeline(PipelineRef ref, const wgpu::RenderPassEncoder& pass) {
|
bool bind_pipeline(PipelineRef ref, const wgpu::RenderPassEncoder& pass) {
|
||||||
|
|
|
@ -125,6 +125,8 @@ extern wgpu::Buffer g_uniformBuffer;
|
||||||
extern wgpu::Buffer g_indexBuffer;
|
extern wgpu::Buffer g_indexBuffer;
|
||||||
extern wgpu::Buffer g_storageBuffer;
|
extern wgpu::Buffer g_storageBuffer;
|
||||||
extern size_t g_staticStorageLastSize;
|
extern size_t g_staticStorageLastSize;
|
||||||
|
// TODO this is a bad place for this...
|
||||||
|
extern std::vector<TextureHandle> g_resolvedTextures;
|
||||||
|
|
||||||
struct TextureRef {
|
struct TextureRef {
|
||||||
wgpu::Texture texture;
|
wgpu::Texture texture;
|
||||||
|
@ -168,7 +170,8 @@ void shutdown();
|
||||||
|
|
||||||
void begin_frame();
|
void begin_frame();
|
||||||
void end_frame(const wgpu::CommandEncoder& cmd);
|
void end_frame(const wgpu::CommandEncoder& cmd);
|
||||||
void render(const wgpu::RenderPassEncoder& pass);
|
void render(wgpu::CommandEncoder& cmd);
|
||||||
|
void render_pass(const wgpu::RenderPassEncoder& pass, u32 idx);
|
||||||
void map_staging_buffer();
|
void map_staging_buffer();
|
||||||
|
|
||||||
Range push_verts(const uint8_t* data, size_t length);
|
Range push_verts(const uint8_t* data, size_t length);
|
||||||
|
|
|
@ -495,6 +495,80 @@ void populate_pipeline_config(PipelineConfig& config, GX::Primitive primitive) n
|
||||||
config.shaderConfig.indexedAttributeCount =
|
config.shaderConfig.indexedAttributeCount =
|
||||||
std::count_if(config.shaderConfig.vtxAttrs.begin(), config.shaderConfig.vtxAttrs.end(),
|
std::count_if(config.shaderConfig.vtxAttrs.begin(), config.shaderConfig.vtxAttrs.end(),
|
||||||
[](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; });
|
[](const auto type) { return type == GX::INDEX8 || type == GX::INDEX16; });
|
||||||
|
for (u8 i = 0; i < MaxTextures; ++i) {
|
||||||
|
const auto& bind = g_gxState.textures[i];
|
||||||
|
bool hasAlpha = false;
|
||||||
|
// TODO check resolved fmt
|
||||||
|
if (bind.handle) {
|
||||||
|
wgpu::TextureFormat format = bind.handle.ref->format;
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::TextureFormat::R8Unorm:
|
||||||
|
case wgpu::TextureFormat::R8Snorm:
|
||||||
|
case wgpu::TextureFormat::R8Uint:
|
||||||
|
case wgpu::TextureFormat::R8Sint:
|
||||||
|
case wgpu::TextureFormat::R16Uint:
|
||||||
|
case wgpu::TextureFormat::R16Sint:
|
||||||
|
case wgpu::TextureFormat::R16Float:
|
||||||
|
case wgpu::TextureFormat::RG8Unorm:
|
||||||
|
case wgpu::TextureFormat::RG8Snorm:
|
||||||
|
case wgpu::TextureFormat::RG8Uint:
|
||||||
|
case wgpu::TextureFormat::RG8Sint:
|
||||||
|
case wgpu::TextureFormat::R32Float:
|
||||||
|
case wgpu::TextureFormat::R32Uint:
|
||||||
|
case wgpu::TextureFormat::R32Sint:
|
||||||
|
case wgpu::TextureFormat::RG16Uint:
|
||||||
|
case wgpu::TextureFormat::RG16Sint:
|
||||||
|
case wgpu::TextureFormat::RG16Float:
|
||||||
|
case wgpu::TextureFormat::RG11B10Ufloat:
|
||||||
|
case wgpu::TextureFormat::RGB9E5Ufloat:
|
||||||
|
case wgpu::TextureFormat::RG32Float:
|
||||||
|
case wgpu::TextureFormat::RG32Uint:
|
||||||
|
case wgpu::TextureFormat::RG32Sint:
|
||||||
|
case wgpu::TextureFormat::BC4RUnorm:
|
||||||
|
case wgpu::TextureFormat::BC4RSnorm:
|
||||||
|
case wgpu::TextureFormat::BC5RGUnorm:
|
||||||
|
case wgpu::TextureFormat::BC5RGSnorm:
|
||||||
|
case wgpu::TextureFormat::BC6HRGBUfloat:
|
||||||
|
case wgpu::TextureFormat::BC6HRGBFloat:
|
||||||
|
case wgpu::TextureFormat::ETC2RGB8Unorm:
|
||||||
|
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
|
||||||
|
hasAlpha = false;
|
||||||
|
break;
|
||||||
|
case wgpu::TextureFormat::RGBA8Unorm:
|
||||||
|
case wgpu::TextureFormat::RGBA8UnormSrgb:
|
||||||
|
case wgpu::TextureFormat::RGBA8Snorm:
|
||||||
|
case wgpu::TextureFormat::RGBA8Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA8Sint:
|
||||||
|
case wgpu::TextureFormat::BGRA8Unorm:
|
||||||
|
case wgpu::TextureFormat::BGRA8UnormSrgb:
|
||||||
|
case wgpu::TextureFormat::RGB10A2Unorm:
|
||||||
|
case wgpu::TextureFormat::RGBA16Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA16Sint:
|
||||||
|
case wgpu::TextureFormat::RGBA16Float:
|
||||||
|
case wgpu::TextureFormat::RGBA32Float:
|
||||||
|
case wgpu::TextureFormat::RGBA32Uint:
|
||||||
|
case wgpu::TextureFormat::RGBA32Sint:
|
||||||
|
case wgpu::TextureFormat::BC1RGBAUnorm:
|
||||||
|
case wgpu::TextureFormat::BC1RGBAUnormSrgb:
|
||||||
|
case wgpu::TextureFormat::BC2RGBAUnorm:
|
||||||
|
case wgpu::TextureFormat::BC2RGBAUnormSrgb:
|
||||||
|
case wgpu::TextureFormat::BC3RGBAUnorm:
|
||||||
|
case wgpu::TextureFormat::BC3RGBAUnormSrgb:
|
||||||
|
case wgpu::TextureFormat::BC7RGBAUnorm:
|
||||||
|
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
|
||||||
|
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
|
||||||
|
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
|
||||||
|
case wgpu::TextureFormat::ETC2RGBA8Unorm:
|
||||||
|
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
|
||||||
|
hasAlpha = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("Unknown texture format {}"), format);
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.shaderConfig.texHasAlpha[i] = hasAlpha;
|
||||||
|
}
|
||||||
config = {
|
config = {
|
||||||
.shaderConfig = config.shaderConfig,
|
.shaderConfig = config.shaderConfig,
|
||||||
.primitive = primitive,
|
.primitive = primitive,
|
||||||
|
@ -681,10 +755,17 @@ GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& confi
|
||||||
.binding = i,
|
.binding = i,
|
||||||
.sampler = sampler_ref(tex.get_descriptor()),
|
.sampler = sampler_ref(tex.get_descriptor()),
|
||||||
};
|
};
|
||||||
|
if (tex.handle) {
|
||||||
textureEntries[i] = {
|
textureEntries[i] = {
|
||||||
.binding = i,
|
.binding = i,
|
||||||
.textureView = tex.handle.ref->view,
|
.textureView = tex.handle.ref->view,
|
||||||
};
|
};
|
||||||
|
} else if (tex.resolvedBindIdx != UINT32_MAX) {
|
||||||
|
textureEntries[i] = {
|
||||||
|
.binding = i,
|
||||||
|
.textureView = g_resolvedTextures[tex.resolvedBindIdx].ref->view,
|
||||||
|
};
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -56,15 +56,20 @@ struct TevStage {
|
||||||
static_assert(std::has_unique_object_representations_v<TevStage>);
|
static_assert(std::has_unique_object_representations_v<TevStage>);
|
||||||
struct TextureBind {
|
struct TextureBind {
|
||||||
aurora::gfx::TextureHandle handle;
|
aurora::gfx::TextureHandle handle;
|
||||||
metaforce::EClampMode clampMode;
|
metaforce::EClampMode clampMode = metaforce::EClampMode::Repeat;
|
||||||
float lod;
|
float lod = 0.f;
|
||||||
|
u32 resolvedBindIdx = UINT32_MAX;
|
||||||
|
|
||||||
TextureBind() noexcept = default;
|
TextureBind() noexcept = default;
|
||||||
|
TextureBind(u32 resolvedBindIdx) noexcept : resolvedBindIdx(resolvedBindIdx) {}
|
||||||
TextureBind(aurora::gfx::TextureHandle handle, metaforce::EClampMode clampMode, float lod) noexcept
|
TextureBind(aurora::gfx::TextureHandle handle, metaforce::EClampMode clampMode, float lod) noexcept
|
||||||
: handle(std::move(handle)), clampMode(clampMode), lod(lod) {}
|
: handle(std::move(handle)), clampMode(clampMode), lod(lod) {}
|
||||||
void reset() noexcept { handle.reset(); };
|
void reset() noexcept {
|
||||||
|
handle.reset();
|
||||||
|
resolvedBindIdx = UINT32_MAX;
|
||||||
|
};
|
||||||
[[nodiscard]] wgpu::SamplerDescriptor get_descriptor() const noexcept;
|
[[nodiscard]] wgpu::SamplerDescriptor get_descriptor() const noexcept;
|
||||||
operator bool() const noexcept { return handle; }
|
operator bool() const noexcept { return handle || resolvedBindIdx != UINT32_MAX; }
|
||||||
};
|
};
|
||||||
// For shader generation
|
// For shader generation
|
||||||
struct ColorChannelConfig {
|
struct ColorChannelConfig {
|
||||||
|
@ -182,11 +187,12 @@ struct ShaderConfig {
|
||||||
std::array<TcgConfig, MaxTexCoord> tcgs;
|
std::array<TcgConfig, MaxTexCoord> tcgs;
|
||||||
AlphaCompare alphaCompare;
|
AlphaCompare alphaCompare;
|
||||||
u32 indexedAttributeCount = 0;
|
u32 indexedAttributeCount = 0;
|
||||||
|
std::array<bool, MaxTextures> texHasAlpha;
|
||||||
bool operator==(const ShaderConfig&) const = default;
|
bool operator==(const ShaderConfig&) const = default;
|
||||||
};
|
};
|
||||||
static_assert(std::has_unique_object_representations_v<ShaderConfig>);
|
static_assert(std::has_unique_object_representations_v<ShaderConfig>);
|
||||||
|
|
||||||
constexpr u32 GXPipelineConfigVersion = 1;
|
constexpr u32 GXPipelineConfigVersion = 2;
|
||||||
struct PipelineConfig {
|
struct PipelineConfig {
|
||||||
u32 version = GXPipelineConfigVersion;
|
u32 version = GXPipelineConfigVersion;
|
||||||
ShaderConfig shaderConfig;
|
ShaderConfig shaderConfig;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <absl/container/flat_hash_map.h>
|
#include <absl/container/flat_hash_map.h>
|
||||||
|
|
||||||
constexpr bool EnableNormalVisualization = false;
|
constexpr bool EnableNormalVisualization = false;
|
||||||
|
constexpr bool EnableDebugPrints = true;
|
||||||
|
|
||||||
namespace aurora::gfx::gx {
|
namespace aurora::gfx::gx {
|
||||||
using namespace fmt::literals;
|
using namespace fmt::literals;
|
||||||
|
@ -119,6 +120,7 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Sha
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
||||||
|
// TODO check for CH_ALPHA + config.texHasAlpha
|
||||||
return fmt::format(FMT_STRING("sampled{}.{}{}{}"), stage.texMapId, chan_comp(swap.red), chan_comp(swap.green),
|
return fmt::format(FMT_STRING("sampled{}.{}{}{}"), stage.texMapId, chan_comp(swap.red), chan_comp(swap.green),
|
||||||
chan_comp(swap.blue));
|
chan_comp(swap.blue));
|
||||||
}
|
}
|
||||||
|
@ -131,6 +133,9 @@ static std::string color_arg_reg(GX::TevColorArg arg, size_t stageIdx, const Sha
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
||||||
|
if (swap.alpha == GX::CH_ALPHA && !config.texHasAlpha[stage.texMapId]) {
|
||||||
|
return "1.0";
|
||||||
|
}
|
||||||
return fmt::format(FMT_STRING("sampled{}.{}"), stage.texMapId, chan_comp(swap.alpha));
|
return fmt::format(FMT_STRING("sampled{}.{}"), stage.texMapId, chan_comp(swap.alpha));
|
||||||
}
|
}
|
||||||
case GX::CC_RASC: {
|
case GX::CC_RASC: {
|
||||||
|
@ -305,6 +310,9 @@ static std::string alpha_arg_reg(GX::TevAlphaArg arg, size_t stageIdx, const Sha
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
const auto swap = config.tevSwapTable[stage.tevSwapTex];
|
||||||
|
if (swap.alpha == GX::CH_ALPHA && !config.texHasAlpha[stage.texMapId]) {
|
||||||
|
return "1.0";
|
||||||
|
}
|
||||||
return fmt::format(FMT_STRING("sampled{}.{}"), stage.texMapId, chan_comp(swap.alpha));
|
return fmt::format(FMT_STRING("sampled{}.{}"), stage.texMapId, chan_comp(swap.alpha));
|
||||||
}
|
}
|
||||||
case GX::CA_RASA: {
|
case GX::CA_RASA: {
|
||||||
|
@ -597,8 +605,8 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
return it->second.first;
|
return it->second.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EnableDebugPrints) {
|
||||||
Log.report(logvisor::Info, FMT_STRING("Shader config (hash {:x}):"), hash);
|
Log.report(logvisor::Info, FMT_STRING("Shader config (hash {:x}):"), hash);
|
||||||
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < config.tevStageCount; ++i) {
|
for (int i = 0; i < config.tevStageCount; ++i) {
|
||||||
const auto& stage = config.tevStages[i];
|
const auto& stage = config.tevStages[i];
|
||||||
|
@ -635,8 +643,8 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
for (int i = 0; i < config.tcgs.size(); ++i) {
|
for (int i = 0; i < config.tcgs.size(); ++i) {
|
||||||
const auto& tcg = config.tcgs[i];
|
const auto& tcg = config.tcgs[i];
|
||||||
if (tcg.src != GX::MAX_TEXGENSRC) {
|
if (tcg.src != GX::MAX_TEXGENSRC) {
|
||||||
Log.report(logvisor::Info, FMT_STRING(" tcg[{}]: src {} mtx {} post {} type {} norm {}"), i, tcg.src, tcg.mtx,
|
Log.report(logvisor::Info, FMT_STRING(" tcg[{}]: src {} mtx {} post {} type {} norm {}"), i, tcg.src,
|
||||||
tcg.postMtx, tcg.type, tcg.normalize);
|
tcg.mtx, tcg.postMtx, tcg.type, tcg.normalize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.report(logvisor::Info, FMT_STRING(" alphaCompare: comp0 {} ref0 {} op {} comp1 {} ref1 {}"),
|
Log.report(logvisor::Info, FMT_STRING(" alphaCompare: comp0 {} ref0 {} op {} comp1 {} ref1 {}"),
|
||||||
|
@ -644,6 +652,13 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
config.alphaCompare.ref1);
|
config.alphaCompare.ref1);
|
||||||
Log.report(logvisor::Info, FMT_STRING(" indexedAttributeCount: {}"), config.indexedAttributeCount);
|
Log.report(logvisor::Info, FMT_STRING(" indexedAttributeCount: {}"), config.indexedAttributeCount);
|
||||||
Log.report(logvisor::Info, FMT_STRING(" fogType: {}"), config.fogType);
|
Log.report(logvisor::Info, FMT_STRING(" fogType: {}"), config.fogType);
|
||||||
|
std::string hasAlphaArr;
|
||||||
|
for (int i = 0; i < config.texHasAlpha.size(); ++i) {
|
||||||
|
if (i != 0) hasAlphaArr += ", ";
|
||||||
|
hasAlphaArr += config.texHasAlpha[i] ? "Y" : "N";
|
||||||
|
}
|
||||||
|
Log.report(logvisor::Info, FMT_STRING(" texHasAlpha: [{}]"), hasAlphaArr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string uniformPre;
|
std::string uniformPre;
|
||||||
|
@ -912,8 +927,15 @@ wgpu::ShaderModule build_shader(const ShaderConfig& config, const ShaderInfo& in
|
||||||
i, postMtxIdx);
|
i, postMtxIdx);
|
||||||
}
|
}
|
||||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = tc{0}_proj.xy;"), i);
|
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.tex{0}_uv = tc{0}_proj.xy;"), i);
|
||||||
|
std::string uvIn;
|
||||||
|
// FIXME terrible hack to flip Y for render textures
|
||||||
|
if (config.texHasAlpha[i]) {
|
||||||
|
uvIn = fmt::format(FMT_STRING("in.tex{0}_uv"), i);
|
||||||
|
} else {
|
||||||
|
uvIn = fmt::format(FMT_STRING("vec2<f32>(in.tex{0}_uv.x, -in.tex{0}_uv.y)"), i);
|
||||||
|
}
|
||||||
fragmentFnPre += fmt::format(
|
fragmentFnPre += fmt::format(
|
||||||
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{0}, tex{0}_samp, in.tex{0}_uv, ubuf.tex{0}_lod);"), i);
|
FMT_STRING("\n var sampled{0} = textureSampleBias(tex{0}, tex{0}_samp, {1}, ubuf.tex{0}_lod);"), i, uvIn);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < info.usesTexMtx.size(); ++i) {
|
for (int i = 0; i < info.usesTexMtx.size(); ++i) {
|
||||||
if (info.usesTexMtx.test(i)) {
|
if (info.usesTexMtx.test(i)) {
|
||||||
|
@ -1052,7 +1074,9 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {{
|
||||||
"vtxOutAttrs"_a = vtxOutAttrs, "vtxInAttrs"_a = vtxInAttrs, "vtxXfrAttrs"_a = vtxXfrAttrs,
|
"vtxOutAttrs"_a = vtxOutAttrs, "vtxInAttrs"_a = vtxInAttrs, "vtxXfrAttrs"_a = vtxXfrAttrs,
|
||||||
"fragmentFn"_a = fragmentFn, "fragmentFnPre"_a = fragmentFnPre, "vtxXfrAttrsPre"_a = vtxXfrAttrsPre,
|
"fragmentFn"_a = fragmentFn, "fragmentFnPre"_a = fragmentFnPre, "vtxXfrAttrsPre"_a = vtxXfrAttrsPre,
|
||||||
"uniformBindings"_a = uniformBindings, "uniformPre"_a = uniformPre);
|
"uniformBindings"_a = uniformBindings, "uniformPre"_a = uniformPre);
|
||||||
|
if (EnableDebugPrints) {
|
||||||
Log.report(logvisor::Info, FMT_STRING("Generated shader: {}"), shaderSource);
|
Log.report(logvisor::Info, FMT_STRING("Generated shader: {}"), shaderSource);
|
||||||
|
}
|
||||||
|
|
||||||
wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{};
|
wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{};
|
||||||
wgslDescriptor.source = shaderSource.c_str();
|
wgslDescriptor.source = shaderSource.c_str();
|
||||||
|
|
|
@ -113,9 +113,30 @@ TextureHandle new_dynamic_texture_2d(uint32_t width, uint32_t height, uint32_t m
|
||||||
return {std::make_shared<TextureRef>(std::move(texture), std::move(textureView), size, wgpuFormat, mips, format)};
|
return {std::make_shared<TextureRef>(std::move(texture), std::move(textureView), size, wgpuFormat, mips, format)};
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureHandle new_render_texture(uint32_t width, uint32_t height, uint32_t color_bind_count, uint32_t depth_bind_count,
|
TextureHandle new_render_texture(uint32_t width, uint32_t height, zstring_view label) noexcept {
|
||||||
zstring_view label) noexcept {
|
const auto wgpuFormat = gpu::g_graphicsConfig.colorFormat;
|
||||||
return {}; // TODO
|
const auto size = wgpu::Extent3D{
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
const auto textureDescriptor = wgpu::TextureDescriptor{
|
||||||
|
.label = label.c_str(),
|
||||||
|
.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst,
|
||||||
|
.size = size,
|
||||||
|
.format = wgpuFormat,
|
||||||
|
.mipLevelCount = 1,
|
||||||
|
};
|
||||||
|
const auto viewLabel = fmt::format(FMT_STRING("{} view"), label);
|
||||||
|
const auto textureViewDescriptor = wgpu::TextureViewDescriptor{
|
||||||
|
.label = viewLabel.c_str(),
|
||||||
|
.format = wgpuFormat,
|
||||||
|
.dimension = wgpu::TextureViewDimension::e2D,
|
||||||
|
.mipLevelCount = 1,
|
||||||
|
};
|
||||||
|
auto texture = g_device.CreateTexture(&textureDescriptor);
|
||||||
|
auto textureView = texture.CreateView(&textureViewDescriptor);
|
||||||
|
return {std::make_shared<TextureRef>(std::move(texture), std::move(textureView), size, wgpuFormat, 1,
|
||||||
|
metaforce::ETexelFormat::Invalid)};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO accept mip/layer parameters
|
// TODO accept mip/layer parameters
|
||||||
|
|
|
@ -28,12 +28,17 @@ TextureWithSampler g_frameBuffer;
|
||||||
TextureWithSampler g_frameBufferResolved;
|
TextureWithSampler g_frameBufferResolved;
|
||||||
TextureWithSampler g_depthBuffer;
|
TextureWithSampler g_depthBuffer;
|
||||||
|
|
||||||
|
// EFB -> XFB copy pipeline
|
||||||
|
static wgpu::BindGroupLayout g_CopyBindGroupLayout;
|
||||||
|
wgpu::RenderPipeline g_CopyPipeline;
|
||||||
|
wgpu::BindGroup g_CopyBindGroup;
|
||||||
|
|
||||||
static std::unique_ptr<dawn::native::Instance> g_Instance;
|
static std::unique_ptr<dawn::native::Instance> g_Instance;
|
||||||
static dawn::native::Adapter g_Adapter;
|
static dawn::native::Adapter g_Adapter;
|
||||||
static wgpu::AdapterProperties g_AdapterProperties;
|
static wgpu::AdapterProperties g_AdapterProperties;
|
||||||
static std::unique_ptr<utils::BackendBinding> g_BackendBinding;
|
static std::unique_ptr<utils::BackendBinding> g_BackendBinding;
|
||||||
|
|
||||||
static TextureWithSampler create_render_texture(bool multisampled) {
|
TextureWithSampler create_render_texture(bool multisampled) {
|
||||||
const auto size = wgpu::Extent3D{
|
const auto size = wgpu::Extent3D{
|
||||||
.width = g_graphicsConfig.width,
|
.width = g_graphicsConfig.width,
|
||||||
.height = g_graphicsConfig.height,
|
.height = g_graphicsConfig.height,
|
||||||
|
@ -45,7 +50,7 @@ static TextureWithSampler create_render_texture(bool multisampled) {
|
||||||
}
|
}
|
||||||
const auto textureDescriptor = wgpu::TextureDescriptor{
|
const auto textureDescriptor = wgpu::TextureDescriptor{
|
||||||
.label = "Render texture",
|
.label = "Render texture",
|
||||||
.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding,
|
.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst,
|
||||||
.size = size,
|
.size = size,
|
||||||
.format = format,
|
.format = format,
|
||||||
.sampleCount = sampleCount,
|
.sampleCount = sampleCount,
|
||||||
|
@ -107,6 +112,119 @@ static TextureWithSampler create_depth_texture() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create_copy_pipeline() {
|
||||||
|
wgpu::ShaderModuleWGSLDescriptor sourceDescriptor{};
|
||||||
|
sourceDescriptor.source = R"""(
|
||||||
|
@group(0) @binding(0)
|
||||||
|
var efb_sampler: sampler;
|
||||||
|
@group(0) @binding(1)
|
||||||
|
var efb_texture: texture_2d<f32>;
|
||||||
|
|
||||||
|
struct VertexOutput {
|
||||||
|
@builtin(position) pos: vec4<f32>,
|
||||||
|
@location(0) uv: vec2<f32>,
|
||||||
|
};
|
||||||
|
|
||||||
|
var<private> pos: array<vec2<f32>, 3> = array<vec2<f32>, 3>(
|
||||||
|
vec2(-1.0, 1.0),
|
||||||
|
vec2(-1.0, -3.0),
|
||||||
|
vec2(3.0, 1.0),
|
||||||
|
);
|
||||||
|
var<private> uvs: array<vec2<f32>, 3> = array<vec2<f32>, 3>(
|
||||||
|
vec2(0.0, 0.0),
|
||||||
|
vec2(0.0, 2.0),
|
||||||
|
vec2(2.0, 0.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
@stage(vertex)
|
||||||
|
fn vs_main(@builtin(vertex_index) vtxIdx: u32) -> VertexOutput {
|
||||||
|
var out: VertexOutput;
|
||||||
|
out.pos = vec4<f32>(pos[vtxIdx], 0.0, 1.0);
|
||||||
|
out.uv = uvs[vtxIdx];
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@stage(fragment)
|
||||||
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
|
return textureSample(efb_texture, efb_sampler, in.uv);
|
||||||
|
}
|
||||||
|
)""";
|
||||||
|
const wgpu::ShaderModuleDescriptor moduleDescriptor{
|
||||||
|
.nextInChain = &sourceDescriptor,
|
||||||
|
.label = "XFB Copy Module",
|
||||||
|
};
|
||||||
|
auto module = g_device.CreateShaderModule(&moduleDescriptor);
|
||||||
|
const std::array colorTargets{
|
||||||
|
wgpu::ColorTargetState{
|
||||||
|
.format = g_graphicsConfig.colorFormat,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const wgpu::FragmentState fragmentState{
|
||||||
|
.module = module,
|
||||||
|
.entryPoint = "fs_main",
|
||||||
|
.targetCount = colorTargets.size(),
|
||||||
|
.targets = colorTargets.data(),
|
||||||
|
};
|
||||||
|
const std::array bindGroupLayoutEntries{
|
||||||
|
wgpu::BindGroupLayoutEntry{
|
||||||
|
.binding = 0,
|
||||||
|
.visibility = wgpu::ShaderStage::Fragment,
|
||||||
|
.sampler =
|
||||||
|
wgpu::SamplerBindingLayout{
|
||||||
|
.type = wgpu::SamplerBindingType::Filtering,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry{
|
||||||
|
.binding = 1,
|
||||||
|
.visibility = wgpu::ShaderStage::Fragment,
|
||||||
|
.texture =
|
||||||
|
wgpu::TextureBindingLayout{
|
||||||
|
.sampleType = wgpu::TextureSampleType::Float,
|
||||||
|
.viewDimension = wgpu::TextureViewDimension::e2D,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const wgpu::BindGroupLayoutDescriptor bindGroupLayoutDescriptor{
|
||||||
|
.entryCount = bindGroupLayoutEntries.size(),
|
||||||
|
.entries = bindGroupLayoutEntries.data(),
|
||||||
|
};
|
||||||
|
g_CopyBindGroupLayout = g_device.CreateBindGroupLayout(&bindGroupLayoutDescriptor);
|
||||||
|
const wgpu::PipelineLayoutDescriptor layoutDescriptor{
|
||||||
|
.bindGroupLayoutCount = 1,
|
||||||
|
.bindGroupLayouts = &g_CopyBindGroupLayout,
|
||||||
|
};
|
||||||
|
auto pipelineLayout = g_device.CreatePipelineLayout(&layoutDescriptor);
|
||||||
|
const wgpu::RenderPipelineDescriptor pipelineDescriptor{
|
||||||
|
.layout = pipelineLayout,
|
||||||
|
.vertex =
|
||||||
|
wgpu::VertexState{
|
||||||
|
.module = module,
|
||||||
|
.entryPoint = "vs_main",
|
||||||
|
},
|
||||||
|
.fragment = &fragmentState,
|
||||||
|
};
|
||||||
|
g_CopyPipeline = g_device.CreateRenderPipeline(&pipelineDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_copy_bind_group() {
|
||||||
|
const std::array bindGroupEntries{
|
||||||
|
wgpu::BindGroupEntry{
|
||||||
|
.binding = 0,
|
||||||
|
.sampler = g_graphicsConfig.msaaSamples > 1 ? gpu::g_frameBufferResolved.sampler : gpu::g_frameBuffer.sampler,
|
||||||
|
},
|
||||||
|
wgpu::BindGroupEntry{
|
||||||
|
.binding = 1,
|
||||||
|
.textureView = g_graphicsConfig.msaaSamples > 1 ? gpu::g_frameBufferResolved.view : gpu::g_frameBuffer.view,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const wgpu::BindGroupDescriptor bindGroupDescriptor{
|
||||||
|
.layout = g_CopyBindGroupLayout,
|
||||||
|
.entryCount = bindGroupEntries.size(),
|
||||||
|
.entries = bindGroupEntries.data(),
|
||||||
|
};
|
||||||
|
g_CopyBindGroup = g_device.CreateBindGroup(&bindGroupDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
static void error_callback(WGPUErrorType type, char const* message, void* userdata) {
|
static void error_callback(WGPUErrorType type, char const* message, void* userdata) {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Dawn error {}: {}"),
|
Log.report(logvisor::Fatal, FMT_STRING("Dawn error {}: {}"),
|
||||||
magic_enum::enum_name(static_cast<wgpu::ErrorType>(type)), message);
|
magic_enum::enum_name(static_cast<wgpu::ErrorType>(type)), message);
|
||||||
|
@ -215,9 +333,10 @@ void initialize(SDL_Window* window) {
|
||||||
.height = size.fb_height,
|
.height = size.fb_height,
|
||||||
.colorFormat = swapChainFormat,
|
.colorFormat = swapChainFormat,
|
||||||
.depthFormat = wgpu::TextureFormat::Depth32Float,
|
.depthFormat = wgpu::TextureFormat::Depth32Float,
|
||||||
.msaaSamples = 1, // TODO 4
|
.msaaSamples = 4,
|
||||||
.textureAnistropy = 16,
|
.textureAnistropy = 16,
|
||||||
};
|
};
|
||||||
|
create_copy_pipeline();
|
||||||
resize_swapchain(size.fb_width, size.fb_height);
|
resize_swapchain(size.fb_width, size.fb_height);
|
||||||
g_windowSize = size;
|
g_windowSize = size;
|
||||||
}
|
}
|
||||||
|
@ -241,5 +360,6 @@ void resize_swapchain(uint32_t width, uint32_t height) {
|
||||||
g_frameBuffer = create_render_texture(true);
|
g_frameBuffer = create_render_texture(true);
|
||||||
g_frameBufferResolved = create_render_texture(false);
|
g_frameBufferResolved = create_render_texture(false);
|
||||||
g_depthBuffer = create_depth_texture();
|
g_depthBuffer = create_depth_texture();
|
||||||
|
create_copy_bind_group();
|
||||||
}
|
}
|
||||||
} // namespace aurora::gpu
|
} // namespace aurora::gpu
|
||||||
|
|
|
@ -48,10 +48,13 @@ extern GraphicsConfig g_graphicsConfig;
|
||||||
extern TextureWithSampler g_frameBuffer;
|
extern TextureWithSampler g_frameBuffer;
|
||||||
extern TextureWithSampler g_frameBufferResolved;
|
extern TextureWithSampler g_frameBufferResolved;
|
||||||
extern TextureWithSampler g_depthBuffer;
|
extern TextureWithSampler g_depthBuffer;
|
||||||
|
extern wgpu::RenderPipeline g_CopyPipeline;
|
||||||
|
extern wgpu::BindGroup g_CopyBindGroup;
|
||||||
|
|
||||||
void initialize(SDL_Window* window);
|
void initialize(SDL_Window* window);
|
||||||
void shutdown();
|
void shutdown();
|
||||||
void resize_swapchain(uint32_t width, uint32_t height);
|
void resize_swapchain(uint32_t width, uint32_t height);
|
||||||
|
TextureWithSampler create_render_texture(bool multisampled);
|
||||||
} // namespace aurora::gpu
|
} // namespace aurora::gpu
|
||||||
|
|
||||||
namespace aurora::gpu::utils {
|
namespace aurora::gpu::utils {
|
||||||
|
|
Loading…
Reference in New Issue