mirror of https://github.com/AxioDL/metaforce.git
Implement HandleTransparency, lighting & fix texture load
This commit is contained in:
parent
a2743b905b
commit
e88f831950
|
@ -305,11 +305,36 @@ void CCubeMaterial::EnsureViewDepStateCached(const CCubeSurface* surface) {
|
|||
u32 CCubeMaterial::HandleColorChannels(u32 chanCount, u32 firstChan) {
|
||||
if (CCubeModel::sRenderModelShadow) {
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
aurora::gfx::set_chan_mat_src(GX::COLOR0A0, 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) {
|
||||
// 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);
|
||||
// GXSetTevAlphaIn(finalTevCount, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_ZERO, TEVALPHAARG_APREV);
|
||||
// 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);
|
||||
// GXSetTevAlphaOp(finalTevCount, 0, 0, 0, 1, 0); // AlphaRegPrev
|
||||
// GXSetTevOrder(finalTevCount, 255, 255, 255);
|
||||
// GXSetTevDirect(finalTevCount);
|
||||
// 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);
|
||||
// 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);
|
||||
// SetStandardTevColorAlphaOp(finalTevCount + 1);
|
||||
// GXSetTevDirect(finalTevCount + 1);
|
||||
// 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);
|
||||
finalKColorCount += 1;
|
||||
finalTevCount += 2;
|
||||
} else {
|
||||
// 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
|
||||
if (modelFlags.x0_blendMode == 8) {
|
||||
// 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
|
||||
}
|
||||
// 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
|
||||
if (modelFlags.x0_blendMode == 2) {
|
||||
// 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
|
||||
}
|
||||
aurora::gfx::update_tev_stage(static_cast<ERglTevStage>(finalTevCount), colorPass, alphaPass, {}, {});
|
||||
// GXSetTevColorIn(finalTevCount)
|
||||
// GXSetTevAlphaIn(finalTevCount)
|
||||
// SetStandardTevColorAlphaOp(finalTevCount);
|
||||
|
@ -422,8 +467,13 @@ void CCubeMaterial::HandleTransparency(u32& finalTevCount, u32& finalKColorCount
|
|||
finalACFlags = 0x100;
|
||||
// GXSetTevDirect(finalTevCount);
|
||||
// GXSetTevOrder(finalTevCount, 255, 255, 255);
|
||||
aurora::gfx::set_tev_k_color(static_cast<GX::TevKColorID>(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);
|
||||
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);
|
||||
finalTevCount += 1;
|
||||
finalKColorCount += 1;
|
||||
|
|
|
@ -78,7 +78,7 @@ bool CCubeModel::TryLockTextures() {
|
|||
}
|
||||
if (loadTexture) {
|
||||
// texture->LoadToMRAM();
|
||||
texturesPumped = true;
|
||||
// texturesPumped = true;
|
||||
}
|
||||
}
|
||||
if (!texturesPumped) {
|
||||
|
|
|
@ -21,7 +21,6 @@ add_library(aurora STATIC
|
|||
lib/imgui.cpp
|
||||
lib/input.cpp
|
||||
lib/dawn/BackendBinding.cpp
|
||||
lib/dawn/Hacks.cpp
|
||||
lib/gfx/common.cpp
|
||||
lib/gfx/texture.cpp
|
||||
lib/gfx/stream.cpp
|
||||
|
|
|
@ -248,9 +248,9 @@ enum class ZComp : uint8_t {
|
|||
|
||||
constexpr u32 MaxLights = 8;
|
||||
struct Light {
|
||||
zeus::CVector3f pos;
|
||||
zeus::CVector3f dir;
|
||||
zeus::CColor color;
|
||||
zeus::CVector3f pos{0.f, 0.f, 0.f};
|
||||
zeus::CVector3f dir{0.f, 0.f, -1.f};
|
||||
zeus::CColor color{0.f, 0.f, 0.f, 0.f};
|
||||
zeus::CVector3f linAtt{1.f, 0.f, 0.f};
|
||||
zeus::CVector3f angAtt{1.f, 0.f, 0.f};
|
||||
};
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -424,24 +424,18 @@ void shutdown() {
|
|||
}
|
||||
|
||||
void render(const wgpu::RenderPassEncoder& pass) {
|
||||
{
|
||||
if (g_verts.size() > 0) {
|
||||
g_queue.WriteBuffer(g_vertexBuffer, 0, g_verts.data(), g_verts.size());
|
||||
g_verts.clear();
|
||||
}
|
||||
if (g_uniforms.size() > 0) {
|
||||
g_queue.WriteBuffer(g_uniformBuffer, 0, g_uniforms.data(), g_uniforms.size());
|
||||
g_uniforms.clear();
|
||||
}
|
||||
if (g_indices.size() > 0) {
|
||||
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();
|
||||
}
|
||||
const auto writeBuffer = [](ByteBuffer& buf, wgpu::Buffer& out) {
|
||||
const auto size = buf.size();
|
||||
if (size > 0) {
|
||||
g_queue.WriteBuffer(out, 0, buf.data(), size);
|
||||
buf.clear();
|
||||
buf.reserve_extra(size); // Reserve size from previous frame
|
||||
}
|
||||
};
|
||||
writeBuffer(g_verts, g_vertexBuffer);
|
||||
writeBuffer(g_uniforms, g_uniformBuffer);
|
||||
writeBuffer(g_indices, g_indexBuffer);
|
||||
writeBuffer(g_storage, g_storageBuffer);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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_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);
|
||||
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) {
|
||||
const auto id = xxh3_hash(descriptor);
|
||||
|
|
|
@ -30,26 +30,32 @@ public:
|
|||
ByteBuffer() noexcept = default;
|
||||
explicit ByteBuffer(size_t size) noexcept
|
||||
: 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 {
|
||||
if (m_data != nullptr) {
|
||||
if (m_data != nullptr && m_owned) {
|
||||
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_length = 0;
|
||||
rhs.m_capacity = 0;
|
||||
rhs.m_owned = true;
|
||||
}
|
||||
ByteBuffer& operator=(ByteBuffer&& rhs) noexcept {
|
||||
if (m_data != nullptr) {
|
||||
if (m_data != nullptr && m_owned) {
|
||||
free(m_data);
|
||||
}
|
||||
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_length = 0;
|
||||
rhs.m_capacity = 0;
|
||||
rhs.m_owned = true;
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer(ByteBuffer const&) = delete;
|
||||
|
@ -61,38 +67,52 @@ public:
|
|||
[[nodiscard]] bool empty() const noexcept { return m_length == 0; }
|
||||
|
||||
void append(const void* data, size_t size) {
|
||||
resize(m_length + size);
|
||||
resize(m_length + size, false);
|
||||
memcpy(m_data + m_length, data, size);
|
||||
m_length += size;
|
||||
}
|
||||
|
||||
void append_zeroes(size_t size) {
|
||||
resize(m_length + size);
|
||||
memset(m_data + m_length, 0, size);
|
||||
resize(m_length + size, true);
|
||||
m_length += size;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (m_data != nullptr) {
|
||||
if (m_data != nullptr && m_owned) {
|
||||
free(m_data);
|
||||
}
|
||||
m_data = nullptr;
|
||||
m_length = 0;
|
||||
m_capacity = 0;
|
||||
m_owned = true;
|
||||
}
|
||||
|
||||
void reserve_extra(size_t size) { resize(m_length + size, true); }
|
||||
|
||||
private:
|
||||
uint8_t* m_data = nullptr;
|
||||
size_t m_length = 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) {
|
||||
clear();
|
||||
} else if (m_data == nullptr) {
|
||||
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) {
|
||||
if (!m_owned) {
|
||||
abort();
|
||||
}
|
||||
m_data = static_cast<uint8_t*>(realloc(m_data, size));
|
||||
if (zeroed) {
|
||||
memset(m_data + m_capacity, 0, size - m_capacity);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -165,6 +185,10 @@ template <typename T>
|
|||
static inline Range push_storage(const T& data) {
|
||||
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>
|
||||
const State& get_state();
|
||||
|
|
|
@ -363,29 +363,53 @@ ShaderInfo populate_pipeline_config(PipelineConfig& config, GX::Primitive primit
|
|||
}
|
||||
|
||||
Range build_uniform(const ShaderInfo& info) noexcept {
|
||||
ByteBuffer uniBuf;
|
||||
auto [buf, range] = map_uniform(info.uniformSize);
|
||||
{
|
||||
const auto xf = get_combined_matrix();
|
||||
uniBuf.append(&xf, 64);
|
||||
buf.append(&g_mv, 64);
|
||||
buf.append(&g_mvInv, 64);
|
||||
buf.append(&g_proj, 64);
|
||||
}
|
||||
for (int i = 0; i < info.usesTevReg.size(); ++i) {
|
||||
if (!info.usesTevReg.test(i)) {
|
||||
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) {
|
||||
if (!info.sampledColorChannels.test(i)) {
|
||||
continue;
|
||||
}
|
||||
uniBuf.append(&g_colorChannels[i].ambColor, 16);
|
||||
uniBuf.append(&g_colorChannels[i].matColor, 16);
|
||||
buf.append(&g_colorChannels[i].ambColor, 16);
|
||||
buf.append(&g_colorChannels[i].matColor, 16);
|
||||
}
|
||||
for (int i = 0; i < info.sampledKcolors.size(); ++i) {
|
||||
if (!info.sampledKcolors.test(i)) {
|
||||
continue;
|
||||
}
|
||||
uniBuf.append(&g_kcolors[i], 16);
|
||||
buf.append(&g_kcolors[i], 16);
|
||||
}
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++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);
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
}
|
||||
|
||||
std::string uniformPre;
|
||||
std::string uniBufAttrs;
|
||||
std::string uniformBindings;
|
||||
std::string sampBindings;
|
||||
|
@ -395,11 +396,15 @@ std::pair<wgpu::ShaderModule, ShaderInfo> build_shader(const ShaderConfig& confi
|
|||
if (config.denormalizedVertexAttributes) {
|
||||
vtxInAttrs += "\n @location(0) in_pos: vec3<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) {
|
||||
vtxOutAttrs += fmt::format(FMT_STRING("\n @location({}) 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;"));
|
||||
vtxXfrAttrsPre += "\n var obj_norm = vec4<f32>(in_nrm, 0.0);"
|
||||
"\n var mv_norm = ubuf.mv_inv * obj_norm;";
|
||||
info.usesNormal = true;
|
||||
}
|
||||
} else {
|
||||
|
@ -424,7 +429,11 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
"\n , @location(1) in_uv_0_4_idx: vec4<i32>"
|
||||
"\n , @location(2) in_uv_5_7_idx: vec4<i32>";
|
||||
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;
|
||||
|
@ -507,6 +516,20 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
}
|
||||
uniBufAttrs += fmt::format(FMT_STRING("\n tevreg{}: vec4<f32>;"), 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) {
|
||||
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}_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;
|
||||
|
||||
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.denormalizedVertexAttributes) {
|
||||
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);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.clr = in_clr;"));
|
||||
vtxInAttrs += fmt::format(FMT_STRING("\n , @location({}) in_clr: vec4<f32>"), locIdx);
|
||||
vtxXfrAttrs += fmt::format(FMT_STRING("\n out.cc{} = in_clr;"), i);
|
||||
}
|
||||
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 {
|
||||
Log.report(logvisor::Fatal, FMT_STRING("SRC_VTX unsupported with normalized vertex attributes"));
|
||||
}
|
||||
info.usesVtxColor = true;
|
||||
} 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) {
|
||||
|
@ -540,6 +586,7 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
uniBufAttrs += fmt::format(FMT_STRING("\n kcolor{}: vec4<f32>;"), i);
|
||||
info.uniformSize += 16;
|
||||
}
|
||||
size_t texBindIdx = 0;
|
||||
for (int i = 0; i < info.sampledTextures.size(); ++i) {
|
||||
if (!info.sampledTextures.test(i)) {
|
||||
continue;
|
||||
|
@ -547,12 +594,13 @@ var<storage, read> v_packed_uvs: Vec2Block;
|
|||
uniBufAttrs += fmt::format(FMT_STRING("\n tex{}_lod: f32;"), i);
|
||||
info.uniformSize += 4;
|
||||
|
||||
sampBindings += fmt::format(FMT_STRING("\n@group(1) @binding({0})\n"
|
||||
"var tex{0}_samp: sampler;"),
|
||||
i);
|
||||
texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({0})\n"
|
||||
"var tex{0}: texture_2d<f32>;"),
|
||||
i);
|
||||
sampBindings += fmt::format(FMT_STRING("\n@group(1) @binding({})\n"
|
||||
"var tex{}_samp: sampler;"),
|
||||
texBindIdx, i);
|
||||
texBindings += fmt::format(FMT_STRING("\n@group(2) @binding({})\n"
|
||||
"var tex{}: texture_2d<f32>;"),
|
||||
texBindIdx, i);
|
||||
++texBindIdx;
|
||||
|
||||
if (config.denormalizedVertexAttributes) {
|
||||
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 =
|
||||
fmt::format(FMT_STRING(R"""(
|
||||
fmt::format(FMT_STRING(R"""({uniformPre}
|
||||
struct Uniform {{
|
||||
xf: mat4x4<f32>;{uniBufAttrs}
|
||||
mv: mat4x4<f32>;
|
||||
mv_inv: mat4x4<f32>;
|
||||
proj: mat4x4<f32>;{uniBufAttrs}
|
||||
}};
|
||||
@group(0) @binding(0)
|
||||
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,
|
||||
"vtxOutAttrs"_a = vtxOutAttrs, "vtxInAttrs"_a = vtxInAttrs, "vtxXfrAttrs"_a = vtxXfrAttrs,
|
||||
"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);
|
||||
|
||||
wgpu::ShaderModuleWGSLDescriptor wgslDescriptor{};
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <memory>
|
||||
|
||||
#include "dawn/BackendBinding.hpp"
|
||||
#include "dawn/Hacks.hpp"
|
||||
|
||||
namespace aurora::gpu {
|
||||
static logvisor::Module Log("aurora::gpu");
|
||||
|
@ -133,16 +132,41 @@ void initialize(SDL_Window* window) {
|
|||
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{
|
||||
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{
|
||||
.nextInChain = &togglesDescriptor,
|
||||
.requiredFeaturesCount = requiredFeatures.size(),
|
||||
.requiredFeatures = requiredFeatures.data(),
|
||||
.requiredLimits = &requiredLimits,
|
||||
};
|
||||
g_device = wgpu::Device::Acquire(g_Adapter.CreateDevice(&deviceDescriptor));
|
||||
g_device.SetUncapturedErrorCallback(&error_callback, nullptr);
|
||||
hacks::apply_toggles(g_device.Get());
|
||||
}
|
||||
g_queue = g_device.GetQueue();
|
||||
|
||||
|
|
Loading…
Reference in New Issue