Implement HandleTransparency, lighting & fix texture load

This commit is contained in:
Luke Street 2022-03-08 17:19:02 -05:00
parent a2743b905b
commit e88f831950
11 changed files with 261 additions and 103 deletions

View File

@ -305,11 +305,36 @@ void CCubeMaterial::EnsureViewDepStateCached(const CCubeSurface* surface) {
u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) { u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) {
if (CCubeModel::sRenderModelShadow) { if (CCubeModel::sRenderModelShadow) {
if (chanCount != 0) { if (chanCount != 0) {
// TODO aurora::gfx::set_chan_amb_color(GX::COLOR1A1, zeus::skBlack);
aurora::gfx::set_chan_mat_color(GX::COLOR1A1, zeus::skWhite);
// TODO chan / lights
aurora::gfx::set_chan_mat_color(GX::COLOR0A0, zeus::skWhite);
} }
return 2; return 2;
} }
if (chanCount == 2) {
aurora::gfx::set_chan_amb_color(GX::COLOR1A1, zeus::skBlack);
aurora::gfx::set_chan_mat_color(GX::COLOR1A1, zeus::skWhite);
} else {
// TODO chan ctrls
}
if (chanCount == 0) {
// TODO more chan ctrls
} else {
auto uVar3 = firstChan & 0xfffffffe;
// TODO enabled lights
// TODO chan ctrl
// if (sEnabledLights == 0) {
// aurora::gfx::set_chan_mat_color(GX::COLOR0A0, amb_clr);
// } else {
aurora::gfx::set_chan_mat_color(GX::COLOR0A0, zeus::skWhite);
// }
}
// TODO // TODO
aurora::gfx::set_chan_mat_src(GX::COLOR0A0, GX::SRC_REG); aurora::gfx::set_chan_mat_src(GX::COLOR0A0, GX::SRC_REG);
aurora::gfx::set_chan_mat_src(GX::COLOR1A1, GX::SRC_REG); aurora::gfx::set_chan_mat_src(GX::COLOR1A1, GX::SRC_REG);
@ -385,36 +410,56 @@ void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount
} }
if (modelFlags.x0_blendMode == 3) { if (modelFlags.x0_blendMode == 3) {
// Stage outputting splatted KAlpha as color to reg0 // Stage outputting splatted KAlpha as color to reg0
aurora::gfx::update_tev_stage(static_cast<ERglTevStage>(finalTevCount),
CTevCombiners::ColorPass{GX::CC_ZERO, GX::CC_ZERO, GX::CC_ZERO, GX::CC_KONST},
CTevCombiners::AlphaPass{GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV},
CTevCombiners::CTevOp{true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, GX::TEVREG0},
CTevCombiners::CTevOp{true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, GX::TEVPREV});
// GXSetTevColorIn(finalTevCount, TEVCOLORARG_ZERO, TEVCOLORARG_ZERO, TEVCOLORARG_ZERO, TEVCOLORARG_KONST); // GXSetTevColorIn(finalTevCount, TEVCOLORARG_ZERO, TEVCOLORARG_ZERO, TEVCOLORARG_ZERO, TEVCOLORARG_KONST);
// GXSetTevAlphaIn(finalTevCount, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV); // GXSetTevAlphaIn(finalTevCount, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV);
// GXSetTevColorOp(finalTevCount, 0, 0, 0, 1, 1); // ColorReg0 // GXSetTevColorOp(finalTevCount, 0, 0, 0, 1, 1); // ColorReg0
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(finalTevCount),
static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0_A));
// GXSetTevKColorSel(finalTevCount, finalKColorCount+28); // GXSetTevKColorSel(finalTevCount, finalKColorCount+28);
// GXSetTevAlphaOp(finalTevCount, 0, 0, 0, 1, 0); // AlphaRegPrev // GXSetTevAlphaOp(finalTevCount, 0, 0, 0, 1, 0); // AlphaRegPrev
// GXSetTevOrder(finalTevCount, 255, 255, 255); // GXSetTevOrder(finalTevCount, 255, 255, 255);
// GXSetTevDirect(finalTevCount); // GXSetTevDirect(finalTevCount);
// Stage interpolating from splatted KAlpha using KColor // Stage interpolating from splatted KAlpha using KColor
aurora::gfx::update_tev_stage(static_cast<ERglTevStage>(finalTevCount + 1),
CTevCombiners::ColorPass{GX::CC_CPREV, GX::CC_C0, GX::CC_KONST, GX::CC_ZERO},
CTevCombiners::AlphaPass{GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_APREV},
CTevCombiners::CTevOp{true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, GX::TEVPREV},
CTevCombiners::CTevOp{true, GX::TEV_ADD, GX::TB_ZERO, GX::CS_SCALE_1, GX::TEVPREV});
// GXSetTevColorIn(finalTevCount + 1, TEVCOLORARG_CPREV, TEVCOLORARG_C0, TEVCOLORARG_KONST, TEVCOLORARG_ZERO); // GXSetTevColorIn(finalTevCount + 1, TEVCOLORARG_CPREV, TEVCOLORARG_C0, TEVCOLORARG_KONST, TEVCOLORARG_ZERO);
// GXSetTevAlphaIn(finalTevCount + 1, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV); // GXSetTevAlphaIn(finalTevCount + 1, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV);
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(finalTevCount + 1),
static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0));
// GXSetTevKColorSel(finalTevCount, finalKColorCount+12); // GXSetTevKColorSel(finalTevCount, finalKColorCount+12);
// SetStandardTevColorAlphaOp(finalTevCount + 1); // SetStandardTevColorAlphaOp(finalTevCount + 1);
// GXSetTevDirect(finalTevCount + 1); // GXSetTevDirect(finalTevCount + 1);
// GXSetTevOrder(finalTevCount + 1, 255, 255, 255); // GXSetTevOrder(finalTevCount + 1, 255, 255, 255);
aurora::gfx::set_tev_k_color(static_cast<GX::TevKColorID>(finalKColorCount), modelFlags.x4_color);
// GXSetTevKColor(finalKColorCount, modelFlags.x4_color); // GXSetTevKColor(finalKColorCount, modelFlags.x4_color);
finalKColorCount += 1; finalKColorCount += 1;
finalTevCount += 2; finalTevCount += 2;
} else { } else {
// Mul KAlpha // Mul KAlpha
CTevCombiners::AlphaPass alphaPass{GX::CA_ZERO, GX::CA_KONST, GX::CA_APREV, GX::CA_ZERO};
u32 tevAlpha = 0x000380C7; // TEVALPHAARG_ZERO, TEVALPHAARG_KONST, TEVALPHAARG_APREV, TEVALPHAARG_ZERO u32 tevAlpha = 0x000380C7; // TEVALPHAARG_ZERO, TEVALPHAARG_KONST, TEVALPHAARG_APREV, TEVALPHAARG_ZERO
if (modelFlags.x0_blendMode == 8) { if (modelFlags.x0_blendMode == 8) {
// Set KAlpha // Set KAlpha
alphaPass = {GX::CA_ZERO, GX::CA_ZERO, GX::CA_ZERO, GX::CA_KONST};
tevAlpha = 0x00031CE7; // TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_KONST tevAlpha = 0x00031CE7; // TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_KONST
} }
// Mul KColor // Mul KColor
CTevCombiners::ColorPass colorPass{GX::CC_ZERO, GX::CC_KONST, GX::CC_CPREV, GX::CC_ZERO};
u32 tevColor = 0x000781CF; // TEVCOLORARG_ZERO, TEVCOLORARG_KONST, TEVCOLORARG_CPREV, TEVCOLORARG_ZERO u32 tevColor = 0x000781CF; // TEVCOLORARG_ZERO, TEVCOLORARG_KONST, TEVCOLORARG_CPREV, TEVCOLORARG_ZERO
if (modelFlags.x0_blendMode == 2) { if (modelFlags.x0_blendMode == 2) {
// Add KColor // Add KColor
colorPass = {GX::CC_ZERO, GX::CC_ONE, GX::CC_CPREV, GX::CC_KONST};
tevColor = 0x0007018F; // TEVCOLORARG_ZERO, TEVCOLORARG_ONE, TEVCOLORARG_CPREV, TEVCOLORARG_KONST tevColor = 0x0007018F; // TEVCOLORARG_ZERO, TEVCOLORARG_ONE, TEVCOLORARG_CPREV, TEVCOLORARG_KONST
} }
aurora::gfx::update_tev_stage(static_cast<ERglTevStage>(finalTevCount), colorPass, alphaPass, {}, {});
// GXSetTevColorIn(finalTevCount) // GXSetTevColorIn(finalTevCount)
// GXSetTevAlphaIn(finalTevCount) // GXSetTevAlphaIn(finalTevCount)
// SetStandardTevColorAlphaOp(finalTevCount); // SetStandardTevColorAlphaOp(finalTevCount);
@ -422,8 +467,13 @@ void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount
finalACFlags = 0x100; finalACFlags = 0x100;
// GXSetTevDirect(finalTevCount); // GXSetTevDirect(finalTevCount);
// GXSetTevOrder(finalTevCount, 255, 255, 255); // GXSetTevOrder(finalTevCount, 255, 255, 255);
aurora::gfx::set_tev_k_color(static_cast<GX::TevKColorID>(finalKColorCount), modelFlags.x4_color);
// GXSetTevKColor(finalKColorCount, modelFlags.x4_color); // GXSetTevKColor(finalKColorCount, modelFlags.x4_color);
aurora::gfx::set_tev_k_color_sel(static_cast<GX::TevStageID>(finalKColorCount),
static_cast<GX::TevKColorSel>(finalKColorCount + GX::TEV_KCSEL_K0));
// GXSetTevKColorSel(finalTevCount, finalKColorCount+12); // GXSetTevKColorSel(finalTevCount, finalKColorCount+12);
aurora::gfx::set_tev_k_alpha_sel(static_cast<GX::TevStageID>(finalTevCount),
static_cast<GX::TevKAlphaSel>(finalKColorCount + GX::TEV_KASEL_K0_A));
// GXSetTevKAlphaSel(finalTevCount, finalKColorCount+28); // GXSetTevKAlphaSel(finalTevCount, finalKColorCount+28);
finalTevCount += 1; finalTevCount += 1;
finalKColorCount += 1; finalKColorCount += 1;
@ -473,8 +523,8 @@ void CCubeMaterial::EnsureTevsDirect() {
return; return;
} }
//CGX::SetNumIndStages(0); // CGX::SetNumIndStages(0);
//CGX::SetTevDirect(sCurrentTevStage); // CGX::SetTevDirect(sCurrentTevStage);
sCurrentTevStage = GX::NULL_STAGE; sCurrentTevStage = GX::NULL_STAGE;
} }
} // namespace metaforce } // namespace metaforce

View File

@ -78,7 +78,7 @@ bool CCubeModel::TryLockTextures() {
} }
if (loadTexture) { if (loadTexture) {
// texture->LoadToMRAM(); // texture->LoadToMRAM();
texturesPumped = true; // texturesPumped = true;
} }
} }
if (!texturesPumped) { if (!texturesPumped) {

View File

@ -21,7 +21,6 @@ add_library(aurora STATIC
lib/imgui.cpp lib/imgui.cpp
lib/input.cpp lib/input.cpp
lib/dawn/BackendBinding.cpp lib/dawn/BackendBinding.cpp
lib/dawn/Hacks.cpp
lib/gfx/common.cpp lib/gfx/common.cpp
lib/gfx/texture.cpp lib/gfx/texture.cpp
lib/gfx/stream.cpp lib/gfx/stream.cpp

View File

@ -248,9 +248,9 @@ enum class ZComp : uint8_t {
constexpr u32 MaxLights = 8; constexpr u32 MaxLights = 8;
struct Light { struct Light {
zeus::CVector3f pos; zeus::CVector3f pos{0.f, 0.f, 0.f};
zeus::CVector3f dir; zeus::CVector3f dir{0.f, 0.f, -1.f};
zeus::CColor color; zeus::CColor color{0.f, 0.f, 0.f, 0.f};
zeus::CVector3f linAtt{1.f, 0.f, 0.f}; zeus::CVector3f linAtt{1.f, 0.f, 0.f};
zeus::CVector3f angAtt{1.f, 0.f, 0.f}; zeus::CVector3f angAtt{1.f, 0.f, 0.f};
}; };

View File

@ -1,29 +0,0 @@
#include "Hacks.hpp"
#include "dawn/native/Device.h"
#ifdef _WIN32
#include "dawn/native/d3d12/AdapterD3D12.h"
#include "dawn/native/d3d12/BackendD3D12.h"
#include "dawn/native/d3d12/DeviceD3D12.h"
#endif
namespace dawn::native {
class HackedDevice : public DeviceBase {
public:
void _ForceSetToggle(Toggle toggle, bool isEnabled) { ForceSetToggle(toggle, isEnabled); }
};
} // namespace dawn::native
namespace aurora::gpu::hacks {
void apply_toggles(WGPUDevice device) {
auto* hack = static_cast<dawn::native::HackedDevice*>(static_cast<void*>(device));
hack->_ForceSetToggle(dawn::native::Toggle::UseUserDefinedLabelsInBackend, true);
#if _WIN32
hack->_ForceSetToggle(dawn::native::Toggle::UseDXC, true);
auto* backend = dawn::native::d3d12::ToBackend(hack->GetAdapter())->GetBackend();
backend->EnsureDxcCompiler();
backend->EnsureDxcLibrary();
backend->EnsureDxcValidator();
#endif
}
} // namespace aurora::gpu::hacks

View File

@ -1,10 +0,0 @@
#pragma once
#include <dawn/webgpu.h>
/**
* Helpers to expose private Dawn APIs
*/
namespace aurora::gpu::hacks {
void apply_toggles(WGPUDevice device);
} // namespace aurora::gpu::hacks

View File

@ -424,24 +424,18 @@ void shutdown() {
} }
void render(const wgpu::RenderPassEncoder& pass) { void render(const wgpu::RenderPassEncoder& pass) {
{ const auto writeBuffer = [](ByteBuffer& buf, wgpu::Buffer& out) {
if (g_verts.size() > 0) { const auto size = buf.size();
g_queue.WriteBuffer(g_vertexBuffer, 0, g_verts.data(), g_verts.size()); if (size > 0) {
g_verts.clear(); g_queue.WriteBuffer(out, 0, buf.data(), size);
buf.clear();
buf.reserve_extra(size); // Reserve size from previous frame
} }
if (g_uniforms.size() > 0) { };
g_queue.WriteBuffer(g_uniformBuffer, 0, g_uniforms.data(), g_uniforms.size()); writeBuffer(g_verts, g_vertexBuffer);
g_uniforms.clear(); writeBuffer(g_uniforms, g_uniformBuffer);
} writeBuffer(g_indices, g_indexBuffer);
if (g_indices.size() > 0) { writeBuffer(g_storage, g_storageBuffer);
g_queue.WriteBuffer(g_indexBuffer, 0, g_indices.data(), g_indices.size());
g_indices.clear();
}
if (g_storage.size() > 0) {
g_queue.WriteBuffer(g_storageBuffer, 0, g_storage.data(), g_storage.size());
g_storage.clear();
}
}
g_currentPipeline = UINT64_MAX; g_currentPipeline = UINT64_MAX;
@ -514,7 +508,19 @@ static inline Range push(ByteBuffer& target, const uint8_t* data, size_t length,
target.append_zeroes(padding); target.append_zeroes(padding);
} }
} }
return {begin, begin + length}; return {begin, begin + length + padding};
}
static inline Range map(ByteBuffer& target, size_t length, size_t alignment) {
size_t padding = 0;
if (alignment != 0) {
padding = alignment - length % alignment;
}
if (length == 0) {
length = alignment;
}
auto begin = target.size();
target.append_zeroes(length + padding);
return {begin, begin + length + padding};
} }
Range push_verts(const uint8_t* data, size_t length) { return push(g_verts, data, length, 0 /* TODO? */); } Range push_verts(const uint8_t* data, size_t length) { return push(g_verts, data, length, 0 /* TODO? */); }
Range push_indices(const uint8_t* data, size_t length) { return push(g_indices, data, length, 0 /* TODO? */); } Range push_indices(const uint8_t* data, size_t length) { return push(g_indices, data, length, 0 /* TODO? */); }
@ -528,6 +534,26 @@ Range push_storage(const uint8_t* data, size_t length) {
g_device.GetLimits(&limits); g_device.GetLimits(&limits);
return push(g_storage, data, length, limits.limits.minStorageBufferOffsetAlignment); return push(g_storage, data, length, limits.limits.minStorageBufferOffsetAlignment);
} }
std::pair<ByteBuffer, Range> map_verts(size_t length) {
const auto range = map(g_verts, length, 0 /* TODO? */);
return {ByteBuffer{g_verts.data() + range.first, range.second - range.first}, range};
}
std::pair<ByteBuffer, Range> map_indices(size_t length) {
const auto range = map(g_indices, length, 0 /* TODO? */);
return {ByteBuffer{g_indices.data() + range.first, range.second - range.first}, range};
}
std::pair<ByteBuffer, Range> map_uniform(size_t length) {
wgpu::SupportedLimits limits;
g_device.GetLimits(&limits);
const auto range = map(g_uniforms, length, limits.limits.minUniformBufferOffsetAlignment);
return {ByteBuffer{g_uniforms.data() + range.first, range.second - range.first}, range};
}
std::pair<ByteBuffer, Range> map_storage(size_t length) {
wgpu::SupportedLimits limits;
g_device.GetLimits(&limits);
const auto range = map(g_storage, length, limits.limits.minStorageBufferOffsetAlignment);
return {ByteBuffer{g_storage.data() + range.first, range.second - range.first}, range};
}
BindGroupRef bind_group_ref(const wgpu::BindGroupDescriptor& descriptor) { BindGroupRef bind_group_ref(const wgpu::BindGroupDescriptor& descriptor) {
const auto id = xxh3_hash(descriptor); const auto id = xxh3_hash(descriptor);

View File

@ -30,26 +30,32 @@ public:
ByteBuffer() noexcept = default; ByteBuffer() noexcept = default;
explicit ByteBuffer(size_t size) noexcept explicit ByteBuffer(size_t size) noexcept
: m_data(static_cast<uint8_t*>(calloc(1, size))), m_length(size), m_capacity(size) {} : m_data(static_cast<uint8_t*>(calloc(1, size))), m_length(size), m_capacity(size) {}
explicit ByteBuffer(uint8_t* data, size_t size) noexcept
: m_data(data), m_length(0), m_capacity(size), m_owned(false) {}
~ByteBuffer() noexcept { ~ByteBuffer() noexcept {
if (m_data != nullptr) { if (m_data != nullptr && m_owned) {
free(m_data); free(m_data);
} }
} }
ByteBuffer(ByteBuffer&& rhs) noexcept : m_data(rhs.m_data), m_length(rhs.m_length), m_capacity(rhs.m_capacity) { ByteBuffer(ByteBuffer&& rhs) noexcept
: m_data(rhs.m_data), m_length(rhs.m_length), m_capacity(rhs.m_capacity), m_owned(rhs.m_owned) {
rhs.m_data = nullptr; rhs.m_data = nullptr;
rhs.m_length = 0; rhs.m_length = 0;
rhs.m_capacity = 0; rhs.m_capacity = 0;
rhs.m_owned = true;
} }
ByteBuffer& operator=(ByteBuffer&& rhs) noexcept { ByteBuffer& operator=(ByteBuffer&& rhs) noexcept {
if (m_data != nullptr) { if (m_data != nullptr && m_owned) {
free(m_data); free(m_data);
} }
m_data = rhs.m_data; m_data = rhs.m_data;
m_length = rhs.m_length; m_length = rhs.m_length;
m_capacity = rhs.m_capacity; m_capacity = rhs.m_capacity;
m_owned = rhs.m_owned;
rhs.m_data = nullptr; rhs.m_data = nullptr;
rhs.m_length = 0; rhs.m_length = 0;
rhs.m_capacity = 0; rhs.m_capacity = 0;
rhs.m_owned = true;
return *this; return *this;
} }
ByteBuffer(ByteBuffer const&) = delete; ByteBuffer(ByteBuffer const&) = delete;
@ -61,38 +67,52 @@ public:
[[nodiscard]] bool empty() const noexcept { return m_length == 0; } [[nodiscard]] bool empty() const noexcept { return m_length == 0; }
void append(const void* data, size_t size) { void append(const void* data, size_t size) {
resize(m_length + size); resize(m_length + size, false);
memcpy(m_data + m_length, data, size); memcpy(m_data + m_length, data, size);
m_length += size; m_length += size;
} }
void append_zeroes(size_t size) { void append_zeroes(size_t size) {
resize(m_length + size); resize(m_length + size, true);
memset(m_data + m_length, 0, size);
m_length += size; m_length += size;
} }
void clear() { void clear() {
if (m_data != nullptr) { if (m_data != nullptr && m_owned) {
free(m_data); free(m_data);
} }
m_data = nullptr; m_data = nullptr;
m_length = 0; m_length = 0;
m_capacity = 0; m_capacity = 0;
m_owned = true;
} }
void reserve_extra(size_t size) { resize(m_length + size, true); }
private: private:
uint8_t* m_data = nullptr; uint8_t* m_data = nullptr;
size_t m_length = 0; size_t m_length = 0;
size_t m_capacity = 0; size_t m_capacity = 0;
bool m_owned = true;
void resize(size_t size) { void resize(size_t size, bool zeroed) {
if (size == 0) { if (size == 0) {
clear(); clear();
} else if (m_data == nullptr) { } else if (m_data == nullptr) {
m_data = static_cast<uint8_t*>(malloc(size)); if (zeroed) {
m_data = static_cast<uint8_t*>(calloc(1, size));
} else {
m_data = static_cast<uint8_t*>(malloc(size));
}
m_owned = true;
} else if (size > m_capacity) { } else if (size > m_capacity) {
if (!m_owned) {
abort();
}
m_data = static_cast<uint8_t*>(realloc(m_data, size)); m_data = static_cast<uint8_t*>(realloc(m_data, size));
if (zeroed) {
memset(m_data + m_capacity, 0, size - m_capacity);
}
} else { } else {
return; return;
} }
@ -165,6 +185,10 @@ template <typename T>
static inline Range push_storage(const T& data) { static inline Range push_storage(const T& data) {
return push_storage(reinterpret_cast<const uint8_t*>(&data), sizeof(T)); return push_storage(reinterpret_cast<const uint8_t*>(&data), sizeof(T));
} }
std::pair<ByteBuffer, Range> map_verts(size_t length);
std::pair<ByteBuffer, Range> map_indices(size_t length);
std::pair<ByteBuffer, Range> map_uniform(size_t length);
std::pair<ByteBuffer, Range> map_storage(size_t length);
template <typename State> template <typename State>
const State& get_state(); const State& get_state();

View File

@ -363,29 +363,53 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
} }
Range build_uniform(const ShaderInfo& info) noexcept { Range build_uniform(const ShaderInfo& info) noexcept {
ByteBuffer uniBuf; auto [buf, range] = map_uniform(info.uniformSize);
{ {
const auto xf = get_combined_matrix(); buf.append(&g_mv, 64);
uniBuf.append(&xf, 64); buf.append(&g_mvInv, 64);
buf.append(&g_proj, 64);
} }
for (int i = 0; i < info.usesTevReg.size(); ++i) { for (int i = 0; i < info.usesTevReg.size(); ++i) {
if (!info.usesTevReg.test(i)) { if (!info.usesTevReg.test(i)) {
continue; continue;
} }
uniBuf.append(&g_colorRegs[i], 16); buf.append(&g_colorRegs[i], 16);
}
if (info.sampledColorChannels.any()) {
zeus::CColor ambient = zeus::skClear;
int addedLights = 0;
for (int i = 0; i < g_lightState.size(); ++i) {
if (!g_lightState.test(i)) {
continue;
}
const auto& variant = g_lights[i];
if (std::holds_alternative<zeus::CColor>(variant)) {
ambient += std::get<zeus::CColor>(variant);
} else if (std::holds_alternative<Light>(variant)) {
static_assert(sizeof(Light) == 80);
buf.append(&std::get<Light>(variant), sizeof(Light));
++addedLights;
}
}
constexpr Light emptyLight{};
for (int i = addedLights; i < MaxLights; ++i) {
buf.append(&emptyLight, sizeof(Light));
}
buf.append(&ambient, 16);
// fmt::print(FMT_STRING("Added lights: {}, ambient: {},{},{},{}\n"), addedLights, ambient.r(), ambient.g(), ambient.b(), ambient.a());
} }
for (int i = 0; i < info.sampledColorChannels.size(); ++i) { for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
if (!info.sampledColorChannels.test(i)) { if (!info.sampledColorChannels.test(i)) {
continue; continue;
} }
uniBuf.append(&g_colorChannels[i].ambColor, 16); buf.append(&g_colorChannels[i].ambColor, 16);
uniBuf.append(&g_colorChannels[i].matColor, 16); buf.append(&g_colorChannels[i].matColor, 16);
} }
for (int i = 0; i < info.sampledKcolors.size(); ++i) { for (int i = 0; i < info.sampledKcolors.size(); ++i) {
if (!info.sampledKcolors.test(i)) { if (!info.sampledKcolors.test(i)) {
continue; continue;
} }
uniBuf.append(&g_kcolors[i], 16); buf.append(&g_kcolors[i], 16);
} }
for (int i = 0; i < info.sampledTextures.size(); ++i) { for (int i = 0; i < info.sampledTextures.size(); ++i) {
if (!info.sampledTextures.test(i)) { if (!info.sampledTextures.test(i)) {
@ -396,9 +420,9 @@ Range build_uniform(const ShaderInfo& info) noexcept {
Log.report(logvisor::Fatal, FMT_STRING("unbound texture {}"), i); Log.report(logvisor::Fatal, FMT_STRING("unbound texture {}"), i);
unreachable(); unreachable();
} }
uniBuf.append(&tex.lod, 4); buf.append(&tex.lod, 4);
} }
return push_uniform(uniBuf.data(), uniBuf.size()); return range;
} }
static std::unordered_map<u32, wgpu::BindGroupLayout> sUniformBindGroupLayouts; static std::unordered_map<u32, wgpu::BindGroupLayout> sUniformBindGroupLayouts;

View File

@ -342,7 +342,7 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
Log.report(logvisor::Info, FMT_STRING("Shader config (hash {:x}):"), hash); Log.report(logvisor::Info, FMT_STRING("Shader config (hash {:x}):"), hash);
ShaderInfo info{ ShaderInfo info{
.uniformSize = 64, // MVP MTX .uniformSize = 64 * 3, // mv, mvInv, proj
}; };
{ {
@ -383,6 +383,7 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
Log.report(logvisor::Info, FMT_STRING(" denormalizedVertexAttributes: {}"), config.denormalizedVertexAttributes); Log.report(logvisor::Info, FMT_STRING(" denormalizedVertexAttributes: {}"), config.denormalizedVertexAttributes);
} }
std::string uniformPre;
std::string uniBufAttrs; std::string uniBufAttrs;
std::string uniformBindings; std::string uniformBindings;
std::string sampBindings; std::string sampBindings;
@ -395,11 +396,15 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
if (config.denormalizedVertexAttributes) { if (config.denormalizedVertexAttributes) {
vtxInAttrs += "\n @location(0) in_pos: vec3<f32>"; vtxInAttrs += "\n @location(0) in_pos: vec3<f32>";
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;"; vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
vtxXfrAttrsPre += "\n out.pos = ubuf.xf * vec4<f32>(in_pos, 1.0);"; vtxXfrAttrsPre += "\n var obj_pos = vec4<f32>(in_pos, 1.0);"
"\n var mv_pos = ubuf.mv * obj_pos;"
"\n out.pos = ubuf.proj * mv_pos;";
if (config.denormalizedHasNrm) { if (config.denormalizedHasNrm) {
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3<f32>;"), locIdx); vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) nrm: vec3<f32>;"), locIdx);
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_nrm: vec3<f32>"), ++locIdx); vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_nrm: vec3<f32>"), ++locIdx);
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.nrm = in_nrm;")); vtxXfrAttrs += fmt::format(FMT_STRING("\n out.nrm = in_nrm;"));
vtxXfrAttrsPre += "\n var obj_norm = vec4<f32>(in_nrm, 0.0);"
"\n var mv_norm = ubuf.mv_inv * obj_norm;";
info.usesNormal = true; info.usesNormal = true;
} }
} else { } else {
@ -424,7 +429,11 @@ var<storage, read> v_packed_uvs: Vec2Block;
"\n , @location(1) in_uv_0_4_idx: vec4<i32>" "\n , @location(1) in_uv_0_4_idx: vec4<i32>"
"\n , @location(2) in_uv_5_7_idx: vec4<i32>"; "\n , @location(2) in_uv_5_7_idx: vec4<i32>";
vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;"; vtxOutAttrs += "\n @builtin(position) pos: vec4<f32>;";
vtxXfrAttrsPre += "\n out.pos = ubuf.xf * vec4<f32>(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"; vtxXfrAttrsPre += "\n var obj_pos = vec4<f32>(v_verts.data[in_pos_nrm_idx[0]].xyz, 1.0);"
"\n var obj_norm = vec4<f32>(v_verts.data[in_pos_nrm_idx[1]].xyz, 0.0);"
"\n var mv_pos = ubuf.mv * obj_pos;"
"\n var mv_norm = ubuf.mv_inv * obj_norm;"
"\n out.pos = ubuf.proj * mv_pos;";
} }
std::string fragmentFnPre; std::string fragmentFnPre;
@ -507,6 +516,20 @@ var<storage, read> v_packed_uvs: Vec2Block;
} }
uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4<f32>;"), i); uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4<f32>;"), i);
fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i); fragmentFnPre += fmt::format(FMT_STRING("\n var tevreg{0} = ubuf.tevreg{0};"), i);
info.uniformSize += 16;
}
if (info.sampledColorChannels.any()) {
uniformPre += "\n"
"struct Light {\n"
" pos: vec3<f32>;\n"
" dir: vec3<f32>;\n"
" color: vec4<f32>;\n"
" lin_att: vec3<f32>;\n"
" ang_att: vec3<f32>;\n"
"};";
uniBufAttrs += fmt::format(FMT_STRING("\n lights: array<Light, {}>;"), MaxLights);
uniBufAttrs += "\n lighting_ambient: vec4<f32>;";
info.uniformSize += (80 * MaxLights) + 16;
} }
for (int i = 0; i < info.sampledColorChannels.size(); ++i) { for (int i = 0; i < info.sampledColorChannels.size(); ++i) {
if (!info.sampledColorChannels.test(i)) { if (!info.sampledColorChannels.test(i)) {
@ -514,23 +537,46 @@ var<storage, read> v_packed_uvs: Vec2Block;
} }
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_amb: vec4<f32>;"), i); uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_amb: vec4<f32>;"), i);
uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4<f32>;"), i); // TODO not needed for SRC_VTX uniBufAttrs += fmt::format(FMT_STRING("\n cc{0}_mat: vec4<f32>;"), i);
info.uniformSize += 32; info.uniformSize += 32;
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) cc{}: vec4<f32>;"), locIdx++, i);
vtxXfrAttrs += fmt::format(FMT_STRING(R"""(
{{
var lighting = ubuf.lighting_ambient + ubuf.cc{0}_amb;
for (var i = 0; i < {1}; i = i + 1) {{
var light = ubuf.lights[i];
var delta = mv_pos.xyz - light.pos;
var dist = length(delta);
var delta_norm = delta / dist;
var ang_dot = max(dot(delta_norm, light.dir), 0.0);
var lin_att = light.lin_att;
var att = 1.0 / (lin_att.z * dist * dist * lin_att.y * dist + lin_att.x);
var ang_att = light.ang_att;
var ang_att_d = ang_att.z * ang_dot * ang_dot * ang_att.y * ang_dot + ang_att.x;
var this_color = light.color.xyz * ang_att_d * att * max(dot(-delta_norm, mv_norm.xyz), 0.0);
// if (i == 0 && c_traits.shader.world_shadow == 1u) {{
// // TODO ExtTex0 sample
// }}
lighting = lighting + vec4<f32>(this_color, 0.0);
}}
out.cc{0} = clamp(lighting, vec4<f32>(0.0), vec4<f32>(1.0));
}}
)"""), i, MaxLights);
if (config.channelMatSrcs[i] == GX::SRC_VTX) { if (config.channelMatSrcs[i] == GX::SRC_VTX) {
if (config.denormalizedVertexAttributes) { if (config.denormalizedVertexAttributes) {
if (!info.usesVtxColor) { if (!info.usesVtxColor) {
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) clr: vec4<f32>;"), locIdx); vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_clr: vec4<f32>"), locIdx);
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_clr: vec4<f32>"), ++locIdx); vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = in_clr;"), i);
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.clr = in_clr;"));
} }
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{} = in.clr; // TODO lighting"), i); fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
} else { } else {
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes")); Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
} }
info.usesVtxColor = true; info.usesVtxColor = true;
} else { } else {
fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = ubuf.cc{0}_amb; // TODO lighting"), i); fragmentFnPre += fmt::format(FMT_STRING("\n var rast{0} = in.cc{0};"), i);
} }
} }
for (int i = 0; i < info.sampledKcolors.size(); ++i) { for (int i = 0; i < info.sampledKcolors.size(); ++i) {
@ -540,6 +586,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
uniBufAttrs += fmt::format(FMT_STRING("\n kcolor{}: vec4<f32>;"), i); uniBufAttrs += fmt::format(FMT_STRING("\n kcolor{}: vec4<f32>;"), i);
info.uniformSize += 16; info.uniformSize += 16;
} }
size_t texBindIdx = 0;
for (int i = 0; i < info.sampledTextures.size(); ++i) { for (int i = 0; i < info.sampledTextures.size(); ++i) {
if (!info.sampledTextures.test(i)) { if (!info.sampledTextures.test(i)) {
continue; continue;
@ -547,12 +594,13 @@ var<storage, read> v_packed_uvs: Vec2Block;
uniBufAttrs += fmt::format(FMT_STRING("\n tex{}_lod: f32;"), i); uniBufAttrs += fmt::format(FMT_STRING("\n tex{}_lod: f32;"), i);
info.uniformSize += 4; info.uniformSize += 4;
sampBindings += fmt::format(FMT_STRING("\n@group(1) @binding({0})\n" sampBindings += fmt::format(FMT_STRING("\n@group(1) @binding({})\n"
"var tex{0}_samp: sampler;"), "var tex{}_samp: sampler;"),
i); texBindIdx, i);
texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({0})\n" texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n"
"var tex{0}: texture_2d<f32>;"), "var tex{}: texture_2d<f32>;"),
i); texBindIdx, i);
++texBindIdx;
if (config.denormalizedVertexAttributes) { if (config.denormalizedVertexAttributes) {
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i); vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) tex{}_uv: vec2<f32>;"), locIdx, i);
@ -576,9 +624,11 @@ var<storage, read> v_packed_uvs: Vec2Block;
} }
const auto shaderSource = const auto shaderSource =
fmt::format(FMT_STRING(R"""( fmt::format(FMT_STRING(R"""({uniformPre}
struct Uniform {{ struct Uniform {{
xf: mat4x4<f32>;{uniBufAttrs} mv: mat4x4<f32>;
mv_inv: mat4x4<f32>;
proj: mat4x4<f32>;{uniBufAttrs}
}}; }};
@group(0) @binding(0) @group(0) @binding(0)
var<uniform> ubuf: Uniform;{uniformBindings}{sampBindings}{texBindings} var<uniform> ubuf: Uniform;{uniformBindings}{sampBindings}{texBindings}
@ -602,7 +652,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {{
"uniBufAttrs"_a = uniBufAttrs, "sampBindings"_a = sampBindings, "texBindings"_a = texBindings, "uniBufAttrs"_a = uniBufAttrs, "sampBindings"_a = sampBindings, "texBindings"_a = texBindings,
"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); "uniformBindings"_a = uniformBindings, "uniformPre"_a = uniformPre);
Log.report(logvisor::Info, FMT_STRING("Generated shader: {}"), shaderSource); Log.report(logvisor::Info, FMT_STRING("Generated shader: {}"), shaderSource);
wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{}; wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{};

View File

@ -8,7 +8,6 @@
#include <memory> #include <memory>
#include "dawn/BackendBinding.hpp" #include "dawn/BackendBinding.hpp"
#include "dawn/Hacks.hpp"
namespace aurora::gpu { namespace aurora::gpu {
static logvisor::Module Log("aurora::gpu"); static logvisor::Module Log("aurora::gpu");
@ -133,16 +132,41 @@ void initialize(SDL_Window* window) {
g_AdapterProperties.driverDescription); g_AdapterProperties.driverDescription);
{ {
WGPUSupportedLimits supportedLimits{};
g_Adapter.GetLimits(&supportedLimits);
const wgpu::RequiredLimits requiredLimits{
.limits =
{
.minUniformBufferOffsetAlignment = supportedLimits.limits.minUniformBufferOffsetAlignment,
.minStorageBufferOffsetAlignment = supportedLimits.limits.minStorageBufferOffsetAlignment,
},
};
const std::array<wgpu::FeatureName, 1> requiredFeatures{ const std::array<wgpu::FeatureName, 1> requiredFeatures{
wgpu::FeatureName::TextureCompressionBC, wgpu::FeatureName::TextureCompressionBC,
}; };
const std::array enableToggles {
/* clang-format off */
#if _WIN32
"use_dxc",
#endif
#ifdef NDEBUG
"skip_validation", "disable_robustness",
#else
"use_user_defined_labels_in_backend",
#endif
/* clang-format on */
};
wgpu::DawnTogglesDeviceDescriptor togglesDescriptor{};
togglesDescriptor.forceEnabledTogglesCount = enableToggles.size();
togglesDescriptor.forceEnabledToggles = enableToggles.data();
const auto deviceDescriptor = wgpu::DeviceDescriptor{ const auto deviceDescriptor = wgpu::DeviceDescriptor{
.nextInChain = &togglesDescriptor,
.requiredFeaturesCount = requiredFeatures.size(), .requiredFeaturesCount = requiredFeatures.size(),
.requiredFeatures = requiredFeatures.data(), .requiredFeatures = requiredFeatures.data(),
.requiredLimits = &requiredLimits,
}; };
g_device = wgpu::Device::Acquire(g_Adapter.CreateDevice(&deviceDescriptor)); g_device = wgpu::Device::Acquire(g_Adapter.CreateDevice(&deviceDescriptor));
g_device.SetUncapturedErrorCallback(&error_callback, nullptr); g_device.SetUncapturedErrorCallback(&error_callback, nullptr);
hacks::apply_toggles(g_device.Get());
} }
g_queue = g_device.GetQueue(); g_queue = g_device.GetQueue();